fix(ct-react): support shorthand fragment notation (#32900)
Closes https://github.com/microsoft/playwright/issues/32853 Vite turns the shorthand fragment notation `<></>` into `import { Fragment } from "react"; <Fragment></Fragment>`. On the Node.js side of things, this `react` import resolves to our mock version of React, which currently mocks `Fragment` as `{}`. Currently, we pass that straight to `React.createElement`, which throws an error. The fix is to make our `Fragment` mock detectable with a tag, and when we render it replace it with the real `__pwReact.Fragment`.
This commit is contained in:
parent
0fd9452127
commit
208a54529d
|
@ -33,12 +33,24 @@ function isJsxComponent(component) {
|
|||
}
|
||||
|
||||
/**
|
||||
* @param {any} type
|
||||
* @returns {boolean} type is Playwright's mock JSX.Fragment
|
||||
*/
|
||||
function isJsxFragment(type) {
|
||||
return typeof type === 'object' && type?.__pw_jsx_fragment;
|
||||
}
|
||||
|
||||
/**
|
||||
* Turns the Playwright representation of JSX (see jsx-runtime.js) into React.createElement calls.
|
||||
* @param {any} value
|
||||
*/
|
||||
function __pwRender(value) {
|
||||
return window.__pwTransformObject(value, v => {
|
||||
if (isJsxComponent(v)) {
|
||||
const component = v;
|
||||
let type = component.type;
|
||||
if (isJsxFragment(type))
|
||||
type = __pwReact.Fragment;
|
||||
const props = component.props ? __pwRender(component.props) : {};
|
||||
const key = component.key ? __pwRender(component.key) : undefined;
|
||||
const { children, ...propsWithoutChildren } = props;
|
||||
|
@ -47,7 +59,7 @@ function __pwRender(value) {
|
|||
const createElementArguments = [propsWithoutChildren];
|
||||
if (children)
|
||||
createElementArguments.push(children);
|
||||
return { result: __pwReact.createElement(component.type, ...createElementArguments) };
|
||||
return { result: __pwReact.createElement(type, ...createElementArguments) };
|
||||
}
|
||||
});
|
||||
}
|
||||
|
|
|
@ -32,7 +32,8 @@ function jsxs(type, props, key) {
|
|||
};
|
||||
}
|
||||
|
||||
const Fragment = {};
|
||||
// this is used in <></> notation
|
||||
const Fragment = { __pw_jsx_fragment: true };
|
||||
|
||||
module.exports = {
|
||||
Fragment,
|
||||
|
|
|
@ -46,3 +46,8 @@ test('render inline component with an error if its nested', async ({ mount }) =>
|
|||
<MyInlineComponent value="Max" />
|
||||
</DefaultChildren>)).rejects.toThrow('Component "MyInlineComponent" cannot be mounted.');
|
||||
});
|
||||
|
||||
test('render Fragment shorthand notation', { annotation: { type: 'issue', description: 'https://github.com/microsoft/playwright/issues/32853' } }, async ({ mount }) => {
|
||||
const component = await mount(<>Learn React</>);
|
||||
await expect(component).toContainText('Learn React');
|
||||
});
|
||||
|
|
Loading…
Reference in New Issue