@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.
@@ -209,12 +209,25 @@ class TestCase extends Base {
209
209
  return titlePath;
210
210
  }
211
211
  outcome() {
212
- const nonSkipped = this.results.filter(result => result.status !== 'skipped' && result.status !== 'interrupted');
213
- if (!nonSkipped.length) return 'skipped';
214
- if (nonSkipped.every(result => result.status === this.expectedStatus)) return 'expected';
215
- if (nonSkipped.some(result => result.status === this.expectedStatus)) return 'flaky';
216
- return 'unexpected';
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
- const nonSkipped = this.results.filter(result => result.status !== 'skipped' && result.status !== 'interrupted');
356
- if (!nonSkipped.length) return 'skipped';
357
- if (nonSkipped.every(result => result.status === this.expectedStatus)) return 'expected';
358
- if (nonSkipped.some(result => result.status === this.expectedStatus)) return 'flaky';
359
- return 'unexpected';
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';
@@ -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 _utils = require("playwright-core/lib/utils");
14
- var _raw = _interopRequireDefault(require("./raw"));
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, reports);
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._tests = new Map();
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, rawReports) {
183
+ async build(metadata, projectSuites) {
187
184
  const data = new Map();
188
- for (const projectJson of rawReports) {
189
- for (const file of projectJson.suites) {
190
- var _projectJson$project$;
191
- const fileName = file.location.file;
192
- const fileId = file.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(file, fileId, projectJson.project.name, (_projectJson$project$ = projectJson.project.metadata) === null || _projectJson$project$ === void 0 ? void 0 : _projectJson$project$.reportName, [], testEntries);
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: rawReports.map(r => r.project.name),
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.map(s => this._processJsonSuite(s, fileId, projectName, reportName, newPath, outTests));
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._tests.set(test.testId, test);
316
- const location = test.location;
317
- path = [...path.slice(1)];
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.testId,
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.testId,
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.errors,
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(step) {
437
- return {
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: step.duration,
441
- snippet: step.snippet,
442
- steps: step.steps.map(s => this._createTestStep(s)),
443
- location: step.location,
444
- error: step.error,
445
- count: step.count
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.37.0",
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.37.0"
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
- * Learn more about [storage state and auth](https://playwright.dev/docs/auth).
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
  /**
@@ -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;