chore: introduce testInfo.testId (#21670)
This commit is contained in:
parent
7666894d77
commit
27048adebe
|
|
@ -248,6 +248,12 @@ Optional description that will be reflected in a test report.
|
||||||
|
|
||||||
Test function as passed to `test(title, testFunction)`.
|
Test function as passed to `test(title, testFunction)`.
|
||||||
|
|
||||||
|
## property: TestInfo.testId
|
||||||
|
* since: v1.32
|
||||||
|
- type: <[string]>
|
||||||
|
|
||||||
|
Test id matching the test case id in the reporter API.
|
||||||
|
|
||||||
## property: TestInfo.line
|
## property: TestInfo.line
|
||||||
* since: v1.10
|
* since: v1.10
|
||||||
- type: <[int]>
|
- type: <[int]>
|
||||||
|
|
|
||||||
|
|
@ -123,14 +123,14 @@ export class Tracing extends SdkObject implements InstrumentationListener, Snaps
|
||||||
|
|
||||||
if (this._state) {
|
if (this._state) {
|
||||||
const o = this._state.options;
|
const o = this._state.options;
|
||||||
if (o.name !== options.name || !o.screenshots !== !options.screenshots || !o.snapshots !== !options.snapshots)
|
if (!o.screenshots !== !options.screenshots || !o.snapshots !== !options.snapshots)
|
||||||
throw new Error('Tracing has been already started with different options');
|
throw new Error('Tracing has been already started with different options');
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
// TODO: passing the same name for two contexts makes them write into a single file
|
// TODO: passing the same name for two contexts makes them write into a single file
|
||||||
// and conflict.
|
// and conflict.
|
||||||
const traceName = options.name || createGuid();
|
const traceName = options.name || createGuid();
|
||||||
// Init the state synchrounously.
|
// Init the state synchronously.
|
||||||
this._state = { options, traceName, traceFile: '', networkFile: '', tracesDir: '', resourcesDir: '', filesCount: 0, traceSha1s: new Set(), networkSha1s: new Set(), recording: false };
|
this._state = { options, traceName, traceFile: '', networkFile: '', tracesDir: '', resourcesDir: '', filesCount: 0, traceSha1s: new Set(), networkSha1s: new Set(), recording: false };
|
||||||
const state = this._state;
|
const state = this._state;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -17,7 +17,7 @@
|
||||||
import fs from 'fs';
|
import fs from 'fs';
|
||||||
import type EventEmitter from 'events';
|
import type EventEmitter from 'events';
|
||||||
import type { ClientSideCallMetadata, StackFrame } from '@protocol/channels';
|
import type { ClientSideCallMetadata, StackFrame } from '@protocol/channels';
|
||||||
import type { SerializedClientSideCallMetadata, SerializedStack, SerializedStackFrame } from '@trace/traceUtils';
|
import type { SerializedClientSideCallMetadata, SerializedStack, SerializedStackFrame } from './isomorphic/traceUtils';
|
||||||
import { yazl, yauzl } from '../zipBundle';
|
import { yazl, yauzl } from '../zipBundle';
|
||||||
import { ManualPromise } from './manualPromise';
|
import { ManualPromise } from './manualPromise';
|
||||||
import type { ActionTraceEvent } from '@trace/trace';
|
import type { ActionTraceEvent } from '@trace/trace';
|
||||||
|
|
|
||||||
|
|
@ -5,3 +5,6 @@ common/
|
||||||
|
|
||||||
[cli.ts]
|
[cli.ts]
|
||||||
**
|
**
|
||||||
|
|
||||||
|
[index.ts]
|
||||||
|
@testIsomorphic/**
|
||||||
|
|
|
||||||
|
|
@ -24,6 +24,7 @@ import type { Fixtures, PlaywrightTestArgs, PlaywrightTestOptions, PlaywrightWor
|
||||||
import type { TestInfoImpl } from './worker/testInfo';
|
import type { TestInfoImpl } from './worker/testInfo';
|
||||||
import { rootTestType } from './common/testType';
|
import { rootTestType } from './common/testType';
|
||||||
import { type ContextReuseMode } from './common/types';
|
import { type ContextReuseMode } from './common/types';
|
||||||
|
import { artifactsFolderName } from './isomorphic/folders';
|
||||||
export { expect } from './matchers/expect';
|
export { expect } from './matchers/expect';
|
||||||
export { store } from './store';
|
export { store } from './store';
|
||||||
export const _baseTest: TestType<{}, {}> = rootTestType.test;
|
export const _baseTest: TestType<{}, {}> = rootTestType.test;
|
||||||
|
|
@ -79,7 +80,7 @@ const playwrightFixtures: Fixtures<TestFixtures, WorkerFixtures> = ({
|
||||||
let dir: string | undefined;
|
let dir: string | undefined;
|
||||||
await use(() => {
|
await use(() => {
|
||||||
if (!dir) {
|
if (!dir) {
|
||||||
dir = path.join(workerInfo.project.outputDir, '.playwright-artifacts-' + workerInfo.workerIndex);
|
dir = path.join(workerInfo.project.outputDir, artifactsFolderName(workerInfo.workerIndex));
|
||||||
fs.mkdirSync(dir, { recursive: true });
|
fs.mkdirSync(dir, { recursive: true });
|
||||||
}
|
}
|
||||||
return dir;
|
return dir;
|
||||||
|
|
@ -88,7 +89,7 @@ const playwrightFixtures: Fixtures<TestFixtures, WorkerFixtures> = ({
|
||||||
await removeFolders([dir]);
|
await removeFolders([dir]);
|
||||||
}, { scope: 'worker', _title: 'playwright configuration' } as any],
|
}, { scope: 'worker', _title: 'playwright configuration' } as any],
|
||||||
|
|
||||||
_browserOptions: [async ({ playwright, headless, channel, launchOptions, connectOptions }, use) => {
|
_browserOptions: [async ({ playwright, headless, channel, launchOptions, connectOptions, _artifactsDir }, use) => {
|
||||||
const options: LaunchOptions = {
|
const options: LaunchOptions = {
|
||||||
handleSIGINT: false,
|
handleSIGINT: false,
|
||||||
timeout: 0,
|
timeout: 0,
|
||||||
|
|
@ -98,6 +99,7 @@ const playwrightFixtures: Fixtures<TestFixtures, WorkerFixtures> = ({
|
||||||
options.headless = headless;
|
options.headless = headless;
|
||||||
if (channel !== undefined)
|
if (channel !== undefined)
|
||||||
options.channel = channel;
|
options.channel = channel;
|
||||||
|
options.tracesDir = path.join(_artifactsDir(), 'traces');
|
||||||
|
|
||||||
for (const browserType of [playwright.chromium, playwright.firefox, playwright.webkit]) {
|
for (const browserType of [playwright.chromium, playwright.firefox, playwright.webkit]) {
|
||||||
(browserType as BrowserTypeImpl)._defaultLaunchOptions = options;
|
(browserType as BrowserTypeImpl)._defaultLaunchOptions = options;
|
||||||
|
|
@ -255,6 +257,7 @@ const playwrightFixtures: Fixtures<TestFixtures, WorkerFixtures> = ({
|
||||||
const temporaryScreenshots: string[] = [];
|
const temporaryScreenshots: string[] = [];
|
||||||
const testInfoImpl = testInfo as TestInfoImpl;
|
const testInfoImpl = testInfo as TestInfoImpl;
|
||||||
const reusedContexts = new Set<BrowserContext>();
|
const reusedContexts = new Set<BrowserContext>();
|
||||||
|
let traceOrdinal = 0;
|
||||||
|
|
||||||
const createInstrumentationListener = (context?: BrowserContext) => {
|
const createInstrumentationListener = (context?: BrowserContext) => {
|
||||||
return {
|
return {
|
||||||
|
|
@ -287,7 +290,11 @@ const playwrightFixtures: Fixtures<TestFixtures, WorkerFixtures> = ({
|
||||||
if (captureTrace) {
|
if (captureTrace) {
|
||||||
const title = [path.relative(testInfo.project.testDir, testInfo.file) + ':' + testInfo.line, ...testInfo.titlePath.slice(1)].join(' › ');
|
const title = [path.relative(testInfo.project.testDir, testInfo.file) + ':' + testInfo.line, ...testInfo.titlePath.slice(1)].join(' › ');
|
||||||
if (!(tracing as any)[kTracingStarted]) {
|
if (!(tracing as any)[kTracingStarted]) {
|
||||||
await tracing.start({ ...traceOptions, title });
|
const ordinalSuffix = traceOrdinal ? `-${traceOrdinal}` : '';
|
||||||
|
++traceOrdinal;
|
||||||
|
const retrySuffix = testInfo.retry ? `-${testInfo.retry}` : '';
|
||||||
|
const name = `${testInfo.testId}${retrySuffix}${ordinalSuffix}`;
|
||||||
|
await tracing.start({ ...traceOptions, title, name });
|
||||||
(tracing as any)[kTracingStarted] = true;
|
(tracing as any)[kTracingStarted] = true;
|
||||||
} else {
|
} else {
|
||||||
await tracing.startChunk({ title });
|
await tracing.startChunk({ title });
|
||||||
|
|
|
||||||
0
packages/playwright-test/src/isomorphic/DEPS.list
Normal file
0
packages/playwright-test/src/isomorphic/DEPS.list
Normal file
19
packages/playwright-test/src/isomorphic/folders.ts
Normal file
19
packages/playwright-test/src/isomorphic/folders.ts
Normal file
|
|
@ -0,0 +1,19 @@
|
||||||
|
/**
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
export function artifactsFolderName(workerIndex: number) {
|
||||||
|
return `.playwright-artifacts-${workerIndex}`;
|
||||||
|
}
|
||||||
|
|
@ -56,6 +56,7 @@ export class TestInfoImpl implements TestInfo {
|
||||||
_lastStepId = 0;
|
_lastStepId = 0;
|
||||||
|
|
||||||
// ------------ TestInfo fields ------------
|
// ------------ TestInfo fields ------------
|
||||||
|
readonly testId: string;
|
||||||
readonly repeatEachIndex: number;
|
readonly repeatEachIndex: number;
|
||||||
readonly retry: number;
|
readonly retry: number;
|
||||||
readonly workerIndex: number;
|
readonly workerIndex: number;
|
||||||
|
|
@ -109,6 +110,7 @@ export class TestInfoImpl implements TestInfo {
|
||||||
onStepEnd: (payload: StepEndPayload) => void,
|
onStepEnd: (payload: StepEndPayload) => void,
|
||||||
) {
|
) {
|
||||||
this._test = test;
|
this._test = test;
|
||||||
|
this.testId = test.id;
|
||||||
this._onStepBegin = onStepBegin;
|
this._onStepBegin = onStepBegin;
|
||||||
this._onStepEnd = onStepEnd;
|
this._onStepEnd = onStepEnd;
|
||||||
this._startTime = monotonicTime();
|
this._startTime = monotonicTime();
|
||||||
|
|
|
||||||
5
packages/playwright-test/types/test.d.ts
vendored
5
packages/playwright-test/types/test.d.ts
vendored
|
|
@ -2244,6 +2244,11 @@ export interface TestInfo {
|
||||||
*/
|
*/
|
||||||
stdout: Array<string|Buffer>;
|
stdout: Array<string|Buffer>;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test id matching the test case id in the reporter API.
|
||||||
|
*/
|
||||||
|
testId: string;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Timeout in milliseconds for the currently running test. Zero means no timeout. Learn more about
|
* Timeout in milliseconds for the currently running test. Zero means no timeout. Learn more about
|
||||||
* [various timeouts](https://playwright.dev/docs/test-timeouts).
|
* [various timeouts](https://playwright.dev/docs/test-timeouts).
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,5 @@
|
||||||
[*]
|
[*]
|
||||||
|
@isomorphic/**
|
||||||
@trace/**
|
@trace/**
|
||||||
@web/**
|
@web/**
|
||||||
ui/
|
ui/
|
||||||
|
|
|
||||||
|
|
@ -16,7 +16,7 @@
|
||||||
|
|
||||||
import type * as trace from '@trace/trace';
|
import type * as trace from '@trace/trace';
|
||||||
import type * as traceV3 from './versions/traceV3';
|
import type * as traceV3 from './versions/traceV3';
|
||||||
import { parseClientSideCallMetadata } from '@trace/traceUtils';
|
import { parseClientSideCallMetadata } from '@isomorphic/traceUtils';
|
||||||
import type zip from '@zip.js/zip.js';
|
import type zip from '@zip.js/zip.js';
|
||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
import zipImport from '@zip.js/zip.js/dist/zip-no-worker-inflate.min.js';
|
import zipImport from '@zip.js/zip.js/dist/zip-no-worker-inflate.min.js';
|
||||||
|
|
|
||||||
|
|
@ -20,8 +20,8 @@ import '@web/common.css';
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { TreeView } from '@web/components/treeView';
|
import { TreeView } from '@web/components/treeView';
|
||||||
import type { TreeState } from '@web/components/treeView';
|
import type { TreeState } from '@web/components/treeView';
|
||||||
import { TeleReporterReceiver, TeleSuite } from '../../../playwright-test/src/isomorphic/teleReceiver';
|
import { TeleReporterReceiver, TeleSuite } from '@testIsomorphic/teleReceiver';
|
||||||
import type { TeleTestCase } from '../../../playwright-test/src/isomorphic/teleReceiver';
|
import type { TeleTestCase } from '@testIsomorphic/teleReceiver';
|
||||||
import type { FullConfig, Suite, TestCase, TestResult, TestStep, Location } from '../../../playwright-test/types/testReporter';
|
import type { FullConfig, Suite, TestCase, TestResult, TestStep, Location } from '../../../playwright-test/types/testReporter';
|
||||||
import { SplitView } from '@web/components/splitView';
|
import { SplitView } from '@web/components/splitView';
|
||||||
import { MultiTraceModel } from './modelUtil';
|
import { MultiTraceModel } from './modelUtil';
|
||||||
|
|
|
||||||
|
|
@ -20,6 +20,7 @@
|
||||||
"@isomorphic/*": ["../playwright-core/src/utils/isomorphic/*"],
|
"@isomorphic/*": ["../playwright-core/src/utils/isomorphic/*"],
|
||||||
"@protocol/*": ["../protocol/src/*"],
|
"@protocol/*": ["../protocol/src/*"],
|
||||||
"@recorder/*": ["../recorder/src/*"],
|
"@recorder/*": ["../recorder/src/*"],
|
||||||
|
"@testIsomorphic/*": ["../playwright-test/src/isomorphic/*"],
|
||||||
"@trace/*": ["../trace/src/*"],
|
"@trace/*": ["../trace/src/*"],
|
||||||
"@web/*": ["../web/src/*"],
|
"@web/*": ["../web/src/*"],
|
||||||
// Resolving type dependencies will start processing types in @playwright/test
|
// Resolving type dependencies will start processing types in @playwright/test
|
||||||
|
|
|
||||||
|
|
@ -32,6 +32,7 @@ export default defineConfig({
|
||||||
'@injected': path.resolve(__dirname, '../playwright-core/src/server/injected'),
|
'@injected': path.resolve(__dirname, '../playwright-core/src/server/injected'),
|
||||||
'@isomorphic': path.resolve(__dirname, '../playwright-core/src/utils/isomorphic'),
|
'@isomorphic': path.resolve(__dirname, '../playwright-core/src/utils/isomorphic'),
|
||||||
'@protocol': path.resolve(__dirname, '../protocol/src'),
|
'@protocol': path.resolve(__dirname, '../protocol/src'),
|
||||||
|
'@testIsomorphic': path.resolve(__dirname, '../playwright-test/src/isomorphic'),
|
||||||
'@trace': path.resolve(__dirname, '../trace/src'),
|
'@trace': path.resolve(__dirname, '../trace/src'),
|
||||||
'@web': path.resolve(__dirname, '../web/src'),
|
'@web': path.resolve(__dirname, '../web/src'),
|
||||||
},
|
},
|
||||||
|
|
|
||||||
|
|
@ -31,6 +31,7 @@ export default defineConfig({
|
||||||
alias: {
|
alias: {
|
||||||
'@isomorphic': path.resolve(__dirname, '../playwright-core/src/utils/isomorphic'),
|
'@isomorphic': path.resolve(__dirname, '../playwright-core/src/utils/isomorphic'),
|
||||||
'@protocol': path.resolve(__dirname, '../protocol/src'),
|
'@protocol': path.resolve(__dirname, '../protocol/src'),
|
||||||
|
'@testIsomorphic': path.resolve(__dirname, '../playwright-core/src/utils/testIsomorphic'),
|
||||||
'@trace': path.resolve(__dirname, '../trace/src'),
|
'@trace': path.resolve(__dirname, '../trace/src'),
|
||||||
'@web': path.resolve(__dirname, '../web/src'),
|
'@web': path.resolve(__dirname, '../web/src'),
|
||||||
},
|
},
|
||||||
|
|
|
||||||
|
|
@ -17,7 +17,7 @@
|
||||||
import type { Frame, Page } from 'playwright-core';
|
import type { Frame, Page } from 'playwright-core';
|
||||||
import { ZipFile } from '../../packages/playwright-core/lib/utils/zipFile';
|
import { ZipFile } from '../../packages/playwright-core/lib/utils/zipFile';
|
||||||
import type { StackFrame } from '../../packages/protocol/src/channels';
|
import type { StackFrame } from '../../packages/protocol/src/channels';
|
||||||
import { parseClientSideCallMetadata } from '../../packages/trace/src/traceUtils';
|
import { parseClientSideCallMetadata } from '../../packages/playwright-core/lib/utils/isomorphic/traceUtils';
|
||||||
import type { ActionTraceEvent } from '../../packages/trace/src/trace';
|
import type { ActionTraceEvent } from '../../packages/trace/src/trace';
|
||||||
|
|
||||||
export async function attachFrame(page: Page, frameId: string, url: string): Promise<Frame> {
|
export async function attachFrame(page: Page, frameId: string, url: string): Promise<Frame> {
|
||||||
|
|
|
||||||
|
|
@ -15,6 +15,7 @@
|
||||||
"@isomorphic/*": ["./packages/playwright-core/src/utils/isomorphic/*"],
|
"@isomorphic/*": ["./packages/playwright-core/src/utils/isomorphic/*"],
|
||||||
"@protocol/*": ["./packages/protocol/src/*"],
|
"@protocol/*": ["./packages/protocol/src/*"],
|
||||||
"@recorder/*": ["./packages/recorder/src/*"],
|
"@recorder/*": ["./packages/recorder/src/*"],
|
||||||
|
"@testIsomorphic/*": ["./packages/playwright-test/src/isomorphic/*"],
|
||||||
"@trace/*": ["./packages/trace/src/*"],
|
"@trace/*": ["./packages/trace/src/*"],
|
||||||
"@web/*": ["./packages/web/src/*"],
|
"@web/*": ["./packages/web/src/*"],
|
||||||
"playwright-core/lib/*": ["./packages/playwright-core/src/*"],
|
"playwright-core/lib/*": ["./packages/playwright-core/src/*"],
|
||||||
|
|
|
||||||
|
|
@ -29,6 +29,7 @@ for (const package of fs.readdirSync(packagesDir))
|
||||||
packages.set(package, packagesDir + '/' + package + '/src/');
|
packages.set(package, packagesDir + '/' + package + '/src/');
|
||||||
packages.set('injected', packagesDir + '/playwright-core/src/server/injected/');
|
packages.set('injected', packagesDir + '/playwright-core/src/server/injected/');
|
||||||
packages.set('isomorphic', packagesDir + '/playwright-core/src/utils/isomorphic/');
|
packages.set('isomorphic', packagesDir + '/playwright-core/src/utils/isomorphic/');
|
||||||
|
packages.set('testIsomorphic', packagesDir + '/playwright-test/src/isomorphic/');
|
||||||
|
|
||||||
const peerDependencies = ['electron', 'react', 'react-dom', '@zip.js/zip.js'];
|
const peerDependencies = ['electron', 'react', 'react-dom', '@zip.js/zip.js'];
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue