mirror of
https://github.com/microsoft/playwright.git
synced 2025-06-26 21:40:17 +00:00
fix(tsx): resolve .js imports to .tsx as well (#20092)
Fixes: https://github.com/microsoft/playwright/issues/20039
This commit is contained in:
parent
3a1eb2abda
commit
736cf5c585
@ -169,11 +169,14 @@ export function resolveHook(filename: string, specifier: string): string | undef
|
||||
|
||||
export function js2ts(resolved: string): string | undefined {
|
||||
const match = resolved.match(/(.*)(\.js|\.jsx|\.mjs)$/);
|
||||
if (match) {
|
||||
const tsResolved = match[1] + match[2].replace('j', 't');
|
||||
if (!fs.existsSync(resolved) && fs.existsSync(tsResolved))
|
||||
return tsResolved;
|
||||
}
|
||||
if (!match || fs.existsSync(resolved))
|
||||
return;
|
||||
const tsResolved = match[1] + match[2].replace('js', 'ts');
|
||||
if (fs.existsSync(tsResolved))
|
||||
return tsResolved;
|
||||
const tsxResolved = match[1] + match[2].replace('js', 'tsx');
|
||||
if (fs.existsSync(tsxResolved))
|
||||
return tsxResolved;
|
||||
}
|
||||
|
||||
export function transformHook(code: string, filename: string, moduleUrl?: string): string {
|
||||
|
||||
@ -17,6 +17,7 @@
|
||||
import path from 'path';
|
||||
import type { T, BabelAPI } from './babelBundle';
|
||||
import { types, declare, traverse } from './babelBundle';
|
||||
import { js2ts } from './transform';
|
||||
const t: typeof T = types;
|
||||
|
||||
const fullNames = new Map<string, string | undefined>();
|
||||
@ -173,7 +174,11 @@ export type ComponentInfo = {
|
||||
|
||||
export function componentInfo(specifier: T.ImportSpecifier | T.ImportDefaultSpecifier, importSource: string, filename: string): ComponentInfo {
|
||||
const isModuleOrAlias = !importSource.startsWith('.');
|
||||
const importPath = isModuleOrAlias ? importSource : require.resolve(path.resolve(path.dirname(filename), importSource));
|
||||
const unresolvedImportPath = path.resolve(path.dirname(filename), importSource);
|
||||
// Support following notations for Button.tsx:
|
||||
// - import { Button } from './Button.js' - via js2ts, it handles tsx too
|
||||
// - import { Button } from './Button' - via require.resolve
|
||||
const importPath = isModuleOrAlias ? importSource : js2ts(unresolvedImportPath) || require.resolve(unresolvedImportPath);
|
||||
const prefix = importPath.replace(/[^\w_\d]/g, '_');
|
||||
const pathInfo = { importPath, isModuleOrAlias };
|
||||
|
||||
|
||||
@ -209,3 +209,72 @@ test('should filter by line', async ({ runInlineTest, nodeVersion }) => {
|
||||
expect(result.failed).toBe(1);
|
||||
expect(result.output).toMatch(/x\.spec\.ts.*two/);
|
||||
});
|
||||
|
||||
test('should resolve .js import to .ts file in ESM mode', async ({ runInlineTest, nodeVersion }) => {
|
||||
test.skip(nodeVersion.major < 16);
|
||||
const result = await runInlineTest({
|
||||
'package.json': `{ "type": "module" }`,
|
||||
'playwright.config.ts': `export default { projects: [{name: 'foo'}] };`,
|
||||
'a.test.ts': `
|
||||
const { test } = pwt;
|
||||
import { gimmeAOne } from './playwright-utils.js';
|
||||
test('pass', ({}) => {
|
||||
expect(gimmeAOne()).toBe(1);
|
||||
});
|
||||
`,
|
||||
'playwright-utils.ts': `
|
||||
export function gimmeAOne() {
|
||||
return 1;
|
||||
}
|
||||
`,
|
||||
});
|
||||
expect(result.passed).toBe(1);
|
||||
expect(result.exitCode).toBe(0);
|
||||
});
|
||||
|
||||
test('should resolve .js import to .tsx file in ESM mode', async ({ runInlineTest, nodeVersion }) => {
|
||||
test.skip(nodeVersion.major < 16);
|
||||
const result = await runInlineTest({
|
||||
'package.json': `{ "type": "module" }`,
|
||||
'playwright.config.ts': `export default { projects: [{name: 'foo'}] };`,
|
||||
'a.test.ts': `
|
||||
const { test } = pwt;
|
||||
import { gimmeAOne } from './playwright-utils.js';
|
||||
test('pass', ({}) => {
|
||||
expect(gimmeAOne()).toBe(1);
|
||||
});
|
||||
`,
|
||||
'playwright-utils.tsx': `
|
||||
export function gimmeAOne() {
|
||||
return 1;
|
||||
}
|
||||
`,
|
||||
});
|
||||
expect(result.passed).toBe(1);
|
||||
expect(result.exitCode).toBe(0);
|
||||
});
|
||||
|
||||
test('should resolve .js import to .tsx file in ESM mode for components', async ({ runInlineTest, nodeVersion }) => {
|
||||
test.skip(nodeVersion.major < 16);
|
||||
const result = await runInlineTest({
|
||||
'package.json': `{ "type": "module" }`,
|
||||
'playwright.config.ts': `export default { projects: [{name: 'foo'}] };`,
|
||||
'playwright/index.html': `<script type="module" src="./index.ts"></script>`,
|
||||
'playwright/index.ts': ``,
|
||||
|
||||
'src/button.tsx': `
|
||||
export const Button = () => <button>Button</button>;
|
||||
`,
|
||||
|
||||
'src/test.spec.tsx': `
|
||||
//@no-header
|
||||
import { test, expect } from '@playwright/experimental-ct-react';
|
||||
import { Button } from './button.js';
|
||||
test('pass', async ({ mount }) => {
|
||||
await mount(<Button></Button>);
|
||||
});
|
||||
`,
|
||||
}, { workers: 1 });
|
||||
expect(result.passed).toBe(1);
|
||||
expect(result.exitCode).toBe(0);
|
||||
});
|
||||
|
||||
@ -542,6 +542,47 @@ test('should resolve .js import to .ts file in non-ESM mode', async ({ runInline
|
||||
expect(result.exitCode).toBe(0);
|
||||
});
|
||||
|
||||
test('should resolve .js import to .tsx file in non-ESM mode', async ({ runInlineTest }) => {
|
||||
const result = await runInlineTest({
|
||||
'a.test.ts': `
|
||||
const { test } = pwt;
|
||||
import { gimmeAOne } from './playwright-utils.js';
|
||||
test('pass', ({}) => {
|
||||
expect(gimmeAOne()).toBe(1);
|
||||
});
|
||||
`,
|
||||
'playwright-utils.tsx': `
|
||||
export function gimmeAOne() {
|
||||
return 1;
|
||||
}
|
||||
`,
|
||||
});
|
||||
expect(result.passed).toBe(1);
|
||||
expect(result.exitCode).toBe(0);
|
||||
});
|
||||
|
||||
test('should resolve .js import to .tsx file in non-ESM mode for components', async ({ runInlineTest }) => {
|
||||
const result = await runInlineTest({
|
||||
'playwright/index.html': `<script type="module" src="./index.ts"></script>`,
|
||||
'playwright/index.ts': ``,
|
||||
|
||||
'src/button.tsx': `
|
||||
export const Button = () => <button>Button</button>;
|
||||
`,
|
||||
|
||||
'src/test.spec.tsx': `
|
||||
//@no-header
|
||||
import { test, expect } from '@playwright/experimental-ct-react';
|
||||
import { Button } from './button.js';
|
||||
test('pass', async ({ mount }) => {
|
||||
await mount(<Button></Button>);
|
||||
});
|
||||
`,
|
||||
}, { workers: 1 });
|
||||
expect(result.passed).toBe(1);
|
||||
expect(result.exitCode).toBe(0);
|
||||
});
|
||||
|
||||
test('should import export assignment from ts', async ({ runInlineTest }) => {
|
||||
const result = await runInlineTest({
|
||||
'a.test.ts': `
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user