fix(jsx): allow passing variables into mount (#14412)
This commit is contained in:
parent
d5c1a5a11f
commit
ea07ff3ae9
|
|
@ -26,7 +26,7 @@ import { tsConfigLoader } from './third_party/tsconfig-loader';
|
||||||
import Module from 'module';
|
import Module from 'module';
|
||||||
import type { BabelTransformFunction } from './babelBundle';
|
import type { BabelTransformFunction } from './babelBundle';
|
||||||
|
|
||||||
const version = 10;
|
const version = 11;
|
||||||
const cacheDir = process.env.PWTEST_CACHE_DIR || path.join(os.tmpdir(), 'playwright-transform-cache');
|
const cacheDir = process.env.PWTEST_CACHE_DIR || path.join(os.tmpdir(), 'playwright-transform-cache');
|
||||||
const sourceMaps: Map<string, string> = new Map();
|
const sourceMaps: Map<string, string> = new Map();
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -124,21 +124,38 @@ export default declare((api: BabelAPI) => {
|
||||||
});
|
});
|
||||||
|
|
||||||
export function collectComponentUsages(node: T.Node) {
|
export function collectComponentUsages(node: T.Node) {
|
||||||
|
const importedLocalNames = new Set<string>();
|
||||||
const names = new Set<string>();
|
const names = new Set<string>();
|
||||||
const identifiers = new Set<T.Identifier>();
|
const identifiers = new Set<T.Identifier>();
|
||||||
traverse(node, {
|
traverse(node, {
|
||||||
enter: p => {
|
enter: p => {
|
||||||
|
|
||||||
|
// First look at all the imports.
|
||||||
|
if (t.isImportDeclaration(p.node)) {
|
||||||
|
const importNode = p.node;
|
||||||
|
if (!t.isStringLiteral(importNode.source))
|
||||||
|
return;
|
||||||
|
|
||||||
|
for (const specifier of importNode.specifiers) {
|
||||||
|
if (t.isImportNamespaceSpecifier(specifier))
|
||||||
|
continue;
|
||||||
|
importedLocalNames.add(specifier.local.name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Treat JSX-everything as component usages.
|
// Treat JSX-everything as component usages.
|
||||||
if (t.isJSXElement(p.node) && t.isJSXIdentifier(p.node.openingElement.name))
|
if (t.isJSXElement(p.node) && t.isJSXIdentifier(p.node.openingElement.name))
|
||||||
names.add(p.node.openingElement.name.name);
|
names.add(p.node.openingElement.name.name);
|
||||||
|
|
||||||
// Treat mount(identifier, ...) as component usage.
|
// Treat mount(identifier, ...) as component usage if it is in the importedLocalNames list.
|
||||||
if (t.isAwaitExpression(p.node) && t.isCallExpression(p.node.argument) && t.isIdentifier(p.node.argument.callee) && p.node.argument.callee.name === 'mount') {
|
if (t.isAwaitExpression(p.node) && t.isCallExpression(p.node.argument) && t.isIdentifier(p.node.argument.callee) && p.node.argument.callee.name === 'mount') {
|
||||||
const callExpression = p.node.argument;
|
const callExpression = p.node.argument;
|
||||||
if (t.isIdentifier(callExpression.arguments[0])) {
|
const arg = callExpression.arguments[0];
|
||||||
names.add(callExpression.arguments[0].name);
|
if (!t.isIdentifier(arg) || !importedLocalNames.has(arg.name))
|
||||||
identifiers.add(callExpression.arguments[0]);
|
return;
|
||||||
}
|
|
||||||
|
names.add(arg.name);
|
||||||
|
identifiers.add(arg);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
|
||||||
|
|
@ -240,3 +240,33 @@ test.fixme('should work with stray JS import', async ({ runInlineTest }) => {
|
||||||
expect(result.exitCode).toBe(0);
|
expect(result.exitCode).toBe(0);
|
||||||
expect(result.passed).toBe(1);
|
expect(result.passed).toBe(1);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test('should work with JSX in variable', async ({ runInlineTest }) => {
|
||||||
|
const result = await runInlineTest({
|
||||||
|
'playwright/index.html': `<script type="module" src="/playwright/index.js"></script>`,
|
||||||
|
'playwright/index.js': `
|
||||||
|
//@no-header
|
||||||
|
`,
|
||||||
|
|
||||||
|
'src/button.jsx': `
|
||||||
|
//@no-header
|
||||||
|
export const Button = () => <button>Button</button>;
|
||||||
|
`,
|
||||||
|
|
||||||
|
'src/button.test.jsx': `
|
||||||
|
//@no-header
|
||||||
|
import { test, expect } from '@playwright/experimental-ct-react';
|
||||||
|
import { Button } from './button';
|
||||||
|
|
||||||
|
const button = <Button></Button>;
|
||||||
|
|
||||||
|
test('pass button', async ({ mount }) => {
|
||||||
|
const component = await mount(button);
|
||||||
|
await expect(component).toHaveText('Button');
|
||||||
|
});
|
||||||
|
`,
|
||||||
|
}, { workers: 1 });
|
||||||
|
|
||||||
|
expect(result.exitCode).toBe(0);
|
||||||
|
expect(result.passed).toBe(1);
|
||||||
|
});
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue