playwright 1.58.0-alpha-2025-12-05 → 1.58.0-alpha-2025-12-06

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.
@@ -70,10 +70,6 @@ class TeleReporterReceiver {
70
70
  this._onAttach(params.testId, params.resultId, params.attachments);
71
71
  return;
72
72
  }
73
- if (method === "onTestError") {
74
- this._onTestError(params.testId, params.resultId, params.error);
75
- return;
76
- }
77
73
  if (method === "onStepEnd") {
78
74
  this._onStepEnd(params.testId, params.resultId, params.step);
79
75
  return;
@@ -127,10 +123,8 @@ class TeleReporterReceiver {
127
123
  const result = test.results.find((r) => r._id === payload.id);
128
124
  result.duration = payload.duration;
129
125
  result.status = payload.status;
130
- if (!!payload.errors) {
131
- result.errors = payload.errors;
132
- result.error = result.errors[0];
133
- }
126
+ result.errors = payload.errors;
127
+ result.error = result.errors?.[0];
134
128
  if (!!payload.attachments)
135
129
  result.attachments = this._parseAttachments(payload.attachments);
136
130
  if (payload.annotations) {
@@ -173,12 +167,6 @@ class TeleReporterReceiver {
173
167
  body: a.base64 && globalThis.Buffer ? Buffer.from(a.base64, "base64") : void 0
174
168
  })));
175
169
  }
176
- _onTestError(testId, resultId, error) {
177
- const test = this._tests.get(testId);
178
- const result = test.results.find((r) => r._id === resultId);
179
- result.errors.push(error);
180
- result.error = result.errors[0];
181
- }
182
170
  _onError(error) {
183
171
  this._reporter.onError?.(error);
184
172
  }
@@ -66,11 +66,8 @@ class InternalReporter {
66
66
  onStdErr(chunk, test, result) {
67
67
  this._reporter.onStdErr?.(chunk, test, result);
68
68
  }
69
- onTestError(test, result, error) {
70
- addLocationAndSnippetToError(this._config, error, test.location.file);
71
- this._reporter.onTestError?.(test, result, error);
72
- }
73
69
  onTestEnd(test, result) {
70
+ this._addSnippetToTestErrors(test, result);
74
71
  this._reporter.onTestEnd?.(test, result);
75
72
  }
76
73
  async onEnd(result) {
@@ -87,20 +84,27 @@ class InternalReporter {
87
84
  await this._reporter.onExit?.();
88
85
  }
89
86
  onError(error) {
90
- addLocationAndSnippetToError(this._config, error, void 0);
87
+ addLocationAndSnippetToError(this._config, error);
91
88
  this._reporter.onError?.(error);
92
89
  }
93
90
  onStepBegin(test, result, step) {
94
91
  this._reporter.onStepBegin?.(test, result, step);
95
92
  }
96
93
  onStepEnd(test, result, step) {
97
- if (step.error)
98
- addLocationAndSnippetToError(this._config, step.error, test.location.file);
94
+ this._addSnippetToStepError(test, step);
99
95
  this._reporter.onStepEnd?.(test, result, step);
100
96
  }
101
97
  printsToStdio() {
102
98
  return this._reporter.printsToStdio ? this._reporter.printsToStdio() : true;
103
99
  }
100
+ _addSnippetToTestErrors(test, result) {
101
+ for (const error of result.errors)
102
+ addLocationAndSnippetToError(this._config, error, test.location.file);
103
+ }
104
+ _addSnippetToStepError(test, step) {
105
+ if (step.error)
106
+ addLocationAndSnippetToError(this._config, step.error, test.location.file);
107
+ }
104
108
  }
105
109
  function addLocationAndSnippetToError(config, error, file) {
106
110
  if (error.stack && !error.location)
@@ -342,7 +342,6 @@ class IdsPatcher {
342
342
  case "onProject":
343
343
  this._onProject(params.project);
344
344
  return;
345
- case "onTestError":
346
345
  case "onAttach":
347
346
  case "onTestBegin":
348
347
  case "onStepBegin":
@@ -424,7 +423,7 @@ class PathSeparatorPatcher {
424
423
  test.annotations?.forEach((annotation) => this._updateAnnotationLocation(annotation));
425
424
  const testResult = jsonEvent.params.result;
426
425
  testResult.annotations?.forEach((annotation) => this._updateAnnotationLocation(annotation));
427
- testResult.errors?.forEach((error) => this._updateErrorLocations(error));
426
+ testResult.errors.forEach((error) => this._updateErrorLocations(error));
428
427
  (testResult.attachments ?? []).forEach((attachment) => {
429
428
  if (attachment.path)
430
429
  attachment.path = this._updatePath(attachment.path);
@@ -442,10 +441,6 @@ class PathSeparatorPatcher {
442
441
  step.annotations?.forEach((annotation) => this._updateAnnotationLocation(annotation));
443
442
  return;
444
443
  }
445
- if (jsonEvent.method === "onTestError") {
446
- this._updateErrorLocations(jsonEvent.params.error);
447
- return;
448
- }
449
444
  if (jsonEvent.method === "onAttach") {
450
445
  const attach = jsonEvent.params;
451
446
  attach.attachments.forEach((attachment) => {
@@ -48,10 +48,6 @@ class Multiplexer {
48
48
  for (const reporter of this._reporters)
49
49
  wrap(() => reporter.onStdErr?.(chunk, test, result));
50
50
  }
51
- onTestError(test, result, error) {
52
- for (const reporter of this._reporters)
53
- wrap(() => reporter.onTestError?.(test, result, error));
54
- }
55
51
  onTestEnd(test, result) {
56
52
  for (const reporter of this._reporters)
57
53
  wrap(() => reporter.onTestEnd?.(test, result));
@@ -66,16 +66,6 @@ class TeleReporterEmitter {
66
66
  }
67
67
  });
68
68
  }
69
- onTestError(test, result, error) {
70
- this._messageSink({
71
- method: "onTestError",
72
- params: {
73
- testId: test.id,
74
- resultId: result[this._idSymbol],
75
- error
76
- }
77
- });
78
- }
79
69
  onTestEnd(test, result) {
80
70
  const testEnd = {
81
71
  testId: test.id,
@@ -235,6 +225,7 @@ class TeleReporterEmitter {
235
225
  id: result[this._idSymbol],
236
226
  duration: result.duration,
237
227
  status: result.status,
228
+ errors: result.errors,
238
229
  annotations: result.annotations?.length ? this._relativeAnnotationLocations(result.annotations) : void 0
239
230
  };
240
231
  }
@@ -243,6 +243,7 @@ class JobDispatcher {
243
243
  _onTestEnd(params) {
244
244
  if (this._failureTracker.hasReachedMaxFailures()) {
245
245
  params.status = "interrupted";
246
+ params.errors = [];
246
247
  }
247
248
  const data = this._dataByTestId.get(params.testId);
248
249
  if (!data) {
@@ -252,6 +253,8 @@ class JobDispatcher {
252
253
  this._remainingByTestId.delete(params.testId);
253
254
  const { result, test } = data;
254
255
  result.duration = params.duration;
256
+ result.errors = params.errors;
257
+ result.error = result.errors[0];
255
258
  result.status = params.status;
256
259
  result.annotations = params.annotations;
257
260
  test.annotations = [...params.annotations];
@@ -338,20 +341,6 @@ class JobDispatcher {
338
341
  this._reporter.onStdErr?.("Internal error: step id not found: " + params.stepId);
339
342
  }
340
343
  }
341
- _onTestErrors(params) {
342
- if (this._failureTracker.hasReachedMaxFailures()) {
343
- return;
344
- }
345
- const data = this._dataByTestId.get(params.testId);
346
- if (!data)
347
- return;
348
- const { test, result } = data;
349
- for (const error of params.errors) {
350
- result.errors.push(error);
351
- result.error = result.errors[0];
352
- this._reporter.onTestError?.(test, result, error);
353
- }
354
- }
355
344
  _failTestWithErrors(test, errors) {
356
345
  const runData = this._dataByTestId.get(test.id);
357
346
  let result;
@@ -361,11 +350,8 @@ class JobDispatcher {
361
350
  result = test._appendTestResult();
362
351
  this._reporter.onTestBegin?.(test, result);
363
352
  }
364
- for (const error of errors) {
365
- result.errors.push(error);
366
- result.error = result.errors[0];
367
- this._reporter.onTestError?.(test, result, error);
368
- }
353
+ result.errors = [...errors];
354
+ result.error = result.errors[0];
369
355
  result.status = errors.length ? "failed" : "skipped";
370
356
  this._reportTestEnd(test, result);
371
357
  this._failedTests.add(test);
@@ -466,32 +452,29 @@ class JobDispatcher {
466
452
  import_utils.eventsHelper.addEventListener(worker, "stepBegin", this._onStepBegin.bind(this)),
467
453
  import_utils.eventsHelper.addEventListener(worker, "stepEnd", this._onStepEnd.bind(this)),
468
454
  import_utils.eventsHelper.addEventListener(worker, "attach", this._onAttach.bind(this)),
469
- import_utils.eventsHelper.addEventListener(worker, "testErrors", this._onTestErrors.bind(this)),
470
455
  import_utils.eventsHelper.addEventListener(worker, "testPaused", this._onTestPaused.bind(this, worker)),
471
456
  import_utils.eventsHelper.addEventListener(worker, "done", this._onDone.bind(this)),
472
457
  import_utils.eventsHelper.addEventListener(worker, "exit", this.onExit.bind(this))
473
458
  ];
474
459
  }
475
460
  _onTestPaused(worker, params) {
476
- const data = this._dataByTestId.get(params.testId);
477
- if (!data)
478
- return;
479
- const { test, result } = data;
480
461
  const sendMessage = async (message) => {
481
462
  try {
482
463
  if (this.jobResult.isDone())
483
464
  throw new Error("Test has already stopped");
484
465
  const response = await worker.sendCustomMessage({ testId: params.testId, request: message.request });
485
466
  if (response.error)
486
- (0, import_internalReporter.addLocationAndSnippetToError)(this._config.config, response.error, test.location.file);
467
+ (0, import_internalReporter.addLocationAndSnippetToError)(this._config.config, response.error);
487
468
  return response;
488
469
  } catch (e) {
489
470
  const error = (0, import_util.serializeError)(e);
490
- (0, import_internalReporter.addLocationAndSnippetToError)(this._config.config, error, test.location.file);
471
+ (0, import_internalReporter.addLocationAndSnippetToError)(this._config.config, error);
491
472
  return { response: void 0, error };
492
473
  }
493
474
  };
494
- this._failureTracker.onTestPaused?.({ errors: result.errors, sendMessage });
475
+ for (const error of params.errors)
476
+ (0, import_internalReporter.addLocationAndSnippetToError)(this._config.config, error);
477
+ this._failureTracker.onTestPaused?.({ ...params, sendMessage });
495
478
  }
496
479
  skipWholeJob() {
497
480
  const allTestsSkipped = this.job.tests.every((test) => test.expectedStatus === "skipped");
@@ -383,8 +383,7 @@ async function runAllTestsWithConfig(config) {
383
383
  (0, import_tasks.createLoadTask)("in-process", { filterOnly: true, failOnLoadErrors: true }),
384
384
  ...(0, import_tasks.createRunTestsTasks)(config)
385
385
  ];
386
- const testRun = new import_tasks.TestRun(config, reporter, { pauseAtEnd: config.configCLIOverrides.debug, pauseOnError: config.configCLIOverrides.debug });
387
- const status = await (0, import_tasks.runTasks)(testRun, tasks, config.config.globalTimeout);
386
+ const status = await (0, import_tasks.runTasks)(new import_tasks.TestRun(config, reporter), tasks, config.config.globalTimeout);
388
387
  await new Promise((resolve) => process.stdout.write("", () => resolve()));
389
388
  await new Promise((resolve) => process.stderr.write("", () => resolve()));
390
389
  return status;
@@ -42,9 +42,8 @@ var import_util = require("../util");
42
42
  var import_testTracing = require("./testTracing");
43
43
  var import_util2 = require("./util");
44
44
  var import_transform = require("../transform/transform");
45
- var import_babelHighlightUtils = require("../transform/babelHighlightUtils");
46
45
  class TestInfoImpl {
47
- constructor(configInternal, projectInternal, workerParams, test, retry, onStepBegin, onStepEnd, onAttach, onErrors, onTestPaused) {
46
+ constructor(configInternal, projectInternal, workerParams, test, retry, onStepBegin, onStepEnd, onAttach, onTestPaused) {
48
47
  this._snapshotNames = { lastAnonymousSnapshotIndex: 0, lastNamedSnapshotIndex: {} };
49
48
  this._ariaSnapshotNames = { lastAnonymousSnapshotIndex: 0, lastNamedSnapshotIndex: {} };
50
49
  this._interruptedPromise = new import_utils.ManualPromise();
@@ -60,12 +59,10 @@ class TestInfoImpl {
60
59
  this.status = "passed";
61
60
  this.snapshotSuffix = "";
62
61
  this.errors = [];
63
- this._reportedErrorCount = 0;
64
62
  this.testId = test?.id ?? "";
65
63
  this._onStepBegin = onStepBegin;
66
64
  this._onStepEnd = onStepEnd;
67
65
  this._onAttach = onAttach;
68
- this._onErrors = onErrors;
69
66
  this._onTestPaused = onTestPaused;
70
67
  this._startTime = (0, import_utils.monotonicTime)();
71
68
  this._startWallTime = Date.now();
@@ -341,32 +338,11 @@ ${(0, import_utils.stringifyStackFrames)(step.boxedStack).join("\n")}`;
341
338
  async _didFinishTestFunction() {
342
339
  const shouldPause = this._workerParams.pauseAtEnd && !this._isFailure() || this._workerParams.pauseOnError && this._isFailure();
343
340
  if (shouldPause) {
344
- const location = (this._isFailure() ? this._errorLocation() : await this._testEndLocation()) ?? { file: this.file, line: this.line, column: this.column };
345
- this._emitErrors();
346
- this._onTestPaused({ testId: this.testId });
347
- await this._runAsStep({ title: this._isFailure() ? "Paused on Error" : "Paused at End", category: "test.step", location }, async () => {
348
- await this._interruptedPromise;
349
- });
341
+ this._onTestPaused({ testId: this.testId, errors: this._isFailure() ? this.errors : [] });
342
+ await this._interruptedPromise;
350
343
  }
351
344
  await this._onDidFinishTestFunctionCallback?.();
352
345
  }
353
- _emitErrors() {
354
- const errors = this.errors.slice(this._reportedErrorCount);
355
- this._reportedErrorCount = Math.max(this._reportedErrorCount, this.errors.length);
356
- if (errors.length)
357
- this._onErrors({ testId: this.testId, errors });
358
- }
359
- _errorLocation() {
360
- if (this.error?.stack)
361
- return (0, import_util.filteredStackTrace)(this.error.stack.split("\n"))[0];
362
- }
363
- async _testEndLocation() {
364
- try {
365
- const source = await import_fs.default.promises.readFile(this.file, "utf-8");
366
- return (0, import_babelHighlightUtils.findTestEndLocation)(source, { file: this.file, line: this.line, column: this.column });
367
- } catch {
368
- }
369
- }
370
346
  // ------------ TestInfo methods ------------
371
347
  async attach(name, options = {}) {
372
348
  const step = this._addStep({
@@ -99,7 +99,6 @@ class WorkerMain extends import_process.ProcessRunner {
99
99
  }, () => {
100
100
  }, () => {
101
101
  }, () => {
102
- }, () => {
103
102
  });
104
103
  const runnable = { type: "teardown" };
105
104
  await fakeTestInfo._runWithTimeout(runnable, () => this._loadIfNeeded()).catch(() => {
@@ -244,7 +243,6 @@ class WorkerMain extends import_process.ProcessRunner {
244
243
  (stepBeginPayload) => this.dispatchEvent("stepBegin", stepBeginPayload),
245
244
  (stepEndPayload) => this.dispatchEvent("stepEnd", stepEndPayload),
246
245
  (attachment) => this.dispatchEvent("attach", attachment),
247
- (errors) => this.dispatchEvent("testErrors", errors),
248
246
  (testPausedPayload) => this.dispatchEvent("testPaused", testPausedPayload)
249
247
  );
250
248
  const processAnnotation = (annotation) => {
@@ -285,7 +283,6 @@ class WorkerMain extends import_process.ProcessRunner {
285
283
  });
286
284
  if (isSkipped && nextTest && !hasAfterAllToRunBeforeNextTest) {
287
285
  testInfo.status = "skipped";
288
- testInfo._emitErrors();
289
286
  this.dispatchEvent("testEnd", buildTestEndPayload(testInfo));
290
287
  return;
291
288
  }
@@ -399,7 +396,6 @@ class WorkerMain extends import_process.ProcessRunner {
399
396
  testInfo.duration = testInfo._timeoutManager.defaultSlot().elapsed + afterHooksSlot.elapsed | 0;
400
397
  this._currentTest = null;
401
398
  (0, import_globals.setCurrentTestInfo)(null);
402
- testInfo._emitErrors();
403
399
  this.dispatchEvent("testEnd", buildTestEndPayload(testInfo));
404
400
  const preserveOutput = this._config.config.preserveOutput === "always" || this._config.config.preserveOutput === "failures-only" && testInfo._isFailure();
405
401
  if (!preserveOutput)
@@ -502,6 +498,7 @@ function buildTestEndPayload(testInfo) {
502
498
  testId: testInfo.testId,
503
499
  duration: testInfo.duration,
504
500
  status: testInfo.status,
501
+ errors: testInfo.errors,
505
502
  hasNonRetriableError: testInfo._hasNonRetriableError,
506
503
  expectedStatus: testInfo.expectedStatus,
507
504
  annotations: testInfo.annotations,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "playwright",
3
- "version": "1.58.0-alpha-2025-12-05",
3
+ "version": "1.58.0-alpha-2025-12-06",
4
4
  "description": "A high-level API to automate web browsers",
5
5
  "repository": {
6
6
  "type": "git",
@@ -64,7 +64,7 @@
64
64
  },
65
65
  "license": "Apache-2.0",
66
66
  "dependencies": {
67
- "playwright-core": "1.58.0-alpha-2025-12-05"
67
+ "playwright-core": "1.58.0-alpha-2025-12-06"
68
68
  },
69
69
  "optionalDependencies": {
70
70
  "fsevents": "2.3.2"
@@ -1,63 +0,0 @@
1
- "use strict";
2
- var __create = Object.create;
3
- var __defProp = Object.defineProperty;
4
- var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
5
- var __getOwnPropNames = Object.getOwnPropertyNames;
6
- var __getProtoOf = Object.getPrototypeOf;
7
- var __hasOwnProp = Object.prototype.hasOwnProperty;
8
- var __export = (target, all) => {
9
- for (var name in all)
10
- __defProp(target, name, { get: all[name], enumerable: true });
11
- };
12
- var __copyProps = (to, from, except, desc) => {
13
- if (from && typeof from === "object" || typeof from === "function") {
14
- for (let key of __getOwnPropNames(from))
15
- if (!__hasOwnProp.call(to, key) && key !== except)
16
- __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
17
- }
18
- return to;
19
- };
20
- var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
21
- // If the importer is in node compatibility mode or this is not an ESM
22
- // file that has been converted to a CommonJS file using a Babel-
23
- // compatible transform (i.e. "__esModule" has not been set), then set
24
- // "default" to the CommonJS "module.exports" for node compatibility.
25
- isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
26
- mod
27
- ));
28
- var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
29
- var babelHighlightUtils_exports = {};
30
- __export(babelHighlightUtils_exports, {
31
- findTestEndLocation: () => findTestEndLocation
32
- });
33
- module.exports = __toCommonJS(babelHighlightUtils_exports);
34
- var import_path = __toESM(require("path"));
35
- var import_babelBundle = require("./babelBundle");
36
- function containsLocation(range, location) {
37
- if (location.line < range.start.line || location.line > range.end.line)
38
- return false;
39
- if (location.line === range.start.line && location.column < range.start.column)
40
- return false;
41
- if (location.line === range.end.line && location.column > range.end.column)
42
- return false;
43
- return true;
44
- }
45
- function findTestEndLocation(text, testStartLocation) {
46
- const ast = (0, import_babelBundle.babelParse)(text, import_path.default.basename(testStartLocation.file), false);
47
- let result;
48
- (0, import_babelBundle.traverse)(ast, {
49
- enter(path2) {
50
- if (import_babelBundle.types.isCallExpression(path2.node) && path2.node.loc && containsLocation(path2.node.loc, testStartLocation)) {
51
- const callNode = path2.node;
52
- const funcNode = callNode.arguments[callNode.arguments.length - 1];
53
- if (callNode.arguments.length >= 2 && import_babelBundle.types.isFunction(funcNode) && funcNode.body.loc)
54
- result = { file: testStartLocation.file, ...funcNode.body.loc.end };
55
- }
56
- }
57
- });
58
- return result;
59
- }
60
- // Annotate the CommonJS export names for ESM import in node:
61
- 0 && (module.exports = {
62
- findTestEndLocation
63
- });