mirror of
https://github.com/microsoft/playwright.git
synced 2025-06-26 21:40:17 +00:00
chore: respect source map sources when filtering in CLI (#22180)
Fixes #22123
This commit is contained in:
parent
8bc7ed0469
commit
87acda74ff
@ -14,9 +14,7 @@
|
|||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import fs from 'fs';
|
|
||||||
import path from 'path';
|
import path from 'path';
|
||||||
import readline from 'readline';
|
|
||||||
import type { Reporter, TestError } from '../../types/testReporter';
|
import type { Reporter, TestError } from '../../types/testReporter';
|
||||||
import { InProcessLoaderHost, OutOfProcessLoaderHost } from './loaderHost';
|
import { InProcessLoaderHost, OutOfProcessLoaderHost } from './loaderHost';
|
||||||
import { Suite } from '../common/test';
|
import { Suite } from '../common/test';
|
||||||
@ -29,6 +27,8 @@ import { requireOrImport } from '../common/transform';
|
|||||||
import { buildFileSuiteForProject, filterByFocusedLine, filterByTestIds, filterOnly, filterTestsRemoveEmptySuites } from '../common/suiteUtils';
|
import { buildFileSuiteForProject, filterByFocusedLine, filterByTestIds, filterOnly, filterTestsRemoveEmptySuites } from '../common/suiteUtils';
|
||||||
import { createTestGroups, filterForShard, type TestGroup } from './testGroups';
|
import { createTestGroups, filterForShard, type TestGroup } from './testGroups';
|
||||||
import { dependenciesForTestFile } from '../common/compilationCache';
|
import { dependenciesForTestFile } from '../common/compilationCache';
|
||||||
|
import { sourceMapSupport } from '../utilsBundle';
|
||||||
|
import type { RawSourceMap } from 'source-map';
|
||||||
|
|
||||||
export async function collectProjectsAndTestFiles(config: FullConfigInternal, projectsToIgnore: Set<FullProjectInternal>, additionalFileMatcher: Matcher | undefined) {
|
export async function collectProjectsAndTestFiles(config: FullConfigInternal, projectsToIgnore: Set<FullProjectInternal>, additionalFileMatcher: Matcher | undefined) {
|
||||||
const fsCache = new Map();
|
const fsCache = new Map();
|
||||||
@ -47,15 +47,16 @@ export async function collectProjectsAndTestFiles(config: FullConfigInternal, pr
|
|||||||
// Filter files based on the file filters, eliminate the empty projects.
|
// Filter files based on the file filters, eliminate the empty projects.
|
||||||
const filesToRunByProject = new Map<FullProjectInternal, string[]>();
|
const filesToRunByProject = new Map<FullProjectInternal, string[]>();
|
||||||
for (const [project, files] of allFilesForProject) {
|
for (const [project, files] of allFilesForProject) {
|
||||||
const matchedFiles = await Promise.all(files.map(async file => {
|
const matchedFiles = files.filter(file => {
|
||||||
if (additionalFileMatcher && !additionalFileMatcher(file))
|
const hasMatchingSources = sourceMapSources(file, sourceMapCache).some(source => {
|
||||||
return;
|
if (additionalFileMatcher && !additionalFileMatcher(source))
|
||||||
if (cliFileMatcher) {
|
return false;
|
||||||
if (!cliFileMatcher(file) && !await isPotentiallyJavaScriptFileWithSourceMap(file, sourceMapCache))
|
if (cliFileMatcher && !cliFileMatcher(source))
|
||||||
return;
|
return false;
|
||||||
}
|
return true;
|
||||||
return file;
|
});
|
||||||
}));
|
return hasMatchingSources;
|
||||||
|
});
|
||||||
const filteredFiles = matchedFiles.filter(Boolean) as string[];
|
const filteredFiles = matchedFiles.filter(Boolean) as string[];
|
||||||
if (filteredFiles.length)
|
if (filteredFiles.length)
|
||||||
filesToRunByProject.set(project, filteredFiles);
|
filesToRunByProject.set(project, filteredFiles);
|
||||||
@ -263,29 +264,20 @@ export function loadReporter(config: FullConfigInternal, file: string): Promise<
|
|||||||
return requireOrImportDefaultFunction(path.resolve(config.rootDir, file), true);
|
return requireOrImportDefaultFunction(path.resolve(config.rootDir, file), true);
|
||||||
}
|
}
|
||||||
|
|
||||||
async function isPotentiallyJavaScriptFileWithSourceMap(file: string, cache: Map<string, boolean>): Promise<boolean> {
|
function sourceMapSources(file: string, cache: Map<string, string[]>): string[] {
|
||||||
|
let sources = [file];
|
||||||
if (!file.endsWith('.js'))
|
if (!file.endsWith('.js'))
|
||||||
return false;
|
return sources;
|
||||||
if (cache.has(file))
|
if (cache.has(file))
|
||||||
return cache.get(file)!;
|
return cache.get(file)!;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const stream = fs.createReadStream(file);
|
const sourceMap = sourceMapSupport.retrieveSourceMap(file);
|
||||||
const rl = readline.createInterface({ input: stream, crlfDelay: Infinity });
|
const sourceMapData: RawSourceMap | undefined = typeof sourceMap?.map === 'string' ? JSON.parse(sourceMap.map) : sourceMap?.map;
|
||||||
let lastLine: string | undefined;
|
if (sourceMapData?.sources)
|
||||||
rl.on('line', line => {
|
sources = sourceMapData.sources.map(source => path.resolve(path.dirname(file), source));
|
||||||
lastLine = line;
|
} finally {
|
||||||
});
|
cache.set(file, sources);
|
||||||
await new Promise((fulfill, reject) => {
|
return sources;
|
||||||
rl.on('close', fulfill);
|
|
||||||
rl.on('error', reject);
|
|
||||||
stream.on('error', reject);
|
|
||||||
});
|
|
||||||
const hasSourceMap = !!lastLine && lastLine.startsWith('//# sourceMappingURL=');
|
|
||||||
cache.set(file, hasSourceMap);
|
|
||||||
return hasSourceMap;
|
|
||||||
} catch (e) {
|
|
||||||
cache.set(file, true);
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -503,21 +503,26 @@ test('should not load tests not matching filter', async ({ runInlineTest }) => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
test('should filter by sourcemapped file names', async ({ runInlineTest }) => {
|
test('should filter by sourcemapped file names', async ({ runInlineTest }) => {
|
||||||
const fileWithSourceMap = `` +
|
|
||||||
`import {test} from '@playwright/test';
|
|
||||||
test.describe('Some describe', ()=>{
|
|
||||||
test('Some test', async ()=>{
|
|
||||||
console.log('test')
|
|
||||||
})
|
|
||||||
})
|
|
||||||
//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbImdoZXJraW4uZmVhdHVyZSJdLCJuYW1lcyI6WyJOb25lIl0sIm1hcHBpbmdzIjoiQUFBQUE7QUFBQUE7QUFBQUE7QUFBQUE7QUFBQUE7QUFBQUEiLCJmaWxlIjoiZ2hlcmtpbi5mZWF0dXJlIiwic291cmNlc0NvbnRlbnQiOlsiVGVzdCJdfQ==`;
|
|
||||||
|
|
||||||
const result = await runInlineTest({
|
const result = await runInlineTest({
|
||||||
'playwright.config.js': `export default { projects: [{}, {}] }`,
|
'gherkin.spec.js': `
|
||||||
'a.spec.js': fileWithSourceMap,
|
|
||||||
|
import { test } from '@playwright/test';
|
||||||
|
test('should run', () => {});
|
||||||
|
//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbImdoZXJraW4uZmVhdHVyZSJdLCJuYW1lcyI6WyJOb25lIl0sIm1hcHBpbmdzIjoiQUFBQUE7QUFBQUE7QUFBQUE7QUFBQUE7QUFBQUE7QUFBQUEiLCJmaWxlIjoiZ2hlcmtpbi5mZWF0dXJlIiwic291cmNlc0NvbnRlbnQiOlsiVGVzdCJdfQ==`,
|
||||||
|
|
||||||
|
'another.spec.js': `
|
||||||
|
|
||||||
|
throw new Error('should not load another.spec.js');
|
||||||
|
//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbImFub3RoZXIuZmVhdHVyZSJdLCJuYW1lcyI6WyJOb25lIl0sIm1hcHBpbmdzIjoiQUFBQUE7QUFBQUE7QUFBQUE7QUFBQUE7QUFBQUE7QUFBQUEiLCJmaWxlIjoiZ2hlcmtpbi5mZWF0dXJlIiwic291cmNlc0NvbnRlbnQiOlsiVGVzdCJdfQ==`,
|
||||||
|
|
||||||
|
'nomap.spec.js': `
|
||||||
|
|
||||||
|
throw new Error('should not load nomap.spec.js');`,
|
||||||
}, {}, {}, { additionalArgs: ['gherkin.feature'] });
|
}, {}, {}, { additionalArgs: ['gherkin.feature'] });
|
||||||
expect(result.exitCode).toBe(0);
|
expect(result.exitCode).toBe(0);
|
||||||
expect(result.passed).toBe(2);
|
expect(result.passed).toBe(1);
|
||||||
expect(result.output).not.toContain('a.spec.js');
|
expect(result.output).not.toContain('spec.js');
|
||||||
|
expect(result.output).not.toContain('another.feature.js');
|
||||||
|
expect(result.output).not.toContain('should not load');
|
||||||
expect(result.output).toContain('gherkin.feature:1');
|
expect(result.output).toContain('gherkin.feature:1');
|
||||||
});
|
});
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user