serialize expect fields in worker only
This commit is contained in:
parent
896ea2dd67
commit
86de48ef08
|
|
@ -24,10 +24,11 @@ import { TimeoutManager, TimeoutManagerError, kMaxDeadline } from './timeoutMana
|
||||||
import type { RunnableDescription } from './timeoutManager';
|
import type { RunnableDescription } from './timeoutManager';
|
||||||
import type { Annotation, FullConfigInternal, FullProjectInternal } from '../common/config';
|
import type { Annotation, FullConfigInternal, FullProjectInternal } from '../common/config';
|
||||||
import type { FullConfig, Location } from '../../types/testReporter';
|
import type { FullConfig, Location } from '../../types/testReporter';
|
||||||
import { debugTest, filteredStackTrace, formatLocation, getContainedPath, normalizeAndSaveAttachment, serializeError, trimLongString, windowsFilesystemFriendlyLength } from '../util';
|
import { debugTest, filteredStackTrace, formatLocation, getContainedPath, normalizeAndSaveAttachment, trimLongString, windowsFilesystemFriendlyLength } from '../util';
|
||||||
import { TestTracing } from './testTracing';
|
import { TestTracing } from './testTracing';
|
||||||
import type { Attachment } from './testTracing';
|
import type { Attachment } from './testTracing';
|
||||||
import type { StackFrame } from '@protocol/channels';
|
import type { StackFrame } from '@protocol/channels';
|
||||||
|
import { serializeWorkerError } from './util';
|
||||||
|
|
||||||
export interface TestStepInternal {
|
export interface TestStepInternal {
|
||||||
complete(result: { error?: Error | unknown, attachments?: Attachment[] }): void;
|
complete(result: { error?: Error | unknown, attachments?: Attachment[] }): void;
|
||||||
|
|
@ -272,7 +273,7 @@ export class TestInfoImpl implements TestInfo {
|
||||||
if (result.error) {
|
if (result.error) {
|
||||||
if (typeof result.error === 'object' && !(result.error as any)?.[stepSymbol])
|
if (typeof result.error === 'object' && !(result.error as any)?.[stepSymbol])
|
||||||
(result.error as any)[stepSymbol] = step;
|
(result.error as any)[stepSymbol] = step;
|
||||||
const error = serializeError(result.error);
|
const error = serializeWorkerError(result.error);
|
||||||
if (data.boxedStack)
|
if (data.boxedStack)
|
||||||
error.stack = `${error.message}\n${stringifyStackFrames(data.boxedStack).join('\n')}`;
|
error.stack = `${error.message}\n${stringifyStackFrames(data.boxedStack).join('\n')}`;
|
||||||
step.error = error;
|
step.error = error;
|
||||||
|
|
@ -330,7 +331,7 @@ export class TestInfoImpl implements TestInfo {
|
||||||
_failWithError(error: Error | unknown) {
|
_failWithError(error: Error | unknown) {
|
||||||
if (this.status === 'passed' || this.status === 'skipped')
|
if (this.status === 'passed' || this.status === 'skipped')
|
||||||
this.status = error instanceof TimeoutManagerError ? 'timedOut' : 'failed';
|
this.status = error instanceof TimeoutManagerError ? 'timedOut' : 'failed';
|
||||||
const serialized = serializeError(error);
|
const serialized = serializeWorkerError(error);
|
||||||
const step: TestStepInternal | undefined = typeof error === 'object' ? (error as any)?.[stepSymbol] : undefined;
|
const step: TestStepInternal | undefined = typeof error === 'object' ? (error as any)?.[stepSymbol] : undefined;
|
||||||
if (step && step.boxedStack)
|
if (step && step.boxedStack)
|
||||||
serialized.stack = `${(error as Error).name}: ${(error as Error).message}\n${stringifyStackFrames(step.boxedStack).join('\n')}`;
|
serialized.stack = `${(error as Error).name}: ${(error as Error).message}\n${stringifyStackFrames(step.boxedStack).join('\n')}`;
|
||||||
|
|
|
||||||
39
packages/playwright/src/worker/util.ts
Normal file
39
packages/playwright/src/worker/util.ts
Normal file
|
|
@ -0,0 +1,39 @@
|
||||||
|
/**
|
||||||
|
* Copyright (c) Microsoft Corporation.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import type { TestInfoError } from '../../types/test';
|
||||||
|
import type { MatcherResult } from '../matchers/matcherHint';
|
||||||
|
import { serializeError } from '../util';
|
||||||
|
|
||||||
|
export function serializeWorkerError(error: Error | any): TestInfoError {
|
||||||
|
return {
|
||||||
|
...serializeError(error),
|
||||||
|
...serializeExpectDetails(error),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
function serializeExpectDetails(e: Error): Pick<TestInfoError, 'shortMessage'|'log'|'expected'|'actual'> {
|
||||||
|
const matcherResult = (e as any).matcherResult as MatcherResult<unknown, unknown>;
|
||||||
|
if (!matcherResult)
|
||||||
|
return {};
|
||||||
|
return {
|
||||||
|
shortMessage: matcherResult.shortMessage,
|
||||||
|
log: matcherResult.log,
|
||||||
|
expected: matcherResult.expected,
|
||||||
|
actual: matcherResult.actual,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
|
@ -15,7 +15,7 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { colors } from 'playwright-core/lib/utilsBundle';
|
import { colors } from 'playwright-core/lib/utilsBundle';
|
||||||
import { debugTest, relativeFilePath, serializeError } from '../util';
|
import { debugTest, relativeFilePath } from '../util';
|
||||||
import { type TestBeginPayload, type TestEndPayload, type RunPayload, type DonePayload, type WorkerInitParams, type TeardownErrorsPayload, stdioChunkToParams } from '../common/ipc';
|
import { type TestBeginPayload, type TestEndPayload, type RunPayload, type DonePayload, type WorkerInitParams, type TeardownErrorsPayload, stdioChunkToParams } from '../common/ipc';
|
||||||
import { setCurrentTestInfo, setIsWorkerProcess } from '../common/globals';
|
import { setCurrentTestInfo, setIsWorkerProcess } from '../common/globals';
|
||||||
import { deserializeConfig } from '../common/configLoader';
|
import { deserializeConfig } from '../common/configLoader';
|
||||||
|
|
@ -32,6 +32,7 @@ import type { TestInfoError } from '../../types/test';
|
||||||
import type { Location } from '../../types/testReporter';
|
import type { Location } from '../../types/testReporter';
|
||||||
import { inheritFixtureNames } from '../common/fixtures';
|
import { inheritFixtureNames } from '../common/fixtures';
|
||||||
import { type TimeSlot } from './timeoutManager';
|
import { type TimeSlot } from './timeoutManager';
|
||||||
|
import { serializeWorkerError } from './util';
|
||||||
|
|
||||||
export class WorkerMain extends ProcessRunner {
|
export class WorkerMain extends ProcessRunner {
|
||||||
private _params: WorkerInitParams;
|
private _params: WorkerInitParams;
|
||||||
|
|
@ -112,7 +113,7 @@ export class WorkerMain extends ProcessRunner {
|
||||||
await fakeTestInfo._runAsStage({ title: 'worker cleanup', runnable }, () => gracefullyCloseAll()).catch(() => {});
|
await fakeTestInfo._runAsStage({ title: 'worker cleanup', runnable }, () => gracefullyCloseAll()).catch(() => {});
|
||||||
this._fatalErrors.push(...fakeTestInfo.errors);
|
this._fatalErrors.push(...fakeTestInfo.errors);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
this._fatalErrors.push(serializeError(e));
|
this._fatalErrors.push(serializeWorkerError(e));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this._fatalErrors.length) {
|
if (this._fatalErrors.length) {
|
||||||
|
|
@ -153,7 +154,7 @@ export class WorkerMain extends ProcessRunner {
|
||||||
// No current test - fatal error.
|
// No current test - fatal error.
|
||||||
if (!this._currentTest) {
|
if (!this._currentTest) {
|
||||||
if (!this._fatalErrors.length)
|
if (!this._fatalErrors.length)
|
||||||
this._fatalErrors.push(serializeError(error));
|
this._fatalErrors.push(serializeWorkerError(error));
|
||||||
void this._stop();
|
void this._stop();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
@ -224,7 +225,7 @@ export class WorkerMain extends ProcessRunner {
|
||||||
// In theory, we should run above code without any errors.
|
// In theory, we should run above code without any errors.
|
||||||
// However, in the case we screwed up, or loadTestFile failed in the worker
|
// However, in the case we screwed up, or loadTestFile failed in the worker
|
||||||
// but not in the runner, let's do a fatal error.
|
// but not in the runner, let's do a fatal error.
|
||||||
this._fatalErrors.push(serializeError(e));
|
this._fatalErrors.push(serializeWorkerError(e));
|
||||||
void this._stop();
|
void this._stop();
|
||||||
} finally {
|
} finally {
|
||||||
const donePayload: DonePayload = {
|
const donePayload: DonePayload = {
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue