fix(trace): do not place expect into unfinished api calls based on time
Fixes https://github.com/microsoft/playwright/issues/31959
This commit is contained in:
parent
76cca7fc2c
commit
e65ac2bb9c
|
|
@ -33,7 +33,7 @@ export interface TestStepInternal {
|
||||||
complete(result: { error?: Error, attachments?: Attachment[] }): void;
|
complete(result: { error?: Error, attachments?: Attachment[] }): void;
|
||||||
stepId: string;
|
stepId: string;
|
||||||
title: string;
|
title: string;
|
||||||
category: 'hook' | 'fixture' | 'test.step' | 'expect' | string;
|
category: 'hook' | 'fixture' | 'test.step' | 'expect' | 'pw:api' | string;
|
||||||
location?: Location;
|
location?: Location;
|
||||||
boxedStack?: StackFrame[];
|
boxedStack?: StackFrame[];
|
||||||
steps: TestStepInternal[];
|
steps: TestStepInternal[];
|
||||||
|
|
@ -252,7 +252,7 @@ export class TestInfoImpl implements TestInfo {
|
||||||
parentStep = this._findLastStageStep();
|
parentStep = this._findLastStageStep();
|
||||||
} else {
|
} else {
|
||||||
parentStep = zones.zoneData<TestStepInternal>('stepZone');
|
parentStep = zones.zoneData<TestStepInternal>('stepZone');
|
||||||
if (!parentStep && data.category !== 'test.step') {
|
if (!parentStep && data.category === 'pw:api') {
|
||||||
// API steps (but not test.step calls) can be nested by time, instead of by stack.
|
// API steps (but not test.step calls) can be nested by time, instead of by stack.
|
||||||
// However, do not nest chains of route.continue by checking the title.
|
// However, do not nest chains of route.continue by checking the title.
|
||||||
parentStep = this._findLastNonFinishedStep(step => step.title !== data.title);
|
parentStep = this._findLastNonFinishedStep(step => step.title !== data.title);
|
||||||
|
|
|
||||||
|
|
@ -1178,3 +1178,69 @@ test('should record trace for manually created context in a failed test', async
|
||||||
// Check console events to make sure that library trace is recorded.
|
// Check console events to make sure that library trace is recorded.
|
||||||
expect(trace.events).toContainEqual(expect.objectContaining({ type: 'console', text: 'from the page' }));
|
expect(trace.events).toContainEqual(expect.objectContaining({ type: 'console', text: 'from the page' }));
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test('expect during fetch', async ({ page, server }) => {
|
||||||
|
server.setRoute('/index', (req, res) => {
|
||||||
|
console.log('index');
|
||||||
|
res.writeHead(200, { 'Content-Type': 'text/html' });
|
||||||
|
res.end(`<script>fetch('/api')</script><div>Hello!</div>`);
|
||||||
|
});
|
||||||
|
server.setRoute('/hang', async (req, res) => {
|
||||||
|
console.log('Hanging request');
|
||||||
|
});
|
||||||
|
await page.route('**/api', async route => {
|
||||||
|
const response = await route.fetch({ url: server.PREFIX + '/hang' });
|
||||||
|
await route.fulfill({ response });
|
||||||
|
});
|
||||||
|
await page.goto(server.PREFIX + '/index');
|
||||||
|
await expect(page.getByText('Hello!')).toBeVisible();
|
||||||
|
await page.unrouteAll({ behavior: 'ignoreErrors' });
|
||||||
|
});
|
||||||
|
|
||||||
|
test('should not nest top level expect into unfinished api calls ', {
|
||||||
|
annotation: { type: 'issue', description: 'https://github.com/microsoft/playwright/issues/31959'}
|
||||||
|
}, async ({ runInlineTest, server }) => {
|
||||||
|
server.setRoute('/index', (req, res) => {
|
||||||
|
res.writeHead(200, { 'Content-Type': 'text/html' });
|
||||||
|
res.end(`<script>fetch('/api')</script><div>Hello!</div>`);
|
||||||
|
});
|
||||||
|
server.setRoute('/hang', () => {});
|
||||||
|
const result = await runInlineTest({
|
||||||
|
'a.spec.ts': `
|
||||||
|
import { test, expect } from '@playwright/test';
|
||||||
|
test('pass', async ({ page }) => {
|
||||||
|
await page.route('**/api', async route => {
|
||||||
|
const response = await route.fetch({ url: '${server.PREFIX}/hang' });
|
||||||
|
await route.fulfill({ response });
|
||||||
|
});
|
||||||
|
await page.goto('${server.PREFIX}/index');
|
||||||
|
await expect(page.getByText('Hello!')).toBeVisible();
|
||||||
|
await page.unrouteAll({ behavior: 'ignoreErrors' });
|
||||||
|
});
|
||||||
|
`,
|
||||||
|
}, { trace: 'on' });
|
||||||
|
expect(result.exitCode).toBe(0);
|
||||||
|
expect(result.failed).toBe(0);
|
||||||
|
|
||||||
|
const tracePath = test.info().outputPath('test-results', 'a-pass', 'trace.zip');
|
||||||
|
const trace = await parseTrace(tracePath);
|
||||||
|
expect(trace.actionTree).toEqual([
|
||||||
|
'Before Hooks',
|
||||||
|
' fixture: browser',
|
||||||
|
' browserType.launch',
|
||||||
|
' fixture: context',
|
||||||
|
' browser.newContext',
|
||||||
|
' fixture: page',
|
||||||
|
' browserContext.newPage',
|
||||||
|
'page.route',
|
||||||
|
'page.goto',
|
||||||
|
' route.fetch',
|
||||||
|
' page.unrouteAll',
|
||||||
|
'expect.toBeVisible',
|
||||||
|
'After Hooks',
|
||||||
|
' fixture: page',
|
||||||
|
' fixture: context',
|
||||||
|
]);
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue