From 9c0c5d6e2a3382c0570cc9babf67475154dd6d7f Mon Sep 17 00:00:00 2001 From: Sander Date: Wed, 29 Mar 2023 22:59:27 +0200 Subject: [PATCH] chore(ct): throw error when props are not json serializable (#22025) --- packages/playwright-test/src/mount.ts | 25 ++++++++++++++++++++++++- 1 file changed, 24 insertions(+), 1 deletion(-) diff --git a/packages/playwright-test/src/mount.ts b/packages/playwright-test/src/mount.ts index f4b9fc5121..0be8824872 100644 --- a/packages/playwright-test/src/mount.ts +++ b/packages/playwright-test/src/mount.ts @@ -51,6 +51,8 @@ export const fixtures: Fixtures< mount: async ({ page }, use) => { await use(async (component: JsxComponent | string, options?: MountOptions) => { + if (options?.props && !isJson(options.props)) + throw new Error('The mount function props are not JSON serializable.'); const selector = await (page as any)._wrapApiCall(async () => { return await innerMount(page, component, options); }, true); @@ -63,7 +65,10 @@ export const fixtures: Fixtures< }); }, update: async (options: JsxComponent | Omit) => { - if (isJsxApi(options)) return await innerUpdate(page, options); + if (isJsxApi(options)) + return await innerUpdate(page, options); + if (options?.props && !isJson(options.props)) + throw new Error('The update function props are not JSON serializable.'); await innerUpdate(page, component, options); } }); @@ -72,6 +77,24 @@ export const fixtures: Fixtures< }, }; +const jsonType: Record = { + string: (value: any) => typeof value === 'string', + number: (value: any) => typeof value === 'number', + boolean: (value: any) => typeof value === 'boolean', + null: (value: any) => value === null, + array: (value: any) => Array.isArray(value) && value.every(isJson), + object: (value: any) => typeof value === 'object' && value !== null && !Array.isArray(value) + && Object.values(value).every(isJson), +}; + +function isJson(value: any): boolean { + const valueType = Array.isArray(value) ? 'array' : typeof value; + const validate = jsonType[valueType]; + if (validate) + return validate(value); + return false; +} + function isJsxApi(options: Record): options is JsxComponent { return options?.kind === 'jsx'; }