From 4d868f6ba8aa87c2b34a132c3979d007dfc94950 Mon Sep 17 00:00:00 2001 From: Jeppe Reinhold Date: Fri, 23 Feb 2024 21:30:42 +0100 Subject: [PATCH] fix(ct-react+ct-react17): only pass `children` to `React.createElement` when they are defined (#29592) --- packages/playwright-ct-react/registerSource.mjs | 8 +++++++- .../playwright-ct-react17/registerSource.mjs | 9 ++++++++- .../src/components/CheckChildrenProp.tsx | 16 ++++++++++++++++ .../ct-react-vite/tests/children.spec.tsx | 6 ++++++ .../src/components/CheckChildrenProp.tsx | 16 ++++++++++++++++ .../ct-react17/tests/children.spec.tsx | 6 ++++++ 6 files changed, 59 insertions(+), 2 deletions(-) create mode 100644 tests/components/ct-react-vite/src/components/CheckChildrenProp.tsx create mode 100644 tests/components/ct-react17/src/components/CheckChildrenProp.tsx diff --git a/packages/playwright-ct-react/registerSource.mjs b/packages/playwright-ct-react/registerSource.mjs index d5e617785a..10dad4c0db 100644 --- a/packages/playwright-ct-react/registerSource.mjs +++ b/packages/playwright-ct-react/registerSource.mjs @@ -40,7 +40,13 @@ function __pwRender(value) { if (isJsxComponent(v)) { const component = v; const props = component.props ? __pwRender(component.props) : {}; - return { result: __pwReact.createElement(/** @type { any } */ (component.type), { ...props, children: undefined }, props.children) }; + const {children, ...propsWithoutChildren} = props; + /** @type {[any, any, any?]} */ + const createElementArguments = [component.type, propsWithoutChildren]; + if(children){ + createElementArguments.push(children); + } + return { result: __pwReact.createElement(...createElementArguments) }; } }); } diff --git a/packages/playwright-ct-react17/registerSource.mjs b/packages/playwright-ct-react17/registerSource.mjs index 2a13152dce..8dfc1d24e9 100644 --- a/packages/playwright-ct-react17/registerSource.mjs +++ b/packages/playwright-ct-react17/registerSource.mjs @@ -40,7 +40,14 @@ function __pwRender(value) { if (isJsxComponent(v)) { const component = v; const props = component.props ? __pwRender(component.props) : {}; - return { result: __pwReact.createElement(/** @type { any } */ (component.type), { ...props, children: undefined }, props.children) }; + + const {children, ...propsWithoutChildren} = props; + /** @type {[any, any, any?]} */ + const createElementArguments = [component.type, propsWithoutChildren]; + if(children){ + createElementArguments.push(children); + } + return { result: __pwReact.createElement(...createElementArguments) }; } }); } diff --git a/tests/components/ct-react-vite/src/components/CheckChildrenProp.tsx b/tests/components/ct-react-vite/src/components/CheckChildrenProp.tsx new file mode 100644 index 0000000000..42b3a361e8 --- /dev/null +++ b/tests/components/ct-react-vite/src/components/CheckChildrenProp.tsx @@ -0,0 +1,16 @@ +type DefaultChildrenProps = { + children?: any; +} + +export default function CheckChildrenProp(props: DefaultChildrenProps) { + const content = 'children' in props ? props.children : 'No Children'; + return
+

Welcome!

+
+ {content} +
+
+ Thanks for visiting. +
+
+} diff --git a/tests/components/ct-react-vite/tests/children.spec.tsx b/tests/components/ct-react-vite/tests/children.spec.tsx index 93e1f1af72..d671b14e64 100644 --- a/tests/components/ct-react-vite/tests/children.spec.tsx +++ b/tests/components/ct-react-vite/tests/children.spec.tsx @@ -1,5 +1,6 @@ import { test, expect } from '@playwright/experimental-ct-react'; import Button from '@/components/Button'; +import CheckChildrenProp from '@/components/CheckChildrenProp'; import DefaultChildren from '@/components/DefaultChildren'; import MultipleChildren from '@/components/MultipleChildren'; @@ -58,3 +59,8 @@ test('render number as child', async ({ mount }) => { const component = await mount({1337}); await expect(component).toContainText('1337'); }); + +test('render without children', async ({ mount }) => { + const component = await mount(); + await expect(component).toContainText('No Children'); +}); diff --git a/tests/components/ct-react17/src/components/CheckChildrenProp.tsx b/tests/components/ct-react17/src/components/CheckChildrenProp.tsx new file mode 100644 index 0000000000..42b3a361e8 --- /dev/null +++ b/tests/components/ct-react17/src/components/CheckChildrenProp.tsx @@ -0,0 +1,16 @@ +type DefaultChildrenProps = { + children?: any; +} + +export default function CheckChildrenProp(props: DefaultChildrenProps) { + const content = 'children' in props ? props.children : 'No Children'; + return
+

Welcome!

+
+ {content} +
+
+ Thanks for visiting. +
+
+} diff --git a/tests/components/ct-react17/tests/children.spec.tsx b/tests/components/ct-react17/tests/children.spec.tsx index b7751d197d..32ddabe7ac 100644 --- a/tests/components/ct-react17/tests/children.spec.tsx +++ b/tests/components/ct-react17/tests/children.spec.tsx @@ -1,5 +1,6 @@ import { test, expect } from '@playwright/experimental-ct-react17'; import Button from '@/components/Button'; +import CheckChildrenProp from '@/components/CheckChildrenProp'; import DefaultChildren from '@/components/DefaultChildren'; import MultipleChildren from '@/components/MultipleChildren'; @@ -58,3 +59,8 @@ test('render number as child', async ({ mount }) => { const component = await mount({1337}); await expect(component).toContainText('1337'); }); + +test('render without children', async ({ mount }) => { + const component = await mount(); + await expect(component).toContainText('No Children'); +});