customer.e2e-spec.ts 26 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684
  1. import { DeletionResult, ErrorCode, HistoryEntryType } from '@vendure/common/lib/generated-types';
  2. import { omit } from '@vendure/common/lib/omit';
  3. import { pick } from '@vendure/common/lib/pick';
  4. import { AccountRegistrationEvent, EventBus } from '@vendure/core';
  5. import { createErrorResultGuard, createTestEnvironment, ErrorResultGuard } from '@vendure/testing';
  6. import path from 'path';
  7. import { afterAll, beforeAll, describe, expect, it, vi } from 'vitest';
  8. import { initialData } from '../../../e2e-common/e2e-initial-data';
  9. import { TEST_SETUP_TIMEOUT_MS, testConfig } from '../../../e2e-common/test-config';
  10. import { customerFragment } from './graphql/fragments-admin';
  11. import { FragmentOf, ResultOf } from './graphql/graphql-admin';
  12. import { FragmentOf as FragmentOfShop } from './graphql/graphql-shop';
  13. import {
  14. addNoteToCustomerDocument,
  15. createAddressDocument,
  16. createAdministratorDocument,
  17. createCustomerDocument,
  18. deleteCustomerAddressDocument,
  19. deleteCustomerDocument,
  20. deleteCustomerNoteDocument,
  21. getCustomerDocument,
  22. getCustomerHistoryDocument,
  23. getCustomerListDocument,
  24. getCustomerOrdersDocument,
  25. getCustomerWithUserDocument,
  26. MeDocument,
  27. updateAddressDocument,
  28. updateCustomerDocument,
  29. updateCustomerNoteDocument,
  30. } from './graphql/shared-definitions';
  31. import {
  32. activeOrderCustomerDocument,
  33. addItemToOrderDocument,
  34. setCustomerDocument,
  35. updatedOrderFragment,
  36. } from './graphql/shop-definitions';
  37. import { assertThrowsWithMessage } from './utils/assert-throws-with-message';
  38. /* eslint-disable @typescript-eslint/no-non-null-assertion */
  39. type CustomerListItem = ResultOf<typeof getCustomerListDocument>['customers']['items'][number];
  40. type CustomerFragment = FragmentOf<typeof customerFragment>;
  41. type UpdatedOrderFragment = FragmentOfShop<typeof updatedOrderFragment>;
  42. type ActiveOrderCustomerFragment = FragmentOfShop<typeof activeOrderCustomerDocument>;
  43. type CustomerOrdersResult = NonNullable<ResultOf<typeof getCustomerOrdersDocument>['customer']>;
  44. type CustomerHistoryResult = NonNullable<ResultOf<typeof getCustomerHistoryDocument>['customer']>;
  45. const customerErrorGuard: ErrorResultGuard<CustomerFragment> = createErrorResultGuard(
  46. input => !!input.emailAddress,
  47. );
  48. const orderResultGuard: ErrorResultGuard<UpdatedOrderFragment> = createErrorResultGuard(
  49. input => 'lines' in input && !!input.lines,
  50. );
  51. const setCustomerForOrderGuard: ErrorResultGuard<ActiveOrderCustomerFragment> = createErrorResultGuard(
  52. input => 'lines' in input && !!input.lines,
  53. );
  54. const customerOrdersGuard: ErrorResultGuard<CustomerOrdersResult> = createErrorResultGuard(
  55. input => !!input.orders,
  56. );
  57. const customerHistoryGuard: ErrorResultGuard<CustomerHistoryResult> = createErrorResultGuard(
  58. input => !!input.history,
  59. );
  60. describe('Customer resolver', () => {
  61. const { server, adminClient, shopClient } = createTestEnvironment(testConfig());
  62. let firstCustomer: CustomerListItem;
  63. let secondCustomer: CustomerListItem;
  64. let thirdCustomer: CustomerListItem;
  65. beforeAll(async () => {
  66. await server.init({
  67. initialData,
  68. productsCsvPath: path.join(__dirname, 'fixtures/e2e-products-minimal.csv'),
  69. customerCount: 5,
  70. });
  71. await adminClient.asSuperAdmin();
  72. }, TEST_SETUP_TIMEOUT_MS);
  73. afterAll(async () => {
  74. await server.destroy();
  75. });
  76. it('customers list', async () => {
  77. const result = await adminClient.query(getCustomerListDocument);
  78. expect(result.customers.items.length).toBe(5);
  79. expect(result.customers.totalItems).toBe(5);
  80. firstCustomer = result.customers.items[0];
  81. secondCustomer = result.customers.items[1];
  82. thirdCustomer = result.customers.items[2];
  83. });
  84. it('customers list filter by postalCode', async () => {
  85. const result = await adminClient.query(getCustomerListDocument, {
  86. options: {
  87. filter: {
  88. postalCode: {
  89. eq: 'NU9 0PW',
  90. },
  91. },
  92. },
  93. });
  94. expect(result.customers.items.length).toBe(1);
  95. expect(result.customers.items[0].emailAddress).toBe('eliezer56@yahoo.com');
  96. });
  97. it('customer resolver resolves User', async () => {
  98. const emailAddress = 'same-email@test.com';
  99. // Create an administrator with the same email first in order to ensure the right user is resolved.
  100. // This test also validates that a customer can be created with the same identifier
  101. // of an existing administrator
  102. const { createAdministrator } = await adminClient.query(createAdministratorDocument, {
  103. input: {
  104. emailAddress,
  105. firstName: 'First',
  106. lastName: 'Last',
  107. password: '123',
  108. roleIds: ['1'],
  109. },
  110. });
  111. expect(createAdministrator.emailAddress).toEqual(emailAddress);
  112. const { createCustomer } = await adminClient.query(createCustomerDocument, {
  113. input: {
  114. emailAddress,
  115. firstName: 'New',
  116. lastName: 'Customer',
  117. },
  118. password: 'test',
  119. });
  120. customerErrorGuard.assertSuccess(createCustomer);
  121. expect(createCustomer.emailAddress).toEqual(emailAddress);
  122. const { customer } = await adminClient.query(getCustomerWithUserDocument, {
  123. id: createCustomer.id,
  124. });
  125. expect(customer!.user).toEqual({
  126. id: createCustomer.user?.id,
  127. identifier: emailAddress,
  128. verified: true,
  129. });
  130. });
  131. describe('addresses', () => {
  132. let firstCustomerAddressIds: string[] = [];
  133. let firstCustomerThirdAddressId: string;
  134. it(
  135. 'createCustomerAddress throws on invalid countryCode',
  136. assertThrowsWithMessage(
  137. () =>
  138. adminClient.query(createAddressDocument, {
  139. id: firstCustomer.id,
  140. input: {
  141. streetLine1: 'streetLine1',
  142. countryCode: 'INVALID',
  143. },
  144. }),
  145. 'The countryCode "INVALID" was not recognized',
  146. ),
  147. );
  148. it('createCustomerAddress creates a new address', async () => {
  149. const result = await adminClient.query(createAddressDocument, {
  150. id: firstCustomer.id,
  151. input: {
  152. fullName: 'fullName',
  153. company: 'company',
  154. streetLine1: 'streetLine1',
  155. streetLine2: 'streetLine2',
  156. city: 'city',
  157. province: 'province',
  158. postalCode: 'postalCode',
  159. countryCode: 'GB',
  160. phoneNumber: 'phoneNumber',
  161. defaultShippingAddress: false,
  162. defaultBillingAddress: false,
  163. },
  164. });
  165. expect(omit(result.createCustomerAddress, ['id'])).toEqual({
  166. fullName: 'fullName',
  167. company: 'company',
  168. streetLine1: 'streetLine1',
  169. streetLine2: 'streetLine2',
  170. city: 'city',
  171. province: 'province',
  172. postalCode: 'postalCode',
  173. country: {
  174. code: 'GB',
  175. name: 'United Kingdom',
  176. },
  177. phoneNumber: 'phoneNumber',
  178. defaultShippingAddress: false,
  179. defaultBillingAddress: false,
  180. });
  181. });
  182. it('customer query returns addresses', async () => {
  183. const result = await adminClient.query(getCustomerDocument, {
  184. id: firstCustomer.id,
  185. });
  186. expect(result.customer!.addresses!.length).toBe(2);
  187. firstCustomerAddressIds = result.customer!.addresses!.map(a => a.id).sort();
  188. });
  189. it('updateCustomerAddress updates the country', async () => {
  190. const result = await adminClient.query(updateAddressDocument, {
  191. input: {
  192. id: firstCustomerAddressIds[0],
  193. countryCode: 'AT',
  194. },
  195. });
  196. expect(result.updateCustomerAddress.country).toEqual({
  197. code: 'AT',
  198. name: 'Austria',
  199. });
  200. });
  201. it('updateCustomerAddress allows only a single default address', async () => {
  202. // set the first customer's second address to be default
  203. const result1 = await adminClient.query(updateAddressDocument, {
  204. input: {
  205. id: firstCustomerAddressIds[1],
  206. defaultShippingAddress: true,
  207. defaultBillingAddress: true,
  208. },
  209. });
  210. expect(result1.updateCustomerAddress.defaultShippingAddress).toBe(true);
  211. expect(result1.updateCustomerAddress.defaultBillingAddress).toBe(true);
  212. // assert the first customer's other address is not default
  213. const result2 = await adminClient.query(getCustomerDocument, {
  214. id: firstCustomer.id,
  215. });
  216. const otherAddress = result2.customer!.addresses!.filter(
  217. a => a.id !== firstCustomerAddressIds[1],
  218. )[0]!;
  219. expect(otherAddress.defaultShippingAddress).toBe(false);
  220. expect(otherAddress.defaultBillingAddress).toBe(false);
  221. // set the first customer's first address to be default
  222. const result3 = await adminClient.query(updateAddressDocument, {
  223. input: {
  224. id: firstCustomerAddressIds[0],
  225. defaultShippingAddress: true,
  226. defaultBillingAddress: true,
  227. },
  228. });
  229. expect(result3.updateCustomerAddress.defaultShippingAddress).toBe(true);
  230. expect(result3.updateCustomerAddress.defaultBillingAddress).toBe(true);
  231. // assert the first customer's second address is not default
  232. const result4 = await adminClient.query(getCustomerDocument, {
  233. id: firstCustomer.id,
  234. });
  235. const otherAddress2 = result4.customer!.addresses!.filter(
  236. a => a.id !== firstCustomerAddressIds[0],
  237. )[0]!;
  238. expect(otherAddress2.defaultShippingAddress).toBe(false);
  239. expect(otherAddress2.defaultBillingAddress).toBe(false);
  240. // get the second customer's address id
  241. const result5 = await adminClient.query(getCustomerDocument, {
  242. id: secondCustomer.id,
  243. });
  244. const secondCustomerAddressId = result5.customer!.addresses![0].id;
  245. // set the second customer's address to be default
  246. const result6 = await adminClient.query(updateAddressDocument, {
  247. input: {
  248. id: secondCustomerAddressId,
  249. defaultShippingAddress: true,
  250. defaultBillingAddress: true,
  251. },
  252. });
  253. expect(result6.updateCustomerAddress.defaultShippingAddress).toBe(true);
  254. expect(result6.updateCustomerAddress.defaultBillingAddress).toBe(true);
  255. // assets the first customer's address defaults are unchanged
  256. const result7 = await adminClient.query(getCustomerDocument, {
  257. id: firstCustomer.id,
  258. });
  259. const firstCustomerFirstAddress = result7.customer!.addresses!.find(
  260. a => a.id === firstCustomerAddressIds[0],
  261. )!;
  262. const firstCustomerSecondAddress = result7.customer!.addresses!.find(
  263. a => a.id === firstCustomerAddressIds[1],
  264. )!;
  265. expect(firstCustomerFirstAddress.defaultShippingAddress).toBe(true);
  266. expect(firstCustomerFirstAddress.defaultBillingAddress).toBe(true);
  267. expect(firstCustomerSecondAddress.defaultShippingAddress).toBe(false);
  268. expect(firstCustomerSecondAddress.defaultBillingAddress).toBe(false);
  269. });
  270. it('createCustomerAddress with true defaults unsets existing defaults', async () => {
  271. const { createCustomerAddress } = await adminClient.query(createAddressDocument, {
  272. id: firstCustomer.id,
  273. input: {
  274. streetLine1: 'new default streetline',
  275. countryCode: 'GB',
  276. defaultShippingAddress: true,
  277. defaultBillingAddress: true,
  278. },
  279. });
  280. expect(omit(createCustomerAddress, ['id'])).toEqual({
  281. fullName: '',
  282. company: '',
  283. streetLine1: 'new default streetline',
  284. streetLine2: '',
  285. city: '',
  286. province: '',
  287. postalCode: '',
  288. country: {
  289. code: 'GB',
  290. name: 'United Kingdom',
  291. },
  292. phoneNumber: '',
  293. defaultShippingAddress: true,
  294. defaultBillingAddress: true,
  295. });
  296. const { customer } = await adminClient.query(getCustomerDocument, {
  297. id: firstCustomer.id,
  298. });
  299. for (const address of customer!.addresses!) {
  300. const shouldBeDefault = address.id === createCustomerAddress.id;
  301. expect(address.defaultShippingAddress).toEqual(shouldBeDefault);
  302. expect(address.defaultBillingAddress).toEqual(shouldBeDefault);
  303. }
  304. firstCustomerThirdAddressId = createCustomerAddress.id;
  305. });
  306. it('deleteCustomerAddress on default address resets defaults', async () => {
  307. const { deleteCustomerAddress } = await adminClient.query(deleteCustomerAddressDocument, {
  308. id: firstCustomerThirdAddressId,
  309. });
  310. expect(deleteCustomerAddress.success).toBe(true);
  311. const { customer } = await adminClient.query(getCustomerDocument, {
  312. id: firstCustomer.id,
  313. });
  314. expect(customer!.addresses!.length).toBe(2);
  315. const defaultAddress = customer!.addresses!.filter(
  316. a => a.defaultBillingAddress && a.defaultShippingAddress,
  317. );
  318. const otherAddress = customer!.addresses!.filter(
  319. a => !a.defaultBillingAddress && !a.defaultShippingAddress,
  320. );
  321. expect(defaultAddress.length).toBe(1);
  322. expect(otherAddress.length).toBe(1);
  323. });
  324. });
  325. describe('orders', () => {
  326. it("lists that user's orders", async () => {
  327. // log in as first customer
  328. await shopClient.asUserWithCredentials(firstCustomer.emailAddress, 'test');
  329. // add an item to the order to create an order
  330. const { addItemToOrder } = await shopClient.query(addItemToOrderDocument, {
  331. productVariantId: 'T_1',
  332. quantity: 1,
  333. });
  334. orderResultGuard.assertSuccess(addItemToOrder);
  335. const { customer } = await adminClient.query(getCustomerOrdersDocument, {
  336. id: firstCustomer.id,
  337. });
  338. customerOrdersGuard.assertSuccess(customer);
  339. expect(customer.orders.totalItems).toBe(1);
  340. expect(customer.orders.items[0].id).toBe(addItemToOrder.id);
  341. });
  342. });
  343. describe('creation', () => {
  344. it('triggers verification event if no password supplied', async () => {
  345. const sendEmailFn = vi.fn();
  346. let resolveFn: () => void;
  347. const subscription = server.app
  348. .get(EventBus)
  349. .ofType(AccountRegistrationEvent)
  350. .subscribe(event => {
  351. sendEmailFn(event);
  352. resolveFn?.();
  353. });
  354. const eventReceived = new Promise<void>(resolve => {
  355. resolveFn = resolve;
  356. });
  357. const { createCustomer } = await adminClient.query(createCustomerDocument, {
  358. input: {
  359. emailAddress: 'test1@test.com',
  360. firstName: 'New',
  361. lastName: 'Customer',
  362. },
  363. });
  364. customerErrorGuard.assertSuccess(createCustomer);
  365. expect(createCustomer.user!.verified).toBe(false);
  366. // Wait for the event to be received before making assertions
  367. await eventReceived;
  368. expect(sendEmailFn).toHaveBeenCalledTimes(1);
  369. expect(sendEmailFn.mock.calls[0][0] instanceof AccountRegistrationEvent).toBe(true);
  370. expect(sendEmailFn.mock.calls[0][0].user.identifier).toBe('test1@test.com');
  371. subscription.unsubscribe();
  372. });
  373. it('creates a verified Customer', async () => {
  374. const sendEmailFn = vi.fn();
  375. let resolveFn: () => void;
  376. const subscription = server.app
  377. .get(EventBus)
  378. .ofType(AccountRegistrationEvent)
  379. .subscribe(event => {
  380. sendEmailFn(event);
  381. resolveFn?.();
  382. });
  383. const eventReceived = new Promise<void>(resolve => {
  384. resolveFn = resolve;
  385. });
  386. const { createCustomer } = await adminClient.query(createCustomerDocument, {
  387. input: {
  388. emailAddress: 'test2@test.com',
  389. firstName: 'New',
  390. lastName: 'Customer',
  391. },
  392. password: 'test',
  393. });
  394. customerErrorGuard.assertSuccess(createCustomer);
  395. // Wait for the event to be received before making assertions
  396. await eventReceived;
  397. expect(createCustomer.user!.verified).toBe(true);
  398. expect(sendEmailFn).toHaveBeenCalledTimes(1);
  399. subscription.unsubscribe();
  400. });
  401. it('return error result when using an existing, non-deleted emailAddress', async () => {
  402. const { createCustomer } = await adminClient.query(createCustomerDocument, {
  403. input: {
  404. emailAddress: 'test2@test.com',
  405. firstName: 'New',
  406. lastName: 'Customer',
  407. },
  408. password: 'test',
  409. });
  410. customerErrorGuard.assertErrorResult(createCustomer);
  411. expect(createCustomer.message).toBe('The email address is not available.');
  412. expect(createCustomer.errorCode).toBe(ErrorCode.EMAIL_ADDRESS_CONFLICT_ERROR);
  413. });
  414. it('normalizes email address on creation', async () => {
  415. const { createCustomer } = await adminClient.query(createCustomerDocument, {
  416. input: {
  417. emailAddress: ' JoeSmith@test.com ',
  418. firstName: 'Joe',
  419. lastName: 'Smith',
  420. },
  421. password: 'test',
  422. });
  423. customerErrorGuard.assertSuccess(createCustomer);
  424. expect(createCustomer.emailAddress).toBe('joesmith@test.com');
  425. });
  426. });
  427. describe('update', () => {
  428. it('returns error result when emailAddress not available', async () => {
  429. const { updateCustomer } = await adminClient.query(updateCustomerDocument, {
  430. input: {
  431. id: thirdCustomer.id,
  432. emailAddress: firstCustomer.emailAddress,
  433. },
  434. });
  435. customerErrorGuard.assertErrorResult(updateCustomer);
  436. expect(updateCustomer.message).toBe('The email address is not available.');
  437. expect(updateCustomer.errorCode).toBe(ErrorCode.EMAIL_ADDRESS_CONFLICT_ERROR);
  438. });
  439. it('succeeds when emailAddress is available', async () => {
  440. const { updateCustomer } = await adminClient.query(updateCustomerDocument, {
  441. input: {
  442. id: thirdCustomer.id,
  443. emailAddress: 'unique-email@test.com',
  444. },
  445. });
  446. customerErrorGuard.assertSuccess(updateCustomer);
  447. expect(updateCustomer.emailAddress).toBe('unique-email@test.com');
  448. });
  449. // https://github.com/vendure-ecommerce/vendure/issues/1071
  450. it('updates the associated User email address', async () => {
  451. await shopClient.asUserWithCredentials('unique-email@test.com', 'test');
  452. const { me } = await shopClient.query(MeDocument);
  453. expect(me?.identifier).toBe('unique-email@test.com');
  454. });
  455. // https://github.com/vendure-ecommerce/vendure/issues/2449
  456. it('normalizes email address on update', async () => {
  457. const { updateCustomer } = await adminClient.query(updateCustomerDocument, {
  458. input: {
  459. id: thirdCustomer.id,
  460. emailAddress: ' Another-Address@test.com ',
  461. },
  462. });
  463. customerErrorGuard.assertSuccess(updateCustomer);
  464. expect(updateCustomer.emailAddress).toBe('another-address@test.com');
  465. await shopClient.asUserWithCredentials('another-address@test.com', 'test');
  466. const { me } = await shopClient.query(MeDocument);
  467. expect(me?.identifier).toBe('another-address@test.com');
  468. });
  469. });
  470. describe('deletion', () => {
  471. it('deletes a customer', async () => {
  472. const result = await adminClient.query(deleteCustomerDocument, { id: thirdCustomer.id });
  473. expect(result.deleteCustomer).toEqual({ result: DeletionResult.DELETED });
  474. });
  475. it('cannot get a deleted customer', async () => {
  476. const result = await adminClient.query(getCustomerDocument, {
  477. id: thirdCustomer.id,
  478. });
  479. expect(result.customer).toBe(null);
  480. });
  481. it('deleted customer omitted from list', async () => {
  482. const result = await adminClient.query(getCustomerListDocument);
  483. expect(result.customers.items.map(c => c.id).includes(thirdCustomer.id)).toBe(false);
  484. });
  485. it(
  486. 'updateCustomer throws for deleted customer',
  487. assertThrowsWithMessage(
  488. () =>
  489. adminClient.query(updateCustomerDocument, {
  490. input: {
  491. id: thirdCustomer.id,
  492. firstName: 'updated',
  493. },
  494. }),
  495. 'No Customer with the id "3" could be found',
  496. ),
  497. );
  498. it('new Customer can be created with same emailAddress as a deleted Customer', async () => {
  499. const { createCustomer } = await adminClient.query(createCustomerDocument, {
  500. input: {
  501. emailAddress: thirdCustomer.emailAddress,
  502. firstName: 'Reusing Email',
  503. lastName: 'Customer',
  504. },
  505. });
  506. customerErrorGuard.assertSuccess(createCustomer);
  507. expect(createCustomer.emailAddress).toBe(thirdCustomer.emailAddress);
  508. expect(createCustomer.firstName).toBe('Reusing Email');
  509. expect(createCustomer.user?.identifier).toBe(thirdCustomer.emailAddress);
  510. });
  511. // https://github.com/vendure-ecommerce/vendure/issues/1960
  512. it('delete a guest Customer', async () => {
  513. const orderErrorGuard: ErrorResultGuard<ActiveOrderCustomerFragment> = createErrorResultGuard(
  514. input => !!input.lines,
  515. );
  516. await shopClient.asAnonymousUser();
  517. await shopClient.query(addItemToOrderDocument, {
  518. productVariantId: 'T_1',
  519. quantity: 1,
  520. });
  521. const { setCustomerForOrder } = await shopClient.query(setCustomerDocument, {
  522. input: {
  523. firstName: 'Guest',
  524. lastName: 'Customer',
  525. emailAddress: 'guest@test.com',
  526. },
  527. });
  528. orderErrorGuard.assertSuccess(setCustomerForOrder);
  529. const result = await adminClient.query(deleteCustomerDocument, {
  530. id: setCustomerForOrder.customer!.id,
  531. });
  532. expect(result.deleteCustomer).toEqual({ result: DeletionResult.DELETED });
  533. });
  534. });
  535. describe('customer notes', () => {
  536. let noteId: string;
  537. it('addNoteToCustomer', async () => {
  538. const { addNoteToCustomer } = await adminClient.query(addNoteToCustomerDocument, {
  539. input: {
  540. id: firstCustomer.id,
  541. isPublic: false,
  542. note: 'Test note',
  543. },
  544. });
  545. const { customer } = await adminClient.query(getCustomerHistoryDocument, {
  546. id: firstCustomer.id,
  547. options: {
  548. filter: {
  549. type: {
  550. eq: HistoryEntryType.CUSTOMER_NOTE,
  551. },
  552. },
  553. },
  554. });
  555. customerHistoryGuard.assertSuccess(customer);
  556. expect(customer.history.items.map(pick(['type', 'data']))).toEqual([
  557. {
  558. type: HistoryEntryType.CUSTOMER_NOTE,
  559. data: {
  560. note: 'Test note',
  561. },
  562. },
  563. ]);
  564. noteId = customer.history.items[0].id;
  565. });
  566. it('update note', async () => {
  567. const { updateCustomerNote } = await adminClient.query(updateCustomerNoteDocument, {
  568. input: {
  569. noteId,
  570. note: 'An updated note',
  571. },
  572. });
  573. expect(updateCustomerNote.data).toEqual({
  574. note: 'An updated note',
  575. });
  576. });
  577. it('delete note', async () => {
  578. const { customer: before } = await adminClient.query(getCustomerHistoryDocument, {
  579. id: firstCustomer.id,
  580. });
  581. const historyCount = before!.history.totalItems;
  582. const { deleteCustomerNote } = await adminClient.query(deleteCustomerNoteDocument, {
  583. id: noteId,
  584. });
  585. expect(deleteCustomerNote.result).toBe(DeletionResult.DELETED);
  586. const { customer: after } = await adminClient.query(getCustomerHistoryDocument, {
  587. id: firstCustomer.id,
  588. });
  589. expect(after?.history.totalItems).toBe(historyCount - 1);
  590. });
  591. });
  592. });