From 0d5ece59923ca4fb2a9072f772b09c8932839c9c Mon Sep 17 00:00:00 2001 From: Yury Semikhatsky Date: Wed, 6 Nov 2024 15:19:11 -0800 Subject: [PATCH] Add zones for route callback --- .../playwright-core/src/client/network.ts | 10 ++++- tests/playwright-test/test-step.spec.ts | 45 +++++++++++++++++++ 2 files changed, 53 insertions(+), 2 deletions(-) diff --git a/packages/playwright-core/src/client/network.ts b/packages/playwright-core/src/client/network.ts index f3b066c171..74b8df9367 100644 --- a/packages/playwright-core/src/client/network.ts +++ b/packages/playwright-core/src/client/network.ts @@ -22,14 +22,14 @@ import { Worker } from './worker'; import type { Headers, RemoteAddr, SecurityDetails, WaitForEventOptions } from './types'; import fs from 'fs'; import { mime } from '../utilsBundle'; -import { assert, isString, headersObjectToArray, isRegExp, rewriteErrorMessage } from '../utils'; +import { assert, isString, headersObjectToArray, isRegExp, rewriteErrorMessage, MultiMap, urlMatches, zones } from '../utils'; +import type { URLMatch, Zone } from '../utils'; import { ManualPromise, LongStandingScope } from '../utils/manualPromise'; import { Events } from './events'; import type { Page } from './page'; import { Waiter } from './waiter'; import type * as api from '../../types/types'; import type { HeadersArray } from '../common/types'; -import { MultiMap, urlMatches, type URLMatch } from '../utils'; import { APIResponse } from './fetch'; import type { Serializable } from '../../types/structs'; import type { BrowserContext } from './browserContext'; @@ -811,12 +811,14 @@ export class RouteHandler { readonly handler: RouteHandlerCallback; private _ignoreException: boolean = false; private _activeInvocations: Set<{ complete: Promise, route: Route }> = new Set(); + private _svedZone: Zone; constructor(baseURL: string | undefined, url: URLMatch, handler: RouteHandlerCallback, times: number = Number.MAX_SAFE_INTEGER) { this._baseURL = baseURL; this._times = times; this.url = url; this.handler = handler; + this._svedZone = zones.currentZone(); } static prepareInterceptionPatterns(handlers: RouteHandler[]) { @@ -840,6 +842,10 @@ export class RouteHandler { } public async handle(route: Route): Promise { + return await this._svedZone.run(async () => this._handleImpl(route)); + } + + private async _handleImpl(route: Route): Promise { const handlerInvocation = { complete: new ManualPromise(), route } ; this._activeInvocations.add(handlerInvocation); try { diff --git a/tests/playwright-test/test-step.spec.ts b/tests/playwright-test/test-step.spec.ts index 06a50b8c9b..1c3dbf5e34 100644 --- a/tests/playwright-test/test-step.spec.ts +++ b/tests/playwright-test/test-step.spec.ts @@ -1363,3 +1363,48 @@ fixture | fixture: page fixture | fixture: context `); }); + +test('calls from page.route callback should be under its parent step', { + annotation: { type: 'issue', description: 'https://github.com/microsoft/playwright/issues/33186' } +}, async ({ runInlineTest, server }) => { + const result = await runInlineTest({ + 'reporter.ts': stepIndentReporter, + 'playwright.config.ts': `module.exports = { reporter: './reporter' };`, + 'a.test.ts': ` + import { test, expect } from '@playwright/test'; + test('waitForResponse step nesting', async ({ page }) => { + await test.step('custom step', async () => { + await page.route('**/empty.html', async route => { + const response = await route.fetch(); + const text = await response.text(); + expect(text).toBe(''); + await route.fulfill({ response }) + }); + await page.goto('${server.EMPTY_PAGE}'); + }); + }); + ` + }, { reporter: '', workers: 1, timeout: 3000 }); + + expect(result.exitCode).toBe(0); + expect(result.passed).toBe(0); + expect(result.output).not.toContain('Internal error'); + expect(stripAnsi(result.output)).toBe(` +hook |Before Hooks +fixture | fixture: browser +pw:api | browserType.launch +fixture | fixture: context +pw:api | browser.newContext +fixture | fixture: page +pw:api | browserContext.newPage +test.step |custom step @ a.test.ts:4 +pw:api | page.route @ a.test.ts:5 +pw:api | page.goto(http://localhost:8907/empty.html) @ a.test.ts:11 +pw:api | apiResponse.text @ a.test.ts:7 +expect | expect.toBe @ a.test.ts:8 +hook |After Hooks +fixture | fixture: page +fixture | fixture: context +`); +}); +