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

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