@playwright/test 1.31.2 → 1.32.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/cli.js +12 -34
- package/lib/common/compilationCache.js +4 -2
- package/lib/common/configLoader.js +4 -1
- package/lib/common/fixtures.js +31 -2
- package/lib/common/globals.js +9 -0
- package/lib/common/process.js +15 -3
- package/lib/common/testType.js +2 -1
- package/lib/common/transform.js +0 -1
- package/lib/index.js +95 -56
- package/lib/isomorphic/folders.js +25 -0
- package/lib/isomorphic/teleReceiver.js +368 -0
- package/lib/matchers/expect.js +35 -16
- package/lib/matchers/matchers.js +48 -48
- package/lib/matchers/toBeTruthy.js +1 -1
- package/lib/matchers/toEqual.js +1 -4
- package/lib/matchers/toMatchSnapshot.js +3 -4
- package/lib/matchers/toMatchText.js +1 -1
- package/lib/plugins/vitePlugin.js +3 -2
- package/lib/reporters/base.js +6 -9
- package/lib/reporters/html.js +7 -2
- package/lib/reporters/json.js +2 -2
- package/lib/reporters/junit.js +2 -2
- package/lib/reporters/teleEmitter.js +209 -0
- package/lib/runner/dispatcher.js +15 -2
- package/lib/runner/loadUtils.js +168 -96
- package/lib/runner/loaderHost.js +2 -2
- package/lib/runner/processHost.js +16 -4
- package/lib/runner/reporters.js +3 -2
- package/lib/runner/runner.js +9 -1
- package/lib/runner/taskRunner.js +6 -8
- package/lib/runner/tasks.js +55 -46
- package/lib/runner/testGroups.js +15 -10
- package/lib/runner/uiMode.js +279 -0
- package/lib/runner/workerHost.js +7 -6
- package/lib/store.js +99 -0
- package/lib/util.js +23 -39
- package/lib/worker/fixtureRunner.js +3 -3
- package/lib/worker/testInfo.js +8 -3
- package/lib/worker/timeoutManager.js +11 -5
- package/lib/worker/workerMain.js +6 -3
- package/package.json +2 -2
- package/types/component.d.ts +1 -1
- package/types/reporterPrivate.ts +22 -0
- package/types/test.d.ts +18 -22
- package/types/testReporter.d.ts +5 -1
- package/lib/common/profiler.js +0 -53
package/lib/store.js
ADDED
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
exports.store = void 0;
|
|
7
|
+
var _fs = _interopRequireDefault(require("fs"));
|
|
8
|
+
var _path = _interopRequireDefault(require("path"));
|
|
9
|
+
var _globals = require("./common/globals");
|
|
10
|
+
var _utilsBundle = require("playwright-core/lib/utilsBundle");
|
|
11
|
+
var _utils = require("playwright-core/lib/utils");
|
|
12
|
+
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
|
13
|
+
/**
|
|
14
|
+
* Copyright Microsoft Corporation. All rights reserved.
|
|
15
|
+
*
|
|
16
|
+
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
17
|
+
* you may not use this file except in compliance with the License.
|
|
18
|
+
* You may obtain a copy of the License at
|
|
19
|
+
*
|
|
20
|
+
* http://www.apache.org/licenses/LICENSE-2.0
|
|
21
|
+
*
|
|
22
|
+
* Unless required by applicable law or agreed to in writing, software
|
|
23
|
+
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
24
|
+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
25
|
+
* See the License for the specific language governing permissions and
|
|
26
|
+
* limitations under the License.
|
|
27
|
+
*/
|
|
28
|
+
|
|
29
|
+
class JsonStore {
|
|
30
|
+
async delete(name) {
|
|
31
|
+
const file = this.path(name);
|
|
32
|
+
await _fs.default.promises.rm(file, {
|
|
33
|
+
force: true
|
|
34
|
+
});
|
|
35
|
+
}
|
|
36
|
+
async get(name) {
|
|
37
|
+
const file = this.path(name);
|
|
38
|
+
try {
|
|
39
|
+
const type = contentType(name);
|
|
40
|
+
if (type === 'binary') return await _fs.default.promises.readFile(file);
|
|
41
|
+
const text = await _fs.default.promises.readFile(file, 'utf-8');
|
|
42
|
+
if (type === 'json') return JSON.parse(text);
|
|
43
|
+
return text;
|
|
44
|
+
} catch (e) {
|
|
45
|
+
return undefined;
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
path(name) {
|
|
49
|
+
return _path.default.join(this.root(), name);
|
|
50
|
+
}
|
|
51
|
+
root() {
|
|
52
|
+
const config = (0, _globals.currentConfig)();
|
|
53
|
+
if (!config) throw new Error('Cannot access store before config is loaded');
|
|
54
|
+
return config._internal.storeDir;
|
|
55
|
+
}
|
|
56
|
+
async set(name, value) {
|
|
57
|
+
const file = this.path(name);
|
|
58
|
+
if (value === undefined) {
|
|
59
|
+
await _fs.default.promises.rm(file, {
|
|
60
|
+
force: true
|
|
61
|
+
});
|
|
62
|
+
return;
|
|
63
|
+
}
|
|
64
|
+
let data = '';
|
|
65
|
+
switch (contentType(name)) {
|
|
66
|
+
case 'json':
|
|
67
|
+
{
|
|
68
|
+
if (Buffer.isBuffer(value)) throw new Error('JSON value must be an Object');
|
|
69
|
+
data = JSON.stringify(value, undefined, 2);
|
|
70
|
+
break;
|
|
71
|
+
}
|
|
72
|
+
case 'text':
|
|
73
|
+
{
|
|
74
|
+
if (!(0, _utils.isString)(value)) throw new Error('Textual value must be a string');
|
|
75
|
+
data = value;
|
|
76
|
+
break;
|
|
77
|
+
}
|
|
78
|
+
case 'binary':
|
|
79
|
+
{
|
|
80
|
+
if (!Buffer.isBuffer(value)) throw new Error('Binary value must be a Buffer');
|
|
81
|
+
data = value;
|
|
82
|
+
break;
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
await _fs.default.promises.mkdir(_path.default.dirname(file), {
|
|
86
|
+
recursive: true
|
|
87
|
+
});
|
|
88
|
+
await _fs.default.promises.writeFile(file, data);
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
function contentType(name) {
|
|
92
|
+
var _mime$getType;
|
|
93
|
+
const mimeType = (_mime$getType = _utilsBundle.mime.getType(_path.default.basename(name))) !== null && _mime$getType !== void 0 ? _mime$getType : 'application/octet-string';
|
|
94
|
+
if ((0, _utils.isJsonMimeType)(mimeType)) return 'json';
|
|
95
|
+
if ((0, _utils.isTextualMimeType)(mimeType)) return 'text';
|
|
96
|
+
return 'binary';
|
|
97
|
+
}
|
|
98
|
+
const store = new JsonStore();
|
|
99
|
+
exports.store = store;
|
package/lib/util.js
CHANGED
|
@@ -5,7 +5,6 @@ Object.defineProperty(exports, "__esModule", {
|
|
|
5
5
|
});
|
|
6
6
|
exports.addSuffixToFilePath = addSuffixToFilePath;
|
|
7
7
|
exports.callLogText = callLogText;
|
|
8
|
-
exports.captureStackTrace = captureStackTrace;
|
|
9
8
|
exports.createFileFiltersFromArguments = createFileFiltersFromArguments;
|
|
10
9
|
exports.createFileMatcher = createFileMatcher;
|
|
11
10
|
exports.createFileMatcherFromArguments = createFileMatcherFromArguments;
|
|
@@ -16,6 +15,8 @@ exports.errorWithFile = errorWithFile;
|
|
|
16
15
|
exports.expectTypes = expectTypes;
|
|
17
16
|
exports.experimentalLoaderOption = experimentalLoaderOption;
|
|
18
17
|
exports.fileIsModule = fileIsModule;
|
|
18
|
+
exports.filterStackTrace = filterStackTrace;
|
|
19
|
+
exports.filteredStackTrace = filteredStackTrace;
|
|
19
20
|
exports.folderIsModule = folderIsModule;
|
|
20
21
|
exports.forceRegExp = forceRegExp;
|
|
21
22
|
exports.formatLocation = formatLocation;
|
|
@@ -26,6 +27,7 @@ exports.normalizeAndSaveAttachment = normalizeAndSaveAttachment;
|
|
|
26
27
|
exports.relativeFilePath = relativeFilePath;
|
|
27
28
|
exports.sanitizeForFilePath = sanitizeForFilePath;
|
|
28
29
|
exports.serializeError = serializeError;
|
|
30
|
+
exports.stringifyStackFrames = stringifyStackFrames;
|
|
29
31
|
exports.trimLongString = trimLongString;
|
|
30
32
|
var _fs = _interopRequireDefault(require("fs"));
|
|
31
33
|
var _utilsBundle = require("playwright-core/lib/utilsBundle");
|
|
@@ -50,51 +52,33 @@ function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { de
|
|
|
50
52
|
* limitations under the License.
|
|
51
53
|
*/
|
|
52
54
|
|
|
53
|
-
const PLAYWRIGHT_CORE_PATH = _path.default.dirname(require.resolve('playwright-core'));
|
|
54
|
-
const EXPECT_PATH = require.resolve('./common/expectBundle');
|
|
55
|
-
const EXPECT_PATH_IMPL = require.resolve('./common/expectBundleImpl');
|
|
56
55
|
const PLAYWRIGHT_TEST_PATH = _path.default.join(__dirname, '..');
|
|
56
|
+
const PLAYWRIGHT_CORE_PATH = _path.default.dirname(require.resolve('playwright-core/package.json'));
|
|
57
57
|
function filterStackTrace(e) {
|
|
58
|
+
var _e$stack;
|
|
58
59
|
if (process.env.PWDEBUGIMPL) return;
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
// NOTE: Error.prepareStackTrace will only be called if `e.stack` has not
|
|
64
|
-
// been accessed before. This is the case for Jest Expect and simple throw
|
|
65
|
-
// statements.
|
|
66
|
-
//
|
|
67
|
-
// If `e.stack` has been accessed, this method will be NOOP.
|
|
68
|
-
const oldPrepare = Error.prepareStackTrace;
|
|
69
|
-
const stackFormatter = oldPrepare || ((error, structuredStackTrace) => [`${error.name}: ${error.message}`, ...structuredStackTrace.map(callSite => ' at ' + callSite.toString())].join('\n'));
|
|
70
|
-
Error.prepareStackTrace = (error, structuredStackTrace) => {
|
|
71
|
-
return stackFormatter(error, structuredStackTrace.filter(callSite => {
|
|
72
|
-
const fileName = callSite.getFileName();
|
|
73
|
-
const functionName = callSite.getFunctionName() || undefined;
|
|
74
|
-
if (!fileName) return true;
|
|
75
|
-
return !fileName.startsWith(PLAYWRIGHT_TEST_PATH) && !fileName.startsWith(PLAYWRIGHT_CORE_PATH) && !(0, _utils.isInternalFileName)(fileName, functionName);
|
|
76
|
-
}));
|
|
77
|
-
};
|
|
78
|
-
// eslint-disable-next-line
|
|
79
|
-
e.stack; // trigger Error.prepareStackTrace
|
|
80
|
-
Error.prepareStackTrace = oldPrepare;
|
|
60
|
+
const stackLines = stringifyStackFrames(filteredStackTrace(((_e$stack = e.stack) === null || _e$stack === void 0 ? void 0 : _e$stack.split('\n')) || []));
|
|
61
|
+
const message = e.message;
|
|
62
|
+
e.stack = `${e.name}: ${e.message}\n${stackLines.join('\n')}`;
|
|
63
|
+
e.message = message;
|
|
81
64
|
}
|
|
82
|
-
function
|
|
83
|
-
const stackTrace = (0, _utils.captureStackTrace)();
|
|
65
|
+
function filteredStackTrace(rawStack) {
|
|
84
66
|
const frames = [];
|
|
85
|
-
const
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
if (
|
|
67
|
+
for (const line of rawStack) {
|
|
68
|
+
const frame = (0, _utilsBundle.parseStackTraceLine)(line);
|
|
69
|
+
if (!frame || !frame.file) continue;
|
|
70
|
+
if (!process.env.PWDEBUGIMPL && frame.file.startsWith(PLAYWRIGHT_TEST_PATH)) continue;
|
|
71
|
+
if (!process.env.PWDEBUGIMPL && frame.file.startsWith(PLAYWRIGHT_CORE_PATH)) continue;
|
|
89
72
|
frames.push(frame);
|
|
90
|
-
frameTexts.push(stackTrace.frameTexts[i]);
|
|
91
73
|
}
|
|
92
|
-
return
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
74
|
+
return frames;
|
|
75
|
+
}
|
|
76
|
+
function stringifyStackFrames(frames) {
|
|
77
|
+
const stackLines = [];
|
|
78
|
+
for (const frame of frames) {
|
|
79
|
+
if (frame.function) stackLines.push(` at ${frame.function} (${frame.file}:${frame.line}:${frame.column})`);else stackLines.push(` at ${frame.file}:${frame.line}:${frame.column}`);
|
|
80
|
+
}
|
|
81
|
+
return stackLines;
|
|
98
82
|
}
|
|
99
83
|
function serializeError(error) {
|
|
100
84
|
if (error instanceof Error) {
|
|
@@ -40,7 +40,8 @@ class Fixture {
|
|
|
40
40
|
this.value = null;
|
|
41
41
|
const title = this.registration.customTitle || this.registration.name;
|
|
42
42
|
this._runnableDescription = {
|
|
43
|
-
title
|
|
43
|
+
title,
|
|
44
|
+
phase: 'setup',
|
|
44
45
|
location: registration.location,
|
|
45
46
|
slot: this.registration.timeout === undefined ? undefined : {
|
|
46
47
|
timeout: this.registration.timeout,
|
|
@@ -109,8 +110,7 @@ class Fixture {
|
|
|
109
110
|
await this._teardownWithDepsComplete;
|
|
110
111
|
}
|
|
111
112
|
_setTeardownDescription(timeoutManager) {
|
|
112
|
-
|
|
113
|
-
this._runnableDescription.title = this.registration.timeout !== undefined ? `Fixture "${title}"` : `tearing down "${title}"`;
|
|
113
|
+
this._runnableDescription.phase = 'teardown';
|
|
114
114
|
timeoutManager.setCurrentFixture(this._runnableDescription);
|
|
115
115
|
}
|
|
116
116
|
async _teardownInternal(timeoutManager) {
|
package/lib/worker/testInfo.js
CHANGED
|
@@ -52,9 +52,11 @@ class TestInfoImpl {
|
|
|
52
52
|
this._startTime = void 0;
|
|
53
53
|
this._startWallTime = void 0;
|
|
54
54
|
this._hasHardError = false;
|
|
55
|
+
this._traceEvents = [];
|
|
55
56
|
this._onTestFailureImmediateCallbacks = new Map();
|
|
56
57
|
this._didTimeout = false;
|
|
57
58
|
this._lastStepId = 0;
|
|
59
|
+
this.testId = void 0;
|
|
58
60
|
this.repeatEachIndex = void 0;
|
|
59
61
|
this.retry = void 0;
|
|
60
62
|
this.workerIndex = void 0;
|
|
@@ -80,6 +82,7 @@ class TestInfoImpl {
|
|
|
80
82
|
this.errors = [];
|
|
81
83
|
this.currentStep = void 0;
|
|
82
84
|
this._test = test;
|
|
85
|
+
this.testId = test.id;
|
|
83
86
|
this._onStepBegin = onStepBegin;
|
|
84
87
|
this._onStepEnd = onStepEnd;
|
|
85
88
|
this._startTime = (0, _utils.monotonicTime)();
|
|
@@ -199,8 +202,7 @@ class TestInfoImpl {
|
|
|
199
202
|
testId: this._test.id,
|
|
200
203
|
stepId,
|
|
201
204
|
...data,
|
|
202
|
-
location
|
|
203
|
-
wallTime: Date.now()
|
|
205
|
+
location
|
|
204
206
|
};
|
|
205
207
|
this._onStepBegin(payload);
|
|
206
208
|
return step;
|
|
@@ -228,7 +230,10 @@ class TestInfoImpl {
|
|
|
228
230
|
this._hasHardError = state.hasHardError;
|
|
229
231
|
}
|
|
230
232
|
async _runAsStep(cb, stepInfo) {
|
|
231
|
-
const step = this._addStep(
|
|
233
|
+
const step = this._addStep({
|
|
234
|
+
...stepInfo,
|
|
235
|
+
wallTime: Date.now()
|
|
236
|
+
});
|
|
232
237
|
try {
|
|
233
238
|
const result = await cb();
|
|
234
239
|
step.complete({});
|
|
@@ -93,8 +93,15 @@ class TimeoutManager {
|
|
|
93
93
|
switch (this._runnable.type) {
|
|
94
94
|
case 'test':
|
|
95
95
|
{
|
|
96
|
-
|
|
97
|
-
|
|
96
|
+
if (this._fixture) {
|
|
97
|
+
if (this._fixture.phase === 'setup') {
|
|
98
|
+
message = `Test timeout of ${timeout}ms exceeded while setting up "${this._fixture.title}".`;
|
|
99
|
+
} else {
|
|
100
|
+
message = [`Test finished within timeout of ${timeout}ms, but tearing down "${this._fixture.title}" ran out of time.`, `Please allow more time for the test, since teardown is attributed towards the test timeout budget.`].join('\n');
|
|
101
|
+
}
|
|
102
|
+
} else {
|
|
103
|
+
message = `Test timeout of ${timeout}ms exceeded.`;
|
|
104
|
+
}
|
|
98
105
|
break;
|
|
99
106
|
}
|
|
100
107
|
case 'afterEach':
|
|
@@ -107,8 +114,7 @@ class TimeoutManager {
|
|
|
107
114
|
break;
|
|
108
115
|
case 'teardown':
|
|
109
116
|
{
|
|
110
|
-
|
|
111
|
-
message = `Worker teardown timeout of ${timeout}ms exceeded${fixtureSuffix}.`;
|
|
117
|
+
if (this._fixture) message = `Worker teardown timeout of ${timeout}ms exceeded while ${this._fixture.phase === 'setup' ? 'setting up' : 'tearing down'} "${this._fixture.title}".`;else message = `Worker teardown timeout of ${timeout}ms exceeded.`;
|
|
112
118
|
break;
|
|
113
119
|
}
|
|
114
120
|
case 'skip':
|
|
@@ -119,7 +125,7 @@ class TimeoutManager {
|
|
|
119
125
|
break;
|
|
120
126
|
}
|
|
121
127
|
const fixtureWithSlot = (_this$_fixture2 = this._fixture) !== null && _this$_fixture2 !== void 0 && _this$_fixture2.slot ? this._fixture : undefined;
|
|
122
|
-
if (fixtureWithSlot) message =
|
|
128
|
+
if (fixtureWithSlot) message = `Fixture "${fixtureWithSlot.title}" timeout of ${timeout}ms exceeded during ${fixtureWithSlot.phase}.`;
|
|
123
129
|
message = _utilsBundle.colors.red(message);
|
|
124
130
|
const location = (fixtureWithSlot || this._runnable).location;
|
|
125
131
|
return {
|
package/lib/worker/workerMain.js
CHANGED
|
@@ -221,7 +221,8 @@ class WorkerMain extends _process.ProcessRunner {
|
|
|
221
221
|
// In theory, we should run above code without any errors.
|
|
222
222
|
// However, in the case we screwed up, or loadTestFile failed in the worker
|
|
223
223
|
// but not in the runner, let's do a fatal error.
|
|
224
|
-
this.
|
|
224
|
+
this._fatalErrors.push((0, _util2.serializeError)(e));
|
|
225
|
+
this._stop();
|
|
225
226
|
} finally {
|
|
226
227
|
const donePayload = {
|
|
227
228
|
fatalErrors: this._fatalErrors,
|
|
@@ -299,7 +300,8 @@ class WorkerMain extends _process.ProcessRunner {
|
|
|
299
300
|
category: 'hook',
|
|
300
301
|
title: 'Before Hooks',
|
|
301
302
|
canHaveChildren: true,
|
|
302
|
-
forceNoParent: true
|
|
303
|
+
forceNoParent: true,
|
|
304
|
+
wallTime: Date.now()
|
|
303
305
|
});
|
|
304
306
|
|
|
305
307
|
// Note: wrap all preparation steps together, because failure/skip in any of them
|
|
@@ -367,7 +369,8 @@ class WorkerMain extends _process.ProcessRunner {
|
|
|
367
369
|
category: 'hook',
|
|
368
370
|
title: 'After Hooks',
|
|
369
371
|
canHaveChildren: true,
|
|
370
|
-
forceNoParent: true
|
|
372
|
+
forceNoParent: true,
|
|
373
|
+
wallTime: Date.now()
|
|
371
374
|
});
|
|
372
375
|
let firstAfterHooksError;
|
|
373
376
|
let afterHooksSlot;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@playwright/test",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.32.0",
|
|
4
4
|
"description": "A high-level API to automate web browsers",
|
|
5
5
|
"repository": "github:Microsoft/playwright",
|
|
6
6
|
"homepage": "https://playwright.dev",
|
|
@@ -34,7 +34,7 @@
|
|
|
34
34
|
"license": "Apache-2.0",
|
|
35
35
|
"dependencies": {
|
|
36
36
|
"@types/node": "*",
|
|
37
|
-
"playwright-core": "1.
|
|
37
|
+
"playwright-core": "1.32.0"
|
|
38
38
|
},
|
|
39
39
|
"optionalDependencies": {
|
|
40
40
|
"fsevents": "2.3.2"
|
package/types/component.d.ts
CHANGED
|
@@ -34,7 +34,7 @@ export type ObjectComponent = {
|
|
|
34
34
|
options?: MountOptions
|
|
35
35
|
};
|
|
36
36
|
|
|
37
|
-
export type Component = JsxComponent | ObjectComponent
|
|
37
|
+
export type Component = JsxComponent | ObjectComponent | number | string | Array<any>;
|
|
38
38
|
|
|
39
39
|
declare global {
|
|
40
40
|
interface Window {
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright (c) Microsoft Corporation.
|
|
3
|
+
*
|
|
4
|
+
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
5
|
+
* you may not use this file except in compliance with the License.
|
|
6
|
+
* You may obtain a copy of the License at
|
|
7
|
+
*
|
|
8
|
+
* http://www.apache.org/licenses/LICENSE-2.0
|
|
9
|
+
*
|
|
10
|
+
* Unless required by applicable law or agreed to in writing, software
|
|
11
|
+
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
12
|
+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
13
|
+
* See the License for the specific language governing permissions and
|
|
14
|
+
* limitations under the License.
|
|
15
|
+
*/
|
|
16
|
+
|
|
17
|
+
import type { Suite } from './testReporter';
|
|
18
|
+
|
|
19
|
+
export interface SuitePrivate extends Suite {
|
|
20
|
+
_fileId: string | undefined;
|
|
21
|
+
_parallelMode: 'default' | 'serial' | 'parallel';
|
|
22
|
+
}
|
package/types/test.d.ts
CHANGED
|
@@ -1782,19 +1782,8 @@ export interface FullConfig<TestArgs = {}, WorkerArgs = {}> {
|
|
|
1782
1782
|
export type TestStatus = 'passed' | 'failed' | 'timedOut' | 'skipped' | 'interrupted';
|
|
1783
1783
|
|
|
1784
1784
|
/**
|
|
1785
|
-
* `WorkerInfo` contains information about the worker that is running tests
|
|
1786
|
-
* [
|
|
1787
|
-
* [test.afterAll(hookFunction)](https://playwright.dev/docs/api/class-test#test-after-all) hooks and worker-scoped
|
|
1788
|
-
* fixtures.
|
|
1789
|
-
*
|
|
1790
|
-
* ```js
|
|
1791
|
-
* import { test, expect } from '@playwright/test';
|
|
1792
|
-
*
|
|
1793
|
-
* test.beforeAll(async ({ browserName }, workerInfo) => {
|
|
1794
|
-
* console.log(`Running ${browserName} in worker #${workerInfo.workerIndex}`);
|
|
1795
|
-
* });
|
|
1796
|
-
* ```
|
|
1797
|
-
*
|
|
1785
|
+
* `WorkerInfo` contains information about the worker that is running tests and is available to worker-scoped
|
|
1786
|
+
* fixtures. `WorkerInfo` is a subset of [TestInfo] that is available in many other places.
|
|
1798
1787
|
*/
|
|
1799
1788
|
export interface WorkerInfo {
|
|
1800
1789
|
/**
|
|
@@ -1826,9 +1815,11 @@ export interface WorkerInfo {
|
|
|
1826
1815
|
}
|
|
1827
1816
|
|
|
1828
1817
|
/**
|
|
1829
|
-
* `TestInfo` contains information about currently running test. It is available to
|
|
1830
|
-
* [test.beforeEach(hookFunction)](https://playwright.dev/docs/api/class-test#test-before-each)
|
|
1831
|
-
* [test.afterEach(hookFunction)](https://playwright.dev/docs/api/class-test#test-after-each)
|
|
1818
|
+
* `TestInfo` contains information about currently running test. It is available to test functions,
|
|
1819
|
+
* [test.beforeEach(hookFunction)](https://playwright.dev/docs/api/class-test#test-before-each),
|
|
1820
|
+
* [test.afterEach(hookFunction)](https://playwright.dev/docs/api/class-test#test-after-each),
|
|
1821
|
+
* [test.beforeAll(hookFunction)](https://playwright.dev/docs/api/class-test#test-before-all) and
|
|
1822
|
+
* [test.afterAll(hookFunction)](https://playwright.dev/docs/api/class-test#test-after-all) hooks, and test-scoped
|
|
1832
1823
|
* fixtures. `TestInfo` provides utilities to control test execution: attach files, update test timeout, determine
|
|
1833
1824
|
* which test is currently running and whether it was retried, etc.
|
|
1834
1825
|
*
|
|
@@ -1871,9 +1862,9 @@ export interface TestInfo {
|
|
|
1871
1862
|
*
|
|
1872
1863
|
* ```js
|
|
1873
1864
|
* import { test, expect } from '@playwright/test';
|
|
1865
|
+
* import { download } from './my-custom-helpers';
|
|
1874
1866
|
*
|
|
1875
1867
|
* test('basic test', async ({}, testInfo) => {
|
|
1876
|
-
* const { download } = require('./my-custom-helpers');
|
|
1877
1868
|
* const tmpPath = await download('a');
|
|
1878
1869
|
* await testInfo.attach('downloaded', { path: tmpPath });
|
|
1879
1870
|
* });
|
|
@@ -2226,6 +2217,11 @@ export interface TestInfo {
|
|
|
2226
2217
|
*/
|
|
2227
2218
|
stdout: Array<string|Buffer>;
|
|
2228
2219
|
|
|
2220
|
+
/**
|
|
2221
|
+
* Test id matching the test case id in the reporter API.
|
|
2222
|
+
*/
|
|
2223
|
+
testId: string;
|
|
2224
|
+
|
|
2229
2225
|
/**
|
|
2230
2226
|
* Timeout in milliseconds for the currently running test. Zero means no timeout. Learn more about
|
|
2231
2227
|
* [various timeouts](https://playwright.dev/docs/test-timeouts).
|
|
@@ -3166,7 +3162,7 @@ export interface TestType<TestArgs extends KeyValue, WorkerArgs extends KeyValue
|
|
|
3166
3162
|
* @param title Step name.
|
|
3167
3163
|
* @param body Step body.
|
|
3168
3164
|
*/
|
|
3169
|
-
step<T>(title: string, body: () => Promise<T>): Promise<T>;
|
|
3165
|
+
step<T>(title: string, body: () => T | Promise<T>): Promise<T>;
|
|
3170
3166
|
/**
|
|
3171
3167
|
* `expect` function can be used to create test assertions. Read more about [test assertions](https://playwright.dev/docs/test-assertions).
|
|
3172
3168
|
*
|
|
@@ -3312,7 +3308,7 @@ type ConnectOptions = {
|
|
|
3312
3308
|
* [testProject.use](https://playwright.dev/docs/api/class-testproject#test-project-use).
|
|
3313
3309
|
*
|
|
3314
3310
|
* ```js
|
|
3315
|
-
* import
|
|
3311
|
+
* import { defineConfig } from '@playwright/test';
|
|
3316
3312
|
* export default defineConfig({
|
|
3317
3313
|
* use: {
|
|
3318
3314
|
* headless: false,
|
|
@@ -3439,7 +3435,7 @@ export type VideoMode = 'off' | 'on' | 'retain-on-failure' | 'on-first-retry';
|
|
|
3439
3435
|
* [testProject.use](https://playwright.dev/docs/api/class-testproject#test-project-use).
|
|
3440
3436
|
*
|
|
3441
3437
|
* ```js
|
|
3442
|
-
* import
|
|
3438
|
+
* import { defineConfig } from '@playwright/test';
|
|
3443
3439
|
* export default defineConfig({
|
|
3444
3440
|
* use: {
|
|
3445
3441
|
* headless: false,
|
|
@@ -4090,12 +4086,12 @@ interface GenericAssertions<R> {
|
|
|
4090
4086
|
*
|
|
4091
4087
|
* ```js
|
|
4092
4088
|
* const value = 'Is 42 enough?';
|
|
4093
|
-
* expect(value).
|
|
4089
|
+
* expect(value).toMatch(/Is \d+ enough/);
|
|
4094
4090
|
* ```
|
|
4095
4091
|
*
|
|
4096
4092
|
* @param expected Regular expression to match against.
|
|
4097
4093
|
*/
|
|
4098
|
-
toMatch(expected: RegExp): R;
|
|
4094
|
+
toMatch(expected: RegExp | string): R;
|
|
4099
4095
|
/**
|
|
4100
4096
|
* Compares contents of the value with contents of `expected`, performing "deep equality" check. Allows extra
|
|
4101
4097
|
* properties to be present in the value, unlike
|
package/types/testReporter.d.ts
CHANGED
|
@@ -319,6 +319,10 @@ export interface FullResult {
|
|
|
319
319
|
* import { Reporter, FullConfig, Suite, TestCase, TestResult, FullResult } from '@playwright/test/reporter';
|
|
320
320
|
*
|
|
321
321
|
* class MyReporter implements Reporter {
|
|
322
|
+
* constructor(options: { customOption?: string } = {}) {
|
|
323
|
+
* console.log(`my-awesome-reporter setup with customOption set to ${options.customOption}`);
|
|
324
|
+
* }
|
|
325
|
+
*
|
|
322
326
|
* onBegin(config: FullConfig, suite: Suite) {
|
|
323
327
|
* console.log(`Starting the run with ${suite.allTests().length} tests`);
|
|
324
328
|
* }
|
|
@@ -347,7 +351,7 @@ export interface FullResult {
|
|
|
347
351
|
* import { defineConfig } from '@playwright/test';
|
|
348
352
|
*
|
|
349
353
|
* export default defineConfig({
|
|
350
|
-
* reporter: './my-awesome-reporter.ts',
|
|
354
|
+
* reporter: ['./my-awesome-reporter.ts', { customOption: 'some value' }],
|
|
351
355
|
* });
|
|
352
356
|
* ```
|
|
353
357
|
*
|
package/lib/common/profiler.js
DELETED
|
@@ -1,53 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
|
|
3
|
-
Object.defineProperty(exports, "__esModule", {
|
|
4
|
-
value: true
|
|
5
|
-
});
|
|
6
|
-
exports.startProfiling = startProfiling;
|
|
7
|
-
exports.stopProfiling = stopProfiling;
|
|
8
|
-
var fs = _interopRequireWildcard(require("fs"));
|
|
9
|
-
var path = _interopRequireWildcard(require("path"));
|
|
10
|
-
function _getRequireWildcardCache(nodeInterop) { if (typeof WeakMap !== "function") return null; var cacheBabelInterop = new WeakMap(); var cacheNodeInterop = new WeakMap(); return (_getRequireWildcardCache = function (nodeInterop) { return nodeInterop ? cacheNodeInterop : cacheBabelInterop; })(nodeInterop); }
|
|
11
|
-
function _interopRequireWildcard(obj, nodeInterop) { if (!nodeInterop && obj && obj.__esModule) { return obj; } if (obj === null || typeof obj !== "object" && typeof obj !== "function") { return { default: obj }; } var cache = _getRequireWildcardCache(nodeInterop); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (key !== "default" && Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj.default = obj; if (cache) { cache.set(obj, newObj); } return newObj; }
|
|
12
|
-
/**
|
|
13
|
-
* Copyright Microsoft Corporation. All rights reserved.
|
|
14
|
-
*
|
|
15
|
-
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
16
|
-
* you may not use this file except in compliance with the License.
|
|
17
|
-
* You may obtain a copy of the License at
|
|
18
|
-
*
|
|
19
|
-
* http://www.apache.org/licenses/LICENSE-2.0
|
|
20
|
-
*
|
|
21
|
-
* Unless required by applicable law or agreed to in writing, software
|
|
22
|
-
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
23
|
-
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
24
|
-
* See the License for the specific language governing permissions and
|
|
25
|
-
* limitations under the License.
|
|
26
|
-
*/
|
|
27
|
-
|
|
28
|
-
const profileDir = process.env.PWTEST_PROFILE_DIR || '';
|
|
29
|
-
let session;
|
|
30
|
-
async function startProfiling() {
|
|
31
|
-
if (!profileDir) return;
|
|
32
|
-
session = new (require('inspector').Session)();
|
|
33
|
-
session.connect();
|
|
34
|
-
await new Promise(f => {
|
|
35
|
-
session.post('Profiler.enable', () => {
|
|
36
|
-
session.post('Profiler.start', f);
|
|
37
|
-
});
|
|
38
|
-
});
|
|
39
|
-
}
|
|
40
|
-
async function stopProfiling(processName) {
|
|
41
|
-
if (!profileDir) return;
|
|
42
|
-
await new Promise(f => session.post('Profiler.stop', (err, {
|
|
43
|
-
profile
|
|
44
|
-
}) => {
|
|
45
|
-
if (!err) {
|
|
46
|
-
fs.mkdirSync(profileDir, {
|
|
47
|
-
recursive: true
|
|
48
|
-
});
|
|
49
|
-
fs.writeFileSync(path.join(profileDir, (processName || 'runner') + '.json'), JSON.stringify(profile));
|
|
50
|
-
}
|
|
51
|
-
f();
|
|
52
|
-
}));
|
|
53
|
-
}
|