order-changed-price-handling.e2e-spec.ts 7.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217
  1. /* tslint:disable:no-non-null-assertion */
  2. import {
  3. ChangedPriceHandlingStrategy,
  4. mergeConfig,
  5. OrderItem,
  6. PriceCalculationResult,
  7. RequestContext,
  8. } from '@vendure/core';
  9. import { createTestEnvironment } from '@vendure/testing';
  10. import path from 'path';
  11. import { initialData } from '../../../e2e-common/e2e-initial-data';
  12. import { testConfig, TEST_SETUP_TIMEOUT_MS } from '../../../e2e-common/test-config';
  13. import { UpdateProductVariants } from './graphql/generated-e2e-admin-types';
  14. import { AddItemToOrder, AdjustItemQuantity, GetActiveOrder } from './graphql/generated-e2e-shop-types';
  15. import { UPDATE_PRODUCT_VARIANTS } from './graphql/shared-definitions';
  16. import { ADD_ITEM_TO_ORDER, ADJUST_ITEM_QUANTITY, GET_ACTIVE_ORDER } from './graphql/shop-definitions';
  17. class TestChangedPriceStrategy implements ChangedPriceHandlingStrategy {
  18. static spy = jest.fn();
  19. static useLatestPrice = true;
  20. handlePriceChange(
  21. ctx: RequestContext,
  22. current: PriceCalculationResult,
  23. existingItems: OrderItem[],
  24. ): PriceCalculationResult {
  25. TestChangedPriceStrategy.spy(current);
  26. if (TestChangedPriceStrategy.useLatestPrice) {
  27. return current;
  28. } else {
  29. return {
  30. price: existingItems[0].listPrice,
  31. priceIncludesTax: existingItems[0].listPriceIncludesTax,
  32. };
  33. }
  34. }
  35. }
  36. describe('ChangedPriceHandlingStrategy', () => {
  37. const { server, shopClient, adminClient } = createTestEnvironment(
  38. mergeConfig(testConfig(), {
  39. orderOptions: {
  40. changedPriceHandlingStrategy: new TestChangedPriceStrategy(),
  41. },
  42. }),
  43. );
  44. beforeAll(async () => {
  45. await server.init({
  46. initialData,
  47. productsCsvPath: path.join(__dirname, 'fixtures/e2e-products-full.csv'),
  48. customerCount: 1,
  49. });
  50. await adminClient.asSuperAdmin();
  51. }, TEST_SETUP_TIMEOUT_MS);
  52. afterAll(async () => {
  53. await server.destroy();
  54. });
  55. it('unitPriceChangeSinceAdded starts as 0', async () => {
  56. TestChangedPriceStrategy.spy.mockClear();
  57. await shopClient.query<AddItemToOrder.Mutation, AddItemToOrder.Variables>(ADD_ITEM_TO_ORDER, {
  58. productVariantId: 'T_12',
  59. quantity: 1,
  60. });
  61. const { activeOrder } = await shopClient.query<GetActiveOrder.Query>(GET_ACTIVE_ORDER);
  62. expect(activeOrder?.lines[0].unitPriceChangeSinceAdded).toBe(0);
  63. expect(activeOrder?.lines[0].unitPrice).toBe(5374);
  64. expect(TestChangedPriceStrategy.spy).not.toHaveBeenCalled();
  65. });
  66. describe('use latest price', () => {
  67. let firstOrderLineId: string;
  68. beforeAll(() => {
  69. TestChangedPriceStrategy.useLatestPrice = true;
  70. });
  71. it('calls handlePriceChange on addItemToOrder', async () => {
  72. TestChangedPriceStrategy.spy.mockClear();
  73. await adminClient.query<UpdateProductVariants.Mutation, UpdateProductVariants.Variables>(
  74. UPDATE_PRODUCT_VARIANTS,
  75. {
  76. input: [
  77. {
  78. id: 'T_12',
  79. price: 6000,
  80. },
  81. ],
  82. },
  83. );
  84. await shopClient.query<AddItemToOrder.Mutation, AddItemToOrder.Variables>(ADD_ITEM_TO_ORDER, {
  85. productVariantId: 'T_12',
  86. quantity: 1,
  87. });
  88. const { activeOrder } = await shopClient.query<GetActiveOrder.Query>(GET_ACTIVE_ORDER);
  89. expect(activeOrder?.lines[0].unitPriceChangeSinceAdded).toBe(626);
  90. expect(activeOrder?.lines[0].unitPrice).toBe(6000);
  91. expect(activeOrder?.lines[0].items.every(i => i.unitPrice === 6000)).toBe(true);
  92. expect(TestChangedPriceStrategy.spy).toHaveBeenCalledTimes(1);
  93. firstOrderLineId = activeOrder!.lines[0].id;
  94. });
  95. it('calls handlePriceChange on adjustOrderLine', async () => {
  96. TestChangedPriceStrategy.spy.mockClear();
  97. await adminClient.query<UpdateProductVariants.Mutation, UpdateProductVariants.Variables>(
  98. UPDATE_PRODUCT_VARIANTS,
  99. {
  100. input: [
  101. {
  102. id: 'T_12',
  103. price: 3000,
  104. },
  105. ],
  106. },
  107. );
  108. await shopClient.query<AdjustItemQuantity.Mutation, AdjustItemQuantity.Variables>(
  109. ADJUST_ITEM_QUANTITY,
  110. {
  111. orderLineId: firstOrderLineId,
  112. quantity: 3,
  113. },
  114. );
  115. const { activeOrder } = await shopClient.query<GetActiveOrder.Query>(GET_ACTIVE_ORDER);
  116. expect(activeOrder?.lines[0].unitPriceChangeSinceAdded).toBe(-2374);
  117. expect(activeOrder?.lines[0].unitPrice).toBe(3000);
  118. expect(activeOrder?.lines[0].items.every(i => i.unitPrice === 3000)).toBe(true);
  119. expect(TestChangedPriceStrategy.spy).toHaveBeenCalledTimes(1);
  120. });
  121. });
  122. describe('use original price', () => {
  123. let secondOrderLineId: string;
  124. const ORIGINAL_PRICE = 7896;
  125. beforeAll(() => {
  126. TestChangedPriceStrategy.useLatestPrice = false;
  127. });
  128. it('calls handlePriceChange on addItemToOrder', async () => {
  129. TestChangedPriceStrategy.spy.mockClear();
  130. await shopClient.query<AddItemToOrder.Mutation, AddItemToOrder.Variables>(ADD_ITEM_TO_ORDER, {
  131. productVariantId: 'T_13',
  132. quantity: 1,
  133. });
  134. await adminClient.query<UpdateProductVariants.Mutation, UpdateProductVariants.Variables>(
  135. UPDATE_PRODUCT_VARIANTS,
  136. {
  137. input: [
  138. {
  139. id: 'T_13',
  140. price: 8000,
  141. },
  142. ],
  143. },
  144. );
  145. await shopClient.query<AddItemToOrder.Mutation, AddItemToOrder.Variables>(ADD_ITEM_TO_ORDER, {
  146. productVariantId: 'T_13',
  147. quantity: 1,
  148. });
  149. const { activeOrder } = await shopClient.query<GetActiveOrder.Query>(GET_ACTIVE_ORDER);
  150. expect(activeOrder?.lines[1].unitPriceChangeSinceAdded).toBe(0);
  151. expect(activeOrder?.lines[1].unitPrice).toBe(ORIGINAL_PRICE);
  152. expect(activeOrder?.lines[1].items.every(i => i.unitPrice === ORIGINAL_PRICE)).toBe(true);
  153. expect(TestChangedPriceStrategy.spy).toHaveBeenCalledTimes(1);
  154. secondOrderLineId = activeOrder!.lines[1].id;
  155. });
  156. it('calls handlePriceChange on adjustOrderLine', async () => {
  157. TestChangedPriceStrategy.spy.mockClear();
  158. await adminClient.query<UpdateProductVariants.Mutation, UpdateProductVariants.Variables>(
  159. UPDATE_PRODUCT_VARIANTS,
  160. {
  161. input: [
  162. {
  163. id: 'T_13',
  164. price: 3000,
  165. },
  166. ],
  167. },
  168. );
  169. await shopClient.query<AdjustItemQuantity.Mutation, AdjustItemQuantity.Variables>(
  170. ADJUST_ITEM_QUANTITY,
  171. {
  172. orderLineId: secondOrderLineId,
  173. quantity: 3,
  174. },
  175. );
  176. const { activeOrder } = await shopClient.query<GetActiveOrder.Query>(GET_ACTIVE_ORDER);
  177. expect(activeOrder?.lines[1].unitPriceChangeSinceAdded).toBe(0);
  178. expect(activeOrder?.lines[1].unitPrice).toBe(ORIGINAL_PRICE);
  179. expect(activeOrder?.lines[1].items.every(i => i.unitPrice === ORIGINAL_PRICE)).toBe(true);
  180. expect(TestChangedPriceStrategy.spy).toHaveBeenCalledTimes(1);
  181. });
  182. });
  183. });