Procházet zdrojové kódy

fix(core): Correctly validate custom field list types

Fixes #1241
Michael Bromley před 4 roky
rodič
revize
6f71bf2586

+ 60 - 0
packages/core/src/api/common/validate-custom-field-value.spec.ts

@@ -1,6 +1,8 @@
 import { LanguageCode } from '@vendure/common/lib/generated-types';
 import { LanguageCode } from '@vendure/common/lib/generated-types';
+import { fail } from 'assert';
 
 
 import { Injector } from '../../common/injector';
 import { Injector } from '../../common/injector';
+import { CustomFieldConfig } from '../../config/custom-field/custom-field-types';
 
 
 import { validateCustomFieldValue } from './validate-custom-field-value';
 import { validateCustomFieldValue } from './validate-custom-field-value';
 
 
@@ -176,4 +178,62 @@ describe('validateCustomFieldValue()', () => {
             await assertThrowsError(validate2('bad', LanguageCode.de), 'ungültig');
             await assertThrowsError(validate2('bad', LanguageCode.de), 'ungültig');
         });
         });
     });
     });
+
+    describe('list types', () => {
+        it('number list', async () => {
+            const validate = (value: number[]) => () =>
+                validateCustomFieldValue(
+                    {
+                        name: 'test',
+                        type: 'int',
+                        list: true,
+                        min: 0,
+                        max: 10,
+                    },
+                    value,
+                    injector,
+                );
+
+            expect(await validate([1, 2, 6])).not.toThrow();
+            await assertThrowsError(validate([1, 15, 3]), 'error.field-invalid-number-range-max');
+        });
+
+        it('string list with options', async () => {
+            const validate = (value: string[]) => () =>
+                validateCustomFieldValue(
+                    {
+                        name: 'test',
+                        list: true,
+                        type: 'string',
+                        options: [{ value: 'small' }, { value: 'large' }],
+                    },
+                    value,
+                    injector,
+                );
+
+            expect(await validate(['small', 'large'])).not.toThrow();
+            await assertThrowsError(validate(['small', 'huge']), 'error.field-invalid-string-option');
+        });
+
+        it('list with validate function', async () => {
+            const validate = (value: string[]) => () =>
+                validateCustomFieldValue(
+                    {
+                        name: 'test',
+                        type: 'string',
+                        list: true,
+                        validate: (v: string[]) => {
+                            if (!v.every(val => val === 'valid')) {
+                                return 'invalid';
+                            }
+                        },
+                    },
+                    value,
+                    injector,
+                );
+
+            expect(await validate(['valid', 'valid'])).not.toThrow();
+            await assertThrowsError(validate(['bad input', 'valid']), 'invalid');
+        });
+    });
 });
 });

+ 12 - 2
packages/core/src/api/common/validate-custom-field-value.ts

@@ -19,7 +19,7 @@ import {
  */
  */
 export async function validateCustomFieldValue(
 export async function validateCustomFieldValue(
     config: CustomFieldConfig,
     config: CustomFieldConfig,
-    value: any,
+    value: any | any[],
     injector: Injector,
     injector: Injector,
     languageCode?: LanguageCode,
     languageCode?: LanguageCode,
 ): Promise<void> {
 ): Promise<void> {
@@ -33,6 +33,17 @@ export async function validateCustomFieldValue(
             });
             });
         }
         }
     }
     }
+    if (config.list === true && Array.isArray(value)) {
+        for (const singleValue of value) {
+            validateSingleValue(config, singleValue);
+        }
+    } else {
+        validateSingleValue(config, value);
+    }
+    await validateCustomFunction(config as TypedCustomFieldConfig<any, any>, value, injector, languageCode);
+}
+
+function validateSingleValue(config: CustomFieldConfig, value: any) {
     switch (config.type) {
     switch (config.type) {
         case 'string':
         case 'string':
         case 'localeString':
         case 'localeString':
@@ -52,7 +63,6 @@ export async function validateCustomFieldValue(
         default:
         default:
             assertNever(config);
             assertNever(config);
     }
     }
-    await validateCustomFunction(config as TypedCustomFieldConfig<any, any>, value, injector, languageCode);
 }
 }
 
 
 async function validateCustomFunction<T extends TypedCustomFieldConfig<any, any>>(
 async function validateCustomFunction<T extends TypedCustomFieldConfig<any, any>>(