diff --git a/packages/playwright-core/src/client/channelOwner.ts b/packages/playwright-core/src/client/channelOwner.ts index 03bde8c975..e731143a9a 100644 --- a/packages/playwright-core/src/client/channelOwner.ts +++ b/packages/playwright-core/src/client/channelOwner.ts @@ -16,7 +16,7 @@ import { EventEmitter } from './eventEmitter'; import { ValidationError, maybeFindValidator } from '../protocol/validator'; -import { methodMetainfo } from '../protocol/debug'; +import { methodMetainfo } from '../utils/isomorphic/protocolMetainfo'; import { captureLibraryStackTrace } from './clientStackTrace'; import { stringifyStackFrames } from '../utils/isomorphic/stackTrace'; diff --git a/packages/playwright-core/src/server/debugger.ts b/packages/playwright-core/src/server/debugger.ts index 1bec695569..2d158e859e 100644 --- a/packages/playwright-core/src/server/debugger.ts +++ b/packages/playwright-core/src/server/debugger.ts @@ -18,7 +18,7 @@ import { EventEmitter } from 'events'; import { debugMode, isUnderTest, monotonicTime } from '../utils'; import { BrowserContext } from './browserContext'; -import { methodMetainfo } from '../protocol/debug'; +import { methodMetainfo } from '../utils/isomorphic/protocolMetainfo'; import type { CallMetadata, InstrumentationListener, SdkObject } from './instrumentation'; diff --git a/packages/playwright-core/src/server/dispatchers/dispatcher.ts b/packages/playwright-core/src/server/dispatchers/dispatcher.ts index 565fd419bd..b73c07bae1 100644 --- a/packages/playwright-core/src/server/dispatchers/dispatcher.ts +++ b/packages/playwright-core/src/server/dispatchers/dispatcher.ts @@ -18,13 +18,12 @@ import { EventEmitter } from 'events'; import { eventsHelper } from '../utils/eventsHelper'; import { ValidationError, createMetadataValidator, findValidator } from '../../protocol/validator'; -import { LongStandingScope, assert, formatProtocolParam, monotonicTime, rewriteErrorMessage } from '../../utils'; +import { LongStandingScope, assert, monotonicTime, rewriteErrorMessage } from '../../utils'; import { isUnderTest } from '../utils/debug'; import { TargetClosedError, isTargetClosedError, serializeError } from '../errors'; import { SdkObject } from '../instrumentation'; import { isProtocolError } from '../protocolError'; import { compressCallLog } from '../callLog'; -import { methodMetainfo } from '../../protocol/debug'; import type { CallMetadata } from '../instrumentation'; import type { PlaywrightDispatcher } from './playwrightDispatcher'; @@ -309,7 +308,7 @@ export class DispatcherConnection { const callMetadata: CallMetadata = { id: `call@${id}`, location: validMetadata.location, - title: renderTitle(dispatcher._type, method, params, validMetadata.title), + title: validMetadata.title, internal: validMetadata.internal, stepId: validMetadata.stepId, objectId: sdkObject?.guid, @@ -389,10 +388,3 @@ function closeReason(sdkObject: SdkObject): string | undefined { sdkObject.attribution.context?._closeReason || sdkObject.attribution.browser?._closeReason; } - -function renderTitle(type: string, method: string, params: Record | undefined, title?: string) { - const titleFormat = title ?? methodMetainfo.get(type + '.' + method)?.title ?? method; - return titleFormat.replace(/\{([^}]+)\}/g, (_, p1) => { - return formatProtocolParam(params, p1); - }); -} diff --git a/packages/playwright-core/src/server/frames.ts b/packages/playwright-core/src/server/frames.ts index 6d4fc32a71..2150e6c6f5 100644 --- a/packages/playwright-core/src/server/frames.ts +++ b/packages/playwright-core/src/server/frames.ts @@ -27,7 +27,7 @@ import * as network from './network'; import { Page } from './page'; import { ProgressController } from './progress'; import * as types from './types'; -import { LongStandingScope, asLocator, assert, constructURLBasedOnBaseURL, makeWaitForNextTask, monotonicTime } from '../utils'; +import { LongStandingScope, asLocator, assert, constructURLBasedOnBaseURL, makeWaitForNextTask, monotonicTime, renderTitleForCall } from '../utils'; import { isSessionClosedError } from './protocolError'; import { debugLogger } from './utils/debugLogger'; import { eventsHelper } from './utils/eventsHelper'; @@ -1432,7 +1432,7 @@ export class Frame extends SdkObject { // Step 1: perform locator handlers checkpoint with a specified timeout. await (new ProgressController(metadata, this)).run(async progress => { - progress.log(`${metadata.title}${timeout ? ` with timeout ${timeout}ms` : ''}`); + progress.log(`${renderTitleForCall(metadata)}${timeout ? ` with timeout ${timeout}ms` : ''}`); progress.log(`waiting for ${this._asLocator(selector)}`); await this._page.performActionPreChecks(progress); }, timeout); diff --git a/packages/playwright-core/src/server/page.ts b/packages/playwright-core/src/server/page.ts index ae5449bbe6..48ad2b739a 100644 --- a/packages/playwright-core/src/server/page.ts +++ b/packages/playwright-core/src/server/page.ts @@ -27,7 +27,7 @@ import { SdkObject } from './instrumentation'; import * as js from './javascript'; import { ProgressController } from './progress'; import { Screenshotter, validateScreenshotOptions } from './screenshotter'; -import { LongStandingScope, assert, trimStringWithEllipsis } from '../utils'; +import { LongStandingScope, assert, renderTitleForCall, trimStringWithEllipsis } from '../utils'; import { asLocator } from '../utils'; import { getComparator } from './utils/comparators'; import { debugLogger } from './utils/debugLogger'; @@ -624,7 +624,7 @@ export class Page extends SdkObject { let actual: Buffer | undefined; let previous: Buffer | undefined; const pollIntervals = [0, 100, 250, 500]; - progress.log(`${metadata.title}${callTimeout ? ` with timeout ${callTimeout}ms` : ''}`); + progress.log(`${renderTitleForCall(metadata)}${callTimeout ? ` with timeout ${callTimeout}ms` : ''}`); if (options.expected) progress.log(` verifying given screenshot expectation`); else diff --git a/packages/playwright-core/src/server/recorder/recorderUtils.ts b/packages/playwright-core/src/server/recorder/recorderUtils.ts index 39b13fb2bf..1487ae1c39 100644 --- a/packages/playwright-core/src/server/recorder/recorderUtils.ts +++ b/packages/playwright-core/src/server/recorder/recorderUtils.ts @@ -14,6 +14,8 @@ * limitations under the License. */ +import { renderTitleForCall } from '../../utils/isomorphic/protocolFormatter'; + import type { Frame } from '../frames'; import type { CallMetadata } from '../instrumentation'; import type { Page } from '../page'; @@ -25,7 +27,7 @@ export function buildFullSelector(framePath: string[], selector: string) { } export function metadataToCallLog(metadata: CallMetadata, status: CallLogStatus): CallLog { - const title = metadata.title; + const title = renderTitleForCall(metadata); if (metadata.error) status = 'error'; const params = { diff --git a/packages/playwright-core/src/server/trace/recorder/tracing.ts b/packages/playwright-core/src/server/trace/recorder/tracing.ts index 1b77156e47..b95afc594a 100644 --- a/packages/playwright-core/src/server/trace/recorder/tracing.ts +++ b/packages/playwright-core/src/server/trace/recorder/tracing.ts @@ -19,7 +19,7 @@ import os from 'os'; import path from 'path'; import { Snapshotter } from './snapshotter'; -import { methodMetainfo } from '../../../protocol/debug'; +import { methodMetainfo } from '../../../utils/isomorphic/protocolMetainfo'; import { assert } from '../../../utils/isomorphic/assert'; import { monotonicTime } from '../../../utils/isomorphic/time'; import { eventsHelper } from '../../utils/eventsHelper'; diff --git a/packages/playwright-core/src/utils.ts b/packages/playwright-core/src/utils.ts index 090d50d42b..4037c44c14 100644 --- a/packages/playwright-core/src/utils.ts +++ b/packages/playwright-core/src/utils.ts @@ -21,6 +21,8 @@ export * from './utils/isomorphic/locatorGenerators'; export * from './utils/isomorphic/manualPromise'; export * from './utils/isomorphic/mimeType'; export * from './utils/isomorphic/multimap'; +export * from './utils/isomorphic/protocolFormatter'; +export * from './utils/isomorphic/protocolMetainfo'; export * from './utils/isomorphic/rtti'; export * from './utils/isomorphic/semaphore'; export * from './utils/isomorphic/stackTrace'; @@ -52,7 +54,4 @@ export * from './server/utils/wsServer'; export * from './server/utils/zipFile'; export * from './server/utils/zones'; -export * from './protocol/debug'; -export * from './protocol/formatter'; - export { colors } from './utilsBundle'; diff --git a/packages/playwright-core/src/protocol/formatter.ts b/packages/playwright-core/src/utils/isomorphic/protocolFormatter.ts similarity index 73% rename from packages/playwright-core/src/protocol/formatter.ts rename to packages/playwright-core/src/utils/isomorphic/protocolFormatter.ts index 6d273cf5a6..80045bb2e2 100644 --- a/packages/playwright-core/src/protocol/formatter.ts +++ b/packages/playwright-core/src/utils/isomorphic/protocolFormatter.ts @@ -14,6 +14,8 @@ * limitations under the License. */ +import { methodMetainfo } from './protocolMetainfo'; + export function formatProtocolParam(params: Record | undefined, name: string): string { if (!params) return ''; @@ -29,8 +31,10 @@ export function formatProtocolParam(params: Record | undefined, return params[name]; } } - if (name === 'timeNumber') + if (name === 'timeNumber') { + // eslint-disable-next-line no-restricted-globals return new Date(params[name]).toString(); + } return deepParam(params, name); } @@ -46,3 +50,10 @@ function deepParam(params: Record, name: string): string { return ''; return String(current); } + +export function renderTitleForCall(metadata: { title?: string, type: string, method: string, params: Record | undefined }) { + const titleFormat = metadata.title ?? methodMetainfo.get(metadata.type + '.' + metadata.method)?.title ?? metadata.method; + return titleFormat.replace(/\{([^}]+)\}/g, (_, p1) => { + return formatProtocolParam(metadata.params, p1); + }); +} diff --git a/packages/playwright-core/src/protocol/debug.ts b/packages/playwright-core/src/utils/isomorphic/protocolMetainfo.ts similarity index 100% rename from packages/playwright-core/src/protocol/debug.ts rename to packages/playwright-core/src/utils/isomorphic/protocolMetainfo.ts diff --git a/packages/playwright/src/index.ts b/packages/playwright/src/index.ts index b1d907acbd..bea4d31157 100644 --- a/packages/playwright/src/index.ts +++ b/packages/playwright/src/index.ts @@ -18,7 +18,7 @@ import fs from 'fs'; import path from 'path'; import * as playwrightLibrary from 'playwright-core'; -import { setBoxedStackPrefixes, createGuid, currentZone, debugMode, jsonStringifyForceASCII, methodMetainfo, asLocatorDescription, formatProtocolParam } from 'playwright-core/lib/utils'; +import { setBoxedStackPrefixes, createGuid, currentZone, debugMode, jsonStringifyForceASCII, asLocatorDescription, renderTitleForCall } from 'playwright-core/lib/utils'; import { currentTestInfo } from './common/globals'; import { rootTestType } from './common/testType'; @@ -758,8 +758,7 @@ class ArtifactsRecorder { } function renderTitle(type: string, method: string, params: Record | undefined, title?: string) { - const titleFormat = title ?? methodMetainfo.get(type + '.' + method)?.title ?? method; - const prefix = titleFormat.replace(/\{([^}]+)\}/g, (_, p1) => formatProtocolParam(params, p1)); + const prefix = renderTitleForCall({ title, type, method, params }); let selector; if (params?.['selector']) selector = asLocatorDescription('javascript', params.selector); diff --git a/packages/trace-viewer/src/ui/actionList.tsx b/packages/trace-viewer/src/ui/actionList.tsx index 5a08951a47..6e86410e24 100644 --- a/packages/trace-viewer/src/ui/actionList.tsx +++ b/packages/trace-viewer/src/ui/actionList.tsx @@ -26,6 +26,8 @@ import type { ActionTraceEventInContext, ActionTreeItem } from './modelUtil'; import type { Boundaries } from './geometry'; import { ToolbarButton } from '@web/components/toolbarButton'; import { testStatusIcon } from './testUtils'; +import { methodMetainfo } from '@isomorphic/protocolMetainfo'; +import { formatProtocolParam } from '@isomorphic/protocolFormatter'; export interface ActionListProps { actions: ActionTraceEventInContext[], @@ -128,10 +130,10 @@ export const renderAction = ( time = 'Timed out'; else if (!isLive) time = '-'; - const renderedTitle = highlightQuotedText(action.title || action.method); + const { elements, title } = renderTitleForCall(action); return
- {renderedTitle} + {elements} {(showDuration || showBadges || showAttachments || isSkipped) &&
} {showAttachments && revealAttachment(action.attachments![0])} />} {showDuration && !isSkipped &&
{time || }
} @@ -145,19 +147,33 @@ export const renderAction = (
; }; -function highlightQuotedText(text: string): React.ReactNode[] { - const result: React.ReactNode[] = []; +export function renderTitleForCall(action: ActionTraceEvent): { elements: React.ReactNode[], title: string } { + const titleFormat = action.title ?? methodMetainfo.get(action.class + '.' + action.method)?.title ?? action.method; + + const elements: React.ReactNode[] = []; + const title: string[] = []; let currentIndex = 0; - const regex = /("[^"]*")/g; + const regex = /\{([^}]+)\}/g; let match; - while ((match = regex.exec(text)) !== null) { + while ((match = regex.exec(titleFormat)) !== null) { const [fullMatch, quotedText] = match; - result.push(text.slice(currentIndex, match.index)); - result.push({quotedText}); + const chunk = titleFormat.slice(currentIndex, match.index); + + elements.push(chunk); + title.push(chunk); + + const param = formatProtocolParam(action.params, quotedText); + elements.push({param}); + title.push(param); currentIndex = match.index + fullMatch.length; } - if (currentIndex < text.length) - result.push(text.slice(currentIndex)); - return result; + + if (currentIndex < titleFormat.length) { + const chunk = titleFormat.slice(currentIndex); + elements.push(chunk); + title.push(chunk); + } + + return { elements, title: title.join('') }; } diff --git a/tests/config/utils.ts b/tests/config/utils.ts index b3d3792428..293fbb81a8 100644 --- a/tests/config/utils.ts +++ b/tests/config/utils.ts @@ -24,6 +24,7 @@ import type { ActionTreeItem } from '../../packages/trace-viewer/src/ui/modelUti import { buildActionTree, MultiTraceModel } from '../../packages/trace-viewer/src/ui/modelUtil'; import type { ActionTraceEvent, ConsoleMessageTraceEvent, EventTraceEvent, TraceEvent } from '@trace/trace'; import style from 'ansi-styles'; +import { renderTitleForCall } from '../../packages/playwright-core/lib/utils/isomorphic/protocolFormatter'; export async function attachFrame(page: Page, frameId: string, url: string): Promise { const handle = await page.evaluateHandle(async ({ frameId, url }) => { @@ -151,7 +152,7 @@ export async function parseTraceRaw(file: string): Promise<{ events: any[], reso return { events, resources, - actions: actionObjects.map(a => a.title ?? a.class.toLowerCase() + '.' + a.method), + actions: actionObjects.map(a => renderTitleForCall({ ...a, type: a.class })), actionObjects, stacks, }; @@ -165,13 +166,14 @@ export async function parseTrace(file: string): Promise<{ resources: Map { - actionTree.push(`${indent}${actionItem.action?.title || actionItem.id}`); + const title = renderTitleForCall({ ...actionItem.action, type: actionItem.action.class }); + actionTree.push(`${indent}${title || actionItem.id}`); for (const child of actionItem.children) visit(child, indent + ' '); }; rootItem.children.forEach(a => visit(a, '')); return { - titles: model.actions.map(a => a.title ?? a.class.toLowerCase() + '.' + a.method), + titles: model.actions.map(a => renderTitleForCall({ ...a, type: a.class })), resources: backend.entries, actions: model.actions, events: model.events, diff --git a/tests/library/trace-viewer.spec.ts b/tests/library/trace-viewer.spec.ts index d1abdb0332..87f7681cb0 100644 --- a/tests/library/trace-viewer.spec.ts +++ b/tests/library/trace-viewer.spec.ts @@ -271,7 +271,7 @@ test('should render console', async ({ showTraceViewer, browserName }) => { await expect.soft(traceViewer.consoleLines.filter({ hasText: 'Cheers!' }).locator('.codicon')).toHaveClass('codicon codicon-browser status-none'); await expect(traceViewer.consoleStacks.first()).toContainText('Error: Unhandled exception'); - await traceViewer.selectAction('EVALUATE'); + await traceViewer.selectAction('Evaluate'); const listViews = traceViewer.page.locator('.console-tab').locator('.list-view-entry'); await expect(listViews.nth(0)).toHaveClass('list-view-entry'); @@ -284,17 +284,17 @@ test('should render console', async ({ showTraceViewer, browserName }) => { test('should open console errors on click', async ({ showTraceViewer, browserName }) => { const traceViewer = await showTraceViewer([traceFile]); - expect(await traceViewer.actionIconsText('EVALUATE')).toEqual(['2', '1']); + expect(await traceViewer.actionIconsText('Evaluate')).toEqual(['2', '1']); expect(await traceViewer.page.isHidden('.console-tab')).toBeTruthy(); - await (await traceViewer.actionIcons('EVALUATE')).click(); + await (await traceViewer.actionIcons('Evaluate')).click(); expect(await traceViewer.page.waitForSelector('.console-tab')).toBeTruthy(); }); test('should show params and return value', async ({ showTraceViewer }) => { const traceViewer = await showTraceViewer([traceFile]); - await traceViewer.selectAction('EVALUATE'); + await traceViewer.selectAction('Evaluate'); await expect(traceViewer.callLines).toHaveText([ - /Evaluate/, + '', /start:[\d\.]+m?s/, /duration:[\d]+ms/, /expression:"\({↵ a↵ }\) => {↵ console\.log\(\'Info\'\);↵ console\.warn\(\'Warning\'\);↵ console/, @@ -318,9 +318,9 @@ test('should show params and return value', async ({ showTraceViewer }) => { test('should show null as a param', async ({ showTraceViewer, browserName }) => { const traceViewer = await showTraceViewer([traceFile]); - await traceViewer.selectAction('EVALUATE', 1); + await traceViewer.selectAction('Evaluate', 1); await expect(traceViewer.callLines).toHaveText([ - /Evaluate/, + '', /start:[\d\.]+m?s/, /duration:[\d]+ms/, 'expression:"() => 1 + 1"', @@ -354,7 +354,7 @@ test('should have correct stack trace', async ({ showTraceViewer }) => { test('should have network requests', async ({ showTraceViewer }) => { const traceViewer = await showTraceViewer([traceFile]); - await traceViewer.selectAction('NAVIGATE'); + await traceViewer.selectAction('Navigate'); await traceViewer.showNetworkTab(); await expect(traceViewer.networkRequests).toContainText([/frame.htmlGET200text\/html/]); await expect(traceViewer.networkRequests).toContainText([/style.cssGET200text\/css/]); @@ -369,7 +369,7 @@ test('should filter network requests by resource type', async ({ page, runAndTra await page.goto(`${server.PREFIX}/network-tab/network.html`); await page.evaluate(() => (window as any).donePromise); }); - await traceViewer.selectAction('NAVIGATE'); + await traceViewer.selectAction('Navigate'); await traceViewer.showNetworkTab(); await traceViewer.page.getByText('JS', { exact: true }).click(); @@ -402,7 +402,7 @@ test('should show font preview', async ({ page, runAndTrace, server }) => { await page.goto(`${server.PREFIX}/network-tab/network.html`); await page.evaluate(() => (window as any).donePromise); }); - await traceViewer.selectAction('NAVIGATE'); + await traceViewer.selectAction('Navigate'); await traceViewer.showNetworkTab(); await traceViewer.page.getByText('Font', { exact: true }).click(); @@ -417,7 +417,7 @@ test('should filter network requests by url', async ({ page, runAndTrace, server await page.goto(`${server.PREFIX}/network-tab/network.html`); await page.evaluate(() => (window as any).donePromise); }); - await traceViewer.selectAction('NAVIGATE'); + await traceViewer.selectAction('Navigate'); await traceViewer.showNetworkTab(); await traceViewer.page.getByPlaceholder('Filter network').fill('script.'); @@ -446,7 +446,7 @@ test('should have network request overrides', async ({ page, server, runAndTrace await page.route('**/style.css', route => route.abort()); await page.goto(server.PREFIX + '/frames/frame.html'); }); - await traceViewer.selectAction('NAVIGATE'); + await traceViewer.selectAction('Navigate'); await traceViewer.showNetworkTab(); await expect(traceViewer.networkRequests).toContainText([/frame.htmlGET200text\/html/]); await expect(traceViewer.networkRequests).toContainText([/style.cssGETx-unknown.*aborted/]); @@ -458,7 +458,7 @@ test('should have network request overrides 2', async ({ page, server, runAndTra await page.route('**/script.js', route => route.continue()); await page.goto(server.PREFIX + '/frames/frame.html'); }); - await traceViewer.selectAction('NAVIGATE'); + await traceViewer.selectAction('Navigate'); await traceViewer.showNetworkTab(); await expect.soft(traceViewer.networkRequests).toContainText([/frame.htmlGET200text\/html.*/]); await expect.soft(traceViewer.networkRequests).toContainText([/script.jsGET200application\/javascript.*continued/]); @@ -1506,7 +1506,7 @@ test('should show correct request start time', { return fetch('/api').then(r => r.text()); }); }); - await traceViewer.selectAction('EVALUATE'); + await traceViewer.selectAction('Evaluate'); await traceViewer.showNetworkTab(); await expect(traceViewer.networkRequests).toContainText([/apiGET200text/]); const line = traceViewer.networkRequests.getByText(/apiGET200text/); @@ -1553,7 +1553,7 @@ test('should show baseURL in metadata pane', { annotation: { type: 'issue', description: 'https://github.com/microsoft/playwright/issues/31847' }, }, async ({ showTraceViewer }) => { const traceViewer = await showTraceViewer([traceFile]); - await traceViewer.selectAction('EVALUATE'); + await traceViewer.selectAction('Evaluate'); await traceViewer.showMetadataTab(); await expect(traceViewer.metadataTab).toContainText('baseURL:https://example.com'); }); @@ -1595,22 +1595,22 @@ test('should not leak recorders', { await expect(traceViewer.snapshotContainer.contentFrame().locator('body')).toContainText(`Hi, I'm frame`); - const frame1 = await forceRecorder('NAVIGATE'); + const frame1 = await forceRecorder('Navigate'); await expect(frame1.locator('body')).toContainText('Hello world'); - const frame2 = await forceRecorder('EVALUATE'); + const frame2 = await forceRecorder('Evaluate'); await expect(frame2.locator('button')).toBeVisible(); await traceViewer.page.requestGC(); await expect.poll(() => aliveCount()).toBeLessThanOrEqual(2); // two snapshot iframes - const frame3 = await forceRecorder('SET VIEWPORT SIZE'); + const frame3 = await forceRecorder('Set viewport size'); await expect(frame3.locator('body')).toContainText(`Hi, I'm frame`); - const frame4 = await forceRecorder('NAVIGATE'); + const frame4 = await forceRecorder('Navigate'); await expect(frame4.locator('body')).toContainText('Hello world'); - const frame5 = await forceRecorder('EVALUATE'); + const frame5 = await forceRecorder('Evaluate'); await expect(frame5.locator('button')).toBeVisible(); await traceViewer.page.requestGC(); @@ -1751,14 +1751,14 @@ test('should show a modal dialog', async ({ runAndTrace, page, platform, browser test('should open settings dialog', async ({ showTraceViewer }) => { const traceViewer = await showTraceViewer([traceFile]); - await traceViewer.selectAction('NAVIGATE'); + await traceViewer.selectAction('Navigate'); await traceViewer.showSettings(); await expect(traceViewer.settingsDialog).toBeVisible(); }); test('should toggle theme color', async ({ showTraceViewer, page }) => { const traceViewer = await showTraceViewer([traceFile]); - await traceViewer.selectAction('NAVIGATE'); + await traceViewer.selectAction('Navigate'); await traceViewer.showSettings(); await expect(traceViewer.darkModeSetting).toBeChecked({ checked: false }); @@ -1781,7 +1781,7 @@ test('should toggle canvas rendering', async ({ runAndTrace, page }) => { let snapshotRequestPromise = traceViewer.page.waitForRequest(request => request.url().includes('/snapshot/')); // Click on the action with a canvas snapshot - await traceViewer.selectAction('NAVIGATE', 0); + await traceViewer.selectAction('Navigate', 0); let snapshotRequest = await snapshotRequestPromise; @@ -1794,12 +1794,12 @@ test('should toggle canvas rendering', async ({ runAndTrace, page }) => { await expect(traceViewer.displayCanvasContentSetting).toBeChecked({ checked: true }); // Deselect canvas - await traceViewer.selectAction('NAVIGATE', 1); + await traceViewer.selectAction('Navigate', 1); snapshotRequestPromise = traceViewer.page.waitForRequest(request => request.url().includes('/snapshot/')); // Select canvas again - await traceViewer.selectAction('NAVIGATE', 0); + await traceViewer.selectAction('Navigate', 0); snapshotRequest = await snapshotRequestPromise; diff --git a/tests/library/tracing.spec.ts b/tests/library/tracing.spec.ts index 2749876a4d..1a88370e38 100644 --- a/tests/library/tracing.spec.ts +++ b/tests/library/tracing.spec.ts @@ -134,7 +134,7 @@ test('should not include buffers in the trace', async ({ context, page, server } await page.screenshot(); await context.tracing.stop({ path: testInfo.outputPath('trace.zip') }); const { actionObjects } = await parseTraceRaw(testInfo.outputPath('trace.zip')); - const screenshotEvent = actionObjects.find(a => a.title === 'Screenshot'); + const screenshotEvent = actionObjects.find(a => a.method === 'screenshot'); expect(screenshotEvent.beforeSnapshot).toBeTruthy(); expect(screenshotEvent.afterSnapshot).toBeTruthy(); expect(screenshotEvent.result).toEqual({ @@ -160,13 +160,12 @@ test('should exclude internal pages', async ({ browserName, context, page, serve expect(pageIds.size).toBe(1); }); -test('should include context API requests', async ({ browserName, context, page, server }, testInfo) => { +test('should include context API requests', async ({ context, page, server }, testInfo) => { await context.tracing.start({ snapshots: true }); await page.request.post(server.PREFIX + '/simple.json', { data: { foo: 'bar' } }); await context.tracing.stop({ path: testInfo.outputPath('trace.zip') }); - const { events } = await parseTraceRaw(testInfo.outputPath('trace.zip')); - const postEvent = events.find(e => e.title === 'Fetch "/simple.json"'); - expect(postEvent).toBeTruthy(); + const { events, actions } = await parseTraceRaw(testInfo.outputPath('trace.zip')); + expect(actions).toContain('Fetch "/simple.json"'); const harEntry = events.find(e => e.type === 'resource-snapshot'); expect(harEntry).toBeTruthy(); expect(harEntry.snapshot.request.url).toBe(server.PREFIX + '/simple.json'); @@ -482,9 +481,8 @@ test('should include interrupted actions', async ({ context, page, server }, tes await context.tracing.stop({ path: testInfo.outputPath('trace.zip') }); await context.close(); - const { events } = await parseTraceRaw(testInfo.outputPath('trace.zip')); - const clickEvent = events.find(e => e.title === 'Click'); - expect(clickEvent).toBeTruthy(); + const { actions } = await parseTraceRaw(testInfo.outputPath('trace.zip')); + expect(actions).toContain('Click'); }); test('should throw when starting with different options', async ({ context }) => { @@ -741,7 +739,6 @@ test('should not flush console events', async ({ context, page, mode }, testInfo await expect(async () => { const traceName = fs.readdirSync(dir).find(name => name.endsWith(testId + '.trace')); content = await fs.promises.readFile(path.join(dir, traceName), 'utf8'); - expect(content).toContain('Evaluate'); expect(content).toContain('31415926'); }).toPass(); expect(content).not.toContain('hello 0'); @@ -823,17 +820,14 @@ test('should not emit after w/o before', async ({ browserType, mode }, testInfo) { type: 'before', callId: expect.any(Number), - title: 'Evaluate' }, { type: 'before', callId: expect.any(Number), - title: 'Wait for event "console"' }, { type: 'after', callId: expect.any(Number), - title: undefined, }, ]); call1 = sanitized[0].callId; @@ -849,12 +843,10 @@ test('should not emit after w/o before', async ({ browserType, mode }, testInfo) { type: 'before', callId: expect.any(Number), - title: 'Evaluate' }, { type: 'after', callId: expect.any(Number), - title: undefined } ]); call2before = sanitized[0].callId; diff --git a/tests/playwright-test/playwright.trace.spec.ts b/tests/playwright-test/playwright.trace.spec.ts index 159d3cc50e..256ce335d4 100644 --- a/tests/playwright-test/playwright.trace.spec.ts +++ b/tests/playwright-test/playwright.trace.spec.ts @@ -1346,7 +1346,7 @@ test('should record trace snapshot for more obscure commands', async ({ runInlin const snapshots = trace.traceModel.storage(); const snapshotFrameOrPageId = snapshots.snapshotsForTest()[0]; - const countAction = trace.actions.find(a => a.title === 'Query count'); + const countAction = trace.actions.find(a => a.method === 'queryCount'); expect(countAction.beforeSnapshot).toBeTruthy(); expect(countAction.afterSnapshot).toBeTruthy(); expect(snapshots.snapshotByName(snapshotFrameOrPageId, countAction.beforeSnapshot)).toBeTruthy(); diff --git a/utils/generate_channels.js b/utils/generate_channels.js index 8746941be5..3389f16275 100755 --- a/utils/generate_channels.js +++ b/utils/generate_channels.js @@ -157,7 +157,7 @@ export type { Validator, ValidatorContext } from './validatorPrimitives'; export { ValidationError, findValidator, maybeFindValidator, createMetadataValidator } from './validatorPrimitives'; `]; -const debug_ts = [ +const metainfo_ts = [ `/** * Copyright (c) Microsoft Corporation. * @@ -328,7 +328,7 @@ for (const [name, item] of Object.entries(protocol)) { } } -debug_ts.push(`export const methodMetainfo = new Map([ +metainfo_ts.push(`export const methodMetainfo = new Map([ ${methodMetainfo.join(`,\n `)} ]);`); @@ -348,6 +348,6 @@ function writeFile(filePath, content) { } writeFile(path.join(__dirname, '..', 'packages', 'protocol', 'src', 'channels.d.ts'), channels_ts.join('\n') + '\n'); -writeFile(path.join(__dirname, '..', 'packages', 'playwright-core', 'src', 'protocol', 'debug.ts'), debug_ts.join('\n') + '\n'); +writeFile(path.join(__dirname, '..', 'packages', 'playwright-core', 'src', 'utils', 'isomorphic', 'protocolMetainfo.ts'), metainfo_ts.join('\n') + '\n'); writeFile(path.join(__dirname, '..', 'packages', 'playwright-core', 'src', 'protocol', 'validator.ts'), validator_ts.join('\n') + '\n'); process.exit(hasChanges ? 1 : 0);