chore: reuse createReporters in the merger (#22636)

#10437
This commit is contained in:
Yury Semikhatsky 2023-04-26 11:48:19 -07:00 committed by GitHub
parent 7fdd7a20fb
commit 9ad9b6b316
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
6 changed files with 25 additions and 51 deletions

View file

@ -179,6 +179,8 @@ async function mergeReports(reportDir: string | undefined, opts: { [key: string]
const configLoader = new ConfigLoader();
const config = await (configFile ? configLoader.loadConfigFile(configFile) : configLoader.loadEmptyConfig(process.cwd()));
const dir = path.resolve(process.cwd(), reportDir || 'playwright-report');
if (!(await fs.promises.stat(dir)).isDirectory())
throw new Error('Directory does not exist: ' + dir);
await createMergedReport(config, dir, opts.reporter || 'list');
}

View file

@ -5,4 +5,4 @@
../utilsBundle.ts
[blob.ts]
../runner/loadUtils.ts
../runner/reporters.ts

View file

@ -16,25 +16,18 @@
import type { EventEmitter } from 'events';
import fs from 'fs';
import path from 'path';
import os from 'os';
import path from 'path';
import { ManualPromise, ZipFile, calculateSha1, removeFolders } from 'playwright-core/lib/utils';
import { mime } from 'playwright-core/lib/utilsBundle';
import { yazl } from 'playwright-core/lib/zipBundle';
import { Readable } from 'stream';
import type { FullConfig, FullResult, Reporter, TestResult } from '../../types/testReporter';
import type { BuiltInReporter, FullConfigInternal } from '../common/config';
import type { FullConfig, FullResult, TestResult } from '../../types/testReporter';
import type { FullConfigInternal } from '../common/config';
import type { Suite } from '../common/test';
import { TeleReporterReceiver, type JsonEvent, type JsonProject, type JsonSuite, type JsonTestResultEnd } from '../isomorphic/teleReceiver';
import DotReporter from '../reporters/dot';
import EmptyReporter from '../reporters/empty';
import GitHubReporter from '../reporters/github';
import JSONReporter from '../reporters/json';
import JUnitReporter from '../reporters/junit';
import LineReporter from '../reporters/line';
import ListReporter from '../reporters/list';
import { loadReporter } from '../runner/loadUtils';
import HtmlReporter, { defaultReportFolder } from './html';
import { createReporters } from '../runner/reporters';
import { defaultReportFolder } from './html';
import { TeleReporterEmitter } from './teleEmitter';
@ -120,40 +113,15 @@ export async function createMergedReport(config: FullConfigInternal, dir: string
const events = mergeEvents(shardReports);
patchAttachmentPaths(events, resourceDir);
const defaultReporters: {[key in BuiltInReporter]: new(arg: any) => Reporter} = {
dot: DotReporter,
line: LineReporter,
list: ListReporter,
github: GitHubReporter,
json: JSONReporter,
junit: JUnitReporter,
null: EmptyReporter,
html: HtmlReporter,
blob: BlobReporter,
};
reporterName ??= 'list';
const arg = config.config.reporter.find(([reporter, arg]) => reporter === reporterName)?.[1];
const options = {
...arg,
configDir: process.cwd(),
};
let reporter: Reporter | undefined;
if (reporterName in defaultReporters) {
reporter = new defaultReporters[reporterName as keyof typeof defaultReporters](options);
} else {
const reporterConstructor = await loadReporter(config, reporterName);
reporter = new reporterConstructor(options);
}
const receiver = new TeleReporterReceiver(path.sep, reporter);
const reporters = await createReporters(config, 'merge', [reporterName]);
const receiver = new TeleReporterReceiver(path.sep, reporters[0]);
for (const event of events)
await receiver.dispatch(event);
} finally {
await removeFolders([resourceDir]);
}
console.log(`Done.`);
}
async function extractReports(dir: string, shardFiles: string[], resourceDir: string): Promise<string[]> {

View file

@ -25,13 +25,13 @@ import JSONReporter from '../reporters/json';
import JUnitReporter from '../reporters/junit';
import LineReporter from '../reporters/line';
import ListReporter from '../reporters/list';
import { Multiplexer } from '../reporters/multiplexer';
import type { Suite } from '../common/test';
import type { BuiltInReporter, FullConfigInternal } from '../common/config';
import { loadReporter } from './loadUtils';
import { BlobReporter } from '../reporters/blob';
import type { ReporterDescription } from '../../types/test';
export async function createReporter(config: FullConfigInternal, mode: 'list' | 'run' | 'ui', additionalReporters: Reporter[] = []): Promise<Multiplexer> {
export async function createReporters(config: FullConfigInternal, mode: 'list' | 'run' | 'ui' | 'merge', reporterNames?: string[]): Promise<Reporter[]> {
const defaultReporters: {[key in BuiltInReporter]: new(arg: any) => Reporter} = {
dot: mode === 'list' ? ListModeReporter : DotReporter,
line: mode === 'list' ? ListModeReporter : LineReporter,
@ -44,7 +44,10 @@ export async function createReporter(config: FullConfigInternal, mode: 'list' |
blob: BlobReporter,
};
const reporters: Reporter[] = [];
for (const r of config.config.reporter) {
const descriptions: ReporterDescription[] = reporterNames ?
reporterNames.map(name => [name, config.config.reporter.find(([reporterName]) => reporterName === name)]) :
config.config.reporter;
for (const r of descriptions) {
const [name, arg] = r;
const options = { ...arg, configDir: config.configDir };
if (name in defaultReporters) {
@ -54,7 +57,6 @@ export async function createReporter(config: FullConfigInternal, mode: 'list' |
reporters.push(new reporterConstructor(options));
}
}
reporters.push(...additionalReporters);
if (process.env.PW_TEST_REPORTER) {
const reporterConstructor = await loadReporter(config, process.env.PW_TEST_REPORTER);
reporters.push(new reporterConstructor());
@ -64,7 +66,7 @@ export async function createReporter(config: FullConfigInternal, mode: 'list' |
const prints = r.printsToStdio ? r.printsToStdio() : true;
return prints;
});
if (reporters.length && !someReporterPrintsToStdio) {
if (reporters.length && !someReporterPrintsToStdio && mode !== 'merge') {
// Add a line/dot/list-mode reporter for convenience.
// Important to put it first, jsut in case some other reporter stalls onEnd.
if (mode === 'list')
@ -72,7 +74,7 @@ export async function createReporter(config: FullConfigInternal, mode: 'list' |
else
reporters.unshift(!process.env.CI ? new LineReporter({ omitFailures: true }) : new DotReporter());
}
return new Multiplexer(reporters);
return reporters;
}
export class ListModeReporter implements Reporter {

View file

@ -19,12 +19,13 @@ import { monotonicTime } from 'playwright-core/lib/utils';
import type { FullResult } from '../../types/testReporter';
import { webServerPluginsForConfig } from '../plugins/webServerPlugin';
import { collectFilesForProject, filterProjects } from './projectUtils';
import { createReporter } from './reporters';
import { createReporters } from './reporters';
import { TestRun, createTaskRunner, createTaskRunnerForList } from './tasks';
import type { FullConfigInternal } from '../common/config';
import { colors } from 'playwright-core/lib/utilsBundle';
import { runWatchModeLoop } from './watchMode';
import { runUIMode } from './uiMode';
import { Multiplexer } from '../reporters/multiplexer';
export class Runner {
private _config: FullConfigInternal;
@ -68,7 +69,7 @@ export class Runner {
// Legacy webServer support.
webServerPluginsForConfig(config).forEach(p => config.plugins.push({ factory: p }));
const reporter = await createReporter(config, listOnly ? 'list' : 'run');
const reporter = new Multiplexer(await createReporters(config, listOnly ? 'list' : 'run'));
const taskRunner = listOnly ? createTaskRunnerForList(config, reporter, 'in-process')
: createTaskRunner(config, reporter);

View file

@ -22,7 +22,7 @@ import { clearCompilationCache, collectAffectedTestFiles, dependenciesForTestFil
import type { FullConfigInternal } from '../common/config';
import { Multiplexer } from '../reporters/multiplexer';
import { TeleReporterEmitter } from '../reporters/teleEmitter';
import { createReporter } from './reporters';
import { createReporters } from './reporters';
import { TestRun, createTaskRunnerForList, createTaskRunnerForWatch, createTaskRunnerForWatchSetup } from './tasks';
import { chokidar } from '../utilsBundle';
import type { FSWatcher } from 'chokidar';
@ -167,8 +167,9 @@ class UIMode {
this._config.cliListOnly = false;
this._config.testIdMatcher = id => !testIdSet || testIdSet.has(id);
const runReporter = new TeleReporterEmitter(e => this._dispatchEvent(e));
const reporter = await createReporter(this._config, 'ui', [runReporter]);
const reporters = await createReporters(this._config, 'ui');
reporters.push(new TeleReporterEmitter(e => this._dispatchEvent(e)));
const reporter = new Multiplexer(reporters);
const taskRunner = createTaskRunnerForWatch(this._config, reporter);
const testRun = new TestRun(this._config, reporter);
clearCompilationCache();