customer.e2e-spec.ts 15 KB

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