customer.e2e-spec.ts 27 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749
  1. import { OnModuleInit } from '@nestjs/common';
  2. import { HistoryEntryType } from '@vendure/common/lib/generated-types';
  3. import { omit } from '@vendure/common/lib/omit';
  4. import { pick } from '@vendure/common/lib/pick';
  5. import {
  6. AccountRegistrationEvent,
  7. EventBus,
  8. EventBusModule,
  9. mergeConfig,
  10. VendurePlugin,
  11. } from '@vendure/core';
  12. import { createErrorResultGuard, createTestEnvironment, ErrorResultGuard } from '@vendure/testing';
  13. import gql from 'graphql-tag';
  14. import path from 'path';
  15. import { initialData } from '../../../e2e-common/e2e-initial-data';
  16. import { testConfig, TEST_SETUP_TIMEOUT_MS } from '../../../e2e-common/test-config';
  17. import { CUSTOMER_FRAGMENT } from './graphql/fragments';
  18. import {
  19. AddNoteToCustomer,
  20. CreateAddress,
  21. CreateCustomer,
  22. CustomerFragment,
  23. DeleteCustomer,
  24. DeleteCustomerAddress,
  25. DeleteCustomerNote,
  26. DeletionResult,
  27. ErrorCode,
  28. GetCustomer,
  29. GetCustomerHistory,
  30. GetCustomerList,
  31. GetCustomerOrders,
  32. GetCustomerWithUser,
  33. Me,
  34. UpdateAddress,
  35. UpdateCustomer,
  36. UpdateCustomerNote,
  37. } from './graphql/generated-e2e-admin-types';
  38. import {
  39. ActiveOrderCustomerFragment,
  40. AddItemToOrder,
  41. AddItemToOrderMutation,
  42. AddItemToOrderMutationVariables,
  43. SetCustomerForOrderMutation,
  44. SetCustomerForOrderMutationVariables,
  45. UpdatedOrderFragment,
  46. } from './graphql/generated-e2e-shop-types';
  47. import {
  48. CREATE_ADDRESS,
  49. CREATE_CUSTOMER,
  50. DELETE_CUSTOMER,
  51. DELETE_CUSTOMER_NOTE,
  52. GET_CUSTOMER,
  53. GET_CUSTOMER_HISTORY,
  54. GET_CUSTOMER_LIST,
  55. ME,
  56. UPDATE_ADDRESS,
  57. UPDATE_CUSTOMER,
  58. UPDATE_CUSTOMER_NOTE,
  59. } from './graphql/shared-definitions';
  60. import { ADD_ITEM_TO_ORDER, SET_CUSTOMER } from './graphql/shop-definitions';
  61. import { assertThrowsWithMessage } from './utils/assert-throws-with-message';
  62. // tslint:disable:no-non-null-assertion
  63. let sendEmailFn: jest.Mock;
  64. /**
  65. * This mock plugin simulates an EmailPlugin which would send emails
  66. * on the registration & password reset events.
  67. */
  68. @VendurePlugin({
  69. imports: [EventBusModule],
  70. })
  71. class TestEmailPlugin implements OnModuleInit {
  72. constructor(private eventBus: EventBus) {}
  73. onModuleInit() {
  74. this.eventBus.ofType(AccountRegistrationEvent).subscribe(event => {
  75. sendEmailFn(event);
  76. });
  77. }
  78. }
  79. describe('Customer resolver', () => {
  80. const { server, adminClient, shopClient } = createTestEnvironment(
  81. mergeConfig(testConfig(), { plugins: [TestEmailPlugin] }),
  82. );
  83. let firstCustomer: GetCustomerList.Items;
  84. let secondCustomer: GetCustomerList.Items;
  85. let thirdCustomer: GetCustomerList.Items;
  86. const customerErrorGuard: ErrorResultGuard<CustomerFragment> = createErrorResultGuard(
  87. input => !!input.emailAddress,
  88. );
  89. beforeAll(async () => {
  90. await server.init({
  91. initialData,
  92. productsCsvPath: path.join(__dirname, 'fixtures/e2e-products-minimal.csv'),
  93. customerCount: 5,
  94. });
  95. await adminClient.asSuperAdmin();
  96. }, TEST_SETUP_TIMEOUT_MS);
  97. afterAll(async () => {
  98. await server.destroy();
  99. });
  100. it('customers list', async () => {
  101. const result = await adminClient.query<GetCustomerList.Query, GetCustomerList.Variables>(
  102. GET_CUSTOMER_LIST,
  103. );
  104. expect(result.customers.items.length).toBe(5);
  105. expect(result.customers.totalItems).toBe(5);
  106. firstCustomer = result.customers.items[0];
  107. secondCustomer = result.customers.items[1];
  108. thirdCustomer = result.customers.items[2];
  109. });
  110. it('customers list filter by postalCode', async () => {
  111. const result = await adminClient.query<GetCustomerList.Query, GetCustomerList.Variables>(
  112. GET_CUSTOMER_LIST,
  113. {
  114. options: {
  115. filter: {
  116. postalCode: {
  117. eq: 'NU9 0PW',
  118. },
  119. },
  120. },
  121. },
  122. );
  123. expect(result.customers.items.length).toBe(1);
  124. expect(result.customers.items[0].emailAddress).toBe('eliezer56@yahoo.com');
  125. });
  126. it('customer resolver resolves User', async () => {
  127. const { customer } = await adminClient.query<
  128. GetCustomerWithUser.Query,
  129. GetCustomerWithUser.Variables
  130. >(GET_CUSTOMER_WITH_USER, {
  131. id: firstCustomer.id,
  132. });
  133. expect(customer!.user).toEqual({
  134. id: 'T_2',
  135. identifier: firstCustomer.emailAddress,
  136. verified: true,
  137. });
  138. });
  139. describe('addresses', () => {
  140. let firstCustomerAddressIds: string[] = [];
  141. let firstCustomerThirdAddressId: string;
  142. it(
  143. 'createCustomerAddress throws on invalid countryCode',
  144. assertThrowsWithMessage(
  145. () =>
  146. adminClient.query<CreateAddress.Mutation, CreateAddress.Variables>(CREATE_ADDRESS, {
  147. id: firstCustomer.id,
  148. input: {
  149. streetLine1: 'streetLine1',
  150. countryCode: 'INVALID',
  151. },
  152. }),
  153. `The countryCode "INVALID" was not recognized`,
  154. ),
  155. );
  156. it('createCustomerAddress creates a new address', async () => {
  157. const result = await adminClient.query<CreateAddress.Mutation, CreateAddress.Variables>(
  158. CREATE_ADDRESS,
  159. {
  160. id: firstCustomer.id,
  161. input: {
  162. fullName: 'fullName',
  163. company: 'company',
  164. streetLine1: 'streetLine1',
  165. streetLine2: 'streetLine2',
  166. city: 'city',
  167. province: 'province',
  168. postalCode: 'postalCode',
  169. countryCode: 'GB',
  170. phoneNumber: 'phoneNumber',
  171. defaultShippingAddress: false,
  172. defaultBillingAddress: false,
  173. },
  174. },
  175. );
  176. expect(omit(result.createCustomerAddress, ['id'])).toEqual({
  177. fullName: 'fullName',
  178. company: 'company',
  179. streetLine1: 'streetLine1',
  180. streetLine2: 'streetLine2',
  181. city: 'city',
  182. province: 'province',
  183. postalCode: 'postalCode',
  184. country: {
  185. code: 'GB',
  186. name: 'United Kingdom',
  187. },
  188. phoneNumber: 'phoneNumber',
  189. defaultShippingAddress: false,
  190. defaultBillingAddress: false,
  191. });
  192. });
  193. it('customer query returns addresses', async () => {
  194. const result = await adminClient.query<GetCustomer.Query, GetCustomer.Variables>(GET_CUSTOMER, {
  195. id: firstCustomer.id,
  196. });
  197. expect(result.customer!.addresses!.length).toBe(2);
  198. firstCustomerAddressIds = result.customer!.addresses!.map(a => a.id).sort();
  199. });
  200. it('updateCustomerAddress updates the country', async () => {
  201. const result = await adminClient.query<UpdateAddress.Mutation, UpdateAddress.Variables>(
  202. UPDATE_ADDRESS,
  203. {
  204. input: {
  205. id: firstCustomerAddressIds[0],
  206. countryCode: 'AT',
  207. },
  208. },
  209. );
  210. expect(result.updateCustomerAddress.country).toEqual({
  211. code: 'AT',
  212. name: 'Austria',
  213. });
  214. });
  215. it('updateCustomerAddress allows only a single default address', async () => {
  216. // set the first customer's second address to be default
  217. const result1 = await adminClient.query<UpdateAddress.Mutation, UpdateAddress.Variables>(
  218. UPDATE_ADDRESS,
  219. {
  220. input: {
  221. id: firstCustomerAddressIds[1],
  222. defaultShippingAddress: true,
  223. defaultBillingAddress: true,
  224. },
  225. },
  226. );
  227. expect(result1.updateCustomerAddress.defaultShippingAddress).toBe(true);
  228. expect(result1.updateCustomerAddress.defaultBillingAddress).toBe(true);
  229. // assert the first customer's other addresse is not default
  230. const result2 = await adminClient.query<GetCustomer.Query, GetCustomer.Variables>(GET_CUSTOMER, {
  231. id: firstCustomer.id,
  232. });
  233. const otherAddress = result2.customer!.addresses!.filter(
  234. a => a.id !== firstCustomerAddressIds[1],
  235. )[0]!;
  236. expect(otherAddress.defaultShippingAddress).toBe(false);
  237. expect(otherAddress.defaultBillingAddress).toBe(false);
  238. // set the first customer's first address to be default
  239. const result3 = await adminClient.query<UpdateAddress.Mutation, UpdateAddress.Variables>(
  240. UPDATE_ADDRESS,
  241. {
  242. input: {
  243. id: firstCustomerAddressIds[0],
  244. defaultShippingAddress: true,
  245. defaultBillingAddress: true,
  246. },
  247. },
  248. );
  249. expect(result3.updateCustomerAddress.defaultShippingAddress).toBe(true);
  250. expect(result3.updateCustomerAddress.defaultBillingAddress).toBe(true);
  251. // assert the first customer's second address is not default
  252. const result4 = await adminClient.query<GetCustomer.Query, GetCustomer.Variables>(GET_CUSTOMER, {
  253. id: firstCustomer.id,
  254. });
  255. const otherAddress2 = result4.customer!.addresses!.filter(
  256. a => a.id !== firstCustomerAddressIds[0],
  257. )[0]!;
  258. expect(otherAddress2.defaultShippingAddress).toBe(false);
  259. expect(otherAddress2.defaultBillingAddress).toBe(false);
  260. // get the second customer's address id
  261. const result5 = await adminClient.query<GetCustomer.Query, GetCustomer.Variables>(GET_CUSTOMER, {
  262. id: secondCustomer.id,
  263. });
  264. const secondCustomerAddressId = result5.customer!.addresses![0].id;
  265. // set the second customer's address to be default
  266. const result6 = await adminClient.query<UpdateAddress.Mutation, UpdateAddress.Variables>(
  267. UPDATE_ADDRESS,
  268. {
  269. input: {
  270. id: secondCustomerAddressId,
  271. defaultShippingAddress: true,
  272. defaultBillingAddress: true,
  273. },
  274. },
  275. );
  276. expect(result6.updateCustomerAddress.defaultShippingAddress).toBe(true);
  277. expect(result6.updateCustomerAddress.defaultBillingAddress).toBe(true);
  278. // assets the first customer's address defaults are unchanged
  279. const result7 = await adminClient.query<GetCustomer.Query, GetCustomer.Variables>(GET_CUSTOMER, {
  280. id: firstCustomer.id,
  281. });
  282. expect(result7.customer!.addresses![0].defaultShippingAddress).toBe(true);
  283. expect(result7.customer!.addresses![0].defaultBillingAddress).toBe(true);
  284. expect(result7.customer!.addresses![1].defaultShippingAddress).toBe(false);
  285. expect(result7.customer!.addresses![1].defaultBillingAddress).toBe(false);
  286. });
  287. it('createCustomerAddress with true defaults unsets existing defaults', async () => {
  288. const { createCustomerAddress } = await adminClient.query<
  289. CreateAddress.Mutation,
  290. CreateAddress.Variables
  291. >(CREATE_ADDRESS, {
  292. id: firstCustomer.id,
  293. input: {
  294. streetLine1: 'new default streetline',
  295. countryCode: 'GB',
  296. defaultShippingAddress: true,
  297. defaultBillingAddress: true,
  298. },
  299. });
  300. expect(omit(createCustomerAddress, ['id'])).toEqual({
  301. fullName: '',
  302. company: '',
  303. streetLine1: 'new default streetline',
  304. streetLine2: '',
  305. city: '',
  306. province: '',
  307. postalCode: '',
  308. country: {
  309. code: 'GB',
  310. name: 'United Kingdom',
  311. },
  312. phoneNumber: '',
  313. defaultShippingAddress: true,
  314. defaultBillingAddress: true,
  315. });
  316. const { customer } = await adminClient.query<GetCustomer.Query, GetCustomer.Variables>(
  317. GET_CUSTOMER,
  318. {
  319. id: firstCustomer.id,
  320. },
  321. );
  322. for (const address of customer!.addresses!) {
  323. const shouldBeDefault = address.id === createCustomerAddress.id;
  324. expect(address.defaultShippingAddress).toEqual(shouldBeDefault);
  325. expect(address.defaultBillingAddress).toEqual(shouldBeDefault);
  326. }
  327. firstCustomerThirdAddressId = createCustomerAddress.id;
  328. });
  329. it('deleteCustomerAddress on default address resets defaults', async () => {
  330. const { deleteCustomerAddress } = await adminClient.query<
  331. DeleteCustomerAddress.Mutation,
  332. DeleteCustomerAddress.Variables
  333. >(
  334. gql`
  335. mutation DeleteCustomerAddress($id: ID!) {
  336. deleteCustomerAddress(id: $id) {
  337. success
  338. }
  339. }
  340. `,
  341. { id: firstCustomerThirdAddressId },
  342. );
  343. expect(deleteCustomerAddress.success).toBe(true);
  344. const { customer } = await adminClient.query<GetCustomer.Query, GetCustomer.Variables>(
  345. GET_CUSTOMER,
  346. {
  347. id: firstCustomer.id,
  348. },
  349. );
  350. expect(customer!.addresses!.length).toBe(2);
  351. const defaultAddress = customer!.addresses!.filter(
  352. a => a.defaultBillingAddress && a.defaultShippingAddress,
  353. );
  354. const otherAddress = customer!.addresses!.filter(
  355. a => !a.defaultBillingAddress && !a.defaultShippingAddress,
  356. );
  357. expect(defaultAddress.length).toBe(1);
  358. expect(otherAddress.length).toBe(1);
  359. });
  360. });
  361. describe('orders', () => {
  362. const orderResultGuard: ErrorResultGuard<UpdatedOrderFragment> = createErrorResultGuard(
  363. input => !!input.lines,
  364. );
  365. it(`lists that user\'s orders`, async () => {
  366. // log in as first customer
  367. await shopClient.asUserWithCredentials(firstCustomer.emailAddress, 'test');
  368. // add an item to the order to create an order
  369. const { addItemToOrder } = await shopClient.query<
  370. AddItemToOrder.Mutation,
  371. AddItemToOrder.Variables
  372. >(ADD_ITEM_TO_ORDER, {
  373. productVariantId: 'T_1',
  374. quantity: 1,
  375. });
  376. orderResultGuard.assertSuccess(addItemToOrder);
  377. const { customer } = await adminClient.query<
  378. GetCustomerOrders.Query,
  379. GetCustomerOrders.Variables
  380. >(GET_CUSTOMER_ORDERS, { id: firstCustomer.id });
  381. expect(customer!.orders.totalItems).toBe(1);
  382. expect(customer!.orders.items[0].id).toBe(addItemToOrder!.id);
  383. });
  384. });
  385. describe('creation', () => {
  386. it('triggers verification event if no password supplied', async () => {
  387. sendEmailFn = jest.fn();
  388. const { createCustomer } = await adminClient.query<
  389. CreateCustomer.Mutation,
  390. CreateCustomer.Variables
  391. >(CREATE_CUSTOMER, {
  392. input: {
  393. emailAddress: 'test1@test.com',
  394. firstName: 'New',
  395. lastName: 'Customer',
  396. },
  397. });
  398. customerErrorGuard.assertSuccess(createCustomer);
  399. expect(createCustomer.user!.verified).toBe(false);
  400. expect(sendEmailFn).toHaveBeenCalledTimes(1);
  401. expect(sendEmailFn.mock.calls[0][0] instanceof AccountRegistrationEvent).toBe(true);
  402. expect(sendEmailFn.mock.calls[0][0].user.identifier).toBe('test1@test.com');
  403. });
  404. it('creates a verified Customer', async () => {
  405. sendEmailFn = jest.fn();
  406. const { createCustomer } = await adminClient.query<
  407. CreateCustomer.Mutation,
  408. CreateCustomer.Variables
  409. >(CREATE_CUSTOMER, {
  410. input: {
  411. emailAddress: 'test2@test.com',
  412. firstName: 'New',
  413. lastName: 'Customer',
  414. },
  415. password: 'test',
  416. });
  417. customerErrorGuard.assertSuccess(createCustomer);
  418. expect(createCustomer.user!.verified).toBe(true);
  419. expect(sendEmailFn).toHaveBeenCalledTimes(0);
  420. });
  421. it('return error result when using an existing, non-deleted emailAddress', async () => {
  422. const { createCustomer } = await adminClient.query<
  423. CreateCustomer.Mutation,
  424. CreateCustomer.Variables
  425. >(CREATE_CUSTOMER, {
  426. input: {
  427. emailAddress: 'test2@test.com',
  428. firstName: 'New',
  429. lastName: 'Customer',
  430. },
  431. password: 'test',
  432. });
  433. customerErrorGuard.assertErrorResult(createCustomer);
  434. expect(createCustomer.message).toBe('The email address is not available.');
  435. expect(createCustomer.errorCode).toBe(ErrorCode.EMAIL_ADDRESS_CONFLICT_ERROR);
  436. });
  437. });
  438. describe('update', () => {
  439. it('returns error result when emailAddress not available', async () => {
  440. const { updateCustomer } = await adminClient.query<
  441. UpdateCustomer.Mutation,
  442. UpdateCustomer.Variables
  443. >(UPDATE_CUSTOMER, {
  444. input: {
  445. id: thirdCustomer.id,
  446. emailAddress: firstCustomer.emailAddress,
  447. },
  448. });
  449. customerErrorGuard.assertErrorResult(updateCustomer);
  450. expect(updateCustomer.message).toBe('The email address is not available.');
  451. expect(updateCustomer.errorCode).toBe(ErrorCode.EMAIL_ADDRESS_CONFLICT_ERROR);
  452. });
  453. it('succeeds when emailAddress is available', async () => {
  454. const { updateCustomer } = await adminClient.query<
  455. UpdateCustomer.Mutation,
  456. UpdateCustomer.Variables
  457. >(UPDATE_CUSTOMER, {
  458. input: {
  459. id: thirdCustomer.id,
  460. emailAddress: 'unique-email@test.com',
  461. },
  462. });
  463. customerErrorGuard.assertSuccess(updateCustomer);
  464. expect(updateCustomer.emailAddress).toBe('unique-email@test.com');
  465. });
  466. // https://github.com/vendure-ecommerce/vendure/issues/1071
  467. it('updates the associated User email address', async () => {
  468. await shopClient.asUserWithCredentials('unique-email@test.com', 'test');
  469. const { me } = await shopClient.query<Me.Query>(ME);
  470. expect(me?.identifier).toBe('unique-email@test.com');
  471. });
  472. });
  473. describe('deletion', () => {
  474. it('deletes a customer', async () => {
  475. const result = await adminClient.query<DeleteCustomer.Mutation, DeleteCustomer.Variables>(
  476. DELETE_CUSTOMER,
  477. { id: thirdCustomer.id },
  478. );
  479. expect(result.deleteCustomer).toEqual({ result: DeletionResult.DELETED });
  480. });
  481. it('cannot get a deleted customer', async () => {
  482. const result = await adminClient.query<GetCustomer.Query, GetCustomer.Variables>(GET_CUSTOMER, {
  483. id: thirdCustomer.id,
  484. });
  485. expect(result.customer).toBe(null);
  486. });
  487. it('deleted customer omitted from list', async () => {
  488. const result = await adminClient.query<GetCustomerList.Query, GetCustomerList.Variables>(
  489. GET_CUSTOMER_LIST,
  490. );
  491. expect(result.customers.items.map(c => c.id).includes(thirdCustomer.id)).toBe(false);
  492. });
  493. it(
  494. 'updateCustomer throws for deleted customer',
  495. assertThrowsWithMessage(
  496. () =>
  497. adminClient.query<UpdateCustomer.Mutation, UpdateCustomer.Variables>(UPDATE_CUSTOMER, {
  498. input: {
  499. id: thirdCustomer.id,
  500. firstName: 'updated',
  501. },
  502. }),
  503. `No Customer with the id '3' could be found`,
  504. ),
  505. );
  506. it(
  507. 'createCustomerAddress throws for deleted customer',
  508. assertThrowsWithMessage(
  509. () =>
  510. adminClient.query<CreateAddress.Mutation, CreateAddress.Variables>(CREATE_ADDRESS, {
  511. id: thirdCustomer.id,
  512. input: {
  513. streetLine1: 'test',
  514. countryCode: 'GB',
  515. },
  516. }),
  517. `No Customer with the id '3' could be found`,
  518. ),
  519. );
  520. it('new Customer can be created with same emailAddress as a deleted Customer', async () => {
  521. const { createCustomer } = await adminClient.query<
  522. CreateCustomer.Mutation,
  523. CreateCustomer.Variables
  524. >(CREATE_CUSTOMER, {
  525. input: {
  526. emailAddress: thirdCustomer.emailAddress,
  527. firstName: 'Reusing Email',
  528. lastName: 'Customer',
  529. },
  530. });
  531. customerErrorGuard.assertSuccess(createCustomer);
  532. expect(createCustomer.emailAddress).toBe(thirdCustomer.emailAddress);
  533. expect(createCustomer.firstName).toBe('Reusing Email');
  534. expect(createCustomer.user?.identifier).toBe(thirdCustomer.emailAddress);
  535. });
  536. // https://github.com/vendure-ecommerce/vendure/issues/1960
  537. it('delete a guest Customer', async () => {
  538. const orderErrorGuard: ErrorResultGuard<ActiveOrderCustomerFragment> = createErrorResultGuard(
  539. input => !!input.lines,
  540. );
  541. await shopClient.asAnonymousUser();
  542. await shopClient.query<AddItemToOrderMutation, AddItemToOrderMutationVariables>(
  543. ADD_ITEM_TO_ORDER,
  544. {
  545. productVariantId: 'T_1',
  546. quantity: 1,
  547. },
  548. );
  549. const { setCustomerForOrder } = await shopClient.query<
  550. SetCustomerForOrderMutation,
  551. SetCustomerForOrderMutationVariables
  552. >(SET_CUSTOMER, {
  553. input: {
  554. firstName: 'Guest',
  555. lastName: 'Customer',
  556. emailAddress: 'guest@test.com',
  557. },
  558. });
  559. orderErrorGuard.assertSuccess(setCustomerForOrder);
  560. const result = await adminClient.query<DeleteCustomer.Mutation, DeleteCustomer.Variables>(
  561. DELETE_CUSTOMER,
  562. { id: setCustomerForOrder.customer!.id },
  563. );
  564. expect(result.deleteCustomer).toEqual({ result: DeletionResult.DELETED });
  565. });
  566. });
  567. describe('customer notes', () => {
  568. let noteId: string;
  569. it('addNoteToCustomer', async () => {
  570. const { addNoteToCustomer } = await adminClient.query<
  571. AddNoteToCustomer.Mutation,
  572. AddNoteToCustomer.Variables
  573. >(ADD_NOTE_TO_CUSTOMER, {
  574. input: {
  575. id: firstCustomer.id,
  576. isPublic: false,
  577. note: 'Test note',
  578. },
  579. });
  580. const { customer } = await adminClient.query<
  581. GetCustomerHistory.Query,
  582. GetCustomerHistory.Variables
  583. >(GET_CUSTOMER_HISTORY, {
  584. id: firstCustomer.id,
  585. options: {
  586. filter: {
  587. type: {
  588. eq: HistoryEntryType.CUSTOMER_NOTE,
  589. },
  590. },
  591. },
  592. });
  593. expect(customer?.history.items.map(pick(['type', 'data']))).toEqual([
  594. {
  595. type: HistoryEntryType.CUSTOMER_NOTE,
  596. data: {
  597. note: 'Test note',
  598. },
  599. },
  600. ]);
  601. noteId = customer?.history.items[0].id!;
  602. });
  603. it('update note', async () => {
  604. const { updateCustomerNote } = await adminClient.query<
  605. UpdateCustomerNote.Mutation,
  606. UpdateCustomerNote.Variables
  607. >(UPDATE_CUSTOMER_NOTE, {
  608. input: {
  609. noteId,
  610. note: 'An updated note',
  611. },
  612. });
  613. expect(updateCustomerNote.data).toEqual({
  614. note: 'An updated note',
  615. });
  616. });
  617. it('delete note', async () => {
  618. const { customer: before } = await adminClient.query<
  619. GetCustomerHistory.Query,
  620. GetCustomerHistory.Variables
  621. >(GET_CUSTOMER_HISTORY, { id: firstCustomer.id });
  622. const historyCount = before?.history.totalItems!;
  623. const { deleteCustomerNote } = await adminClient.query<
  624. DeleteCustomerNote.Mutation,
  625. DeleteCustomerNote.Variables
  626. >(DELETE_CUSTOMER_NOTE, {
  627. id: noteId,
  628. });
  629. expect(deleteCustomerNote.result).toBe(DeletionResult.DELETED);
  630. const { customer: after } = await adminClient.query<
  631. GetCustomerHistory.Query,
  632. GetCustomerHistory.Variables
  633. >(GET_CUSTOMER_HISTORY, { id: firstCustomer.id });
  634. expect(after?.history.totalItems).toBe(historyCount - 1);
  635. });
  636. });
  637. });
  638. const GET_CUSTOMER_WITH_USER = gql`
  639. query GetCustomerWithUser($id: ID!) {
  640. customer(id: $id) {
  641. id
  642. user {
  643. id
  644. identifier
  645. verified
  646. }
  647. }
  648. }
  649. `;
  650. const GET_CUSTOMER_ORDERS = gql`
  651. query GetCustomerOrders($id: ID!) {
  652. customer(id: $id) {
  653. orders {
  654. items {
  655. id
  656. }
  657. totalItems
  658. }
  659. }
  660. }
  661. `;
  662. const ADD_NOTE_TO_CUSTOMER = gql`
  663. mutation AddNoteToCustomer($input: AddNoteToCustomerInput!) {
  664. addNoteToCustomer(input: $input) {
  665. ...Customer
  666. }
  667. }
  668. ${CUSTOMER_FRAGMENT}
  669. `;