added Dmitry's changes

Signed-off-by: René <snooz@posteo.de>
This commit is contained in:
René 2024-10-21 13:56:58 +02:00
parent 906faf7c8d
commit 93d9a43e80
5 changed files with 24 additions and 10 deletions

View file

@ -168,7 +168,7 @@ export abstract class ChannelOwner<T extends channels.Channel = channels.Channel
return channel; return channel;
} }
async _wrapApiCall<R>(func: (apiZone: ApiZone) => Promise<R>, isInternal = false): Promise<R> { async _wrapApiCall<R>(func: (apiZone: ApiZone) => Promise<R>, isInternal?: boolean): Promise<R> {
const logger = this._logger; const logger = this._logger;
const apiZone = zones.zoneData<ApiZone>('apiZone'); const apiZone = zones.zoneData<ApiZone>('apiZone');
if (apiZone) if (apiZone)
@ -178,7 +178,8 @@ export abstract class ChannelOwner<T extends channels.Channel = channels.Channel
let apiName: string | undefined = stackTrace.apiName; let apiName: string | undefined = stackTrace.apiName;
const frames: channels.StackFrame[] = stackTrace.frames; const frames: channels.StackFrame[] = stackTrace.frames;
isInternal = isInternal || this._isInternalType; if (isInternal === undefined)
isInternal = this._isInternalType;
if (isInternal) if (isInternal)
apiName = undefined; apiName = undefined;

View file

@ -52,11 +52,15 @@ export class Tracing extends ChannelOwner<channels.TracingChannel> implements ap
} }
async group(name: string, options: { location?: { file: string, line?: number, column?: number } } = {}) { async group(name: string, options: { location?: { file: string, line?: number, column?: number } } = {}) {
await this._channel.tracingGroup({ name, location: options.location }); await this._wrapApiCall(async () => {
await this._channel.tracingGroup({ name, location: options.location });
}, false);
} }
async groupEnd() { async groupEnd() {
await this._channel.tracingGroupEnd(); await this._wrapApiCall(async () => {
await this._channel.tracingGroupEnd();
}, false);
} }
private async _startCollectingStacks(traceName: string) { private async _startCollectingStacks(traceName: string) {

View file

@ -214,8 +214,9 @@ export class Tracing extends SdkObject implements InstrumentationListener, Snaps
startTime: metadata.startTime, startTime: metadata.startTime,
apiName: name, apiName: name,
class: 'Tracing', class: 'Tracing',
method: 'group', method: 'tracingGroup',
params: { }, params: { },
stepId: metadata.stepId,
stack: stackFrames, stack: stackFrames,
}; };
if (this._state.groupStack.length) if (this._state.groupStack.length)

View file

@ -20,7 +20,7 @@ import type { APIRequestContext, BrowserContext, Browser, BrowserContextOptions,
import * as playwrightLibrary from 'playwright-core'; import * as playwrightLibrary from 'playwright-core';
import { createGuid, debugMode, addInternalStackPrefix, isString, asLocator, jsonStringifyForceASCII } from 'playwright-core/lib/utils'; import { createGuid, debugMode, addInternalStackPrefix, isString, asLocator, jsonStringifyForceASCII } from 'playwright-core/lib/utils';
import type { Fixtures, PlaywrightTestArgs, PlaywrightTestOptions, PlaywrightWorkerArgs, PlaywrightWorkerOptions, ScreenshotMode, TestInfo, TestType, VideoMode } from '../types/test'; import type { Fixtures, PlaywrightTestArgs, PlaywrightTestOptions, PlaywrightWorkerArgs, PlaywrightWorkerOptions, ScreenshotMode, TestInfo, TestType, VideoMode } from '../types/test';
import type { TestInfoImpl } from './worker/testInfo'; import type { TestInfoImpl, TestStepInternal } from './worker/testInfo';
import { rootTestType } from './common/testType'; import { rootTestType } from './common/testType';
import type { ContextReuseMode } from './common/config'; import type { ContextReuseMode } from './common/config';
import type { ClientInstrumentation, ClientInstrumentationListener } from '../../playwright-core/src/client/clientInstrumentation'; import type { ClientInstrumentation, ClientInstrumentationListener } from '../../playwright-core/src/client/clientInstrumentation';
@ -255,20 +255,28 @@ const playwrightFixtures: Fixtures<TestFixtures, WorkerFixtures> = ({
const artifactsRecorder = new ArtifactsRecorder(playwright, tracing().artifactsDir(), screenshot); const artifactsRecorder = new ArtifactsRecorder(playwright, tracing().artifactsDir(), screenshot);
await artifactsRecorder.willStartTest(testInfo as TestInfoImpl); await artifactsRecorder.willStartTest(testInfo as TestInfoImpl);
let tracingGroupSteps: TestStepInternal[] = [];
const csiListener: ClientInstrumentationListener = { const csiListener: ClientInstrumentationListener = {
onApiCallBegin: (apiName: string, params: Record<string, any>, frames: StackFrame[], userData: any, out: { stepId?: string }) => { onApiCallBegin: (apiName: string, params: Record<string, any>, frames: StackFrame[], userData: any, out: { stepId?: string }) => {
const testInfo = currentTestInfo(); const testInfo = currentTestInfo();
if (!testInfo || apiName.includes('setTestIdAttribute')) if (!testInfo || apiName.includes('setTestIdAttribute'))
return { userObject: null }; return { userObject: null };
if (apiName === 'tracing.groupEnd') {
tracingGroupSteps.pop();
return { userObject: null };
}
const step = testInfo._addStep({ const step = testInfo._addStep({
location: frames[0] as any, location: frames[0] as any,
category: 'pw:api', category: 'pw:api',
title: renderApiCall(apiName, params), title: renderApiCall(apiName, params),
apiName, apiName,
params, params,
}); }, tracingGroupSteps[tracingGroupSteps.length - 1]);
userData.userObject = step; userData.userObject = step;
out.stepId = step.stepId; out.stepId = step.stepId;
if (apiName === 'tracing.group')
tracingGroupSteps.push(step);
}, },
onApiCallEnd: (userData: any, error?: Error) => { onApiCallEnd: (userData: any, error?: Error) => {
const step = userData.userObject; const step = userData.userObject;

View file

@ -237,15 +237,15 @@ export class TestInfoImpl implements TestInfo {
} }
} }
_addStep(data: Omit<TestStepInternal, 'complete' | 'stepId' | 'steps'>): TestStepInternal { _addStep(data: Omit<TestStepInternal, 'complete' | 'stepId' | 'steps'>, parentStep?: TestStepInternal): TestStepInternal {
const stepId = `${data.category}@${++this._lastStepId}`; const stepId = `${data.category}@${++this._lastStepId}`;
let parentStep: TestStepInternal | undefined;
if (data.isStage) { if (data.isStage) {
// Predefined stages form a fixed hierarchy - use the current one as parent. // Predefined stages form a fixed hierarchy - use the current one as parent.
parentStep = this._findLastStageStep(this._steps); parentStep = this._findLastStageStep(this._steps);
} else { } else {
parentStep = zones.zoneData<TestStepInternal>('stepZone'); if (!parentStep)
parentStep = zones.zoneData<TestStepInternal>('stepZone');
if (!parentStep) { if (!parentStep) {
// If no parent step on stack, assume the current stage as parent. // If no parent step on stack, assume the current stage as parent.
parentStep = this._findLastStageStep(this._steps); parentStep = this._findLastStageStep(this._steps);