mirror of
https://github.com/microsoft/playwright.git
synced 2025-06-26 21:40:17 +00:00
chore: implement lightweight test listing (#11551)
This commit is contained in:
parent
295d0a65c3
commit
baf0e5b47a
@ -246,6 +246,7 @@ if (!process.env.PW_CLI_TARGET_LANG) {
|
|||||||
if (playwrightTestPackagePath) {
|
if (playwrightTestPackagePath) {
|
||||||
require(playwrightTestPackagePath).addTestCommand(program);
|
require(playwrightTestPackagePath).addTestCommand(program);
|
||||||
require(playwrightTestPackagePath).addShowReportCommand(program);
|
require(playwrightTestPackagePath).addShowReportCommand(program);
|
||||||
|
require(playwrightTestPackagePath).addListTestsCommand(program);
|
||||||
} else {
|
} else {
|
||||||
{
|
{
|
||||||
const command = program.command('test').allowUnknownOption(true);
|
const command = program.command('test').allowUnknownOption(true);
|
||||||
|
|||||||
@ -73,6 +73,21 @@ Examples:
|
|||||||
$ npx playwright test --browser=webkit`);
|
$ npx playwright test --browser=webkit`);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function addListTestsCommand(program: Command) {
|
||||||
|
const command = program.command('list-tests [test-filter...]', { hidden: true });
|
||||||
|
command.description('List tests with Playwright Test');
|
||||||
|
command.option('-c, --config <file>', `Configuration file, or a test directory with optional ${kDefaultConfigFiles.map(file => `"${file}"`).join('/')}`);
|
||||||
|
command.option('--project <project-name...>', `Only run tests from the specified list of projects (default: list all projects)`);
|
||||||
|
command.action(async (args, opts) => {
|
||||||
|
try {
|
||||||
|
await listTests(opts);
|
||||||
|
} catch (e) {
|
||||||
|
console.error(e);
|
||||||
|
process.exit(1);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
export function addShowReportCommand(program: Command) {
|
export function addShowReportCommand(program: Command) {
|
||||||
const command = program.command('show-report [report]');
|
const command = program.command('show-report [report]');
|
||||||
command.description('show HTML report');
|
command.description('show HTML report');
|
||||||
@ -151,6 +166,16 @@ async function runTests(args: string[], opts: { [key: string]: any }) {
|
|||||||
process.exit(result.status === 'passed' ? 0 : 1);
|
process.exit(result.status === 'passed' ? 0 : 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
async function listTests(opts: { [key: string]: any }) {
|
||||||
|
const configFile = opts.config ? path.resolve(process.cwd(), opts.config) : process.cwd();
|
||||||
|
const runner = new Runner({}, { defaultConfig: {} });
|
||||||
|
await runner.loadConfigFromFile(configFile);
|
||||||
|
const report = await runner.listAllTestFiles(opts.project);
|
||||||
|
process.stdout.write(JSON.stringify(report));
|
||||||
|
process.exit(0);
|
||||||
|
}
|
||||||
|
|
||||||
function forceRegExp(pattern: string): RegExp {
|
function forceRegExp(pattern: string): RegExp {
|
||||||
const match = pattern.match(/^\/(.*)\/([gi]*)$/);
|
const match = pattern.match(/^\/(.*)\/([gi]*)$/);
|
||||||
if (match)
|
if (match)
|
||||||
|
|||||||
@ -163,10 +163,27 @@ export class Runner {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async _run(list: boolean, testFileReFilters: FilePatternFilter[], projectNames?: string[]): Promise<FullResult> {
|
async listAllTestFiles(projectNames: string[] | undefined): Promise<any> {
|
||||||
const testFileFilter = testFileReFilters.length ? createFileMatcher(testFileReFilters.map(e => e.re)) : () => true;
|
const filesByProject = await this._collectFiles([], projectNames);
|
||||||
const config = this._loader.fullConfig();
|
const report: any = {
|
||||||
|
projects: []
|
||||||
|
};
|
||||||
|
for (const [project, files] of filesByProject) {
|
||||||
|
report.projects.push({
|
||||||
|
name: project.config.name,
|
||||||
|
files: files
|
||||||
|
});
|
||||||
|
}
|
||||||
|
return report;
|
||||||
|
}
|
||||||
|
|
||||||
|
private async _run(list: boolean, testFileReFilters: FilePatternFilter[], projectNames?: string[]): Promise<FullResult> {
|
||||||
|
const filesByProject = await this._collectFiles(testFileReFilters, projectNames);
|
||||||
|
return await this._runFiles(list, filesByProject, testFileReFilters);
|
||||||
|
}
|
||||||
|
|
||||||
|
private async _collectFiles(testFileReFilters: FilePatternFilter[], projectNames?: string[]): Promise<Map<ProjectImpl, string[]>> {
|
||||||
|
const testFileFilter = testFileReFilters.length ? createFileMatcher(testFileReFilters.map(e => e.re)) : () => true;
|
||||||
let projectsToFind: Set<string> | undefined;
|
let projectsToFind: Set<string> | undefined;
|
||||||
let unknownProjects: Map<string, string> | undefined;
|
let unknownProjects: Map<string, string> | undefined;
|
||||||
if (projectNames) {
|
if (projectNames) {
|
||||||
@ -194,7 +211,6 @@ export class Runner {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const files = new Map<ProjectImpl, string[]>();
|
const files = new Map<ProjectImpl, string[]>();
|
||||||
const allTestFiles = new Set<string>();
|
|
||||||
for (const project of projects) {
|
for (const project of projects) {
|
||||||
const testDir = project.config.testDir;
|
const testDir = project.config.testDir;
|
||||||
if (!fs.existsSync(testDir))
|
if (!fs.existsSync(testDir))
|
||||||
@ -208,9 +224,16 @@ export class Runner {
|
|||||||
const testFileExtension = (file: string) => extensions.includes(path.extname(file));
|
const testFileExtension = (file: string) => extensions.includes(path.extname(file));
|
||||||
const testFiles = allFiles.filter(file => !testIgnore(file) && testMatch(file) && testFileFilter(file) && testFileExtension(file));
|
const testFiles = allFiles.filter(file => !testIgnore(file) && testMatch(file) && testFileFilter(file) && testFileExtension(file));
|
||||||
files.set(project, testFiles);
|
files.set(project, testFiles);
|
||||||
testFiles.forEach(file => allTestFiles.add(file));
|
|
||||||
}
|
}
|
||||||
|
return files;
|
||||||
|
}
|
||||||
|
|
||||||
|
private async _runFiles(list: boolean, filesByProject: Map<ProjectImpl, string[]>, testFileReFilters: FilePatternFilter[]): Promise<FullResult> {
|
||||||
|
const allTestFiles = new Set<string>();
|
||||||
|
for (const files of filesByProject.values())
|
||||||
|
files.forEach(file => allTestFiles.add(file));
|
||||||
|
|
||||||
|
const config = this._loader.fullConfig();
|
||||||
const internalGlobalTeardowns: (() => Promise<void>)[] = [];
|
const internalGlobalTeardowns: (() => Promise<void>)[] = [];
|
||||||
if (!list) {
|
if (!list) {
|
||||||
for (const internalGlobalSetup of this._internalGlobalSetups)
|
for (const internalGlobalSetup of this._internalGlobalSetups)
|
||||||
@ -257,11 +280,11 @@ export class Runner {
|
|||||||
const grepMatcher = createTitleMatcher(config.grep);
|
const grepMatcher = createTitleMatcher(config.grep);
|
||||||
const grepInvertMatcher = config.grepInvert ? createTitleMatcher(config.grepInvert) : null;
|
const grepInvertMatcher = config.grepInvert ? createTitleMatcher(config.grepInvert) : null;
|
||||||
const rootSuite = new Suite('');
|
const rootSuite = new Suite('');
|
||||||
for (const project of projects) {
|
for (const [project, files] of filesByProject) {
|
||||||
const projectSuite = new Suite(project.config.name);
|
const projectSuite = new Suite(project.config.name);
|
||||||
projectSuite._projectConfig = project.config;
|
projectSuite._projectConfig = project.config;
|
||||||
rootSuite._addSuite(projectSuite);
|
rootSuite._addSuite(projectSuite);
|
||||||
for (const file of files.get(project)!) {
|
for (const file of files) {
|
||||||
const fileSuite = fileSuites.get(file);
|
const fileSuite = fileSuites.get(file);
|
||||||
if (!fileSuite)
|
if (!fileSuite)
|
||||||
continue;
|
continue;
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user