Skip to content

Commit ea07ff3

Browse files
authored
fix(jsx): allow passing variables into mount (#14412)
1 parent d5c1a5a commit ea07ff3

File tree

3 files changed

+53
-6
lines changed

3 files changed

+53
-6
lines changed

packages/playwright-test/src/transform.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ import { tsConfigLoader } from './third_party/tsconfig-loader';
2626
import Module from 'module';
2727
import type { BabelTransformFunction } from './babelBundle';
2828

29-
const version = 10;
29+
const version = 11;
3030
const cacheDir = process.env.PWTEST_CACHE_DIR || path.join(os.tmpdir(), 'playwright-transform-cache');
3131
const sourceMaps: Map<string, string> = new Map();
3232

packages/playwright-test/src/tsxTransform.ts

Lines changed: 22 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -124,21 +124,38 @@ export default declare((api: BabelAPI) => {
124124
});
125125

126126
export function collectComponentUsages(node: T.Node) {
127+
const importedLocalNames = new Set<string>();
127128
const names = new Set<string>();
128129
const identifiers = new Set<T.Identifier>();
129130
traverse(node, {
130131
enter: p => {
132+
133+
// First look at all the imports.
134+
if (t.isImportDeclaration(p.node)) {
135+
const importNode = p.node;
136+
if (!t.isStringLiteral(importNode.source))
137+
return;
138+
139+
for (const specifier of importNode.specifiers) {
140+
if (t.isImportNamespaceSpecifier(specifier))
141+
continue;
142+
importedLocalNames.add(specifier.local.name);
143+
}
144+
}
145+
131146
// Treat JSX-everything as component usages.
132147
if (t.isJSXElement(p.node) && t.isJSXIdentifier(p.node.openingElement.name))
133148
names.add(p.node.openingElement.name.name);
134149

135-
// Treat mount(identifier, ...) as component usage.
150+
// Treat mount(identifier, ...) as component usage if it is in the importedLocalNames list.
136151
if (t.isAwaitExpression(p.node) && t.isCallExpression(p.node.argument) && t.isIdentifier(p.node.argument.callee) && p.node.argument.callee.name === 'mount') {
137152
const callExpression = p.node.argument;
138-
if (t.isIdentifier(callExpression.arguments[0])) {
139-
names.add(callExpression.arguments[0].name);
140-
identifiers.add(callExpression.arguments[0]);
141-
}
153+
const arg = callExpression.arguments[0];
154+
if (!t.isIdentifier(arg) || !importedLocalNames.has(arg.name))
155+
return;
156+
157+
names.add(arg.name);
158+
identifiers.add(arg);
142159
}
143160
}
144161
});

tests/playwright-test/playwright.ct-react.spec.ts

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -240,3 +240,33 @@ test.fixme('should work with stray JS import', async ({ runInlineTest }) => {
240240
expect(result.exitCode).toBe(0);
241241
expect(result.passed).toBe(1);
242242
});
243+
244+
test('should work with JSX in variable', async ({ runInlineTest }) => {
245+
const result = await runInlineTest({
246+
'playwright/index.html': `<script type="module" src="/playwright/index.js"></script>`,
247+
'playwright/index.js': `
248+
//@no-header
249+
`,
250+
251+
'src/button.jsx': `
252+
//@no-header
253+
export const Button = () => <button>Button</button>;
254+
`,
255+
256+
'src/button.test.jsx': `
257+
//@no-header
258+
import { test, expect } from '@playwright/experimental-ct-react';
259+
import { Button } from './button';
260+
261+
const button = <Button></Button>;
262+
263+
test('pass button', async ({ mount }) => {
264+
const component = await mount(button);
265+
await expect(component).toHaveText('Button');
266+
});
267+
`,
268+
}, { workers: 1 });
269+
270+
expect(result.exitCode).toBe(0);
271+
expect(result.passed).toBe(1);
272+
});

0 commit comments

Comments
 (0)