diff --git a/packages/playwright-ct-react/registerSource.mjs b/packages/playwright-ct-react/registerSource.mjs index 9ad2612bc4..e5a14c3db6 100644 --- a/packages/playwright-ct-react/registerSource.mjs +++ b/packages/playwright-ct-react/registerSource.mjs @@ -40,7 +40,10 @@ function __pwRender(value) { if (isJsxComponent(v)) { const component = v; const props = component.props ? __pwRender(component.props) : {}; + const key = component.key ? __pwRender(component.key) : undefined; const { children, ...propsWithoutChildren } = props; + if (key) + propsWithoutChildren.key = key; const createElementArguments = [propsWithoutChildren]; if (children) createElementArguments.push(children); diff --git a/packages/playwright-ct-react17/registerSource.mjs b/packages/playwright-ct-react17/registerSource.mjs index 158984f3ac..1c484b2b12 100644 --- a/packages/playwright-ct-react17/registerSource.mjs +++ b/packages/playwright-ct-react17/registerSource.mjs @@ -40,7 +40,10 @@ function __pwRender(value) { if (isJsxComponent(v)) { const component = v; const props = component.props ? __pwRender(component.props) : {}; + const key = component.key ? __pwRender(component.key) : undefined; const { children, ...propsWithoutChildren } = props; + if (key) + propsWithoutChildren.key = key; const createElementArguments = [propsWithoutChildren]; if (children) createElementArguments.push(children); diff --git a/packages/playwright/jsx-runtime.js b/packages/playwright/jsx-runtime.js index b8900a05bb..d35e5e6e8d 100644 --- a/packages/playwright/jsx-runtime.js +++ b/packages/playwright/jsx-runtime.js @@ -14,19 +14,21 @@ * limitations under the License. */ -function jsx(type, props) { +function jsx(type, props, key) { return { __pw_type: 'jsx', type, props, + key, }; } -function jsxs(type, props) { +function jsxs(type, props, key) { return { __pw_type: 'jsx', type, props, + key, }; } diff --git a/tests/playwright-test/playwright.ct-react.spec.ts b/tests/playwright-test/playwright.ct-react.spec.ts index 6f1780ce55..e7f938fb4a 100644 --- a/tests/playwright-test/playwright.ct-react.spec.ts +++ b/tests/playwright-test/playwright.ct-react.spec.ts @@ -250,6 +250,57 @@ test('should work with JSX in variable', async ({ runInlineTest }) => { expect(result.passed).toBe(1); }); +test('should pass "key" attribute from JSX in variable', async ({ runInlineTest }) => { + const result = await runInlineTest({ + 'playwright.config.ts': playwrightCtConfigText, + 'playwright/index.html': ``, + 'playwright/index.js': ` + `, + + 'src/container.jsx': ` + import { useState } from 'react'; + export function Container({ children }) { + const [index, setIndex] = useState(0); + return ( +
setIndex((index + 1) % children.length)}> + {children[index]} +
+ ); + } + `, + + 'src/button.jsx': ` + import { useState } from 'react'; + export function Button({ value }) { + const [state, setState] = useState(value); + return ; + } + `, + + 'src/index.test.jsx': ` + import { test, expect } from '@playwright/experimental-ct-react'; + import { Button } from './button'; + import { Container } from './container'; + + test('key should tear down and recreate component', async ({ mount }) => { + const component = await mount( + +