fix(test runner): avoid dependency tracking colliding between esm and cjs
When collecting dependencies both from CJS loader and from ESM loader, the latter would overwrite the dependencies set instead of appending. Also make sure cts/cjs/mts/mjs are all supported equally.
This commit is contained in:
parent
0db1d40abc
commit
1dcc04bb6a
|
|
@ -15,7 +15,7 @@
|
|||
*/
|
||||
|
||||
import util from 'util';
|
||||
import { serializeCompilationCache } from '../transform/compilationCache';
|
||||
import { type SerializedCompilationCache, serializeCompilationCache } from '../transform/compilationCache';
|
||||
import type { ConfigLocation, FullConfigInternal } from './config';
|
||||
import type { ReporterDescription, TestInfoError, TestStatus } from '../../types/test';
|
||||
|
||||
|
|
@ -43,7 +43,7 @@ export type ConfigCLIOverrides = {
|
|||
export type SerializedConfig = {
|
||||
location: ConfigLocation;
|
||||
configCLIOverrides: ConfigCLIOverrides;
|
||||
compilationCache: any;
|
||||
compilationCache?: SerializedCompilationCache;
|
||||
};
|
||||
|
||||
export type TtyParams = {
|
||||
|
|
|
|||
|
|
@ -27,7 +27,7 @@ export type MemoryCache = {
|
|||
moduleUrl?: string;
|
||||
};
|
||||
|
||||
type SerializedCompilationCache = {
|
||||
export type SerializedCompilationCache = {
|
||||
sourceMaps: [string, string][],
|
||||
memoryCache: [string, MemoryCache][],
|
||||
fileDependencies: [string, string[]][],
|
||||
|
|
@ -158,15 +158,19 @@ export function serializeCompilationCache(): SerializedCompilationCache {
|
|||
};
|
||||
}
|
||||
|
||||
export function addToCompilationCache(payload: any) {
|
||||
export function addToCompilationCache(payload: SerializedCompilationCache) {
|
||||
for (const entry of payload.sourceMaps)
|
||||
sourceMaps.set(entry[0], entry[1]);
|
||||
for (const entry of payload.memoryCache)
|
||||
memoryCache.set(entry[0], entry[1]);
|
||||
for (const entry of payload.fileDependencies)
|
||||
fileDependencies.set(entry[0], new Set(entry[1]));
|
||||
for (const entry of payload.externalDependencies)
|
||||
externalDependencies.set(entry[0], new Set(entry[1]));
|
||||
for (const entry of payload.fileDependencies) {
|
||||
const existing = fileDependencies.get(entry[0]) || [];
|
||||
fileDependencies.set(entry[0], new Set([...entry[1], ...existing]));
|
||||
}
|
||||
for (const entry of payload.externalDependencies) {
|
||||
const existing = externalDependencies.get(entry[0]) || [];
|
||||
externalDependencies.set(entry[0], new Set([...entry[1], ...existing]));
|
||||
}
|
||||
}
|
||||
|
||||
function calculateCachePath(filePath: string, hash: string): string {
|
||||
|
|
@ -249,9 +253,9 @@ const kPlaywrightCoveragePrefix = path.resolve(__dirname, '../../../../tests/con
|
|||
export function belongsToNodeModules(file: string) {
|
||||
if (file.includes(`${path.sep}node_modules${path.sep}`))
|
||||
return true;
|
||||
if (file.startsWith(kPlaywrightInternalPrefix) && file.endsWith('.js'))
|
||||
if (file.startsWith(kPlaywrightInternalPrefix) && (file.endsWith('.js') || file.endsWith('.mjs')))
|
||||
return true;
|
||||
if (file.startsWith(kPlaywrightCoveragePrefix) && file.endsWith('.js'))
|
||||
if (file.startsWith(kPlaywrightCoveragePrefix) && (file.endsWith('.js') || file.endsWith('.mjs')))
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -240,7 +240,7 @@ function installTransform(): () => void {
|
|||
if (!shouldTransform(filename))
|
||||
return code;
|
||||
return transformHook(code, filename).code;
|
||||
}, { exts: ['.ts', '.tsx', '.js', '.jsx', '.mjs'] });
|
||||
}, { exts: ['.ts', '.tsx', '.js', '.jsx', '.mjs', '.mts', '.cjs', '.cts'] });
|
||||
|
||||
return () => {
|
||||
reverted = true;
|
||||
|
|
|
|||
|
|
@ -171,7 +171,7 @@ export class TestInfoImpl implements TestInfo {
|
|||
this._timeoutManager = new TimeoutManager(this.project.timeout);
|
||||
|
||||
this.outputDir = (() => {
|
||||
const relativeTestFilePath = path.relative(this.project.testDir, this._requireFile.replace(/\.(spec|test)\.(js|ts|mjs)$/, ''));
|
||||
const relativeTestFilePath = path.relative(this.project.testDir, this._requireFile.replace(/\.(spec|test)\.(js|ts|jsx|tsx|mjs|mts|cjs|cts)$/, ''));
|
||||
const sanitizedRelativePath = relativeTestFilePath.replace(process.platform === 'win32' ? new RegExp('\\\\', 'g') : new RegExp('/', 'g'), '-');
|
||||
const fullTitleWithoutSpec = this.titlePath.slice(1).join(' ');
|
||||
|
||||
|
|
|
|||
|
|
@ -91,8 +91,85 @@ test('should print dependencies in ESM mode', async ({ runInlineTest }) => {
|
|||
const output = result.output;
|
||||
const deps = JSON.parse(output.match(/###(.*)###/)![1]);
|
||||
expect(deps).toEqual({
|
||||
'a.test.ts': ['helperA.ts', 'index.mjs'],
|
||||
'b.test.ts': ['helperA.ts', 'helperB.ts', 'index.mjs'],
|
||||
'a.test.ts': ['helperA.ts'],
|
||||
'b.test.ts': ['helperA.ts', 'helperB.ts'],
|
||||
});
|
||||
});
|
||||
|
||||
test('should print dependencies in mixed CJS/ESM mode 1', async ({ runInlineTest }) => {
|
||||
const result = await runInlineTest({
|
||||
'package.json': `{ "type": "module" }`,
|
||||
'playwright.config.ts': `
|
||||
import { defineConfig } from '@playwright/test';
|
||||
export default defineConfig({
|
||||
globalTeardown: './globalTeardown.ts',
|
||||
});
|
||||
`,
|
||||
'helperA.cjs': `exports.foo = () => {}`,
|
||||
'helperB.cjs': `require('./helperA');`,
|
||||
'a.test.ts': `
|
||||
import './helperA';
|
||||
import { test, expect } from '@playwright/test';
|
||||
test('passes', () => {});
|
||||
`,
|
||||
'b.test.cjs': `
|
||||
require('./helperB');
|
||||
const { test, expect } = require('@playwright/test');
|
||||
test('passes', () => {});
|
||||
`,
|
||||
'globalTeardown.ts': `
|
||||
import { fileDependencies } from 'playwright/lib/internalsForTest';
|
||||
export default () => {
|
||||
console.log('###' + JSON.stringify(fileDependencies()) + '###');
|
||||
};
|
||||
`
|
||||
}, {});
|
||||
|
||||
expect(result.exitCode).toBe(0);
|
||||
expect(result.passed).toBe(2);
|
||||
const output = result.output;
|
||||
const deps = JSON.parse(output.match(/###(.*)###/)![1]);
|
||||
expect(deps).toEqual({
|
||||
'a.test.ts': ['helperA.cjs'],
|
||||
'b.test.cjs': ['helperA.cjs', 'helperB.cjs'],
|
||||
});
|
||||
});
|
||||
|
||||
test('should print dependencies in mixed CJS/ESM mode 2', async ({ runInlineTest }) => {
|
||||
const result = await runInlineTest({
|
||||
'playwright.config.mts': `
|
||||
import { defineConfig } from '@playwright/test';
|
||||
export default defineConfig({
|
||||
globalTeardown: './globalTeardown.ts',
|
||||
});
|
||||
`,
|
||||
'helperA.cjs': `exports.foo = () => {}`,
|
||||
'helperB.cts': `import './helperA';`,
|
||||
'a.test.mts': `
|
||||
import './helperA';
|
||||
import { test, expect } from '@playwright/test';
|
||||
test('passes', () => {});
|
||||
`,
|
||||
'b.test.ts': `
|
||||
import './helperB';
|
||||
const { test, expect } = require('@playwright/test');
|
||||
test('passes', () => {});
|
||||
`,
|
||||
'globalTeardown.ts': `
|
||||
import { fileDependencies } from 'playwright/lib/internalsForTest';
|
||||
export default () => {
|
||||
console.log('###' + JSON.stringify(fileDependencies()) + '###');
|
||||
};
|
||||
`
|
||||
}, {});
|
||||
|
||||
expect(result.exitCode).toBe(0);
|
||||
expect(result.passed).toBe(2);
|
||||
const output = result.output;
|
||||
const deps = JSON.parse(output.match(/###(.*)###/)![1]);
|
||||
expect(deps).toEqual({
|
||||
'a.test.mts': ['helperA.cjs'],
|
||||
'b.test.ts': ['helperA.cjs', 'helperB.cts'],
|
||||
});
|
||||
});
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue