mirror of
https://github.com/microsoft/playwright.git
synced 2025-06-26 21:40:17 +00:00
chore: move from apiName to title in tracing (#36003)
This commit is contained in:
parent
3c888d59dd
commit
27ce0eb867
@ -47,7 +47,7 @@ import type * as har from '@trace/har';
|
||||
import type { FrameSnapshot } from '@trace/snapshot';
|
||||
import type * as trace from '@trace/trace';
|
||||
|
||||
const version: trace.VERSION = 7;
|
||||
const version: trace.VERSION = 8;
|
||||
|
||||
export type TracerOptions = {
|
||||
name?: string;
|
||||
@ -230,7 +230,7 @@ export class Tracing extends SdkObject implements InstrumentationListener, Snaps
|
||||
type: 'before',
|
||||
callId: metadata.id,
|
||||
startTime: metadata.startTime,
|
||||
apiName: name,
|
||||
title: name,
|
||||
class: 'Tracing',
|
||||
method: 'tracingGroup',
|
||||
params: { },
|
||||
@ -650,7 +650,10 @@ function createBeforeActionTraceEvent(metadata: CallMetadata, parentId?: string)
|
||||
type: 'before',
|
||||
callId: metadata.id,
|
||||
startTime: metadata.startTime,
|
||||
apiName: metadata.apiName || metadata.type + '.' + metadata.method,
|
||||
// This will disappear for action trace events, their titles will be
|
||||
// built based on the protocol metainfo. If I don't do this now,
|
||||
// trace ill get frame.click instead of page.click in trace viewer.
|
||||
title: metadata.apiName,
|
||||
class: metadata.type,
|
||||
method: metadata.method,
|
||||
params: metadata.params,
|
||||
|
@ -329,7 +329,7 @@ export class TestInfoImpl implements TestInfo {
|
||||
location: data.location,
|
||||
};
|
||||
this._onStepBegin(payload);
|
||||
this._tracing.appendBeforeActionForStep(stepId, parentStep?.stepId, data.apiName || data.title, data.params, data.location ? [data.location] : []);
|
||||
this._tracing.appendBeforeActionForStep(stepId, parentStep?.stepId, { title: data.title, params: data.params, stack: data.location ? [data.location] : [] });
|
||||
return step;
|
||||
}
|
||||
|
||||
@ -425,7 +425,7 @@ export class TestInfoImpl implements TestInfo {
|
||||
this._stepMap.get(stepId)!.attachmentIndices.push(index);
|
||||
} else {
|
||||
const callId = `attach@${createGuid()}`;
|
||||
this._tracing.appendBeforeActionForStep(callId, undefined, `Attach "${attachment.name}"`, undefined, []);
|
||||
this._tracing.appendBeforeActionForStep(callId, undefined, { title: `Attach "${attachment.name}"`, stack: [] });
|
||||
this._tracing.appendAfterActionForStep(callId, undefined, [attachment]);
|
||||
}
|
||||
|
||||
|
@ -31,7 +31,7 @@ import type EventEmitter from 'events';
|
||||
|
||||
export type Attachment = TestInfo['attachments'][0];
|
||||
export const testTraceEntryName = 'test.trace';
|
||||
const version: trace.VERSION = 7;
|
||||
const version: trace.VERSION = 8;
|
||||
let traceOrdinal = 0;
|
||||
|
||||
type TraceFixtureValue = PlaywrightWorkerOptions['trace'] | undefined;
|
||||
@ -267,7 +267,7 @@ export class TestTracing {
|
||||
});
|
||||
}
|
||||
|
||||
appendBeforeActionForStep(callId: string, parentId: string | undefined, apiName: string, params: Record<string, any> | undefined, stack: StackFrame[]) {
|
||||
appendBeforeActionForStep(callId: string, parentId: string | undefined, options: { title: string, params?: Record<string, any>, stack: StackFrame[] }) {
|
||||
this._appendTraceEvent({
|
||||
type: 'before',
|
||||
callId,
|
||||
@ -275,9 +275,9 @@ export class TestTracing {
|
||||
startTime: monotonicTime(),
|
||||
class: 'Test',
|
||||
method: 'step',
|
||||
apiName,
|
||||
params: Object.fromEntries(Object.entries(params || {}).map(([name, value]) => [name, generatePreview(value)])),
|
||||
stack,
|
||||
title: options.title,
|
||||
params: Object.fromEntries(Object.entries(options.params || {}).map(([name, value]) => [name, generatePreview(value)])),
|
||||
stack: options.stack,
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -20,6 +20,7 @@ import type * as traceV4 from './versions/traceV4';
|
||||
import type * as traceV5 from './versions/traceV5';
|
||||
import type * as traceV6 from './versions/traceV6';
|
||||
import type * as traceV7 from './versions/traceV7';
|
||||
import type * as traceV8 from './versions/traceV8';
|
||||
import type { ActionEntry, ContextEntry, PageEntry } from '../types/entries';
|
||||
import type { SnapshotStorage } from './snapshotStorage';
|
||||
|
||||
@ -32,7 +33,7 @@ export class TraceVersionError extends Error {
|
||||
|
||||
// 6 => 10/2023 ~1.40
|
||||
// 7 => 05/2024 ~1.45
|
||||
const latestVersion: trace.VERSION = 7;
|
||||
const latestVersion: trace.VERSION = 8;
|
||||
|
||||
export class TraceModernizer {
|
||||
private _contextEntry: ContextEntry;
|
||||
@ -409,4 +410,15 @@ export class TraceModernizer {
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
_modernize_7_to_8(events: traceV7.TraceEvent[]): traceV8.TraceEvent[] {
|
||||
const result: traceV8.TraceEvent[] = [];
|
||||
for (const event of events) {
|
||||
result.push(event);
|
||||
if (event.type !== 'before' || !event.apiName)
|
||||
continue;
|
||||
(event as traceV8.BeforeActionTraceEvent).title = event.apiName;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
260
packages/trace-viewer/src/sw/versions/traceV8.ts
Normal file
260
packages/trace-viewer/src/sw/versions/traceV8.ts
Normal file
@ -0,0 +1,260 @@
|
||||
/**
|
||||
* 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 { Entry as ResourceSnapshot } from '@trace/har';
|
||||
|
||||
type Language = 'javascript' | 'python' | 'java' | 'csharp' | 'jsonl';
|
||||
type Point = { x: number, y: number };
|
||||
type Size = { width: number, height: number };
|
||||
|
||||
type StackFrame = {
|
||||
file: string,
|
||||
line: number,
|
||||
column: number,
|
||||
function?: string,
|
||||
};
|
||||
|
||||
type Binary = Buffer;
|
||||
|
||||
type SerializedValue = {
|
||||
n?: number,
|
||||
b?: boolean,
|
||||
s?: string,
|
||||
v?: 'null' | 'undefined' | 'NaN' | 'Infinity' | '-Infinity' | '-0',
|
||||
d?: string,
|
||||
u?: string,
|
||||
bi?: string,
|
||||
ta?: {
|
||||
b: Binary,
|
||||
k: 'i8' | 'ui8' | 'ui8c' | 'i16' | 'ui16' | 'i32' | 'ui32' | 'f32' | 'f64' | 'bi64' | 'bui64',
|
||||
},
|
||||
e?: {
|
||||
m: string,
|
||||
n: string,
|
||||
s: string,
|
||||
},
|
||||
r?: {
|
||||
p: string,
|
||||
f: string,
|
||||
},
|
||||
a?: SerializedValue[],
|
||||
o?: {
|
||||
k: string,
|
||||
v: SerializedValue,
|
||||
}[],
|
||||
h?: number,
|
||||
id?: number,
|
||||
ref?: number,
|
||||
};
|
||||
|
||||
type SerializedError = {
|
||||
error?: {
|
||||
message: string,
|
||||
name: string,
|
||||
stack?: string,
|
||||
},
|
||||
value?: SerializedValue,
|
||||
};
|
||||
|
||||
// Text node.
|
||||
type TextNodeSnapshot = string;
|
||||
// Subtree reference, "x snapshots ago, node #y". Could point to a text node.
|
||||
// Only nodes that are not references are counted, starting from zero, using post-order traversal.
|
||||
type SubtreeReferenceSnapshot = [ [number, number] ];
|
||||
// Node name, and optional attributes and child nodes.
|
||||
type NodeNameAttributesChildNodesSnapshot = [ string ] | [ string, Record<string, string>, ...NodeSnapshot[] ];
|
||||
|
||||
type NodeSnapshot =
|
||||
TextNodeSnapshot |
|
||||
SubtreeReferenceSnapshot |
|
||||
NodeNameAttributesChildNodesSnapshot;
|
||||
|
||||
type ResourceOverride = {
|
||||
url: string,
|
||||
sha1?: string,
|
||||
ref?: number
|
||||
};
|
||||
|
||||
type FrameSnapshot = {
|
||||
snapshotName?: string,
|
||||
callId: string,
|
||||
pageId: string,
|
||||
frameId: string,
|
||||
frameUrl: string,
|
||||
timestamp: number,
|
||||
wallTime?: number,
|
||||
collectionTime: number,
|
||||
doctype?: string,
|
||||
html: NodeSnapshot,
|
||||
resourceOverrides: ResourceOverride[],
|
||||
viewport: { width: number, height: number },
|
||||
isMainFrame: boolean,
|
||||
};
|
||||
|
||||
type BrowserContextEventOptions = {
|
||||
baseURL?: string,
|
||||
viewport?: Size,
|
||||
deviceScaleFactor?: number,
|
||||
isMobile?: boolean,
|
||||
userAgent?: string,
|
||||
};
|
||||
|
||||
export type ContextCreatedTraceEvent = {
|
||||
version: number,
|
||||
type: 'context-options',
|
||||
origin: 'testRunner' | 'library',
|
||||
browserName: string,
|
||||
channel?: string,
|
||||
platform: string,
|
||||
wallTime: number,
|
||||
monotonicTime: number,
|
||||
title?: string,
|
||||
options: BrowserContextEventOptions,
|
||||
sdkLanguage?: Language,
|
||||
testIdAttributeName?: string,
|
||||
contextId?: string,
|
||||
};
|
||||
|
||||
export type ScreencastFrameTraceEvent = {
|
||||
type: 'screencast-frame',
|
||||
pageId: string,
|
||||
sha1: string,
|
||||
width: number,
|
||||
height: number,
|
||||
timestamp: number,
|
||||
frameSwapWallTime?: number,
|
||||
};
|
||||
|
||||
export type BeforeActionTraceEvent = {
|
||||
type: 'before',
|
||||
callId: string;
|
||||
startTime: number;
|
||||
title?: string;
|
||||
class: string;
|
||||
method: string;
|
||||
params: Record<string, any>;
|
||||
stepId?: string;
|
||||
beforeSnapshot?: string;
|
||||
stack?: StackFrame[];
|
||||
pageId?: string;
|
||||
parentId?: string;
|
||||
};
|
||||
|
||||
export type InputActionTraceEvent = {
|
||||
type: 'input',
|
||||
callId: string;
|
||||
inputSnapshot?: string;
|
||||
point?: Point;
|
||||
};
|
||||
|
||||
export type AfterActionTraceEventAttachment = {
|
||||
name: string;
|
||||
contentType: string;
|
||||
path?: string;
|
||||
sha1?: string;
|
||||
base64?: string;
|
||||
};
|
||||
|
||||
export type AfterActionTraceEventAnnotation = {
|
||||
type: string,
|
||||
description?: string
|
||||
};
|
||||
|
||||
export type AfterActionTraceEvent = {
|
||||
type: 'after',
|
||||
callId: string;
|
||||
endTime: number;
|
||||
afterSnapshot?: string;
|
||||
error?: SerializedError['error'];
|
||||
attachments?: AfterActionTraceEventAttachment[];
|
||||
annotations?: AfterActionTraceEventAnnotation[];
|
||||
result?: any;
|
||||
point?: Point;
|
||||
};
|
||||
|
||||
export type LogTraceEvent = {
|
||||
type: 'log',
|
||||
callId: string;
|
||||
time: number;
|
||||
message: string;
|
||||
};
|
||||
|
||||
export type EventTraceEvent = {
|
||||
type: 'event',
|
||||
time: number;
|
||||
class: string;
|
||||
method: string;
|
||||
params: any;
|
||||
pageId?: string;
|
||||
};
|
||||
|
||||
export type ConsoleMessageTraceEvent = {
|
||||
type: 'console';
|
||||
time: number;
|
||||
pageId?: string;
|
||||
messageType: string,
|
||||
text: string,
|
||||
args?: { preview: string, value: any }[],
|
||||
location: {
|
||||
url: string,
|
||||
lineNumber: number,
|
||||
columnNumber: number,
|
||||
},
|
||||
};
|
||||
|
||||
export type ResourceSnapshotTraceEvent = {
|
||||
type: 'resource-snapshot',
|
||||
snapshot: ResourceSnapshot,
|
||||
};
|
||||
|
||||
export type FrameSnapshotTraceEvent = {
|
||||
type: 'frame-snapshot',
|
||||
snapshot: FrameSnapshot,
|
||||
};
|
||||
|
||||
export type ActionTraceEvent = {
|
||||
type: 'action',
|
||||
} & Omit<BeforeActionTraceEvent, 'type'>
|
||||
& Omit<AfterActionTraceEvent, 'type'>
|
||||
& Omit<InputActionTraceEvent, 'type'>;
|
||||
|
||||
export type StdioTraceEvent = {
|
||||
type: 'stdout' | 'stderr';
|
||||
timestamp: number;
|
||||
text?: string;
|
||||
base64?: string;
|
||||
};
|
||||
|
||||
export type ErrorTraceEvent = {
|
||||
type: 'error';
|
||||
message: string;
|
||||
stack?: StackFrame[];
|
||||
};
|
||||
|
||||
export type TraceEvent =
|
||||
ContextCreatedTraceEvent |
|
||||
ScreencastFrameTraceEvent |
|
||||
ActionTraceEvent |
|
||||
BeforeActionTraceEvent |
|
||||
InputActionTraceEvent |
|
||||
AfterActionTraceEvent |
|
||||
EventTraceEvent |
|
||||
LogTraceEvent |
|
||||
ConsoleMessageTraceEvent |
|
||||
ResourceSnapshotTraceEvent |
|
||||
FrameSnapshotTraceEvent |
|
||||
StdioTraceEvent |
|
||||
ErrorTraceEvent;
|
@ -128,9 +128,10 @@ export const renderAction = (
|
||||
time = 'Timed out';
|
||||
else if (!isLive)
|
||||
time = '-';
|
||||
const title = action.title ?? action.class.toLowerCase() + '.' + action.method;
|
||||
return <>
|
||||
<div className='action-title' title={action.apiName}>
|
||||
<span>{action.apiName}</span>
|
||||
<div className='action-title' title={title}>
|
||||
<span>{title}</span>
|
||||
{parameterString &&
|
||||
(parameterString.type === 'locator' ? (
|
||||
<>
|
||||
|
@ -42,7 +42,7 @@ export const CallTab: React.FunctionComponent<{
|
||||
|
||||
return (
|
||||
<div className='call-tab'>
|
||||
<div className='call-line'>{action.apiName}</div>
|
||||
<div className='call-line'>{action.title}</div>
|
||||
<div className='call-section'>Time</div>
|
||||
<DateTimeCallLine name='start:' value={startTime} />
|
||||
<DateTimeCallLine name='duration:' value={renderDuration(action)} />
|
||||
|
@ -153,9 +153,9 @@ function indexModel(context: ContextEntry) {
|
||||
}
|
||||
let lastNonRouteAction = undefined;
|
||||
for (let i = context.actions.length - 1; i >= 0; i--) {
|
||||
const action = context.actions[i] as any;
|
||||
action[nextInContextSymbol] = lastNonRouteAction;
|
||||
if (!action.apiName.includes('route.'))
|
||||
const action = context.actions[i] as ActionTraceEvent;
|
||||
(action as any)[nextInContextSymbol] = lastNonRouteAction;
|
||||
if (action.class !== 'Route')
|
||||
lastNonRouteAction = action;
|
||||
}
|
||||
for (const event of context.events)
|
||||
@ -249,7 +249,7 @@ function mergeActionsAndUpdateTimingSameTrace(contexts: ContextEntry[]): ActionT
|
||||
|
||||
for (const context of libraryContexts) {
|
||||
for (const action of context.actions) {
|
||||
const key = matchByStepId ? action.stepId! : `${action.apiName}@${(action as any).wallTime}`;
|
||||
const key = matchByStepId ? action.stepId! : `${action.title}@${(action as any).wallTime}`;
|
||||
map.set(key, { ...action, context });
|
||||
}
|
||||
}
|
||||
@ -265,7 +265,7 @@ function mergeActionsAndUpdateTimingSameTrace(contexts: ContextEntry[]): ActionT
|
||||
const nonPrimaryIdToPrimaryId = new Map<string, string>();
|
||||
for (const context of testRunnerContexts) {
|
||||
for (const action of context.actions) {
|
||||
const key = matchByStepId ? action.callId : `${action.apiName}@${(action as any).wallTime}`;
|
||||
const key = matchByStepId ? action.callId : `${action.title}@${(action as any).wallTime}`;
|
||||
const existing = map.get(key);
|
||||
if (existing) {
|
||||
nonPrimaryIdToPrimaryId.set(action.callId, existing.callId);
|
||||
@ -326,7 +326,7 @@ function monotonicTimeDeltaBetweenLibraryAndRunner(nonPrimaryContexts: ContextEn
|
||||
for (const action of context.actions) {
|
||||
if (!action.startTime)
|
||||
continue;
|
||||
const key = matchByStepId ? action.callId! : `${action.apiName}@${(action as any).wallTime}`;
|
||||
const key = matchByStepId ? action.callId! : `${action.title}@${(action as any).wallTime}`;
|
||||
const libraryAction = libraryActions.get(key);
|
||||
if (libraryAction)
|
||||
return action.startTime - libraryAction.startTime;
|
||||
@ -436,6 +436,7 @@ const kRouteMethods = new Set([
|
||||
'browsercontext.unroute',
|
||||
'browsercontext.unrouteall',
|
||||
]);
|
||||
|
||||
{
|
||||
// .NET adds async suffix.
|
||||
for (const method of [...kRouteMethods])
|
||||
@ -449,6 +450,3 @@ const kRouteMethods = new Set([
|
||||
])
|
||||
kRouteMethods.add(method);
|
||||
}
|
||||
export function isRouteAction(action: ActionTraceEventInContext) {
|
||||
return action.class === 'Route' || kRouteMethods.has(action.apiName.toLowerCase());
|
||||
}
|
||||
|
@ -105,7 +105,7 @@ export const Workbench: React.FunctionComponent<{
|
||||
// Select the last non-after hooks item.
|
||||
let index = model.actions.length - 1;
|
||||
for (let i = 0; i < model.actions.length; ++i) {
|
||||
if (model.actions[i].apiName === 'After Hooks' && i) {
|
||||
if (model.actions[i].title === 'After Hooks' && i) {
|
||||
index = i - 1;
|
||||
break;
|
||||
}
|
||||
|
@ -20,8 +20,8 @@ import type { Point, SerializedError, StackFrame } from '@protocol/channels';
|
||||
|
||||
export type Size = { width: number, height: number };
|
||||
|
||||
// Make sure you add _modernize_N_to_N1(event: any) to traceModel.ts.
|
||||
export type VERSION = 7;
|
||||
// Make sure you add _modernize_N_to_N1(event: any) to traceModernizer.ts.
|
||||
export type VERSION = 8;
|
||||
|
||||
export type BrowserContextEventOptions = {
|
||||
baseURL?: string,
|
||||
@ -61,7 +61,7 @@ export type BeforeActionTraceEvent = {
|
||||
type: 'before',
|
||||
callId: string;
|
||||
startTime: number;
|
||||
apiName: string;
|
||||
title?: string;
|
||||
class: string;
|
||||
method: string;
|
||||
params: Record<string, any>;
|
||||
|
@ -151,13 +151,13 @@ export async function parseTraceRaw(file: string): Promise<{ events: any[], reso
|
||||
return {
|
||||
events,
|
||||
resources,
|
||||
actions: actionObjects.map(a => a.apiName),
|
||||
actions: actionObjects.map(a => a.title ?? a.class.toLowerCase() + '.' + a.method),
|
||||
actionObjects,
|
||||
stacks,
|
||||
};
|
||||
}
|
||||
|
||||
export async function parseTrace(file: string): Promise<{ resources: Map<string, Buffer>, events: (EventTraceEvent | ConsoleMessageTraceEvent)[], actions: ActionTraceEvent[], apiNames: string[], traceModel: TraceModel, model: MultiTraceModel, actionTree: string[], errors: string[] }> {
|
||||
export async function parseTrace(file: string): Promise<{ resources: Map<string, Buffer>, events: (EventTraceEvent | ConsoleMessageTraceEvent)[], actions: ActionTraceEvent[], titles: string[], traceModel: TraceModel, model: MultiTraceModel, actionTree: string[], errors: string[] }> {
|
||||
const backend = new TraceBackend(file);
|
||||
const traceModel = new TraceModel();
|
||||
await traceModel.load(backend, () => {});
|
||||
@ -165,13 +165,13 @@ export async function parseTrace(file: string): Promise<{ resources: Map<string,
|
||||
const { rootItem } = buildActionTree(model.actions);
|
||||
const actionTree: string[] = [];
|
||||
const visit = (actionItem: ActionTreeItem, indent: string) => {
|
||||
actionTree.push(`${indent}${actionItem.action?.apiName || actionItem.id}`);
|
||||
actionTree.push(`${indent}${actionItem.action?.title || actionItem.id}`);
|
||||
for (const child of actionItem.children)
|
||||
visit(child, indent + ' ');
|
||||
};
|
||||
rootItem.children.forEach(a => visit(a, ''));
|
||||
return {
|
||||
apiNames: model.actions.map(a => a.apiName),
|
||||
titles: model.actions.map(a => a.title ?? a.class.toLowerCase() + '.' + a.method),
|
||||
resources: backend.entries,
|
||||
actions: model.actions,
|
||||
events: model.events,
|
||||
|
@ -64,7 +64,7 @@ test('should collect trace with resources, but no js', async ({ context, page, s
|
||||
expect(script.snapshot.response.content._sha1).toBe(undefined);
|
||||
});
|
||||
|
||||
test('should use the correct apiName for event driven callbacks', async ({ context, page, server }, testInfo) => {
|
||||
test('should use the correct title for event driven callbacks', async ({ context, page, server }, testInfo) => {
|
||||
await context.tracing.start();
|
||||
// route.* calls should not be included in the trace
|
||||
await page.route('**/empty.html', route => route.continue());
|
||||
@ -125,7 +125,7 @@ test('can call tracing.group/groupEnd at any time and auto-close', async ({ cont
|
||||
const { events } = await parseTraceRaw(testInfo.outputPath('trace.zip'));
|
||||
const groups = events.filter(e => e.method === 'tracingGroup');
|
||||
expect(groups).toHaveLength(1);
|
||||
expect(groups[0].apiName).toBe('actual');
|
||||
expect(groups[0].title).toBe('actual');
|
||||
expect(events.some(e => e.type === 'after' && e.callId === groups[0].callId)).toBe(true);
|
||||
});
|
||||
|
||||
@ -135,7 +135,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.apiName === 'page.screenshot');
|
||||
const screenshotEvent = actionObjects.find(a => a.title === 'page.screenshot');
|
||||
expect(screenshotEvent.beforeSnapshot).toBeTruthy();
|
||||
expect(screenshotEvent.afterSnapshot).toBeTruthy();
|
||||
expect(screenshotEvent.result).toEqual({
|
||||
@ -166,7 +166,7 @@ test('should include context API requests', async ({ browserName, context, page,
|
||||
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.apiName === 'apiRequestContext.post');
|
||||
const postEvent = events.find(e => e.title === 'apiRequestContext.post');
|
||||
expect(postEvent).toBeTruthy();
|
||||
const harEntry = events.find(e => e.type === 'resource-snapshot');
|
||||
expect(harEntry).toBeTruthy();
|
||||
@ -484,7 +484,7 @@ test('should include interrupted actions', async ({ context, page, server }, tes
|
||||
await context.close();
|
||||
|
||||
const { events } = await parseTraceRaw(testInfo.outputPath('trace.zip'));
|
||||
const clickEvent = events.find(e => e.apiName === 'page.click');
|
||||
const clickEvent = events.find(e => e.title === 'page.click');
|
||||
expect(clickEvent).toBeTruthy();
|
||||
});
|
||||
|
||||
@ -605,7 +605,7 @@ test('should hide internal stack frames', async ({ context, page }, testInfo) =>
|
||||
await context.tracing.stop({ path: tracePath });
|
||||
|
||||
const trace = await parseTraceRaw(tracePath);
|
||||
const actions = trace.actionObjects.filter(a => !a.apiName.startsWith('tracing.'));
|
||||
const actions = trace.actionObjects.filter(a => a.class !== 'Tracing');
|
||||
expect(actions).toHaveLength(4);
|
||||
for (const action of actions)
|
||||
expect(relativeStack(action, trace.stacks)).toEqual(['tracing.spec.ts']);
|
||||
@ -626,7 +626,7 @@ test('should hide internal stack frames in expect', async ({ context, page }, te
|
||||
await context.tracing.stop({ path: tracePath });
|
||||
|
||||
const trace = await parseTraceRaw(tracePath);
|
||||
const actions = trace.actionObjects.filter(a => !a.apiName.startsWith('tracing.'));
|
||||
const actions = trace.actionObjects.filter(a => a.class !== 'Tracing');
|
||||
expect(actions).toHaveLength(5);
|
||||
for (const action of actions)
|
||||
expect(relativeStack(action, trace.stacks)).toEqual(['tracing.spec.ts']);
|
||||
@ -813,7 +813,7 @@ test('should not emit after w/o before', async ({ browserType, mode }, testInfo)
|
||||
return {
|
||||
type: e.type,
|
||||
callId: +e.callId.split('@')[1] - minCallId,
|
||||
apiName: e.apiName,
|
||||
title: e.title,
|
||||
};
|
||||
}
|
||||
};
|
||||
@ -826,17 +826,17 @@ test('should not emit after w/o before', async ({ browserType, mode }, testInfo)
|
||||
{
|
||||
type: 'before',
|
||||
callId: expect.any(Number),
|
||||
apiName: 'page.evaluate'
|
||||
title: 'page.evaluate'
|
||||
},
|
||||
{
|
||||
type: 'before',
|
||||
callId: expect.any(Number),
|
||||
apiName: 'page.waitForEvent'
|
||||
title: 'page.waitForEvent'
|
||||
},
|
||||
{
|
||||
type: 'after',
|
||||
callId: expect.any(Number),
|
||||
apiName: undefined,
|
||||
title: undefined,
|
||||
},
|
||||
]);
|
||||
call1 = sanitized[0].callId;
|
||||
@ -852,12 +852,12 @@ test('should not emit after w/o before', async ({ browserType, mode }, testInfo)
|
||||
{
|
||||
type: 'before',
|
||||
callId: expect.any(Number),
|
||||
apiName: 'page.evaluateHandle'
|
||||
title: 'page.evaluateHandle'
|
||||
},
|
||||
{
|
||||
type: 'after',
|
||||
callId: expect.any(Number),
|
||||
apiName: undefined
|
||||
title: undefined
|
||||
}
|
||||
]);
|
||||
call2before = sanitized[0].callId;
|
||||
|
@ -213,7 +213,7 @@ test('should record trace', async ({ runInlineTest }) => {
|
||||
expect(fs.existsSync(test.info().outputPath('test-results', 'a-pass', 'trace.zip'))).toBe(false);
|
||||
|
||||
const trace = await parseTrace(test.info().outputPath('test-results', 'a-fail', 'trace.zip'));
|
||||
expect(trace.apiNames).toEqual([
|
||||
expect(trace.titles).toEqual([
|
||||
'Before Hooks',
|
||||
'fixture: context',
|
||||
'browser.newContext',
|
||||
|
@ -478,14 +478,14 @@ test('should reset tracing', async ({ runInlineTest }, testInfo) => {
|
||||
expect(result.passed).toBe(2);
|
||||
|
||||
const trace1 = await parseTrace(traceFile1);
|
||||
expect(trace1.apiNames).toEqual([
|
||||
expect(trace1.titles).toEqual([
|
||||
'page.setContent',
|
||||
'page.click',
|
||||
]);
|
||||
expect(trace1.traceModel.storage().snapshotsForTest().length).toBeGreaterThan(0);
|
||||
|
||||
const trace2 = await parseTrace(traceFile2);
|
||||
expect(trace2.apiNames).toEqual([
|
||||
expect(trace2.titles).toEqual([
|
||||
'page.setContent',
|
||||
'page.fill',
|
||||
'locator.click',
|
||||
|
@ -465,7 +465,7 @@ test(`trace:retain-on-failure should create trace if context is closed before fa
|
||||
}, { trace: 'retain-on-failure' });
|
||||
const tracePath = test.info().outputPath('test-results', 'a-passing-test', 'trace.zip');
|
||||
const trace = await parseTrace(tracePath);
|
||||
expect(trace.apiNames).toContain('page.goto');
|
||||
expect(trace.titles).toContain('page.goto');
|
||||
expect(result.failed).toBe(1);
|
||||
});
|
||||
|
||||
@ -487,7 +487,7 @@ test(`trace:retain-on-failure should create trace if context is closed before fa
|
||||
}, { trace: 'retain-on-failure' });
|
||||
const tracePath = test.info().outputPath('test-results', 'a-passing-test', 'trace.zip');
|
||||
const trace = await parseTrace(tracePath);
|
||||
expect(trace.apiNames).toContain('page.goto');
|
||||
expect(trace.titles).toContain('page.goto');
|
||||
expect(result.failed).toBe(1);
|
||||
});
|
||||
|
||||
@ -507,7 +507,7 @@ test(`trace:retain-on-failure should create trace if request context is disposed
|
||||
}, { trace: 'retain-on-failure' });
|
||||
const tracePath = test.info().outputPath('test-results', 'a-passing-test', 'trace.zip');
|
||||
const trace = await parseTrace(tracePath);
|
||||
expect(trace.apiNames).toContain('apiRequestContext.get');
|
||||
expect(trace.titles).toContain('apiRequestContext.get');
|
||||
expect(result.failed).toBe(1);
|
||||
});
|
||||
|
||||
@ -528,7 +528,7 @@ test('should include attachments by default', async ({ runInlineTest, server },
|
||||
expect(result.exitCode).toBe(0);
|
||||
expect(result.passed).toBe(1);
|
||||
const trace = await parseTrace(testInfo.outputPath('test-results', 'a-pass', 'trace.zip'));
|
||||
expect(trace.apiNames).toEqual([
|
||||
expect(trace.titles).toEqual([
|
||||
'Before Hooks',
|
||||
`attach "foo"`,
|
||||
'After Hooks',
|
||||
@ -558,7 +558,7 @@ test('should opt out of attachments', async ({ runInlineTest, server }, testInfo
|
||||
expect(result.exitCode).toBe(0);
|
||||
expect(result.passed).toBe(1);
|
||||
const trace = await parseTrace(testInfo.outputPath('test-results', 'a-pass', 'trace.zip'));
|
||||
expect(trace.apiNames).toEqual([
|
||||
expect(trace.titles).toEqual([
|
||||
'Before Hooks',
|
||||
`attach "foo"`,
|
||||
'After Hooks',
|
||||
@ -729,7 +729,7 @@ test('should not throw when attachment is missing', async ({ runInlineTest }, te
|
||||
expect(result.exitCode).toBe(0);
|
||||
expect(result.passed).toBe(1);
|
||||
const trace = await parseTrace(testInfo.outputPath('test-results', 'a-passes', 'trace.zip'));
|
||||
expect(trace.apiNames).toContain('Attach "screenshot"');
|
||||
expect(trace.titles).toContain('Attach "screenshot"');
|
||||
});
|
||||
|
||||
test('should not throw when screenshot on failure fails', async ({ runInlineTest, server }, testInfo) => {
|
||||
@ -1102,7 +1102,7 @@ test('trace:retain-on-first-failure should create trace but only on first failur
|
||||
|
||||
const tracePath = test.info().outputPath('test-results', 'a-fail', 'trace.zip');
|
||||
const trace = await parseTrace(tracePath);
|
||||
expect(trace.apiNames).toContain('page.goto');
|
||||
expect(trace.titles).toContain('page.goto');
|
||||
expect(result.failed).toBe(1);
|
||||
});
|
||||
|
||||
@ -1119,7 +1119,7 @@ test('trace:retain-on-first-failure should create trace if context is closed bef
|
||||
}, { trace: 'retain-on-first-failure' });
|
||||
const tracePath = test.info().outputPath('test-results', 'a-fail', 'trace.zip');
|
||||
const trace = await parseTrace(tracePath);
|
||||
expect(trace.apiNames).toContain('page.goto');
|
||||
expect(trace.titles).toContain('page.goto');
|
||||
expect(result.failed).toBe(1);
|
||||
});
|
||||
|
||||
@ -1138,7 +1138,7 @@ test('trace:retain-on-first-failure should create trace if context is closed bef
|
||||
}, { trace: 'retain-on-first-failure' });
|
||||
const tracePath = test.info().outputPath('test-results', 'a-fail', 'trace.zip');
|
||||
const trace = await parseTrace(tracePath);
|
||||
expect(trace.apiNames).toContain('page.goto');
|
||||
expect(trace.titles).toContain('page.goto');
|
||||
expect(result.failed).toBe(1);
|
||||
});
|
||||
|
||||
@ -1155,7 +1155,7 @@ test('trace:retain-on-first-failure should create trace if request context is di
|
||||
}, { trace: 'retain-on-first-failure' });
|
||||
const tracePath = test.info().outputPath('test-results', 'a-fail', 'trace.zip');
|
||||
const trace = await parseTrace(tracePath);
|
||||
expect(trace.apiNames).toContain('apiRequestContext.get');
|
||||
expect(trace.titles).toContain('apiRequestContext.get');
|
||||
expect(result.failed).toBe(1);
|
||||
});
|
||||
|
||||
@ -1348,13 +1348,13 @@ 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.apiName === 'locator.count');
|
||||
const countAction = trace.actions.find(a => a.title === 'locator.count');
|
||||
expect(countAction.beforeSnapshot).toBeTruthy();
|
||||
expect(countAction.afterSnapshot).toBeTruthy();
|
||||
expect(snapshots.snapshotByName(snapshotFrameOrPageId, countAction.beforeSnapshot)).toBeTruthy();
|
||||
expect(snapshots.snapshotByName(snapshotFrameOrPageId, countAction.afterSnapshot)).toBeTruthy();
|
||||
|
||||
const boundingBoxAction = trace.actions.find(a => a.apiName === 'locator.boundingBox');
|
||||
const boundingBoxAction = trace.actions.find(a => a.title === 'locator.boundingBox');
|
||||
expect(boundingBoxAction.beforeSnapshot).toBeTruthy();
|
||||
expect(boundingBoxAction.afterSnapshot).toBeTruthy();
|
||||
expect(snapshots.snapshotByName(snapshotFrameOrPageId, boundingBoxAction.beforeSnapshot)).toBeTruthy();
|
||||
|
Loading…
x
Reference in New Issue
Block a user