fix(test-runner): accept unix separators even on windows (#8881)

.
This commit is contained in:
Joel Einbinder 2021-09-13 12:09:38 -04:00 committed by GitHub
parent 5953472899
commit bf35da3656
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 62 additions and 11 deletions

4
package-lock.json generated
View File

@ -8894,6 +8894,7 @@
},
"node_modules/socksv5/node_modules/ipv6": {
"version": "3.1.1",
"resolved": "https://registry.npmjs.org/ipv6/-/ipv6-3.1.1.tgz",
"dev": true,
"inBundle": true,
"license": "MIT",
@ -8912,6 +8913,7 @@
},
"node_modules/socksv5/node_modules/ipv6/node_modules/sprintf": {
"version": "0.1.3",
"resolved": "https://registry.npmjs.org/sprintf/-/sprintf-0.1.3.tgz",
"dev": true,
"inBundle": true,
"engines": {
@ -17858,6 +17860,7 @@
"dependencies": {
"ipv6": {
"version": "3.1.1",
"resolved": "https://registry.npmjs.org/ipv6/-/ipv6-3.1.1.tgz",
"bundled": true,
"dev": true,
"requires": {
@ -17868,6 +17871,7 @@
"dependencies": {
"sprintf": {
"version": "0.1.3",
"resolved": "https://registry.npmjs.org/sprintf/-/sprintf-0.1.3.tgz",
"bundled": true,
"dev": true
}

View File

@ -21,7 +21,7 @@ import * as fs from 'fs';
import * as path from 'path';
import { promisify } from 'util';
import { Dispatcher, TestGroup } from './dispatcher';
import { createMatcher, FilePatternFilter, monotonicTime } from './util';
import { createFileMatcher, createTitleMatcher, FilePatternFilter, monotonicTime } from './util';
import { TestCase, Suite } from './test';
import { Loader } from './loader';
import { Reporter } from '../../types/testReporter';
@ -131,7 +131,7 @@ export class Runner {
}
async _run(list: boolean, testFileReFilters: FilePatternFilter[], projectNames?: string[]): Promise<RunResult> {
const testFileFilter = testFileReFilters.length ? createMatcher(testFileReFilters.map(e => e.re)) : () => true;
const testFileFilter = testFileReFilters.length ? createFileMatcher(testFileReFilters.map(e => e.re)) : () => true;
const config = this._loader.fullConfig();
let projectsToFind: Set<string> | undefined;
@ -169,8 +169,8 @@ export class Runner {
if (!fs.statSync(testDir).isDirectory())
throw new Error(`${testDir} is not a directory`);
const allFiles = await collectFiles(project.config.testDir);
const testMatch = createMatcher(project.config.testMatch);
const testIgnore = createMatcher(project.config.testIgnore);
const testMatch = createFileMatcher(project.config.testMatch);
const testIgnore = createFileMatcher(project.config.testIgnore);
const testFileExtension = (file: string) => ['.js', '.ts', '.mjs'].includes(path.extname(file));
const testFiles = allFiles.filter(file => !testIgnore(file) && testMatch(file) && testFileFilter(file) && testFileExtension(file));
files.set(project, testFiles);
@ -210,8 +210,8 @@ export class Runner {
fileSuites.set(fileSuite._requireFile, fileSuite);
const outputDirs = new Set<string>();
const grepMatcher = createMatcher(config.grep);
const grepInvertMatcher = config.grepInvert ? createMatcher(config.grepInvert) : null;
const grepMatcher = createTitleMatcher(config.grep);
const grepInvertMatcher = config.grepInvert ? createTitleMatcher(config.grepInvert) : null;
const rootSuite = new Suite('');
for (const project of projects) {
const projectSuite = new Suite(project.config.name);

View File

@ -17,6 +17,7 @@
import type { TestInfoImpl } from './types';
import util from 'util';
import path from 'path';
import url from 'url';
import type { TestError, Location } from './types';
import { default as minimatch } from 'minimatch';
import { errors } from '../..';
@ -91,7 +92,7 @@ export type FilePatternFilter = {
line: number | null;
};
export function createMatcher(patterns: string | RegExp | (string | RegExp)[]): Matcher {
export function createFileMatcher(patterns: string | RegExp | (string | RegExp)[]): Matcher {
const reList: RegExp[] = [];
const filePatterns: string[] = [];
for (const pattern of Array.isArray(patterns) ? patterns : [patterns]) {
@ -104,17 +105,38 @@ export function createMatcher(patterns: string | RegExp | (string | RegExp)[]):
filePatterns.push(pattern);
}
}
return (filePath: string) => {
for (const re of reList) {
re.lastIndex = 0;
if (re.test(filePath))
return true;
}
// Windows might still recieve unix style paths from Cygwin or Git Bash.
// Check against the file url as well.
if (path.sep === '\\') {
const fileURL = url.pathToFileURL(filePath).href;
for (const re of reList) {
re.lastIndex = 0;
if (re.test(fileURL))
return true;
}
}
for (const pattern of filePatterns) {
if (minimatch(filePath, pattern, { nocase: true, dot: true }))
return true;
}
return false;
};
}
export function createTitleMatcher(patterns: RegExp | RegExp[]): Matcher {
const reList = Array.isArray(patterns) ? patterns : [patterns];
return (value: string) => {
for (const re of reList) {
re.lastIndex = 0;
if (re.test(value))
return true;
}
for (const pattern of filePatterns) {
if (minimatch(value, pattern, { nocase: true, dot: true }))
return true;
}
return false;
};
}

View File

@ -418,3 +418,28 @@ test('should match in dot-directories', async ({ runInlineTest }) => {
expect(result.report.suites.map(s => s.file).sort()).toEqual(['.dir/a.test.ts', '.dir/b.test.js']);
expect(result.exitCode).toBe(0);
});
test('should always work with unix separators', async ({ runInlineTest }) => {
// Cygwin or Git Bash might send us a path with unix separators.
const result = await runInlineTest({
'playwright.config.ts': `
import * as path from 'path';
module.exports = { testDir: path.join(__dirname, 'dir') };
`,
'dir/a.test.ts': `
const { test } = pwt;
test('pass', ({}) => {});
`,
'dir/b.test.ts': `
const { test } = pwt;
test('pass', ({}) => {});
`,
'a.test.ts': `
const { test } = pwt;
test('pass', ({}) => {});
`
}, { args: [`dir/a`] });
expect(result.passed).toBe(1);
expect(result.report.suites.map(s => s.file).sort()).toEqual(['a.test.ts']);
expect(result.exitCode).toBe(0);
});