fix(error): create a step for raw runtime error (#24057)
Fix https://github.com/microsoft/playwright/issues/23850
This commit is contained in:
parent
88010333f3
commit
608e336dba
|
|
@ -23,7 +23,7 @@ import { ConfigLoader } from '../common/configLoader';
|
||||||
import type { Suite, TestCase } from '../common/test';
|
import type { Suite, TestCase } from '../common/test';
|
||||||
import type { Annotation, FullConfigInternal, FullProjectInternal } from '../common/config';
|
import type { Annotation, FullConfigInternal, FullProjectInternal } from '../common/config';
|
||||||
import { FixtureRunner } from './fixtureRunner';
|
import { FixtureRunner } from './fixtureRunner';
|
||||||
import { ManualPromise } from 'playwright-core/lib/utils';
|
import { ManualPromise, captureLibraryStackTrace } from 'playwright-core/lib/utils';
|
||||||
import { TestInfoImpl } from './testInfo';
|
import { TestInfoImpl } from './testInfo';
|
||||||
import { TimeoutManager, type TimeSlot } from './timeoutManager';
|
import { TimeoutManager, type TimeSlot } from './timeoutManager';
|
||||||
import { ProcessRunner } from '../common/process';
|
import { ProcessRunner } from '../common/process';
|
||||||
|
|
@ -369,13 +369,25 @@ export class WorkerMain extends ProcessRunner {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
await testInfo._runAndFailOnError(async () => {
|
const error = await testInfo._runAndFailOnError(async () => {
|
||||||
// Now run the test itself.
|
// Now run the test itself.
|
||||||
debugTest(`test function started`);
|
debugTest(`test function started`);
|
||||||
const fn = test.fn; // Extract a variable to get a better stack trace ("myTest" vs "TestCase.myTest [as fn]").
|
const fn = test.fn; // Extract a variable to get a better stack trace ("myTest" vs "TestCase.myTest [as fn]").
|
||||||
await fn(testFunctionParams, testInfo);
|
await fn(testFunctionParams, testInfo);
|
||||||
debugTest(`test function finished`);
|
debugTest(`test function finished`);
|
||||||
}, 'allowSkips');
|
}, 'allowSkips');
|
||||||
|
|
||||||
|
// If there are no steps with errors in the test, but the test has an error - append artificial trace entry.
|
||||||
|
if (error && !testInfo._steps.some(s => !!s.error)) {
|
||||||
|
const frames = error.stack ? captureLibraryStackTrace(error.stack.split('\n')).frames : [];
|
||||||
|
const step = testInfo._addStep({
|
||||||
|
wallTime: Date.now(),
|
||||||
|
title: error.message || 'error',
|
||||||
|
category: 'hook',
|
||||||
|
location: frames[0],
|
||||||
|
});
|
||||||
|
step.complete({ error });
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
if (didFailBeforeAllForSuite) {
|
if (didFailBeforeAllForSuite) {
|
||||||
|
|
|
||||||
|
|
@ -331,6 +331,7 @@ test('should not override trace file in afterAll', async ({ runInlineTest, serve
|
||||||
' fixture: page',
|
' fixture: page',
|
||||||
' browserContext.newPage',
|
' browserContext.newPage',
|
||||||
'page.goto',
|
'page.goto',
|
||||||
|
'error',
|
||||||
'After Hooks',
|
'After Hooks',
|
||||||
' fixture: page',
|
' fixture: page',
|
||||||
' fixture: context',
|
' fixture: context',
|
||||||
|
|
@ -650,3 +651,38 @@ test('should expand expect.toPass', async ({ runInlineTest }, testInfo) => {
|
||||||
' fixture: context',
|
' fixture: context',
|
||||||
]);
|
]);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test('should show non-expect error in trace', async ({ runInlineTest }, testInfo) => {
|
||||||
|
const result = await runInlineTest({
|
||||||
|
'playwright.config.ts': `
|
||||||
|
module.exports = { use: { trace: { mode: 'on' } } };
|
||||||
|
`,
|
||||||
|
'a.spec.ts': `
|
||||||
|
import { test, expect } from '@playwright/test';
|
||||||
|
test('fail', async ({ page }) => {
|
||||||
|
expect(1).toBe(1);
|
||||||
|
undefinedVariable1 = 'this throws an exception';
|
||||||
|
expect(1).toBe(2);
|
||||||
|
});
|
||||||
|
`,
|
||||||
|
}, { workers: 1 });
|
||||||
|
|
||||||
|
expect(result.exitCode).toBe(1);
|
||||||
|
expect(result.failed).toBe(1);
|
||||||
|
const trace = await parseTrace(testInfo.outputPath('test-results', 'a-fail', 'trace.zip'));
|
||||||
|
expect(trace.actionTree).toEqual([
|
||||||
|
'Before Hooks',
|
||||||
|
' fixture: browser',
|
||||||
|
' browserType.launch',
|
||||||
|
' fixture: context',
|
||||||
|
' browser.newContext',
|
||||||
|
' tracing.start',
|
||||||
|
' fixture: page',
|
||||||
|
' browserContext.newPage',
|
||||||
|
'expect.toBe',
|
||||||
|
'undefinedVariable1 is not defined',
|
||||||
|
'After Hooks',
|
||||||
|
' fixture: page',
|
||||||
|
' fixture: context',
|
||||||
|
]);
|
||||||
|
});
|
||||||
|
|
|
||||||
|
|
@ -780,7 +780,7 @@ for (const useIntermediateMergeReport of [false, true] as const) {
|
||||||
await showReport();
|
await showReport();
|
||||||
|
|
||||||
await page.locator('text=sample').first().click();
|
await page.locator('text=sample').first().click();
|
||||||
await expect(page.locator('text=ouch')).toBeVisible();
|
await expect(page.locator('text=ouch')).toHaveCount(2);
|
||||||
await page.locator('text=All').first().click();
|
await page.locator('text=All').first().click();
|
||||||
|
|
||||||
await page.locator('text=sample').nth(1).click();
|
await page.locator('text=sample').nth(1).click();
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue