customer.e2e-spec.ts 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383
  1. import gql from 'graphql-tag';
  2. import path from 'path';
  3. import {
  4. CREATE_CUSTOMER_ADDRESS,
  5. GET_CUSTOMER,
  6. GET_CUSTOMER_LIST,
  7. UPDATE_CUSTOMER,
  8. UPDATE_CUSTOMER_ADDRESS,
  9. } from '../../admin-ui/src/app/data/definitions/customer-definitions';
  10. import {
  11. CreateCustomerAddress,
  12. DeletionResult,
  13. GetCustomer,
  14. GetCustomerList,
  15. UpdateCustomer,
  16. UpdateCustomerAddress,
  17. } from '../../shared/generated-types';
  18. import { omit } from '../../shared/omit';
  19. import { TEST_SETUP_TIMEOUT_MS } from './config/test-config';
  20. import { TestAdminClient, TestShopClient } from './test-client';
  21. import { TestServer } from './test-server';
  22. import { assertThrowsWithMessage } from './test-utils';
  23. // tslint:disable:no-non-null-assertion
  24. describe('Customer resolver', () => {
  25. const adminClient = new TestAdminClient();
  26. const shopClient = new TestShopClient();
  27. const server = new TestServer();
  28. let firstCustomer: GetCustomerList.Items;
  29. let secondCustomer: GetCustomerList.Items;
  30. let thirdCustomer: GetCustomerList.Items;
  31. beforeAll(async () => {
  32. const token = await server.init({
  33. productsCsvPath: path.join(__dirname, 'fixtures/e2e-products-minimal.csv'),
  34. customerCount: 5,
  35. });
  36. await adminClient.init();
  37. }, TEST_SETUP_TIMEOUT_MS);
  38. afterAll(async () => {
  39. await server.destroy();
  40. });
  41. it('customers list', async () => {
  42. const result = await adminClient.query<GetCustomerList.Query, GetCustomerList.Variables>(
  43. GET_CUSTOMER_LIST,
  44. );
  45. expect(result.customers.items.length).toBe(5);
  46. expect(result.customers.totalItems).toBe(5);
  47. firstCustomer = result.customers.items[0];
  48. secondCustomer = result.customers.items[1];
  49. thirdCustomer = result.customers.items[2];
  50. });
  51. describe('addresses', () => {
  52. let firstCustomerAddressIds: string[] = [];
  53. let firstCustomerThirdAddressId: string;
  54. it(
  55. 'createCustomerAddress throws on invalid countryCode',
  56. assertThrowsWithMessage(
  57. () =>
  58. adminClient.query(CREATE_ADDRESS, {
  59. id: firstCustomer.id,
  60. input: {
  61. streetLine1: 'streetLine1',
  62. countryCode: 'INVALID',
  63. },
  64. }),
  65. `The countryCode "INVALID" was not recognized`,
  66. ),
  67. );
  68. it('createCustomerAddress creates a new address', async () => {
  69. const result = await adminClient.query(CREATE_ADDRESS, {
  70. id: firstCustomer.id,
  71. input: {
  72. fullName: 'fullName',
  73. company: 'company',
  74. streetLine1: 'streetLine1',
  75. streetLine2: 'streetLine2',
  76. city: 'city',
  77. province: 'province',
  78. postalCode: 'postalCode',
  79. countryCode: 'GB',
  80. phoneNumber: 'phoneNumber',
  81. defaultShippingAddress: false,
  82. defaultBillingAddress: false,
  83. },
  84. });
  85. expect(omit(result.createCustomerAddress, ['id'])).toEqual({
  86. fullName: 'fullName',
  87. company: 'company',
  88. streetLine1: 'streetLine1',
  89. streetLine2: 'streetLine2',
  90. city: 'city',
  91. province: 'province',
  92. postalCode: 'postalCode',
  93. country: {
  94. code: 'GB',
  95. name: 'United Kingdom',
  96. },
  97. phoneNumber: 'phoneNumber',
  98. defaultShippingAddress: false,
  99. defaultBillingAddress: false,
  100. });
  101. });
  102. it('customer query returns addresses', async () => {
  103. const result = await adminClient.query<GetCustomer.Query, GetCustomer.Variables>(GET_CUSTOMER, {
  104. id: firstCustomer.id,
  105. });
  106. expect(result.customer!.addresses!.length).toBe(2);
  107. firstCustomerAddressIds = result.customer!.addresses!.map(a => a.id);
  108. });
  109. it('updateCustomerAddress allows only a single default address', async () => {
  110. // set the first customer's second address to be default
  111. const result1 = await adminClient.query(UPDATE_ADDRESS, {
  112. input: {
  113. id: firstCustomerAddressIds[1],
  114. defaultShippingAddress: true,
  115. defaultBillingAddress: true,
  116. },
  117. });
  118. expect(result1.updateCustomerAddress.defaultShippingAddress).toBe(true);
  119. expect(result1.updateCustomerAddress.defaultBillingAddress).toBe(true);
  120. // assert the first customer's first address is not default
  121. const result2 = await adminClient.query<GetCustomer.Query, GetCustomer.Variables>(GET_CUSTOMER, {
  122. id: firstCustomer.id,
  123. });
  124. expect(result2.customer!.addresses![0].defaultShippingAddress).toBe(false);
  125. expect(result2.customer!.addresses![0].defaultBillingAddress).toBe(false);
  126. // set the first customer's first address to be default
  127. const result3 = await adminClient.query(UPDATE_ADDRESS, {
  128. input: {
  129. id: firstCustomerAddressIds[0],
  130. defaultShippingAddress: true,
  131. defaultBillingAddress: true,
  132. },
  133. });
  134. expect(result3.updateCustomerAddress.defaultShippingAddress).toBe(true);
  135. expect(result3.updateCustomerAddress.defaultBillingAddress).toBe(true);
  136. // assert the first customer's second address is not default
  137. const result4 = await adminClient.query<GetCustomer.Query, GetCustomer.Variables>(GET_CUSTOMER, {
  138. id: firstCustomer.id,
  139. });
  140. expect(result4.customer!.addresses![1].defaultShippingAddress).toBe(false);
  141. expect(result4.customer!.addresses![1].defaultBillingAddress).toBe(false);
  142. // get the second customer's address id
  143. const result5 = await adminClient.query<GetCustomer.Query, GetCustomer.Variables>(GET_CUSTOMER, {
  144. id: secondCustomer.id,
  145. });
  146. const secondCustomerAddressId = result5.customer!.addresses![0].id;
  147. // set the second customer's address to be default
  148. const result6 = await adminClient.query(UPDATE_ADDRESS, {
  149. input: {
  150. id: secondCustomerAddressId,
  151. defaultShippingAddress: true,
  152. defaultBillingAddress: true,
  153. },
  154. });
  155. expect(result6.updateCustomerAddress.defaultShippingAddress).toBe(true);
  156. expect(result6.updateCustomerAddress.defaultBillingAddress).toBe(true);
  157. // assets the first customer's address defaults are unchanged
  158. const result7 = await adminClient.query<GetCustomer.Query, GetCustomer.Variables>(GET_CUSTOMER, {
  159. id: firstCustomer.id,
  160. });
  161. expect(result7.customer!.addresses![0].defaultShippingAddress).toBe(true);
  162. expect(result7.customer!.addresses![0].defaultBillingAddress).toBe(true);
  163. expect(result7.customer!.addresses![1].defaultShippingAddress).toBe(false);
  164. expect(result7.customer!.addresses![1].defaultBillingAddress).toBe(false);
  165. });
  166. it('createCustomerAddress with true defaults unsets existing defaults', async () => {
  167. const result1 = await adminClient.query(CREATE_ADDRESS, {
  168. id: firstCustomer.id,
  169. input: {
  170. streetLine1: 'new default streetline',
  171. countryCode: 'GB',
  172. defaultShippingAddress: true,
  173. defaultBillingAddress: true,
  174. },
  175. });
  176. expect(omit(result1.createCustomerAddress, ['id'])).toEqual({
  177. fullName: '',
  178. company: '',
  179. streetLine1: 'new default streetline',
  180. streetLine2: '',
  181. city: '',
  182. province: '',
  183. postalCode: '',
  184. country: {
  185. code: 'GB',
  186. name: 'United Kingdom',
  187. },
  188. phoneNumber: '',
  189. defaultShippingAddress: true,
  190. defaultBillingAddress: true,
  191. });
  192. const result2 = await adminClient.query<GetCustomer.Query, GetCustomer.Variables>(GET_CUSTOMER, {
  193. id: firstCustomer.id,
  194. });
  195. expect(result2.customer!.addresses![0].defaultShippingAddress).toBe(false);
  196. expect(result2.customer!.addresses![0].defaultBillingAddress).toBe(false);
  197. expect(result2.customer!.addresses![1].defaultShippingAddress).toBe(false);
  198. expect(result2.customer!.addresses![1].defaultBillingAddress).toBe(false);
  199. expect(result2.customer!.addresses![2].defaultShippingAddress).toBe(true);
  200. expect(result2.customer!.addresses![2].defaultBillingAddress).toBe(true);
  201. firstCustomerThirdAddressId = result2.customer!.addresses![2].id;
  202. });
  203. it('deleteCustomerAddress on default address resets defaults', async () => {
  204. const result = await adminClient.query(
  205. gql`
  206. mutation DeleteCustomerAddress($id: ID!) {
  207. deleteCustomerAddress(id: $id)
  208. }
  209. `,
  210. { id: firstCustomerThirdAddressId },
  211. );
  212. expect(result.deleteCustomerAddress).toBe(true);
  213. const result2 = await adminClient.query<GetCustomer.Query, GetCustomer.Variables>(GET_CUSTOMER, {
  214. id: firstCustomer.id,
  215. });
  216. expect(result2.customer!.addresses!.length).toBe(2);
  217. expect(result2.customer!.addresses![0].defaultShippingAddress).toBe(true);
  218. expect(result2.customer!.addresses![0].defaultBillingAddress).toBe(true);
  219. expect(result2.customer!.addresses![1].defaultShippingAddress).toBe(false);
  220. expect(result2.customer!.addresses![1].defaultBillingAddress).toBe(false);
  221. });
  222. });
  223. describe('orders', () => {
  224. it(`lists that user\'s orders`, async () => {
  225. // log in as first customer
  226. await shopClient.asUserWithCredentials(firstCustomer.emailAddress, 'test');
  227. // add an item to the order to create an order
  228. const result1 = await shopClient.query(ADD_ITEM_TO_ORDER, {
  229. productVariantId: 'T_1',
  230. quantity: 1,
  231. });
  232. const result2 = await adminClient.query(GET_CUSTOMER_ORDERS, { id: firstCustomer.id });
  233. expect(result2.customer.orders.totalItems).toBe(1);
  234. expect(result2.customer.orders.items[0].id).toBe(result1.addItemToOrder.id);
  235. });
  236. });
  237. describe('deletion', () => {
  238. it('deletes a customer', async () => {
  239. const result = await adminClient.query(DELETE_CUSTOMER, { id: thirdCustomer.id });
  240. expect(result.deleteCustomer).toEqual({ result: DeletionResult.DELETED });
  241. });
  242. it('cannot get a deleted customer', async () => {
  243. const result = await adminClient.query<GetCustomer.Query, GetCustomer.Variables>(GET_CUSTOMER, {
  244. id: thirdCustomer.id,
  245. });
  246. expect(result.customer).toBe(null);
  247. });
  248. it('deleted customer omitted from list', async () => {
  249. const result = await adminClient.query<GetCustomerList.Query, GetCustomerList.Variables>(
  250. GET_CUSTOMER_LIST,
  251. );
  252. expect(result.customers.items.map(c => c.id).includes(thirdCustomer.id)).toBe(false);
  253. });
  254. it(
  255. 'updateCustomer throws for deleted customer',
  256. assertThrowsWithMessage(
  257. () =>
  258. adminClient.query<UpdateCustomer.Mutation, UpdateCustomer.Variables>(UPDATE_CUSTOMER, {
  259. input: {
  260. id: thirdCustomer.id,
  261. firstName: 'updated',
  262. },
  263. }),
  264. `No Customer with the id '3' could be found`,
  265. ),
  266. );
  267. it(
  268. 'createCustomerAddress throws for deleted customer',
  269. assertThrowsWithMessage(
  270. () =>
  271. adminClient.query<CreateCustomerAddress.Mutation, CreateCustomerAddress.Variables>(
  272. CREATE_CUSTOMER_ADDRESS,
  273. {
  274. customerId: thirdCustomer.id,
  275. input: {
  276. streetLine1: 'test',
  277. countryCode: 'GB',
  278. },
  279. },
  280. ),
  281. `No Customer with the id '3' could be found`,
  282. ),
  283. );
  284. });
  285. });
  286. const CREATE_ADDRESS = gql`
  287. mutation CreateAddress($id: ID!, $input: CreateAddressInput!) {
  288. createCustomerAddress(customerId: $id, input: $input) {
  289. id
  290. fullName
  291. company
  292. streetLine1
  293. streetLine2
  294. city
  295. province
  296. postalCode
  297. country {
  298. code
  299. name
  300. }
  301. phoneNumber
  302. defaultShippingAddress
  303. defaultBillingAddress
  304. }
  305. }
  306. `;
  307. const UPDATE_ADDRESS = gql`
  308. mutation UpdateAddress($input: UpdateAddressInput!) {
  309. updateCustomerAddress(input: $input) {
  310. id
  311. defaultShippingAddress
  312. defaultBillingAddress
  313. }
  314. }
  315. `;
  316. const ADD_ITEM_TO_ORDER = gql`
  317. mutation AddItemToOrder($productVariantId: ID!, $quantity: Int!) {
  318. addItemToOrder(productVariantId: $productVariantId, quantity: $quantity) {
  319. id
  320. }
  321. }
  322. `;
  323. const GET_CUSTOMER_ORDERS = gql`
  324. query GetCustomerOrders($id: ID!) {
  325. customer(id: $id) {
  326. orders {
  327. items {
  328. id
  329. }
  330. totalItems
  331. }
  332. }
  333. }
  334. `;
  335. const DELETE_CUSTOMER = gql`
  336. mutation DeleteCustomer($id: ID!) {
  337. deleteCustomer(id: $id) {
  338. result
  339. }
  340. }
  341. `;