@playwright/test 1.37.0 → 1.38.0-alpha-aug-11-2023
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/common/test.js +18 -5
- package/lib/isomorphic/teleReceiver.js +18 -5
- package/lib/reporters/html.js +129 -46
- package/package.json +2 -2
- package/types/test.d.ts +102 -64
- package/lib/reporters/raw.js +0 -239
package/lib/common/test.js
CHANGED
|
@@ -209,12 +209,25 @@ class TestCase extends Base {
|
|
|
209
209
|
return titlePath;
|
|
210
210
|
}
|
|
211
211
|
outcome() {
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
212
|
+
// Ignore initial skips that may be a result of "skipped because previous test in serial mode failed".
|
|
213
|
+
const results = [...this.results];
|
|
214
|
+
while (((_results$ = results[0]) === null || _results$ === void 0 ? void 0 : _results$.status) === 'skipped' || ((_results$2 = results[0]) === null || _results$2 === void 0 ? void 0 : _results$2.status) === 'interrupted') {
|
|
215
|
+
var _results$, _results$2;
|
|
216
|
+
results.shift();
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
// All runs were skipped.
|
|
220
|
+
if (!results.length) return 'skipped';
|
|
221
|
+
const failures = results.filter(result => result.status !== 'skipped' && result.status !== 'interrupted' && result.status !== this.expectedStatus);
|
|
222
|
+
if (!failures.length)
|
|
223
|
+
// all passed
|
|
224
|
+
return 'expected';
|
|
225
|
+
if (failures.length === results.length)
|
|
226
|
+
// all failed
|
|
227
|
+
return 'unexpected';
|
|
228
|
+
return 'flaky'; // mixed bag
|
|
217
229
|
}
|
|
230
|
+
|
|
218
231
|
ok() {
|
|
219
232
|
const status = this.outcome();
|
|
220
233
|
return status === 'expected' || status === 'flaky' || status === 'skipped';
|
|
@@ -352,12 +352,25 @@ class TeleTestCase {
|
|
|
352
352
|
return titlePath;
|
|
353
353
|
}
|
|
354
354
|
outcome() {
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
355
|
+
// Ignore initial skips that may be a result of "skipped because previous test in serial mode failed".
|
|
356
|
+
const results = [...this.results];
|
|
357
|
+
while (((_results$ = results[0]) === null || _results$ === void 0 ? void 0 : _results$.status) === 'skipped' || ((_results$2 = results[0]) === null || _results$2 === void 0 ? void 0 : _results$2.status) === 'interrupted') {
|
|
358
|
+
var _results$, _results$2;
|
|
359
|
+
results.shift();
|
|
360
|
+
}
|
|
361
|
+
|
|
362
|
+
// All runs were skipped.
|
|
363
|
+
if (!results.length) return 'skipped';
|
|
364
|
+
const failures = results.filter(result => result.status !== 'skipped' && result.status !== 'interrupted' && result.status !== this.expectedStatus);
|
|
365
|
+
if (!failures.length)
|
|
366
|
+
// all passed
|
|
367
|
+
return 'expected';
|
|
368
|
+
if (failures.length === results.length)
|
|
369
|
+
// all failed
|
|
370
|
+
return 'unexpected';
|
|
371
|
+
return 'flaky'; // mixed bag
|
|
360
372
|
}
|
|
373
|
+
|
|
361
374
|
ok() {
|
|
362
375
|
const status = this.outcome();
|
|
363
376
|
return status === 'expected' || status === 'flaky' || status === 'skipped';
|
package/lib/reporters/html.js
CHANGED
|
@@ -7,11 +7,12 @@ exports.default = void 0;
|
|
|
7
7
|
exports.showHTMLReport = showHTMLReport;
|
|
8
8
|
exports.startHtmlReportServer = startHtmlReportServer;
|
|
9
9
|
var _utilsBundle = require("playwright-core/lib/utilsBundle");
|
|
10
|
+
var _utils = require("playwright-core/lib/utils");
|
|
10
11
|
var _fs = _interopRequireDefault(require("fs"));
|
|
11
12
|
var _path = _interopRequireDefault(require("path"));
|
|
12
13
|
var _stream = require("stream");
|
|
13
|
-
var
|
|
14
|
-
var
|
|
14
|
+
var _json = require("./json");
|
|
15
|
+
var _babelBundle = require("../transform/babelBundle");
|
|
15
16
|
var _base = require("./base");
|
|
16
17
|
var _util = require("../util");
|
|
17
18
|
var _zipBundle = require("playwright-core/lib/zipBundle");
|
|
@@ -89,14 +90,9 @@ class HtmlReporter extends _empty.default {
|
|
|
89
90
|
}
|
|
90
91
|
async onEnd() {
|
|
91
92
|
const projectSuites = this.suite.suites;
|
|
92
|
-
const reports = projectSuites.map(suite => {
|
|
93
|
-
const rawReporter = new _raw.default();
|
|
94
|
-
const report = rawReporter.generateProjectReport(this.config, suite);
|
|
95
|
-
return report;
|
|
96
|
-
});
|
|
97
93
|
await (0, _utils.removeFolders)([this._outputFolder]);
|
|
98
|
-
const builder = new HtmlBuilder(this._outputFolder, this._attachmentsBaseURL);
|
|
99
|
-
this._buildResult = await builder.build(this.config.metadata,
|
|
94
|
+
const builder = new HtmlBuilder(this.config, this._outputFolder, this._attachmentsBaseURL);
|
|
95
|
+
this._buildResult = await builder.build(this.config.metadata, projectSuites);
|
|
100
96
|
}
|
|
101
97
|
async onExit() {
|
|
102
98
|
var _FullConfigInternal$f;
|
|
@@ -169,13 +165,14 @@ function startHtmlReportServer(folder) {
|
|
|
169
165
|
return server;
|
|
170
166
|
}
|
|
171
167
|
class HtmlBuilder {
|
|
172
|
-
constructor(outputDir, attachmentsBaseURL) {
|
|
168
|
+
constructor(config, outputDir, attachmentsBaseURL) {
|
|
169
|
+
this._config = void 0;
|
|
173
170
|
this._reportFolder = void 0;
|
|
174
|
-
this.
|
|
175
|
-
this._testPath = new Map();
|
|
171
|
+
this._stepsInFile = new _utils.MultiMap();
|
|
176
172
|
this._dataZipFile = void 0;
|
|
177
173
|
this._hasTraces = false;
|
|
178
174
|
this._attachmentsBaseURL = void 0;
|
|
175
|
+
this._config = config;
|
|
179
176
|
this._reportFolder = outputDir;
|
|
180
177
|
_fs.default.mkdirSync(this._reportFolder, {
|
|
181
178
|
recursive: true
|
|
@@ -183,13 +180,13 @@ class HtmlBuilder {
|
|
|
183
180
|
this._dataZipFile = new _zipBundle.yazl.ZipFile();
|
|
184
181
|
this._attachmentsBaseURL = attachmentsBaseURL;
|
|
185
182
|
}
|
|
186
|
-
async build(metadata,
|
|
183
|
+
async build(metadata, projectSuites) {
|
|
187
184
|
const data = new Map();
|
|
188
|
-
for (const
|
|
189
|
-
for (const
|
|
190
|
-
var
|
|
191
|
-
const fileName =
|
|
192
|
-
const fileId =
|
|
185
|
+
for (const projectSuite of projectSuites) {
|
|
186
|
+
for (const fileSuite of projectSuite.suites) {
|
|
187
|
+
var _metadata;
|
|
188
|
+
const fileName = this._relativeLocation(fileSuite.location).file;
|
|
189
|
+
const fileId = fileSuite._fileId;
|
|
193
190
|
let fileEntry = data.get(fileId);
|
|
194
191
|
if (!fileEntry) {
|
|
195
192
|
fileEntry = {
|
|
@@ -212,13 +209,14 @@ class HtmlBuilder {
|
|
|
212
209
|
testFileSummary
|
|
213
210
|
} = fileEntry;
|
|
214
211
|
const testEntries = [];
|
|
215
|
-
this._processJsonSuite(
|
|
212
|
+
this._processJsonSuite(fileSuite, fileId, projectSuite.project().name, (_metadata = projectSuite.project().metadata) === null || _metadata === void 0 ? void 0 : _metadata.reportName, [], testEntries);
|
|
216
213
|
for (const test of testEntries) {
|
|
217
214
|
testFile.tests.push(test.testCase);
|
|
218
215
|
testFileSummary.tests.push(test.testCaseSummary);
|
|
219
216
|
}
|
|
220
217
|
}
|
|
221
218
|
}
|
|
219
|
+
createSnippets(this._stepsInFile);
|
|
222
220
|
let ok = true;
|
|
223
221
|
for (const [fileId, {
|
|
224
222
|
testFile,
|
|
@@ -246,7 +244,7 @@ class HtmlBuilder {
|
|
|
246
244
|
const htmlReport = {
|
|
247
245
|
metadata,
|
|
248
246
|
files: [...data.values()].map(e => e.testFileSummary),
|
|
249
|
-
projectNames:
|
|
247
|
+
projectNames: projectSuites.map(r => r.project().name),
|
|
250
248
|
stats: {
|
|
251
249
|
...[...data.values()].reduce((a, e) => addStats(a, e.testFileSummary.stats), emptyStats()),
|
|
252
250
|
duration: metadata.totalTime
|
|
@@ -307,41 +305,39 @@ class HtmlBuilder {
|
|
|
307
305
|
}
|
|
308
306
|
_processJsonSuite(suite, fileId, projectName, reportName, path, outTests) {
|
|
309
307
|
const newPath = [...path, suite.title];
|
|
310
|
-
suite.suites.
|
|
308
|
+
suite.suites.forEach(s => this._processJsonSuite(s, fileId, projectName, reportName, newPath, outTests));
|
|
311
309
|
suite.tests.forEach(t => outTests.push(this._createTestEntry(t, projectName, reportName, newPath)));
|
|
312
310
|
}
|
|
313
311
|
_createTestEntry(test, projectName, reportName, path) {
|
|
314
312
|
const duration = test.results.reduce((a, r) => a + r.duration, 0);
|
|
315
|
-
this.
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
this._testPath.set(test.testId, path);
|
|
319
|
-
const results = test.results.map(r => this._createTestResult(r));
|
|
313
|
+
const location = this._relativeLocation(test.location);
|
|
314
|
+
path = path.slice(1);
|
|
315
|
+
const results = test.results.map(r => this._createTestResult(test, r));
|
|
320
316
|
return {
|
|
321
317
|
testCase: {
|
|
322
|
-
testId: test.
|
|
318
|
+
testId: test.id,
|
|
323
319
|
title: test.title,
|
|
324
320
|
projectName,
|
|
325
321
|
reportName,
|
|
326
322
|
location,
|
|
327
323
|
duration,
|
|
328
324
|
annotations: test.annotations,
|
|
329
|
-
outcome: test.outcome,
|
|
325
|
+
outcome: test.outcome(),
|
|
330
326
|
path,
|
|
331
327
|
results,
|
|
332
|
-
ok: test.outcome === 'expected' || test.outcome === 'flaky'
|
|
328
|
+
ok: test.outcome() === 'expected' || test.outcome() === 'flaky'
|
|
333
329
|
},
|
|
334
330
|
testCaseSummary: {
|
|
335
|
-
testId: test.
|
|
331
|
+
testId: test.id,
|
|
336
332
|
title: test.title,
|
|
337
333
|
projectName,
|
|
338
334
|
reportName,
|
|
339
335
|
location,
|
|
340
336
|
duration,
|
|
341
337
|
annotations: test.annotations,
|
|
342
|
-
outcome: test.outcome,
|
|
338
|
+
outcome: test.outcome(),
|
|
343
339
|
path,
|
|
344
|
-
ok: test.outcome === 'expected' || test.outcome === 'flaky',
|
|
340
|
+
ok: test.outcome() === 'expected' || test.outcome() === 'flaky',
|
|
345
341
|
results: results.map(result => {
|
|
346
342
|
return {
|
|
347
343
|
attachments: result.attachments.map(a => ({
|
|
@@ -422,27 +418,43 @@ class HtmlBuilder {
|
|
|
422
418
|
};
|
|
423
419
|
}).filter(Boolean);
|
|
424
420
|
}
|
|
425
|
-
_createTestResult(result) {
|
|
421
|
+
_createTestResult(test, result) {
|
|
426
422
|
return {
|
|
427
423
|
duration: result.duration,
|
|
428
|
-
startTime: result.startTime,
|
|
424
|
+
startTime: result.startTime.toISOString(),
|
|
429
425
|
retry: result.retry,
|
|
430
|
-
steps: result.steps.map(s => this._createTestStep(s)),
|
|
431
|
-
errors: result.
|
|
426
|
+
steps: dedupeSteps(result.steps).map(s => this._createTestStep(s)),
|
|
427
|
+
errors: (0, _base.formatResultFailure)(test, result, '', true).map(error => error.message),
|
|
432
428
|
status: result.status,
|
|
433
|
-
attachments: this._serializeAttachments(result.attachments)
|
|
429
|
+
attachments: this._serializeAttachments([...result.attachments, ...result.stdout.map(m => stdioAttachment(m, 'stdout')), ...result.stderr.map(m => stdioAttachment(m, 'stderr'))])
|
|
434
430
|
};
|
|
435
431
|
}
|
|
436
|
-
_createTestStep(
|
|
437
|
-
|
|
432
|
+
_createTestStep(dedupedStep) {
|
|
433
|
+
var _step$error;
|
|
434
|
+
const {
|
|
435
|
+
step,
|
|
436
|
+
duration,
|
|
437
|
+
count
|
|
438
|
+
} = dedupedStep;
|
|
439
|
+
const result = {
|
|
438
440
|
title: step.title,
|
|
439
|
-
startTime: step.startTime,
|
|
440
|
-
duration
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
441
|
+
startTime: step.startTime.toISOString(),
|
|
442
|
+
duration,
|
|
443
|
+
steps: dedupeSteps(step.steps).map(s => this._createTestStep(s)),
|
|
444
|
+
location: this._relativeLocation(step.location),
|
|
445
|
+
error: (_step$error = step.error) === null || _step$error === void 0 ? void 0 : _step$error.message,
|
|
446
|
+
count
|
|
447
|
+
};
|
|
448
|
+
if (result.location) this._stepsInFile.set(result.location.file, result);
|
|
449
|
+
return result;
|
|
450
|
+
}
|
|
451
|
+
_relativeLocation(location) {
|
|
452
|
+
if (!location) return undefined;
|
|
453
|
+
const file = (0, _json.toPosixPath)(_path.default.relative(this._config.rootDir, location.file));
|
|
454
|
+
return {
|
|
455
|
+
file,
|
|
456
|
+
line: location.line,
|
|
457
|
+
column: location.column
|
|
446
458
|
};
|
|
447
459
|
}
|
|
448
460
|
}
|
|
@@ -494,5 +506,76 @@ class Base64Encoder extends _stream.Transform {
|
|
|
494
506
|
function isTextContentType(contentType) {
|
|
495
507
|
return contentType.startsWith('text/') || contentType.startsWith('application/json');
|
|
496
508
|
}
|
|
509
|
+
function stdioAttachment(chunk, type) {
|
|
510
|
+
if (typeof chunk === 'string') {
|
|
511
|
+
return {
|
|
512
|
+
name: type,
|
|
513
|
+
contentType: 'text/plain',
|
|
514
|
+
body: chunk
|
|
515
|
+
};
|
|
516
|
+
}
|
|
517
|
+
return {
|
|
518
|
+
name: type,
|
|
519
|
+
contentType: 'application/octet-stream',
|
|
520
|
+
body: chunk
|
|
521
|
+
};
|
|
522
|
+
}
|
|
523
|
+
function dedupeSteps(steps) {
|
|
524
|
+
const result = [];
|
|
525
|
+
let lastResult = undefined;
|
|
526
|
+
for (const step of steps) {
|
|
527
|
+
var _step$location, _lastResult, _step$location2, _lastStep$location, _step$location3, _lastStep$location2, _step$location4, _lastStep$location3;
|
|
528
|
+
const canDedupe = !step.error && step.duration >= 0 && ((_step$location = step.location) === null || _step$location === void 0 ? void 0 : _step$location.file) && !step.steps.length;
|
|
529
|
+
const lastStep = (_lastResult = lastResult) === null || _lastResult === void 0 ? void 0 : _lastResult.step;
|
|
530
|
+
if (canDedupe && lastResult && lastStep && step.category === lastStep.category && step.title === lastStep.title && ((_step$location2 = step.location) === null || _step$location2 === void 0 ? void 0 : _step$location2.file) === ((_lastStep$location = lastStep.location) === null || _lastStep$location === void 0 ? void 0 : _lastStep$location.file) && ((_step$location3 = step.location) === null || _step$location3 === void 0 ? void 0 : _step$location3.line) === ((_lastStep$location2 = lastStep.location) === null || _lastStep$location2 === void 0 ? void 0 : _lastStep$location2.line) && ((_step$location4 = step.location) === null || _step$location4 === void 0 ? void 0 : _step$location4.column) === ((_lastStep$location3 = lastStep.location) === null || _lastStep$location3 === void 0 ? void 0 : _lastStep$location3.column)) {
|
|
531
|
+
++lastResult.count;
|
|
532
|
+
lastResult.duration += step.duration;
|
|
533
|
+
continue;
|
|
534
|
+
}
|
|
535
|
+
lastResult = {
|
|
536
|
+
step,
|
|
537
|
+
count: 1,
|
|
538
|
+
duration: step.duration
|
|
539
|
+
};
|
|
540
|
+
result.push(lastResult);
|
|
541
|
+
if (!canDedupe) lastResult = undefined;
|
|
542
|
+
}
|
|
543
|
+
return result;
|
|
544
|
+
}
|
|
545
|
+
function createSnippets(stepsInFile) {
|
|
546
|
+
for (const file of stepsInFile.keys()) {
|
|
547
|
+
let source;
|
|
548
|
+
try {
|
|
549
|
+
source = _fs.default.readFileSync(file, 'utf-8') + '\n//';
|
|
550
|
+
} catch (e) {
|
|
551
|
+
continue;
|
|
552
|
+
}
|
|
553
|
+
const lines = source.split('\n').length;
|
|
554
|
+
const highlighted = (0, _babelBundle.codeFrameColumns)(source, {
|
|
555
|
+
start: {
|
|
556
|
+
line: lines,
|
|
557
|
+
column: 1
|
|
558
|
+
}
|
|
559
|
+
}, {
|
|
560
|
+
highlightCode: true,
|
|
561
|
+
linesAbove: lines,
|
|
562
|
+
linesBelow: 0
|
|
563
|
+
});
|
|
564
|
+
const highlightedLines = highlighted.split('\n');
|
|
565
|
+
const lineWithArrow = highlightedLines[highlightedLines.length - 1];
|
|
566
|
+
for (const step of stepsInFile.get(file)) {
|
|
567
|
+
// Don't bother with snippets that have less than 3 lines.
|
|
568
|
+
if (step.location.line < 2 || step.location.line >= lines) continue;
|
|
569
|
+
// Cut out snippet.
|
|
570
|
+
const snippetLines = highlightedLines.slice(step.location.line - 2, step.location.line + 1);
|
|
571
|
+
// Relocate arrow.
|
|
572
|
+
const index = lineWithArrow.indexOf('^');
|
|
573
|
+
const shiftedArrow = lineWithArrow.slice(0, index) + ' '.repeat(step.location.column - 1) + lineWithArrow.slice(index);
|
|
574
|
+
// Insert arrow line.
|
|
575
|
+
snippetLines.splice(2, 0, shiftedArrow);
|
|
576
|
+
step.snippet = snippetLines.join('\n');
|
|
577
|
+
}
|
|
578
|
+
}
|
|
579
|
+
}
|
|
497
580
|
var _default = HtmlReporter;
|
|
498
581
|
exports.default = _default;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@playwright/test",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.38.0-alpha-aug-11-2023",
|
|
4
4
|
"description": "A high-level API to automate web browsers",
|
|
5
5
|
"repository": "github:Microsoft/playwright",
|
|
6
6
|
"homepage": "https://playwright.dev",
|
|
@@ -41,7 +41,7 @@
|
|
|
41
41
|
"license": "Apache-2.0",
|
|
42
42
|
"dependencies": {
|
|
43
43
|
"@types/node": "*",
|
|
44
|
-
"playwright-core": "1.
|
|
44
|
+
"playwright-core": "1.38.0-alpha-aug-11-2023"
|
|
45
45
|
},
|
|
46
46
|
"optionalDependencies": {
|
|
47
47
|
"fsevents": "2.3.2"
|
package/types/test.d.ts
CHANGED
|
@@ -3480,6 +3480,11 @@ export interface PlaywrightWorkerOptions {
|
|
|
3480
3480
|
browserName: BrowserName;
|
|
3481
3481
|
defaultBrowserType: BrowserName;
|
|
3482
3482
|
/**
|
|
3483
|
+
* Whether to run browser in headless mode. More details for
|
|
3484
|
+
* [Chromium](https://developers.google.com/web/updates/2017/04/headless-chrome) and
|
|
3485
|
+
* [Firefox](https://developer.mozilla.org/en-US/docs/Mozilla/Firefox/Headless_mode). Defaults to `true` unless the
|
|
3486
|
+
* `devtools` option is `true`.
|
|
3487
|
+
*
|
|
3483
3488
|
* **Usage**
|
|
3484
3489
|
*
|
|
3485
3490
|
* ```js
|
|
@@ -3493,13 +3498,13 @@ export interface PlaywrightWorkerOptions {
|
|
|
3493
3498
|
* });
|
|
3494
3499
|
* ```
|
|
3495
3500
|
*
|
|
3496
|
-
* Whether to run browser in headless mode. More details for
|
|
3497
|
-
* [Chromium](https://developers.google.com/web/updates/2017/04/headless-chrome) and
|
|
3498
|
-
* [Firefox](https://developer.mozilla.org/en-US/docs/Mozilla/Firefox/Headless_mode). Defaults to `true` unless the
|
|
3499
|
-
* `devtools` option is `true`.
|
|
3500
3501
|
*/
|
|
3501
3502
|
headless: boolean;
|
|
3502
3503
|
/**
|
|
3504
|
+
* Browser distribution channel. Supported values are "chrome", "chrome-beta", "chrome-dev", "chrome-canary",
|
|
3505
|
+
* "msedge", "msedge-beta", "msedge-dev", "msedge-canary". Read more about using
|
|
3506
|
+
* [Google Chrome and Microsoft Edge](https://playwright.dev/docs/browsers#google-chrome--microsoft-edge).
|
|
3507
|
+
*
|
|
3503
3508
|
* **Usage**
|
|
3504
3509
|
*
|
|
3505
3510
|
* ```js
|
|
@@ -3519,9 +3524,6 @@ export interface PlaywrightWorkerOptions {
|
|
|
3519
3524
|
* });
|
|
3520
3525
|
* ```
|
|
3521
3526
|
*
|
|
3522
|
-
* Browser distribution channel. Supported values are "chrome", "chrome-beta", "chrome-dev", "chrome-canary",
|
|
3523
|
-
* "msedge", "msedge-beta", "msedge-dev", "msedge-canary". Read more about using
|
|
3524
|
-
* [Google Chrome and Microsoft Edge](https://playwright.dev/docs/browsers#google-chrome--microsoft-edge).
|
|
3525
3527
|
*/
|
|
3526
3528
|
channel: BrowserChannel | undefined;
|
|
3527
3529
|
/**
|
|
@@ -3700,6 +3702,8 @@ export type VideoMode = 'off' | 'on' | 'retain-on-failure' | 'on-first-retry';
|
|
|
3700
3702
|
*/
|
|
3701
3703
|
export interface PlaywrightTestOptions {
|
|
3702
3704
|
/**
|
|
3705
|
+
* Whether to automatically download all the attachments. Defaults to `true` where all the downloads are accepted.
|
|
3706
|
+
*
|
|
3703
3707
|
* **Usage**
|
|
3704
3708
|
*
|
|
3705
3709
|
* ```js
|
|
@@ -3713,10 +3717,11 @@ export interface PlaywrightTestOptions {
|
|
|
3713
3717
|
* });
|
|
3714
3718
|
* ```
|
|
3715
3719
|
*
|
|
3716
|
-
* Whether to automatically download all the attachments. Defaults to `true` where all the downloads are accepted.
|
|
3717
3720
|
*/
|
|
3718
3721
|
acceptDownloads: boolean;
|
|
3719
3722
|
/**
|
|
3723
|
+
* Toggles bypassing page's Content-Security-Policy. Defaults to `false`.
|
|
3724
|
+
*
|
|
3720
3725
|
* **Usage**
|
|
3721
3726
|
*
|
|
3722
3727
|
* ```js
|
|
@@ -3730,10 +3735,13 @@ export interface PlaywrightTestOptions {
|
|
|
3730
3735
|
* });
|
|
3731
3736
|
* ```
|
|
3732
3737
|
*
|
|
3733
|
-
* Toggles bypassing page's Content-Security-Policy. Defaults to `false`.
|
|
3734
3738
|
*/
|
|
3735
3739
|
bypassCSP: boolean;
|
|
3736
3740
|
/**
|
|
3741
|
+
* Emulates `'prefers-colors-scheme'` media feature, supported values are `'light'`, `'dark'`, `'no-preference'`. See
|
|
3742
|
+
* [page.emulateMedia([options])](https://playwright.dev/docs/api/class-page#page-emulate-media) for more details.
|
|
3743
|
+
* Passing `null` resets emulation to system defaults. Defaults to `'light'`.
|
|
3744
|
+
*
|
|
3737
3745
|
* **Usage**
|
|
3738
3746
|
*
|
|
3739
3747
|
* ```js
|
|
@@ -3747,12 +3755,12 @@ export interface PlaywrightTestOptions {
|
|
|
3747
3755
|
* });
|
|
3748
3756
|
* ```
|
|
3749
3757
|
*
|
|
3750
|
-
* Emulates `'prefers-colors-scheme'` media feature, supported values are `'light'`, `'dark'`, `'no-preference'`. See
|
|
3751
|
-
* [page.emulateMedia([options])](https://playwright.dev/docs/api/class-page#page-emulate-media) for more details.
|
|
3752
|
-
* Passing `null` resets emulation to system defaults. Defaults to `'light'`.
|
|
3753
3758
|
*/
|
|
3754
3759
|
colorScheme: ColorScheme;
|
|
3755
3760
|
/**
|
|
3761
|
+
* Specify device scale factor (can be thought of as dpr). Defaults to `1`. Learn more about
|
|
3762
|
+
* [emulating devices with device scale factor](https://playwright.dev/docs/emulation#devices).
|
|
3763
|
+
*
|
|
3756
3764
|
* **Usage**
|
|
3757
3765
|
*
|
|
3758
3766
|
* ```js
|
|
@@ -3767,11 +3775,11 @@ export interface PlaywrightTestOptions {
|
|
|
3767
3775
|
* });
|
|
3768
3776
|
* ```
|
|
3769
3777
|
*
|
|
3770
|
-
* Specify device scale factor (can be thought of as dpr). Defaults to `1`. Learn more about
|
|
3771
|
-
* [emulating devices with device scale factor](https://playwright.dev/docs/emulation#devices).
|
|
3772
3778
|
*/
|
|
3773
3779
|
deviceScaleFactor: number | undefined;
|
|
3774
3780
|
/**
|
|
3781
|
+
* An object containing additional HTTP headers to be sent with every request. Defaults to none.
|
|
3782
|
+
*
|
|
3775
3783
|
* **Usage**
|
|
3776
3784
|
*
|
|
3777
3785
|
* ```js
|
|
@@ -3787,7 +3795,6 @@ export interface PlaywrightTestOptions {
|
|
|
3787
3795
|
* });
|
|
3788
3796
|
* ```
|
|
3789
3797
|
*
|
|
3790
|
-
* An object containing additional HTTP headers to be sent with every request. Defaults to none.
|
|
3791
3798
|
*/
|
|
3792
3799
|
extraHTTPHeaders: ExtraHTTPHeaders | undefined;
|
|
3793
3800
|
/**
|
|
@@ -3808,6 +3815,9 @@ export interface PlaywrightTestOptions {
|
|
|
3808
3815
|
*/
|
|
3809
3816
|
geolocation: Geolocation | undefined;
|
|
3810
3817
|
/**
|
|
3818
|
+
* Specifies if viewport supports touch events. Defaults to false. Learn more about
|
|
3819
|
+
* [mobile emulation](https://playwright.dev/docs/emulation#devices).
|
|
3820
|
+
*
|
|
3811
3821
|
* **Usage**
|
|
3812
3822
|
*
|
|
3813
3823
|
* ```js
|
|
@@ -3821,11 +3831,12 @@ export interface PlaywrightTestOptions {
|
|
|
3821
3831
|
* });
|
|
3822
3832
|
* ```
|
|
3823
3833
|
*
|
|
3824
|
-
* Specifies if viewport supports touch events. Defaults to false. Learn more about
|
|
3825
|
-
* [mobile emulation](https://playwright.dev/docs/emulation#devices).
|
|
3826
3834
|
*/
|
|
3827
3835
|
hasTouch: boolean;
|
|
3828
3836
|
/**
|
|
3837
|
+
* Credentials for [HTTP authentication](https://developer.mozilla.org/en-US/docs/Web/HTTP/Authentication). If no
|
|
3838
|
+
* origin is specified, the username and password are sent to any servers upon unauthorized responses.
|
|
3839
|
+
*
|
|
3829
3840
|
* **Usage**
|
|
3830
3841
|
*
|
|
3831
3842
|
* ```js
|
|
@@ -3842,11 +3853,11 @@ export interface PlaywrightTestOptions {
|
|
|
3842
3853
|
* });
|
|
3843
3854
|
* ```
|
|
3844
3855
|
*
|
|
3845
|
-
* Credentials for [HTTP authentication](https://developer.mozilla.org/en-US/docs/Web/HTTP/Authentication). If no
|
|
3846
|
-
* origin is specified, the username and password are sent to any servers upon unauthorized responses.
|
|
3847
3856
|
*/
|
|
3848
3857
|
httpCredentials: HTTPCredentials | undefined;
|
|
3849
3858
|
/**
|
|
3859
|
+
* Whether to ignore HTTPS errors when sending network requests. Defaults to `false`.
|
|
3860
|
+
*
|
|
3850
3861
|
* **Usage**
|
|
3851
3862
|
*
|
|
3852
3863
|
* ```js
|
|
@@ -3860,10 +3871,13 @@ export interface PlaywrightTestOptions {
|
|
|
3860
3871
|
* });
|
|
3861
3872
|
* ```
|
|
3862
3873
|
*
|
|
3863
|
-
* Whether to ignore HTTPS errors when sending network requests. Defaults to `false`.
|
|
3864
3874
|
*/
|
|
3865
3875
|
ignoreHTTPSErrors: boolean;
|
|
3866
3876
|
/**
|
|
3877
|
+
* Whether the `meta viewport` tag is taken into account and touch events are enabled. isMobile is a part of device,
|
|
3878
|
+
* so you don't actually need to set it manually. Defaults to `false` and is not supported in Firefox. Learn more
|
|
3879
|
+
* about [mobile emulation](https://playwright.dev/docs/emulation#ismobile).
|
|
3880
|
+
*
|
|
3867
3881
|
* **Usage**
|
|
3868
3882
|
*
|
|
3869
3883
|
* ```js
|
|
@@ -3877,12 +3891,12 @@ export interface PlaywrightTestOptions {
|
|
|
3877
3891
|
* });
|
|
3878
3892
|
* ```
|
|
3879
3893
|
*
|
|
3880
|
-
* Whether the `meta viewport` tag is taken into account and touch events are enabled. isMobile is a part of device,
|
|
3881
|
-
* so you don't actually need to set it manually. Defaults to `false` and is not supported in Firefox. Learn more
|
|
3882
|
-
* about [mobile emulation](https://playwright.dev/docs/emulation#ismobile).
|
|
3883
3894
|
*/
|
|
3884
3895
|
isMobile: boolean;
|
|
3885
3896
|
/**
|
|
3897
|
+
* Whether or not to enable JavaScript in the context. Defaults to `true`. Learn more about
|
|
3898
|
+
* [disabling JavaScript](https://playwright.dev/docs/emulation#javascript-enabled).
|
|
3899
|
+
*
|
|
3886
3900
|
* **Usage**
|
|
3887
3901
|
*
|
|
3888
3902
|
* ```js
|
|
@@ -3896,11 +3910,13 @@ export interface PlaywrightTestOptions {
|
|
|
3896
3910
|
* });
|
|
3897
3911
|
* ```
|
|
3898
3912
|
*
|
|
3899
|
-
* Whether or not to enable JavaScript in the context. Defaults to `true`. Learn more about
|
|
3900
|
-
* [disabling JavaScript](https://playwright.dev/docs/emulation#javascript-enabled).
|
|
3901
3913
|
*/
|
|
3902
3914
|
javaScriptEnabled: boolean;
|
|
3903
3915
|
/**
|
|
3916
|
+
* Specify user locale, for example `en-GB`, `de-DE`, etc. Locale will affect `navigator.language` value,
|
|
3917
|
+
* `Accept-Language` request header value as well as number and date formatting rules. Defaults to the system default
|
|
3918
|
+
* locale. Learn more about emulation in our [emulation guide](https://playwright.dev/docs/emulation#locale--timezone).
|
|
3919
|
+
*
|
|
3904
3920
|
* **Usage**
|
|
3905
3921
|
*
|
|
3906
3922
|
* ```js
|
|
@@ -3914,12 +3930,12 @@ export interface PlaywrightTestOptions {
|
|
|
3914
3930
|
* });
|
|
3915
3931
|
* ```
|
|
3916
3932
|
*
|
|
3917
|
-
* Specify user locale, for example `en-GB`, `de-DE`, etc. Locale will affect `navigator.language` value,
|
|
3918
|
-
* `Accept-Language` request header value as well as number and date formatting rules. Defaults to the system default
|
|
3919
|
-
* locale. Learn more about emulation in our [emulation guide](https://playwright.dev/docs/emulation#locale--timezone).
|
|
3920
3933
|
*/
|
|
3921
3934
|
locale: string | undefined;
|
|
3922
3935
|
/**
|
|
3936
|
+
* Whether to emulate network being offline. Defaults to `false`. Learn more about
|
|
3937
|
+
* [network emulation](https://playwright.dev/docs/emulation#offline).
|
|
3938
|
+
*
|
|
3923
3939
|
* **Usage**
|
|
3924
3940
|
*
|
|
3925
3941
|
* ```js
|
|
@@ -3933,11 +3949,13 @@ export interface PlaywrightTestOptions {
|
|
|
3933
3949
|
* });
|
|
3934
3950
|
* ```
|
|
3935
3951
|
*
|
|
3936
|
-
* Whether to emulate network being offline. Defaults to `false`. Learn more about
|
|
3937
|
-
* [network emulation](https://playwright.dev/docs/emulation#offline).
|
|
3938
3952
|
*/
|
|
3939
3953
|
offline: boolean;
|
|
3940
3954
|
/**
|
|
3955
|
+
* A list of permissions to grant to all pages in this context. See
|
|
3956
|
+
* [browserContext.grantPermissions(permissions[, options])](https://playwright.dev/docs/api/class-browsercontext#browser-context-grant-permissions)
|
|
3957
|
+
* for more details. Defaults to none.
|
|
3958
|
+
*
|
|
3941
3959
|
* **Usage**
|
|
3942
3960
|
*
|
|
3943
3961
|
* ```js
|
|
@@ -3951,12 +3969,11 @@ export interface PlaywrightTestOptions {
|
|
|
3951
3969
|
* });
|
|
3952
3970
|
* ```
|
|
3953
3971
|
*
|
|
3954
|
-
* A list of permissions to grant to all pages in this context. See
|
|
3955
|
-
* [browserContext.grantPermissions(permissions[, options])](https://playwright.dev/docs/api/class-browsercontext#browser-context-grant-permissions)
|
|
3956
|
-
* for more details. Defaults to none.
|
|
3957
3972
|
*/
|
|
3958
3973
|
permissions: string[] | undefined;
|
|
3959
3974
|
/**
|
|
3975
|
+
* Network proxy settings.
|
|
3976
|
+
*
|
|
3960
3977
|
* **Usage**
|
|
3961
3978
|
*
|
|
3962
3979
|
* ```js
|
|
@@ -3973,10 +3990,15 @@ export interface PlaywrightTestOptions {
|
|
|
3973
3990
|
* });
|
|
3974
3991
|
* ```
|
|
3975
3992
|
*
|
|
3976
|
-
* Network proxy settings.
|
|
3977
3993
|
*/
|
|
3978
3994
|
proxy: Proxy | undefined;
|
|
3979
3995
|
/**
|
|
3996
|
+
* Learn more about [storage state and auth](https://playwright.dev/docs/auth).
|
|
3997
|
+
*
|
|
3998
|
+
* Populates context with given storage state. This option can be used to initialize context with logged-in
|
|
3999
|
+
* information obtained via
|
|
4000
|
+
* [browserContext.storageState([options])](https://playwright.dev/docs/api/class-browsercontext#browser-context-storage-state).
|
|
4001
|
+
*
|
|
3980
4002
|
* **Usage**
|
|
3981
4003
|
*
|
|
3982
4004
|
* ```js
|
|
@@ -3990,14 +4012,29 @@ export interface PlaywrightTestOptions {
|
|
|
3990
4012
|
* });
|
|
3991
4013
|
* ```
|
|
3992
4014
|
*
|
|
3993
|
-
*
|
|
4015
|
+
* **Details**
|
|
4016
|
+
*
|
|
4017
|
+
* When storage state is set up in the config, it is possible to reset storage state for a file:
|
|
4018
|
+
*
|
|
4019
|
+
* ```js
|
|
4020
|
+
* // not-signed-in.spec.ts
|
|
4021
|
+
* import { test } from '@playwright/test';
|
|
4022
|
+
*
|
|
4023
|
+
* // Reset storage state for this file to avoid being authenticated
|
|
4024
|
+
* test.use({ storageState: { cookies: [], origins: [] } });
|
|
4025
|
+
*
|
|
4026
|
+
* test('not signed in test', async ({ page }) => {
|
|
4027
|
+
* // ...
|
|
4028
|
+
* });
|
|
4029
|
+
* ```
|
|
3994
4030
|
*
|
|
3995
|
-
* Populates context with given storage state. This option can be used to initialize context with logged-in
|
|
3996
|
-
* information obtained via
|
|
3997
|
-
* [browserContext.storageState([options])](https://playwright.dev/docs/api/class-browsercontext#browser-context-storage-state).
|
|
3998
4031
|
*/
|
|
3999
4032
|
storageState: StorageState | undefined;
|
|
4000
4033
|
/**
|
|
4034
|
+
* Changes the timezone of the context. See
|
|
4035
|
+
* [ICU's metaZones.txt](https://cs.chromium.org/chromium/src/third_party/icu/source/data/misc/metaZones.txt?rcl=faee8bc70570192d82d2978a71e2a615788597d1)
|
|
4036
|
+
* for a list of supported timezone IDs. Defaults to the system timezone.
|
|
4037
|
+
*
|
|
4001
4038
|
* **Usage**
|
|
4002
4039
|
*
|
|
4003
4040
|
* ```js
|
|
@@ -4011,12 +4048,11 @@ export interface PlaywrightTestOptions {
|
|
|
4011
4048
|
* });
|
|
4012
4049
|
* ```
|
|
4013
4050
|
*
|
|
4014
|
-
* Changes the timezone of the context. See
|
|
4015
|
-
* [ICU's metaZones.txt](https://cs.chromium.org/chromium/src/third_party/icu/source/data/misc/metaZones.txt?rcl=faee8bc70570192d82d2978a71e2a615788597d1)
|
|
4016
|
-
* for a list of supported timezone IDs. Defaults to the system timezone.
|
|
4017
4051
|
*/
|
|
4018
4052
|
timezoneId: string | undefined;
|
|
4019
4053
|
/**
|
|
4054
|
+
* Specific user agent to use in this context.
|
|
4055
|
+
*
|
|
4020
4056
|
* **Usage**
|
|
4021
4057
|
*
|
|
4022
4058
|
* ```js
|
|
@@ -4030,10 +4066,15 @@ export interface PlaywrightTestOptions {
|
|
|
4030
4066
|
* });
|
|
4031
4067
|
* ```
|
|
4032
4068
|
*
|
|
4033
|
-
* Specific user agent to use in this context.
|
|
4034
4069
|
*/
|
|
4035
4070
|
userAgent: string | undefined;
|
|
4036
4071
|
/**
|
|
4072
|
+
* Emulates consistent viewport for each page. Defaults to an 1280x720 viewport. Use `null` to disable the consistent
|
|
4073
|
+
* viewport emulation. Learn more about [viewport emulation](https://playwright.dev/docs/emulation#viewport).
|
|
4074
|
+
*
|
|
4075
|
+
* **NOTE** The `null` value opts out from the default presets, makes viewport depend on the host window size defined
|
|
4076
|
+
* by the operating system. It makes the execution of the tests non-deterministic.
|
|
4077
|
+
*
|
|
4037
4078
|
* **Usage**
|
|
4038
4079
|
*
|
|
4039
4080
|
* ```js
|
|
@@ -4047,27 +4088,9 @@ export interface PlaywrightTestOptions {
|
|
|
4047
4088
|
* });
|
|
4048
4089
|
* ```
|
|
4049
4090
|
*
|
|
4050
|
-
* Emulates consistent viewport for each page. Defaults to an 1280x720 viewport. Use `null` to disable the consistent
|
|
4051
|
-
* viewport emulation. Learn more about [viewport emulation](https://playwright.dev/docs/emulation#viewport).
|
|
4052
|
-
*
|
|
4053
|
-
* **NOTE** The `null` value opts out from the default presets, makes viewport depend on the host window size defined
|
|
4054
|
-
* by the operating system. It makes the execution of the tests non-deterministic.
|
|
4055
4091
|
*/
|
|
4056
4092
|
viewport: ViewportSize | null;
|
|
4057
4093
|
/**
|
|
4058
|
-
* **Usage**
|
|
4059
|
-
*
|
|
4060
|
-
* ```js
|
|
4061
|
-
* import { defineConfig, devices } from '@playwright/test';
|
|
4062
|
-
*
|
|
4063
|
-
* export default defineConfig({
|
|
4064
|
-
* use: {
|
|
4065
|
-
* /* Base URL to use in actions like `await page.goto('/')`. *\/
|
|
4066
|
-
* baseURL: 'http://localhost:3000',
|
|
4067
|
-
* },
|
|
4068
|
-
* });
|
|
4069
|
-
* ```
|
|
4070
|
-
*
|
|
4071
4094
|
* When using [page.goto(url[, options])](https://playwright.dev/docs/api/class-page#page-goto),
|
|
4072
4095
|
* [page.route(url, handler[, options])](https://playwright.dev/docs/api/class-page#page-route),
|
|
4073
4096
|
* [page.waitForURL(url[, options])](https://playwright.dev/docs/api/class-page#page-wait-for-url),
|
|
@@ -4082,6 +4105,20 @@ export interface PlaywrightTestOptions {
|
|
|
4082
4105
|
* `http://localhost:3000/foo/bar.html`
|
|
4083
4106
|
* - baseURL: `http://localhost:3000/foo` (without trailing slash) and navigating to `./bar.html` results in
|
|
4084
4107
|
* `http://localhost:3000/bar.html`
|
|
4108
|
+
*
|
|
4109
|
+
* **Usage**
|
|
4110
|
+
*
|
|
4111
|
+
* ```js
|
|
4112
|
+
* import { defineConfig, devices } from '@playwright/test';
|
|
4113
|
+
*
|
|
4114
|
+
* export default defineConfig({
|
|
4115
|
+
* use: {
|
|
4116
|
+
* /* Base URL to use in actions like `await page.goto('/')`. *\/
|
|
4117
|
+
* baseURL: 'http://localhost:3000',
|
|
4118
|
+
* },
|
|
4119
|
+
* });
|
|
4120
|
+
* ```
|
|
4121
|
+
*
|
|
4085
4122
|
*/
|
|
4086
4123
|
baseURL: string | undefined;
|
|
4087
4124
|
/**
|
|
@@ -4152,6 +4189,11 @@ export interface PlaywrightTestOptions {
|
|
|
4152
4189
|
*/
|
|
4153
4190
|
navigationTimeout: number;
|
|
4154
4191
|
/**
|
|
4192
|
+
* Whether to allow sites to register Service workers. Defaults to `'allow'`.
|
|
4193
|
+
* - `'allow'`: [Service Workers](https://developer.mozilla.org/en-US/docs/Web/API/Service_Worker_API) can be
|
|
4194
|
+
* registered.
|
|
4195
|
+
* - `'block'`: Playwright will block all registration of Service Workers.
|
|
4196
|
+
*
|
|
4155
4197
|
* **Usage**
|
|
4156
4198
|
*
|
|
4157
4199
|
* ```js
|
|
@@ -4165,10 +4207,6 @@ export interface PlaywrightTestOptions {
|
|
|
4165
4207
|
* });
|
|
4166
4208
|
* ```
|
|
4167
4209
|
*
|
|
4168
|
-
* Whether to allow sites to register Service workers. Defaults to `'allow'`.
|
|
4169
|
-
* - `'allow'`: [Service Workers](https://developer.mozilla.org/en-US/docs/Web/API/Service_Worker_API) can be
|
|
4170
|
-
* registered.
|
|
4171
|
-
* - `'block'`: Playwright will block all registration of Service Workers.
|
|
4172
4210
|
*/
|
|
4173
4211
|
serviceWorkers: ServiceWorkerPolicy;
|
|
4174
4212
|
/**
|
package/lib/reporters/raw.js
DELETED
|
@@ -1,239 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
|
|
3
|
-
Object.defineProperty(exports, "__esModule", {
|
|
4
|
-
value: true
|
|
5
|
-
});
|
|
6
|
-
exports.default = void 0;
|
|
7
|
-
var _fs = _interopRequireDefault(require("fs"));
|
|
8
|
-
var _path = _interopRequireDefault(require("path"));
|
|
9
|
-
var _utils = require("playwright-core/lib/utils");
|
|
10
|
-
var _base = require("./base");
|
|
11
|
-
var _json = require("./json");
|
|
12
|
-
var _babelBundle = require("../transform/babelBundle");
|
|
13
|
-
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
|
14
|
-
/**
|
|
15
|
-
* Copyright (c) Microsoft Corporation.
|
|
16
|
-
*
|
|
17
|
-
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
18
|
-
* you may not use this file except in compliance with the License.
|
|
19
|
-
* You may obtain a copy of the License at
|
|
20
|
-
*
|
|
21
|
-
* http://www.apache.org/licenses/LICENSE-2.0
|
|
22
|
-
*
|
|
23
|
-
* Unless required by applicable law or agreed to in writing, software
|
|
24
|
-
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
25
|
-
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
26
|
-
* See the License for the specific language governing permissions and
|
|
27
|
-
* limitations under the License.
|
|
28
|
-
*/
|
|
29
|
-
|
|
30
|
-
class RawReporter {
|
|
31
|
-
constructor() {
|
|
32
|
-
this.config = void 0;
|
|
33
|
-
this.suite = void 0;
|
|
34
|
-
this.stepsInFile = new _utils.MultiMap();
|
|
35
|
-
}
|
|
36
|
-
onBegin(config, suite) {
|
|
37
|
-
this.config = config;
|
|
38
|
-
this.suite = suite;
|
|
39
|
-
}
|
|
40
|
-
async onEnd() {
|
|
41
|
-
const projectSuites = this.suite.suites;
|
|
42
|
-
for (const suite of projectSuites) {
|
|
43
|
-
const project = suite.project();
|
|
44
|
-
(0, _utils.assert)(project, 'Internal Error: Invalid project structure');
|
|
45
|
-
const reportFolder = _path.default.join(project.outputDir, 'report');
|
|
46
|
-
_fs.default.mkdirSync(reportFolder, {
|
|
47
|
-
recursive: true
|
|
48
|
-
});
|
|
49
|
-
let reportFile;
|
|
50
|
-
for (let i = 0; i < 10; ++i) {
|
|
51
|
-
reportFile = _path.default.join(reportFolder, (0, _utils.sanitizeForFilePath)(project.name || 'project') + (i ? '-' + i : '') + '.report');
|
|
52
|
-
try {
|
|
53
|
-
if (_fs.default.existsSync(reportFile)) continue;
|
|
54
|
-
} catch (e) {}
|
|
55
|
-
break;
|
|
56
|
-
}
|
|
57
|
-
if (!reportFile) throw new Error('Internal error, could not create report file');
|
|
58
|
-
const report = this.generateProjectReport(this.config, suite);
|
|
59
|
-
_fs.default.writeFileSync(reportFile, JSON.stringify(report, undefined, 2));
|
|
60
|
-
}
|
|
61
|
-
}
|
|
62
|
-
generateAttachments(attachments, ioStreams) {
|
|
63
|
-
const out = [];
|
|
64
|
-
for (const attachment of attachments) {
|
|
65
|
-
if (attachment.body) {
|
|
66
|
-
out.push({
|
|
67
|
-
name: attachment.name,
|
|
68
|
-
contentType: attachment.contentType,
|
|
69
|
-
body: attachment.body
|
|
70
|
-
});
|
|
71
|
-
} else if (attachment.path) {
|
|
72
|
-
out.push({
|
|
73
|
-
name: attachment.name,
|
|
74
|
-
contentType: attachment.contentType,
|
|
75
|
-
path: attachment.path
|
|
76
|
-
});
|
|
77
|
-
}
|
|
78
|
-
}
|
|
79
|
-
if (ioStreams) {
|
|
80
|
-
for (const chunk of ioStreams.stdout) out.push(this._stdioAttachment(chunk, 'stdout'));
|
|
81
|
-
for (const chunk of ioStreams.stderr) out.push(this._stdioAttachment(chunk, 'stderr'));
|
|
82
|
-
}
|
|
83
|
-
return out;
|
|
84
|
-
}
|
|
85
|
-
generateProjectReport(config, suite) {
|
|
86
|
-
this.config = config;
|
|
87
|
-
const project = suite.project();
|
|
88
|
-
(0, _utils.assert)(project, 'Internal Error: Invalid project structure');
|
|
89
|
-
const report = {
|
|
90
|
-
config: filterOutPrivateFields(config),
|
|
91
|
-
project: {
|
|
92
|
-
metadata: project.metadata,
|
|
93
|
-
name: project.name,
|
|
94
|
-
outputDir: project.outputDir,
|
|
95
|
-
repeatEach: project.repeatEach,
|
|
96
|
-
retries: project.retries,
|
|
97
|
-
testDir: project.testDir,
|
|
98
|
-
testIgnore: (0, _json.serializePatterns)(project.testIgnore),
|
|
99
|
-
testMatch: (0, _json.serializePatterns)(project.testMatch),
|
|
100
|
-
timeout: project.timeout
|
|
101
|
-
},
|
|
102
|
-
suites: suite.suites.map(fileSuite => {
|
|
103
|
-
return this._serializeSuite(fileSuite);
|
|
104
|
-
})
|
|
105
|
-
};
|
|
106
|
-
for (const file of this.stepsInFile.keys()) {
|
|
107
|
-
let source;
|
|
108
|
-
try {
|
|
109
|
-
source = _fs.default.readFileSync(file, 'utf-8') + '\n//';
|
|
110
|
-
} catch (e) {
|
|
111
|
-
continue;
|
|
112
|
-
}
|
|
113
|
-
const lines = source.split('\n').length;
|
|
114
|
-
const highlighted = (0, _babelBundle.codeFrameColumns)(source, {
|
|
115
|
-
start: {
|
|
116
|
-
line: lines,
|
|
117
|
-
column: 1
|
|
118
|
-
}
|
|
119
|
-
}, {
|
|
120
|
-
highlightCode: true,
|
|
121
|
-
linesAbove: lines,
|
|
122
|
-
linesBelow: 0
|
|
123
|
-
});
|
|
124
|
-
const highlightedLines = highlighted.split('\n');
|
|
125
|
-
const lineWithArrow = highlightedLines[highlightedLines.length - 1];
|
|
126
|
-
for (const step of this.stepsInFile.get(file)) {
|
|
127
|
-
// Don't bother with snippets that have less than 3 lines.
|
|
128
|
-
if (step.location.line < 2 || step.location.line >= lines) continue;
|
|
129
|
-
// Cut out snippet.
|
|
130
|
-
const snippetLines = highlightedLines.slice(step.location.line - 2, step.location.line + 1);
|
|
131
|
-
// Relocate arrow.
|
|
132
|
-
const index = lineWithArrow.indexOf('^');
|
|
133
|
-
const shiftedArrow = lineWithArrow.slice(0, index) + ' '.repeat(step.location.column - 1) + lineWithArrow.slice(index);
|
|
134
|
-
// Insert arrow line.
|
|
135
|
-
snippetLines.splice(2, 0, shiftedArrow);
|
|
136
|
-
step.snippet = snippetLines.join('\n');
|
|
137
|
-
}
|
|
138
|
-
}
|
|
139
|
-
return report;
|
|
140
|
-
}
|
|
141
|
-
_serializeSuite(suite) {
|
|
142
|
-
const location = this._relativeLocation(suite.location);
|
|
143
|
-
const result = {
|
|
144
|
-
title: suite.title,
|
|
145
|
-
fileId: suite._fileId,
|
|
146
|
-
location,
|
|
147
|
-
suites: suite.suites.map(s => this._serializeSuite(s)),
|
|
148
|
-
tests: suite.tests.map(t => this._serializeTest(t))
|
|
149
|
-
};
|
|
150
|
-
return result;
|
|
151
|
-
}
|
|
152
|
-
_serializeTest(test) {
|
|
153
|
-
return {
|
|
154
|
-
testId: test.id,
|
|
155
|
-
title: test.title,
|
|
156
|
-
location: this._relativeLocation(test.location),
|
|
157
|
-
expectedStatus: test.expectedStatus,
|
|
158
|
-
timeout: test.timeout,
|
|
159
|
-
annotations: test.annotations,
|
|
160
|
-
retries: test.retries,
|
|
161
|
-
ok: test.ok(),
|
|
162
|
-
outcome: test.outcome(),
|
|
163
|
-
results: test.results.map(r => this._serializeResult(test, r))
|
|
164
|
-
};
|
|
165
|
-
}
|
|
166
|
-
_serializeResult(test, result) {
|
|
167
|
-
return {
|
|
168
|
-
retry: result.retry,
|
|
169
|
-
workerIndex: result.workerIndex,
|
|
170
|
-
startTime: result.startTime.toISOString(),
|
|
171
|
-
duration: result.duration,
|
|
172
|
-
status: result.status,
|
|
173
|
-
errors: (0, _base.formatResultFailure)(test, result, '', true).map(error => error.message),
|
|
174
|
-
attachments: this.generateAttachments(result.attachments, result),
|
|
175
|
-
steps: dedupeSteps(result.steps.map(step => this._serializeStep(test, step)))
|
|
176
|
-
};
|
|
177
|
-
}
|
|
178
|
-
_serializeStep(test, step) {
|
|
179
|
-
var _step$error;
|
|
180
|
-
const result = {
|
|
181
|
-
title: step.title,
|
|
182
|
-
category: step.category,
|
|
183
|
-
startTime: step.startTime.toISOString(),
|
|
184
|
-
duration: step.duration,
|
|
185
|
-
error: (_step$error = step.error) === null || _step$error === void 0 ? void 0 : _step$error.message,
|
|
186
|
-
location: this._relativeLocation(step.location),
|
|
187
|
-
steps: dedupeSteps(step.steps.map(step => this._serializeStep(test, step))),
|
|
188
|
-
count: 1
|
|
189
|
-
};
|
|
190
|
-
if (step.location) this.stepsInFile.set(step.location.file, result);
|
|
191
|
-
return result;
|
|
192
|
-
}
|
|
193
|
-
_stdioAttachment(chunk, type) {
|
|
194
|
-
if (typeof chunk === 'string') {
|
|
195
|
-
return {
|
|
196
|
-
name: type,
|
|
197
|
-
contentType: 'text/plain',
|
|
198
|
-
body: chunk
|
|
199
|
-
};
|
|
200
|
-
}
|
|
201
|
-
return {
|
|
202
|
-
name: type,
|
|
203
|
-
contentType: 'application/octet-stream',
|
|
204
|
-
body: chunk
|
|
205
|
-
};
|
|
206
|
-
}
|
|
207
|
-
_relativeLocation(location) {
|
|
208
|
-
if (!location) return undefined;
|
|
209
|
-
const file = (0, _json.toPosixPath)(_path.default.relative(this.config.rootDir, location.file));
|
|
210
|
-
return {
|
|
211
|
-
file,
|
|
212
|
-
line: location.line,
|
|
213
|
-
column: location.column
|
|
214
|
-
};
|
|
215
|
-
}
|
|
216
|
-
}
|
|
217
|
-
function dedupeSteps(steps) {
|
|
218
|
-
const result = [];
|
|
219
|
-
let lastStep;
|
|
220
|
-
for (const step of steps) {
|
|
221
|
-
var _step$location, _step$location2, _lastStep$location, _step$location3, _lastStep$location2, _step$location4, _lastStep$location3;
|
|
222
|
-
const canDedupe = !step.error && step.duration >= 0 && ((_step$location = step.location) === null || _step$location === void 0 ? void 0 : _step$location.file) && !step.steps.length;
|
|
223
|
-
if (canDedupe && lastStep && step.category === lastStep.category && step.title === lastStep.title && ((_step$location2 = step.location) === null || _step$location2 === void 0 ? void 0 : _step$location2.file) === ((_lastStep$location = lastStep.location) === null || _lastStep$location === void 0 ? void 0 : _lastStep$location.file) && ((_step$location3 = step.location) === null || _step$location3 === void 0 ? void 0 : _step$location3.line) === ((_lastStep$location2 = lastStep.location) === null || _lastStep$location2 === void 0 ? void 0 : _lastStep$location2.line) && ((_step$location4 = step.location) === null || _step$location4 === void 0 ? void 0 : _step$location4.column) === ((_lastStep$location3 = lastStep.location) === null || _lastStep$location3 === void 0 ? void 0 : _lastStep$location3.column)) {
|
|
224
|
-
++lastStep.count;
|
|
225
|
-
lastStep.duration += step.duration;
|
|
226
|
-
continue;
|
|
227
|
-
}
|
|
228
|
-
result.push(step);
|
|
229
|
-
lastStep = canDedupe ? step : undefined;
|
|
230
|
-
}
|
|
231
|
-
return result;
|
|
232
|
-
}
|
|
233
|
-
function filterOutPrivateFields(object) {
|
|
234
|
-
if (!object || typeof object !== 'object') return object;
|
|
235
|
-
if (Array.isArray(object)) return object.map(filterOutPrivateFields);
|
|
236
|
-
return Object.fromEntries(Object.entries(object).filter(entry => !entry[0].startsWith('_')).map(entry => [entry[0], filterOutPrivateFields(entry[1])]));
|
|
237
|
-
}
|
|
238
|
-
var _default = RawReporter;
|
|
239
|
-
exports.default = _default;
|