Explorar el Código

fix(core): Correctly handle out-of-order config args

Relates to #1682
Michael Bromley hace 3 años
padre
commit
43887f337a

+ 126 - 0
packages/core/e2e/shipping-method.e2e-spec.ts

@@ -338,6 +338,132 @@ describe('ShippingMethod resolver', () => {
         const listResult2 = await adminClient.query<GetShippingMethodList.Query>(GET_SHIPPING_METHOD_LIST);
         expect(listResult2.shippingMethods.items.map(i => i.id)).toEqual(['T_1', 'T_2']);
     });
+
+    describe('argument ordering', () => {
+        it('createShippingMethod corrects order of arguments', async () => {
+            const { createShippingMethod } = await adminClient.query<
+                CreateShippingMethod.Mutation,
+                CreateShippingMethod.Variables
+            >(CREATE_SHIPPING_METHOD, {
+                input: {
+                    code: 'new-method',
+                    fulfillmentHandler: manualFulfillmentHandler.code,
+                    checker: {
+                        code: defaultShippingEligibilityChecker.code,
+                        arguments: [
+                            {
+                                name: 'orderMinimum',
+                                value: '0',
+                            },
+                        ],
+                    },
+                    calculator: {
+                        code: defaultShippingCalculator.code,
+                        arguments: [
+                            { name: 'rate', value: '500' },
+                            { name: 'taxRate', value: '20' },
+                            { name: 'includesTax', value: 'include' },
+                        ],
+                    },
+                    translations: [{ languageCode: LanguageCode.en, name: 'new method', description: '' }],
+                },
+            });
+
+            expect(createShippingMethod.calculator).toEqual({
+                code: defaultShippingCalculator.code,
+                args: [
+                    { name: 'rate', value: '500' },
+                    { name: 'includesTax', value: 'include' },
+                    { name: 'taxRate', value: '20' },
+                ],
+            });
+        });
+
+        it('updateShippingMethod corrects order of arguments', async () => {
+            const { updateShippingMethod } = await adminClient.query<
+                UpdateShippingMethod.Mutation,
+                UpdateShippingMethod.Variables
+            >(UPDATE_SHIPPING_METHOD, {
+                input: {
+                    id: 'T_4',
+                    translations: [],
+                    calculator: {
+                        code: defaultShippingCalculator.code,
+                        arguments: [
+                            { name: 'rate', value: '500' },
+                            { name: 'taxRate', value: '20' },
+                            { name: 'includesTax', value: 'include' },
+                        ],
+                    },
+                },
+            });
+
+            expect(updateShippingMethod.calculator).toEqual({
+                code: defaultShippingCalculator.code,
+                args: [
+                    { name: 'rate', value: '500' },
+                    { name: 'includesTax', value: 'include' },
+                    { name: 'taxRate', value: '20' },
+                ],
+            });
+        });
+
+        it('get shippingMethod preserves correct ordering', async () => {
+            const { shippingMethod } = await adminClient.query<
+                GetShippingMethod.Query,
+                GetShippingMethod.Variables
+            >(GET_SHIPPING_METHOD, {
+                id: 'T_4',
+            });
+
+            expect(shippingMethod?.calculator.args).toEqual([
+                { name: 'rate', value: '500' },
+                { name: 'includesTax', value: 'include' },
+                { name: 'taxRate', value: '20' },
+            ]);
+        });
+
+        it('testShippingMethod corrects order of arguments', async () => {
+            const { testShippingMethod } = await adminClient.query<
+                TestShippingMethod.Query,
+                TestShippingMethod.Variables
+            >(TEST_SHIPPING_METHOD, {
+                input: {
+                    calculator: {
+                        code: defaultShippingCalculator.code,
+                        arguments: [
+                            { name: 'rate', value: '500' },
+                            { name: 'taxRate', value: '0' },
+                            { name: 'includesTax', value: 'include' },
+                        ],
+                    },
+                    checker: {
+                        code: defaultShippingEligibilityChecker.code,
+                        arguments: [
+                            {
+                                name: 'orderMinimum',
+                                value: '0',
+                            },
+                        ],
+                    },
+                    lines: [{ productVariantId: 'T_1', quantity: 1 }],
+                    shippingAddress: {
+                        streetLine1: '',
+                        countryCode: 'GB',
+                    },
+                },
+            });
+
+            expect(testShippingMethod).toEqual({
+                eligible: true,
+                quote: {
+                    metadata: null,
+                    price: 500,
+                    priceWithTax: 500,
+                },
+            });
+        });
+    });
 });
 
 const GET_SHIPPING_METHOD = gql`

+ 16 - 1
packages/core/src/service/helpers/config-arg/config-arg.service.ts

@@ -69,12 +69,27 @@ export class ConfigArgService {
     parseInput(defType: ConfigDefType, input: ConfigurableOperationInput): ConfigurableOperation {
         const match = this.getByCode(defType, input.code);
         this.validateRequiredFields(input, match);
+        const orderedArgs = this.orderArgsToMatchDef(match, input.arguments);
         return {
             code: input.code,
-            args: input.arguments,
+            args: orderedArgs,
         };
     }
 
+    private orderArgsToMatchDef<T extends ConfigDefType>(
+        def: ConfigDefTypeMap[T],
+        args: ConfigurableOperation['args'],
+    ) {
+        const output: ConfigurableOperation['args'] = [];
+        for (const name of Object.keys(def.args)) {
+            const match = args.find(arg => arg.name === name);
+            if (match) {
+                output.push(match);
+            }
+        }
+        return output;
+    }
+
     private parseOperationArgs(
         input: ConfigurableOperationInput,
         checkerOrCalculator: ShippingEligibilityChecker | ShippingCalculator,