chore: respect tsconfig paths in js files (#18191)
Fixes: https://github.com/microsoft/playwright/issues/17804
This commit is contained in:
parent
af38449f42
commit
ad9729f246
|
|
@ -37,6 +37,7 @@ interface Tsconfig {
|
|||
baseUrl?: string;
|
||||
paths?: { [key: string]: Array<string> };
|
||||
strict?: boolean;
|
||||
allowJs?: boolean;
|
||||
};
|
||||
}
|
||||
|
||||
|
|
@ -45,6 +46,7 @@ export interface TsConfigLoaderResult {
|
|||
baseUrl: string | undefined;
|
||||
paths: { [key: string]: Array<string> } | undefined;
|
||||
serialized: string | undefined;
|
||||
allowJs: boolean;
|
||||
}
|
||||
|
||||
export interface TsConfigLoaderParams {
|
||||
|
|
@ -72,6 +74,7 @@ function loadSyncDefault(
|
|||
baseUrl: undefined,
|
||||
paths: undefined,
|
||||
serialized: undefined,
|
||||
allowJs: false,
|
||||
};
|
||||
}
|
||||
const config = loadTsconfig(configPath);
|
||||
|
|
@ -82,6 +85,7 @@ function loadSyncDefault(
|
|||
(config && config.compilerOptions && config.compilerOptions.baseUrl),
|
||||
paths: config && config.compilerOptions && config.compilerOptions.paths,
|
||||
serialized: undefined,
|
||||
allowJs: !!config?.compilerOptions?.allowJs,
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -33,6 +33,7 @@ const sourceMaps: Map<string, string> = new Map();
|
|||
type ParsedTsConfigData = {
|
||||
absoluteBaseUrl: string;
|
||||
paths: { key: string, values: string[] }[];
|
||||
allowJs: boolean;
|
||||
};
|
||||
const cachedTSConfigs = new Map<string, ParsedTsConfigData | undefined>();
|
||||
|
||||
|
|
@ -73,7 +74,11 @@ function validateTsConfig(tsconfig: TsConfigLoaderResult): ParsedTsConfigData |
|
|||
// Make 'baseUrl' absolute, because it is relative to the tsconfig.json, not to cwd.
|
||||
const absoluteBaseUrl = path.resolve(path.dirname(tsconfig.tsConfigPath), tsconfig.baseUrl);
|
||||
const paths = tsconfig.paths || { '*': ['*'] };
|
||||
return { absoluteBaseUrl, paths: Object.entries(paths).map(([key, values]) => ({ key, values })) };
|
||||
return {
|
||||
allowJs: tsconfig.allowJs,
|
||||
absoluteBaseUrl,
|
||||
paths: Object.entries(paths).map(([key, values]) => ({ key, values }))
|
||||
};
|
||||
}
|
||||
|
||||
function loadAndValidateTsconfigForFile(file: string): ParsedTsConfigData | undefined {
|
||||
|
|
@ -95,9 +100,16 @@ const builtins = new Set(Module.builtinModules);
|
|||
export function resolveHook(isModule: boolean, filename: string, specifier: string): string | undefined {
|
||||
if (builtins.has(specifier))
|
||||
return;
|
||||
// In real life, playwright-test is under node_modules, but in the tests it isn't.
|
||||
if (filename.startsWith(kPlaywrightInternalPrefix))
|
||||
return;
|
||||
|
||||
if (isRelativeSpecifier(specifier))
|
||||
return isModule ? js2ts(path.resolve(path.dirname(filename), specifier)) : undefined;
|
||||
|
||||
const isTypeScript = filename.endsWith('.ts') || filename.endsWith('.tsx');
|
||||
const tsconfig = isTypeScript ? loadAndValidateTsconfigForFile(filename) : undefined;
|
||||
if (tsconfig && !isRelativeSpecifier(specifier)) {
|
||||
const tsconfig = loadAndValidateTsconfigForFile(filename);
|
||||
if (tsconfig && (isTypeScript || tsconfig.allowJs)) {
|
||||
let longestPrefixLength = -1;
|
||||
let pathMatchedByLongestPrefix: string | undefined;
|
||||
|
||||
|
|
|
|||
|
|
@ -14,7 +14,7 @@
|
|||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { test, expect } from './playwright-test-fixtures';
|
||||
import { test, expect, stripAnsi } from './playwright-test-fixtures';
|
||||
|
||||
test('should respect path resolver', async ({ runInlineTest }) => {
|
||||
test.info().annotations.push({ type: 'issue', description: 'https://github.com/microsoft/playwright/issues/11656' });
|
||||
|
|
@ -343,3 +343,58 @@ test('should not use baseurl for relative imports when dir with same name exists
|
|||
expect(result.output).not.toContain(`Could not`);
|
||||
expect(result.output).not.toContain(`Cannot`);
|
||||
});
|
||||
|
||||
test('should respect path resolver for JS files when allowJs', async ({ runInlineTest }) => {
|
||||
const result = await runInlineTest({
|
||||
'playwright.config.ts': `export default { projects: [{name: 'foo'}], };`,
|
||||
'tsconfig.json': `{
|
||||
"compilerOptions": {
|
||||
"allowJs": true,
|
||||
"baseUrl": ".",
|
||||
"paths": {
|
||||
"util/*": ["./foo/bar/util/*"],
|
||||
},
|
||||
},
|
||||
}`,
|
||||
'a.test.js': `
|
||||
const { foo } = require('util/b');
|
||||
const { test } = pwt;
|
||||
test('test', ({}, testInfo) => {
|
||||
expect(testInfo.project.name).toBe(foo);
|
||||
});
|
||||
`,
|
||||
'foo/bar/util/b.ts': `
|
||||
module.exports = { foo: 'foo' };
|
||||
`,
|
||||
});
|
||||
|
||||
expect(result.passed).toBe(1);
|
||||
expect(result.exitCode).toBe(0);
|
||||
});
|
||||
|
||||
test('should not respect path resolver for JS files w/o allowJS', async ({ runInlineTest }) => {
|
||||
const result = await runInlineTest({
|
||||
'playwright.config.ts': `export default { projects: [{name: 'foo'}], };`,
|
||||
'tsconfig.json': `{
|
||||
"compilerOptions": {
|
||||
"baseUrl": ".",
|
||||
"paths": {
|
||||
"util/*": ["./foo/bar/util/*"],
|
||||
},
|
||||
},
|
||||
}`,
|
||||
'a.test.js': `
|
||||
const { foo } = require('util/b');
|
||||
const { test } = pwt;
|
||||
test('test', ({}, testInfo) => {
|
||||
expect(testInfo.project.name).toBe(foo);
|
||||
});
|
||||
`,
|
||||
'foo/bar/util/b.ts': `
|
||||
module.exports = { foo: 'foo' };
|
||||
`,
|
||||
});
|
||||
|
||||
expect(stripAnsi(result.output)).toContain('Cannot find module \'util/b\'');
|
||||
expect(result.exitCode).toBe(1);
|
||||
});
|
||||
|
|
|
|||
Loading…
Reference in a new issue