fix(ui): print config and global setup errors (#30531)
Fixes: https://github.com/microsoft/playwright/issues/30513
This commit is contained in:
parent
59689c9c97
commit
ff3d3ae8f2
|
|
@ -124,9 +124,9 @@ export type JsonEvent = {
|
|||
};
|
||||
|
||||
type TeleReporterReceiverOptions = {
|
||||
mergeProjects: boolean;
|
||||
mergeTestCases: boolean;
|
||||
resolvePath: (rootDir: string, relativePath: string) => string;
|
||||
mergeProjects?: boolean;
|
||||
mergeTestCases?: boolean;
|
||||
resolvePath?: (rootDir: string, relativePath: string) => string;
|
||||
configOverrides?: Pick<reporterTypes.FullConfig, 'configFile' | 'quiet' | 'reportSlowTests' | 'reporter'>;
|
||||
clearPreviousResultsWhenTestBegins?: boolean;
|
||||
};
|
||||
|
|
@ -140,7 +140,7 @@ export class TeleReporterReceiver {
|
|||
private _rootDir!: string;
|
||||
private _config!: reporterTypes.FullConfig;
|
||||
|
||||
constructor(reporter: Partial<ReporterV2>, options: TeleReporterReceiverOptions) {
|
||||
constructor(reporter: Partial<ReporterV2>, options: TeleReporterReceiverOptions = {}) {
|
||||
this._rootSuite = new TeleSuite('', 'root');
|
||||
this._options = options;
|
||||
this._reporter = reporter;
|
||||
|
|
@ -388,7 +388,7 @@ export class TeleReporterReceiver {
|
|||
private _absolutePath(relativePath?: string): string | undefined {
|
||||
if (relativePath === undefined)
|
||||
return;
|
||||
return this._options.resolvePath(this._rootDir, relativePath);
|
||||
return this._options.resolvePath ? this._options.resolvePath(this._rootDir, relativePath) : this._rootDir + '/' + relativePath;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -8,4 +8,5 @@
|
|||
../util.ts
|
||||
../utilsBundle.ts
|
||||
../isomorphic/folders.ts
|
||||
../isomorphic/teleReceiver.ts
|
||||
../fsWatcher.ts
|
||||
|
|
|
|||
|
|
@ -39,6 +39,7 @@ import type { TraceViewerRedirectOptions, TraceViewerServerOptions } from 'playw
|
|||
import type { TestRunnerPluginRegistration } from '../plugins';
|
||||
import { serializeError } from '../util';
|
||||
import { cacheDir } from '../transform/compilationCache';
|
||||
import { baseFullConfig } from '../isomorphic/teleReceiver';
|
||||
|
||||
const originalStdoutWrite = process.stdout.write;
|
||||
const originalStderrWrite = process.stderr.write;
|
||||
|
|
@ -147,7 +148,10 @@ class TestServerDispatcher implements TestServerInterface {
|
|||
const { reporter, report } = await this._collectingReporter();
|
||||
const { config, error } = await this._loadConfig();
|
||||
if (!config) {
|
||||
// Produce dummy config when it has an error.
|
||||
reporter.onConfigure(baseFullConfig);
|
||||
reporter.onError(error!);
|
||||
await reporter.onExit();
|
||||
return { status: 'failed', report };
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -115,11 +115,7 @@ export class TeleSuiteUpdater {
|
|||
this._options.onUpdate();
|
||||
},
|
||||
|
||||
onError: (error: reporterTypes.TestError) => {
|
||||
this.loadErrors.push(error);
|
||||
this._options.onError?.(error);
|
||||
this._options.onUpdate();
|
||||
},
|
||||
onError: (error: reporterTypes.TestError) => this._handleOnError(error),
|
||||
|
||||
printsToStdio: () => {
|
||||
return false;
|
||||
|
|
@ -133,6 +129,17 @@ export class TeleSuiteUpdater {
|
|||
};
|
||||
}
|
||||
|
||||
processGlobalReport(report: any[]) {
|
||||
const receiver = new TeleReporterReceiver({
|
||||
onConfigure: (c: reporterTypes.FullConfig) => {
|
||||
this.config = c;
|
||||
},
|
||||
onError: (error: reporterTypes.TestError) => this._handleOnError(error)
|
||||
});
|
||||
for (const message of report)
|
||||
receiver.dispatch(message);
|
||||
}
|
||||
|
||||
processListReport(report: any[]) {
|
||||
// Save test results and reset all projects, the results will be restored after
|
||||
// new project structure is built.
|
||||
|
|
@ -150,6 +157,12 @@ export class TeleSuiteUpdater {
|
|||
this._receiver.dispatch(message)?.catch(() => {});
|
||||
}
|
||||
|
||||
private _handleOnError(error: reporterTypes.TestError) {
|
||||
this.loadErrors.push(error);
|
||||
this._options.onError?.(error);
|
||||
this._options.onUpdate();
|
||||
}
|
||||
|
||||
asModel(): TestModel {
|
||||
return {
|
||||
rootSuite: this.rootSuite || new TeleSuite('', 'root'),
|
||||
|
|
|
|||
|
|
@ -172,24 +172,29 @@ export const UIModeView: React.FC<{}> = ({
|
|||
setIsLoading(true);
|
||||
setWatchedTreeIds({ value: new Set() });
|
||||
(async () => {
|
||||
await testServerConnection.initialize({
|
||||
interceptStdio: true,
|
||||
watchTestDirs: true
|
||||
});
|
||||
const { status } = await testServerConnection.runGlobalSetup({});
|
||||
if (status !== 'passed')
|
||||
return;
|
||||
const result = await testServerConnection.listTests({ projects: queryParams.projects, locations: queryParams.args });
|
||||
teleSuiteUpdater.processListReport(result.report);
|
||||
try {
|
||||
await testServerConnection.initialize({
|
||||
interceptStdio: true,
|
||||
watchTestDirs: true
|
||||
});
|
||||
const { status, report } = await testServerConnection.runGlobalSetup({});
|
||||
teleSuiteUpdater.processGlobalReport(report);
|
||||
if (status !== 'passed')
|
||||
return;
|
||||
|
||||
testServerConnection.onListChanged(updateList);
|
||||
testServerConnection.onReport(params => {
|
||||
teleSuiteUpdater.processTestReportEvent(params);
|
||||
});
|
||||
setIsLoading(false);
|
||||
const result = await testServerConnection.listTests({ projects: queryParams.projects, locations: queryParams.args });
|
||||
teleSuiteUpdater.processListReport(result.report);
|
||||
|
||||
const { hasBrowsers } = await testServerConnection.checkBrowsers({});
|
||||
setHasBrowsers(hasBrowsers);
|
||||
testServerConnection.onListChanged(updateList);
|
||||
testServerConnection.onReport(params => {
|
||||
teleSuiteUpdater.processTestReportEvent(params);
|
||||
});
|
||||
|
||||
const { hasBrowsers } = await testServerConnection.checkBrowsers({});
|
||||
setHasBrowsers(hasBrowsers);
|
||||
} finally {
|
||||
setIsLoading(false);
|
||||
}
|
||||
})();
|
||||
return () => {
|
||||
clearTimeout(throttleTimer);
|
||||
|
|
|
|||
|
|
@ -84,6 +84,17 @@ test('should teardown on sigint', async ({ runUITest, nodeVersion }) => {
|
|||
]);
|
||||
});
|
||||
|
||||
test('should show errors in config', async ({ runUITest }) => {
|
||||
const { page } = await runUITest({
|
||||
'playwright.config.ts': `
|
||||
import { defineConfig, devices } from '@playwright/test';
|
||||
throw new Error("URL is empty")
|
||||
`,
|
||||
});
|
||||
await page.getByText('playwright.config.ts').click();
|
||||
await expect(page.getByText('Error: URL is empty')).toBeInViewport();
|
||||
});
|
||||
|
||||
const testsWithSetup = {
|
||||
'playwright.config.ts': `
|
||||
import { defineConfig } from '@playwright/test';
|
||||
|
|
|
|||
Loading…
Reference in a new issue