|
|
@@ -0,0 +1,217 @@
|
|
|
+/* tslint:disable:no-non-null-assertion */
|
|
|
+import {
|
|
|
+ ChangedPriceHandlingStrategy,
|
|
|
+ mergeConfig,
|
|
|
+ OrderItem,
|
|
|
+ PriceCalculationResult,
|
|
|
+ RequestContext,
|
|
|
+} from '@vendure/core';
|
|
|
+import { createTestEnvironment } from '@vendure/testing';
|
|
|
+import path from 'path';
|
|
|
+
|
|
|
+import { initialData } from '../../../e2e-common/e2e-initial-data';
|
|
|
+import { testConfig, TEST_SETUP_TIMEOUT_MS } from '../../../e2e-common/test-config';
|
|
|
+
|
|
|
+import { UpdateProductVariants } from './graphql/generated-e2e-admin-types';
|
|
|
+import { AddItemToOrder, AdjustItemQuantity, GetActiveOrder } from './graphql/generated-e2e-shop-types';
|
|
|
+import { UPDATE_PRODUCT_VARIANTS } from './graphql/shared-definitions';
|
|
|
+import { ADD_ITEM_TO_ORDER, ADJUST_ITEM_QUANTITY, GET_ACTIVE_ORDER } from './graphql/shop-definitions';
|
|
|
+
|
|
|
+class TestChangedPriceStrategy implements ChangedPriceHandlingStrategy {
|
|
|
+ static spy = jest.fn();
|
|
|
+ static useLatestPrice = true;
|
|
|
+
|
|
|
+ handlePriceChange(
|
|
|
+ ctx: RequestContext,
|
|
|
+ current: PriceCalculationResult,
|
|
|
+ existingItems: OrderItem[],
|
|
|
+ ): PriceCalculationResult {
|
|
|
+ TestChangedPriceStrategy.spy(current);
|
|
|
+ if (TestChangedPriceStrategy.useLatestPrice) {
|
|
|
+ return current;
|
|
|
+ } else {
|
|
|
+ return {
|
|
|
+ price: existingItems[0].listPrice,
|
|
|
+ priceIncludesTax: existingItems[0].listPriceIncludesTax,
|
|
|
+ };
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+describe('ChangedPriceHandlingStrategy', () => {
|
|
|
+ const { server, shopClient, adminClient } = createTestEnvironment(
|
|
|
+ mergeConfig(testConfig, {
|
|
|
+ orderOptions: {
|
|
|
+ changedPriceHandlingStrategy: new TestChangedPriceStrategy(),
|
|
|
+ },
|
|
|
+ }),
|
|
|
+ );
|
|
|
+
|
|
|
+ beforeAll(async () => {
|
|
|
+ await server.init({
|
|
|
+ initialData,
|
|
|
+ productsCsvPath: path.join(__dirname, 'fixtures/e2e-products-full.csv'),
|
|
|
+ customerCount: 1,
|
|
|
+ });
|
|
|
+ await adminClient.asSuperAdmin();
|
|
|
+ }, TEST_SETUP_TIMEOUT_MS);
|
|
|
+
|
|
|
+ afterAll(async () => {
|
|
|
+ await server.destroy();
|
|
|
+ });
|
|
|
+
|
|
|
+ it('unitPriceChangeSinceAdded starts as 0', async () => {
|
|
|
+ TestChangedPriceStrategy.spy.mockClear();
|
|
|
+
|
|
|
+ await shopClient.query<AddItemToOrder.Mutation, AddItemToOrder.Variables>(ADD_ITEM_TO_ORDER, {
|
|
|
+ productVariantId: 'T_12',
|
|
|
+ quantity: 1,
|
|
|
+ });
|
|
|
+
|
|
|
+ const { activeOrder } = await shopClient.query<GetActiveOrder.Query>(GET_ACTIVE_ORDER);
|
|
|
+
|
|
|
+ expect(activeOrder?.lines[0].unitPriceChangeSinceAdded).toBe(0);
|
|
|
+ expect(activeOrder?.lines[0].unitPrice).toBe(5374);
|
|
|
+ expect(TestChangedPriceStrategy.spy).not.toHaveBeenCalled();
|
|
|
+ });
|
|
|
+
|
|
|
+ describe('use latest price', () => {
|
|
|
+ let firstOrderLineId: string;
|
|
|
+
|
|
|
+ beforeAll(() => {
|
|
|
+ TestChangedPriceStrategy.useLatestPrice = true;
|
|
|
+ });
|
|
|
+
|
|
|
+ it('calls handlePriceChange on addItemToOrder', async () => {
|
|
|
+ TestChangedPriceStrategy.spy.mockClear();
|
|
|
+
|
|
|
+ await adminClient.query<UpdateProductVariants.Mutation, UpdateProductVariants.Variables>(
|
|
|
+ UPDATE_PRODUCT_VARIANTS,
|
|
|
+ {
|
|
|
+ input: [
|
|
|
+ {
|
|
|
+ id: 'T_12',
|
|
|
+ price: 6000,
|
|
|
+ },
|
|
|
+ ],
|
|
|
+ },
|
|
|
+ );
|
|
|
+
|
|
|
+ await shopClient.query<AddItemToOrder.Mutation, AddItemToOrder.Variables>(ADD_ITEM_TO_ORDER, {
|
|
|
+ productVariantId: 'T_12',
|
|
|
+ quantity: 1,
|
|
|
+ });
|
|
|
+
|
|
|
+ const { activeOrder } = await shopClient.query<GetActiveOrder.Query>(GET_ACTIVE_ORDER);
|
|
|
+ expect(activeOrder?.lines[0].unitPriceChangeSinceAdded).toBe(626);
|
|
|
+ expect(activeOrder?.lines[0].unitPrice).toBe(6000);
|
|
|
+ expect(activeOrder?.lines[0].items.every(i => i.unitPrice === 6000)).toBe(true);
|
|
|
+ expect(TestChangedPriceStrategy.spy).toHaveBeenCalledTimes(1);
|
|
|
+
|
|
|
+ firstOrderLineId = activeOrder!.lines[0].id;
|
|
|
+ });
|
|
|
+
|
|
|
+ it('calls handlePriceChange on adjustOrderLine', async () => {
|
|
|
+ TestChangedPriceStrategy.spy.mockClear();
|
|
|
+
|
|
|
+ await adminClient.query<UpdateProductVariants.Mutation, UpdateProductVariants.Variables>(
|
|
|
+ UPDATE_PRODUCT_VARIANTS,
|
|
|
+ {
|
|
|
+ input: [
|
|
|
+ {
|
|
|
+ id: 'T_12',
|
|
|
+ price: 3000,
|
|
|
+ },
|
|
|
+ ],
|
|
|
+ },
|
|
|
+ );
|
|
|
+
|
|
|
+ await shopClient.query<AdjustItemQuantity.Mutation, AdjustItemQuantity.Variables>(
|
|
|
+ ADJUST_ITEM_QUANTITY,
|
|
|
+ {
|
|
|
+ orderLineId: firstOrderLineId,
|
|
|
+ quantity: 3,
|
|
|
+ },
|
|
|
+ );
|
|
|
+
|
|
|
+ const { activeOrder } = await shopClient.query<GetActiveOrder.Query>(GET_ACTIVE_ORDER);
|
|
|
+ expect(activeOrder?.lines[0].unitPriceChangeSinceAdded).toBe(-2374);
|
|
|
+ expect(activeOrder?.lines[0].unitPrice).toBe(3000);
|
|
|
+ expect(activeOrder?.lines[0].items.every(i => i.unitPrice === 3000)).toBe(true);
|
|
|
+ expect(TestChangedPriceStrategy.spy).toHaveBeenCalledTimes(1);
|
|
|
+ });
|
|
|
+ });
|
|
|
+
|
|
|
+ describe('use original price', () => {
|
|
|
+ let secondOrderLineId: string;
|
|
|
+ const ORIGINAL_PRICE = 7896;
|
|
|
+
|
|
|
+ beforeAll(() => {
|
|
|
+ TestChangedPriceStrategy.useLatestPrice = false;
|
|
|
+ });
|
|
|
+
|
|
|
+ it('calls handlePriceChange on addItemToOrder', async () => {
|
|
|
+ TestChangedPriceStrategy.spy.mockClear();
|
|
|
+
|
|
|
+ await shopClient.query<AddItemToOrder.Mutation, AddItemToOrder.Variables>(ADD_ITEM_TO_ORDER, {
|
|
|
+ productVariantId: 'T_13',
|
|
|
+ quantity: 1,
|
|
|
+ });
|
|
|
+
|
|
|
+ await adminClient.query<UpdateProductVariants.Mutation, UpdateProductVariants.Variables>(
|
|
|
+ UPDATE_PRODUCT_VARIANTS,
|
|
|
+ {
|
|
|
+ input: [
|
|
|
+ {
|
|
|
+ id: 'T_13',
|
|
|
+ price: 8000,
|
|
|
+ },
|
|
|
+ ],
|
|
|
+ },
|
|
|
+ );
|
|
|
+
|
|
|
+ await shopClient.query<AddItemToOrder.Mutation, AddItemToOrder.Variables>(ADD_ITEM_TO_ORDER, {
|
|
|
+ productVariantId: 'T_13',
|
|
|
+ quantity: 1,
|
|
|
+ });
|
|
|
+
|
|
|
+ const { activeOrder } = await shopClient.query<GetActiveOrder.Query>(GET_ACTIVE_ORDER);
|
|
|
+ expect(activeOrder?.lines[1].unitPriceChangeSinceAdded).toBe(0);
|
|
|
+ expect(activeOrder?.lines[1].unitPrice).toBe(ORIGINAL_PRICE);
|
|
|
+ expect(activeOrder?.lines[1].items.every(i => i.unitPrice === ORIGINAL_PRICE)).toBe(true);
|
|
|
+ expect(TestChangedPriceStrategy.spy).toHaveBeenCalledTimes(1);
|
|
|
+
|
|
|
+ secondOrderLineId = activeOrder!.lines[1].id;
|
|
|
+ });
|
|
|
+
|
|
|
+ it('calls handlePriceChange on adjustOrderLine', async () => {
|
|
|
+ TestChangedPriceStrategy.spy.mockClear();
|
|
|
+
|
|
|
+ await adminClient.query<UpdateProductVariants.Mutation, UpdateProductVariants.Variables>(
|
|
|
+ UPDATE_PRODUCT_VARIANTS,
|
|
|
+ {
|
|
|
+ input: [
|
|
|
+ {
|
|
|
+ id: 'T_13',
|
|
|
+ price: 3000,
|
|
|
+ },
|
|
|
+ ],
|
|
|
+ },
|
|
|
+ );
|
|
|
+
|
|
|
+ await shopClient.query<AdjustItemQuantity.Mutation, AdjustItemQuantity.Variables>(
|
|
|
+ ADJUST_ITEM_QUANTITY,
|
|
|
+ {
|
|
|
+ orderLineId: secondOrderLineId,
|
|
|
+ quantity: 3,
|
|
|
+ },
|
|
|
+ );
|
|
|
+
|
|
|
+ const { activeOrder } = await shopClient.query<GetActiveOrder.Query>(GET_ACTIVE_ORDER);
|
|
|
+ expect(activeOrder?.lines[1].unitPriceChangeSinceAdded).toBe(0);
|
|
|
+ expect(activeOrder?.lines[1].unitPrice).toBe(ORIGINAL_PRICE);
|
|
|
+ expect(activeOrder?.lines[1].items.every(i => i.unitPrice === ORIGINAL_PRICE)).toBe(true);
|
|
|
+ expect(TestChangedPriceStrategy.spy).toHaveBeenCalledTimes(1);
|
|
|
+ });
|
|
|
+ });
|
|
|
+});
|