fix: do not throw when merging into blob report (#26355)
We cannot import a Symbol to isomorphic code from config. Instead, __projectId property is used.
This commit is contained in:
parent
0f0045be94
commit
bc2c7946bb
|
|
@ -142,6 +142,7 @@ export class FullConfigInternal {
|
||||||
if (usedNames.has(candidate))
|
if (usedNames.has(candidate))
|
||||||
continue;
|
continue;
|
||||||
p.id = candidate;
|
p.id = candidate;
|
||||||
|
(p.project as any).__projectId = p.id;
|
||||||
usedNames.add(candidate);
|
usedNames.add(candidate);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
@ -160,10 +161,6 @@ export class FullProjectInternal {
|
||||||
deps: FullProjectInternal[] = [];
|
deps: FullProjectInternal[] = [];
|
||||||
teardown: FullProjectInternal | undefined;
|
teardown: FullProjectInternal | undefined;
|
||||||
|
|
||||||
static from(config: FullProject): FullProjectInternal {
|
|
||||||
return (config as any)[projectInternalSymbol];
|
|
||||||
}
|
|
||||||
|
|
||||||
constructor(configDir: string, config: Config, fullConfig: FullConfigInternal, projectConfig: Project, configCLIOverrides: ConfigCLIOverrides, throwawayArtifactsPath: string) {
|
constructor(configDir: string, config: Config, fullConfig: FullConfigInternal, projectConfig: Project, configCLIOverrides: ConfigCLIOverrides, throwawayArtifactsPath: string) {
|
||||||
this.fullConfig = fullConfig;
|
this.fullConfig = fullConfig;
|
||||||
const testDir = takeFirst(pathResolve(configDir, projectConfig.testDir), pathResolve(configDir, config.testDir), fullConfig.configDir);
|
const testDir = takeFirst(pathResolve(configDir, projectConfig.testDir), pathResolve(configDir, config.testDir), fullConfig.configDir);
|
||||||
|
|
@ -189,7 +186,6 @@ export class FullProjectInternal {
|
||||||
dependencies: projectConfig.dependencies || [],
|
dependencies: projectConfig.dependencies || [],
|
||||||
teardown: projectConfig.teardown,
|
teardown: projectConfig.teardown,
|
||||||
};
|
};
|
||||||
(this.project as any)[projectInternalSymbol] = this;
|
|
||||||
this.fullyParallel = takeFirst(configCLIOverrides.fullyParallel, projectConfig.fullyParallel, config.fullyParallel, undefined);
|
this.fullyParallel = takeFirst(configCLIOverrides.fullyParallel, projectConfig.fullyParallel, config.fullyParallel, undefined);
|
||||||
this.expect = takeFirst(projectConfig.expect, config.expect, {});
|
this.expect = takeFirst(projectConfig.expect, config.expect, {});
|
||||||
this.respectGitIgnore = !projectConfig.testDir && !config.testDir;
|
this.respectGitIgnore = !projectConfig.testDir && !config.testDir;
|
||||||
|
|
@ -278,4 +274,7 @@ export const defaultGrep = /.*/;
|
||||||
export const defaultReporter = process.env.CI ? 'dot' : 'list';
|
export const defaultReporter = process.env.CI ? 'dot' : 'list';
|
||||||
|
|
||||||
const configInternalSymbol = Symbol('configInternalSymbol');
|
const configInternalSymbol = Symbol('configInternalSymbol');
|
||||||
const projectInternalSymbol = Symbol('projectInternalSymbol');
|
|
||||||
|
export function getProjectId(project: FullProject): string {
|
||||||
|
return (project as any).__projectId!;
|
||||||
|
}
|
||||||
|
|
@ -197,7 +197,7 @@ export class TeleReporterReceiver {
|
||||||
}
|
}
|
||||||
|
|
||||||
private _onProject(project: JsonProject) {
|
private _onProject(project: JsonProject) {
|
||||||
let projectSuite = this._rootSuite.suites.find(suite => suite.project()!.id === project.id);
|
let projectSuite = this._rootSuite.suites.find(suite => suite.project()!.__projectId === project.id);
|
||||||
if (!projectSuite) {
|
if (!projectSuite) {
|
||||||
projectSuite = new TeleSuite(project.name, 'project');
|
projectSuite = new TeleSuite(project.name, 'project');
|
||||||
this._rootSuite.suites.push(projectSuite);
|
this._rootSuite.suites.push(projectSuite);
|
||||||
|
|
@ -323,7 +323,7 @@ export class TeleReporterReceiver {
|
||||||
|
|
||||||
private _parseProject(project: JsonProject): TeleFullProject {
|
private _parseProject(project: JsonProject): TeleFullProject {
|
||||||
return {
|
return {
|
||||||
id: project.id,
|
__projectId: project.id,
|
||||||
metadata: project.metadata,
|
metadata: project.metadata,
|
||||||
name: project.name,
|
name: project.name,
|
||||||
outputDir: this._absolutePath(project.outputDir),
|
outputDir: this._absolutePath(project.outputDir),
|
||||||
|
|
@ -577,7 +577,7 @@ class TeleTestResult implements reporterTypes.TestResult {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export type TeleFullProject = FullProject & { id: string };
|
export type TeleFullProject = FullProject & { __projectId: string };
|
||||||
|
|
||||||
export const baseFullConfig: FullConfig = {
|
export const baseFullConfig: FullConfig = {
|
||||||
forbidOnly: false,
|
forbidOnly: false,
|
||||||
|
|
|
||||||
|
|
@ -20,7 +20,7 @@ import type { FullConfig, TestCase, Suite, TestResult, TestError, TestStep, Full
|
||||||
import { formatError, prepareErrorStack } from './base';
|
import { formatError, prepareErrorStack } from './base';
|
||||||
import { MultiMap } from 'playwright-core/lib/utils';
|
import { MultiMap } from 'playwright-core/lib/utils';
|
||||||
import { assert } from 'playwright-core/lib/utils';
|
import { assert } from 'playwright-core/lib/utils';
|
||||||
import { FullProjectInternal } from '../common/config';
|
import { getProjectId } from '../common/config';
|
||||||
import EmptyReporter from './empty';
|
import EmptyReporter from './empty';
|
||||||
|
|
||||||
export function toPosixPath(aPath: string): string {
|
export function toPosixPath(aPath: string): string {
|
||||||
|
|
@ -69,7 +69,7 @@ class JSONReporter extends EmptyReporter {
|
||||||
repeatEach: project.repeatEach,
|
repeatEach: project.repeatEach,
|
||||||
retries: project.retries,
|
retries: project.retries,
|
||||||
metadata: project.metadata,
|
metadata: project.metadata,
|
||||||
id: FullProjectInternal.from(project).id,
|
id: getProjectId(project),
|
||||||
name: project.name,
|
name: project.name,
|
||||||
testDir: toPosixPath(project.testDir),
|
testDir: toPosixPath(project.testDir),
|
||||||
testIgnore: serializePatterns(project.testIgnore),
|
testIgnore: serializePatterns(project.testIgnore),
|
||||||
|
|
@ -86,7 +86,7 @@ class JSONReporter extends EmptyReporter {
|
||||||
private _mergeSuites(suites: Suite[]): JSONReportSuite[] {
|
private _mergeSuites(suites: Suite[]): JSONReportSuite[] {
|
||||||
const fileSuites = new MultiMap<string, JSONReportSuite>();
|
const fileSuites = new MultiMap<string, JSONReportSuite>();
|
||||||
for (const projectSuite of suites) {
|
for (const projectSuite of suites) {
|
||||||
const projectId = FullProjectInternal.from(projectSuite.project()!).id;
|
const projectId = getProjectId(projectSuite.project()!);
|
||||||
const projectName = projectSuite.project()!.name;
|
const projectName = projectSuite.project()!.name;
|
||||||
for (const fileSuite of projectSuite.suites) {
|
for (const fileSuite of projectSuite.suites) {
|
||||||
const file = fileSuite.location!.file;
|
const file = fileSuite.location!.file;
|
||||||
|
|
|
||||||
|
|
@ -18,7 +18,7 @@ import path from 'path';
|
||||||
import { createGuid } from 'playwright-core/lib/utils';
|
import { createGuid } from 'playwright-core/lib/utils';
|
||||||
import type { SuitePrivate } from '../../types/reporterPrivate';
|
import type { SuitePrivate } from '../../types/reporterPrivate';
|
||||||
import type { FullConfig, FullResult, Location, TestCase, TestError, TestResult, TestStep } from '../../types/testReporter';
|
import type { FullConfig, FullResult, Location, TestCase, TestError, TestResult, TestStep } from '../../types/testReporter';
|
||||||
import { FullConfigInternal, FullProjectInternal } from '../common/config';
|
import { FullConfigInternal, getProjectId } from '../common/config';
|
||||||
import type { Suite } from '../common/test';
|
import type { Suite } from '../common/test';
|
||||||
import type { JsonAttachment, JsonConfig, JsonEvent, JsonProject, JsonStdIOType, JsonSuite, JsonTestCase, JsonTestEnd, JsonTestResultEnd, JsonTestResultStart, JsonTestStepEnd, JsonTestStepStart } from '../isomorphic/teleReceiver';
|
import type { JsonAttachment, JsonConfig, JsonEvent, JsonProject, JsonStdIOType, JsonSuite, JsonTestCase, JsonTestEnd, JsonTestResultEnd, JsonTestResultStart, JsonTestStepEnd, JsonTestStepStart } from '../isomorphic/teleReceiver';
|
||||||
import { serializeRegexPatterns } from '../isomorphic/teleReceiver';
|
import { serializeRegexPatterns } from '../isomorphic/teleReceiver';
|
||||||
|
|
@ -151,7 +151,7 @@ export class TeleReporterEmitter implements ReporterV2 {
|
||||||
private _serializeProject(suite: Suite): JsonProject {
|
private _serializeProject(suite: Suite): JsonProject {
|
||||||
const project = suite.project()!;
|
const project = suite.project()!;
|
||||||
const report: JsonProject = {
|
const report: JsonProject = {
|
||||||
id: FullProjectInternal.from(project).id,
|
id: getProjectId(project),
|
||||||
metadata: project.metadata,
|
metadata: project.metadata,
|
||||||
name: project.name,
|
name: project.name,
|
||||||
outputDir: this._relativePath(project.outputDir),
|
outputDir: this._relativePath(project.outputDir),
|
||||||
|
|
|
||||||
|
|
@ -236,6 +236,62 @@ test('should merge into html with dependencies', async ({ runInlineTest, mergeRe
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test('should merge blob into blob', async ({ runInlineTest, mergeReports, showReport, page }) => {
|
||||||
|
const reportDir = test.info().outputPath('blob-report-orig');
|
||||||
|
const files = {
|
||||||
|
'playwright.config.ts': `
|
||||||
|
module.exports = {
|
||||||
|
retries: 1,
|
||||||
|
reporter: [['blob', { outputDir: '${reportDir.replace(/\\/g, '/')}' }]]
|
||||||
|
};
|
||||||
|
`,
|
||||||
|
'a.test.js': `
|
||||||
|
import { test, expect } from '@playwright/test';
|
||||||
|
test('math 1', async ({}) => {
|
||||||
|
expect(1 + 1).toBe(2);
|
||||||
|
});
|
||||||
|
test('failing 1', async ({}) => {
|
||||||
|
expect(1).toBe(2);
|
||||||
|
});
|
||||||
|
test('flaky 1', async ({}) => {
|
||||||
|
expect(test.info().retry).toBe(1);
|
||||||
|
});
|
||||||
|
test.skip('skipped 1', async ({}) => {});
|
||||||
|
`,
|
||||||
|
'b.test.js': `
|
||||||
|
import { test, expect } from '@playwright/test';
|
||||||
|
test('math 2', async ({}) => {
|
||||||
|
expect(1 + 1).toBe(2);
|
||||||
|
});
|
||||||
|
test('failing 2', async ({}) => {
|
||||||
|
expect(1).toBe(2);
|
||||||
|
});
|
||||||
|
test.skip('skipped 2', async ({}) => {});
|
||||||
|
`
|
||||||
|
};
|
||||||
|
await runInlineTest(files, { shard: `1/2` }, { PWTEST_BLOB_DO_NOT_REMOVE: '1' });
|
||||||
|
await runInlineTest(files, { shard: `2/2` }, { PWTEST_BLOB_DO_NOT_REMOVE: '1' });
|
||||||
|
{
|
||||||
|
const reportFiles = await fs.promises.readdir(reportDir);
|
||||||
|
reportFiles.sort();
|
||||||
|
expect(reportFiles).toEqual(['report-1.zip', 'report-2.zip']);
|
||||||
|
const { exitCode } = await mergeReports(reportDir, undefined, { additionalArgs: ['--reporter', 'blob'] });
|
||||||
|
expect(exitCode).toBe(0);
|
||||||
|
}
|
||||||
|
{
|
||||||
|
const compinedBlobReportDir = test.info().outputPath('blob-report');
|
||||||
|
const { exitCode } = await mergeReports(compinedBlobReportDir, { 'PW_TEST_HTML_REPORT_OPEN': 'never' }, { additionalArgs: ['--reporter', 'html,json'] });
|
||||||
|
expect(exitCode).toBe(0);
|
||||||
|
expect(fs.existsSync(test.info().outputPath('report.json'))).toBe(true);
|
||||||
|
await showReport();
|
||||||
|
await expect(page.locator('.subnav-item:has-text("All") .counter')).toHaveText('7');
|
||||||
|
await expect(page.locator('.subnav-item:has-text("Passed") .counter')).toHaveText('2');
|
||||||
|
await expect(page.locator('.subnav-item:has-text("Failed") .counter')).toHaveText('2');
|
||||||
|
await expect(page.locator('.subnav-item:has-text("Flaky") .counter')).toHaveText('1');
|
||||||
|
await expect(page.locator('.subnav-item:has-text("Skipped") .counter')).toHaveText('2');
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
test('be able to merge incomplete shards', async ({ runInlineTest, mergeReports, showReport, page }) => {
|
test('be able to merge incomplete shards', async ({ runInlineTest, mergeReports, showReport, page }) => {
|
||||||
const reportDir = test.info().outputPath('blob-report');
|
const reportDir = test.info().outputPath('blob-report');
|
||||||
const files = {
|
const files = {
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue