playwright 1.54.1 → 1.56.1

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.
Files changed (116) hide show
  1. package/README.md +3 -3
  2. package/ThirdPartyNotices.txt +2727 -434
  3. package/lib/agents/generateAgents.js +263 -0
  4. package/lib/agents/generator.md +102 -0
  5. package/lib/agents/healer.md +78 -0
  6. package/lib/agents/planner.md +135 -0
  7. package/lib/common/config.js +3 -1
  8. package/lib/common/configLoader.js +2 -1
  9. package/lib/common/expectBundle.js +3 -0
  10. package/lib/common/expectBundleImpl.js +51 -51
  11. package/lib/common/fixtures.js +1 -1
  12. package/lib/common/suiteUtils.js +0 -9
  13. package/lib/index.js +127 -115
  14. package/lib/isomorphic/testTree.js +35 -8
  15. package/lib/matchers/expect.js +6 -7
  16. package/lib/matchers/matcherHint.js +43 -15
  17. package/lib/matchers/matchers.js +10 -4
  18. package/lib/matchers/toBeTruthy.js +16 -14
  19. package/lib/matchers/toEqual.js +18 -13
  20. package/lib/matchers/toHaveURL.js +12 -27
  21. package/lib/matchers/toMatchAriaSnapshot.js +26 -31
  22. package/lib/matchers/toMatchSnapshot.js +15 -12
  23. package/lib/matchers/toMatchText.js +29 -35
  24. package/lib/mcp/browser/actions.d.js +16 -0
  25. package/lib/mcp/browser/browserContextFactory.js +296 -0
  26. package/lib/mcp/browser/browserServerBackend.js +76 -0
  27. package/lib/mcp/browser/codegen.js +66 -0
  28. package/lib/mcp/browser/config.js +383 -0
  29. package/lib/mcp/browser/context.js +284 -0
  30. package/lib/mcp/browser/response.js +228 -0
  31. package/lib/mcp/browser/sessionLog.js +160 -0
  32. package/lib/mcp/browser/tab.js +277 -0
  33. package/lib/mcp/browser/tools/common.js +63 -0
  34. package/lib/mcp/browser/tools/console.js +44 -0
  35. package/lib/mcp/browser/tools/dialogs.js +60 -0
  36. package/lib/mcp/browser/tools/evaluate.js +70 -0
  37. package/lib/mcp/browser/tools/files.js +58 -0
  38. package/lib/mcp/browser/tools/form.js +74 -0
  39. package/lib/mcp/browser/tools/install.js +69 -0
  40. package/lib/mcp/browser/tools/keyboard.js +85 -0
  41. package/lib/mcp/browser/tools/mouse.js +107 -0
  42. package/lib/mcp/browser/tools/navigate.js +62 -0
  43. package/lib/mcp/browser/tools/network.js +54 -0
  44. package/lib/mcp/browser/tools/pdf.js +59 -0
  45. package/lib/mcp/browser/tools/screenshot.js +88 -0
  46. package/lib/mcp/browser/tools/snapshot.js +182 -0
  47. package/lib/mcp/browser/tools/tabs.js +67 -0
  48. package/lib/mcp/browser/tools/tool.js +49 -0
  49. package/lib/mcp/browser/tools/tracing.js +74 -0
  50. package/lib/mcp/browser/tools/utils.js +100 -0
  51. package/lib/mcp/browser/tools/verify.js +154 -0
  52. package/lib/mcp/browser/tools/wait.js +63 -0
  53. package/lib/mcp/browser/tools.js +80 -0
  54. package/lib/mcp/browser/watchdog.js +44 -0
  55. package/lib/mcp/config.d.js +16 -0
  56. package/lib/mcp/extension/cdpRelay.js +351 -0
  57. package/lib/mcp/extension/extensionContextFactory.js +75 -0
  58. package/lib/mcp/extension/protocol.js +28 -0
  59. package/lib/mcp/index.js +61 -0
  60. package/lib/mcp/log.js +35 -0
  61. package/lib/mcp/program.js +96 -0
  62. package/lib/mcp/sdk/bundle.js +81 -0
  63. package/lib/mcp/sdk/exports.js +32 -0
  64. package/lib/mcp/sdk/http.js +180 -0
  65. package/lib/mcp/sdk/inProcessTransport.js +71 -0
  66. package/lib/mcp/sdk/mdb.js +208 -0
  67. package/lib/mcp/sdk/proxyBackend.js +128 -0
  68. package/lib/mcp/sdk/server.js +190 -0
  69. package/lib/mcp/sdk/tool.js +51 -0
  70. package/lib/mcp/test/browserBackend.js +98 -0
  71. package/lib/mcp/test/generatorTools.js +122 -0
  72. package/lib/mcp/test/plannerTools.js +46 -0
  73. package/lib/mcp/test/seed.js +72 -0
  74. package/lib/mcp/test/streams.js +39 -0
  75. package/lib/mcp/test/testBackend.js +97 -0
  76. package/lib/mcp/test/testContext.js +176 -0
  77. package/lib/mcp/test/testTool.js +30 -0
  78. package/lib/mcp/test/testTools.js +115 -0
  79. package/lib/mcpBundleImpl.js +41 -0
  80. package/lib/plugins/webServerPlugin.js +2 -0
  81. package/lib/program.js +77 -57
  82. package/lib/reporters/base.js +34 -29
  83. package/lib/reporters/dot.js +11 -11
  84. package/lib/reporters/github.js +2 -1
  85. package/lib/reporters/html.js +58 -41
  86. package/lib/reporters/internalReporter.js +2 -1
  87. package/lib/reporters/line.js +15 -15
  88. package/lib/reporters/list.js +24 -19
  89. package/lib/reporters/listModeReporter.js +69 -0
  90. package/lib/reporters/markdown.js +3 -3
  91. package/lib/reporters/merge.js +3 -1
  92. package/lib/reporters/teleEmitter.js +3 -1
  93. package/lib/runner/dispatcher.js +9 -2
  94. package/lib/runner/failureTracker.js +12 -2
  95. package/lib/runner/lastRun.js +7 -4
  96. package/lib/runner/loadUtils.js +46 -12
  97. package/lib/runner/projectUtils.js +8 -2
  98. package/lib/runner/reporters.js +7 -32
  99. package/lib/runner/tasks.js +20 -10
  100. package/lib/runner/testRunner.js +390 -0
  101. package/lib/runner/testServer.js +57 -276
  102. package/lib/runner/watchMode.js +5 -1
  103. package/lib/runner/workerHost.js +8 -6
  104. package/lib/transform/babelBundleImpl.js +179 -195
  105. package/lib/transform/compilationCache.js +22 -5
  106. package/lib/transform/transform.js +1 -1
  107. package/lib/util.js +12 -35
  108. package/lib/utilsBundleImpl.js +1 -1
  109. package/lib/worker/fixtureRunner.js +7 -2
  110. package/lib/worker/testInfo.js +76 -45
  111. package/lib/worker/testTracing.js +8 -7
  112. package/lib/worker/workerMain.js +12 -3
  113. package/package.json +10 -2
  114. package/types/test.d.ts +63 -44
  115. package/types/testReporter.d.ts +1 -1
  116. package/lib/runner/runner.js +0 -110
@@ -59,6 +59,7 @@ var import_toMatchText = require("./toMatchText");
59
59
  var import_config = require("../common/config");
60
60
  var import_globals = require("../common/globals");
61
61
  var import_testInfo = require("../worker/testInfo");
62
+ var import_matcherHint = require("./matcherHint");
62
63
  function toBeAttached(locator, options) {
63
64
  const attached = !options || options.attached === void 0 || options.attached;
64
65
  const expected = attached ? "attached" : "detached";
@@ -146,7 +147,7 @@ function toContainText(locator, expected, options = {}) {
146
147
  return import_toMatchText.toMatchText.call(this, "toContainText", locator, "Locator", async (isNot, timeout) => {
147
148
  const expectedText = (0, import_utils.serializeExpectedTextValues)([expected], { matchSubstring: true, normalizeWhiteSpace: true, ignoreCase: options.ignoreCase });
148
149
  return await locator._expect("to.have.text", { expectedText, isNot, useInnerText: options.useInnerText, timeout });
149
- }, expected, options);
150
+ }, expected, { ...options, matchSubstring: true });
150
151
  }
151
152
  }
152
153
  function toHaveAccessibleDescription(locator, expected, options) {
@@ -273,7 +274,7 @@ function toHaveTitle(page, expected, options = {}) {
273
274
  return import_toMatchText.toMatchText.call(this, "toHaveTitle", page, "Page", async (isNot, timeout) => {
274
275
  const expectedText = (0, import_utils.serializeExpectedTextValues)([expected], { normalizeWhiteSpace: true });
275
276
  return await page.mainFrame()._expect("to.have.title", { expectedText, isNot, timeout });
276
- }, expected, { receiverLabel: "page", ...options });
277
+ }, expected, options);
277
278
  }
278
279
  function toHaveURL(page, expected, options) {
279
280
  if (typeof expected === "function")
@@ -283,7 +284,7 @@ function toHaveURL(page, expected, options) {
283
284
  return import_toMatchText.toMatchText.call(this, "toHaveURL", page, "Page", async (isNot, timeout) => {
284
285
  const expectedText = (0, import_utils.serializeExpectedTextValues)([expected], { ignoreCase: options?.ignoreCase });
285
286
  return await page.mainFrame()._expect("to.have.url", { expectedText, isNot, timeout });
286
- }, expected, { receiverLabel: "page", ...options });
287
+ }, expected, options);
287
288
  }
288
289
  async function toBeOK(response) {
289
290
  const matcherName = "toBeOK";
@@ -294,7 +295,12 @@ async function toBeOK(response) {
294
295
  response._fetchLog(),
295
296
  isTextEncoding ? response.text() : null
296
297
  ]) : [];
297
- const message = () => this.utils.matcherHint(matcherName, void 0, "", { isNot: this.isNot }) + (0, import_util.callLogText)(log) + (text === null ? "" : `
298
+ const message = () => (0, import_matcherHint.formatMatcherMessage)(this, {
299
+ matcherName,
300
+ receiver: "response",
301
+ expectation: "",
302
+ log
303
+ }) + (text === null ? "" : `
298
304
  Response text:
299
305
  ${import_utils2.colors.dim(text?.substring(0, 1e3) || "")}`);
300
306
  const pass = response.ok();
@@ -23,14 +23,10 @@ __export(toBeTruthy_exports, {
23
23
  module.exports = __toCommonJS(toBeTruthy_exports);
24
24
  var import_util = require("../util");
25
25
  var import_matcherHint = require("./matcherHint");
26
- async function toBeTruthy(matcherName, receiver, receiverType, expected, arg, query, options = {}) {
27
- (0, import_util.expectTypes)(receiver, [receiverType], matcherName);
28
- const matcherOptions = {
29
- isNot: this.isNot,
30
- promise: this.promise
31
- };
26
+ async function toBeTruthy(matcherName, locator, receiverType, expected, arg, query, options = {}) {
27
+ (0, import_util.expectTypes)(locator, [receiverType], matcherName);
32
28
  const timeout = options.timeout ?? this.timeout;
33
- const { matches: pass, log, timedOut, received } = await query(!!this.isNot, timeout);
29
+ const { matches: pass, log, timedOut, received, errorMessage } = await query(!!this.isNot, timeout);
34
30
  if (pass === !this.isNot) {
35
31
  return {
36
32
  name: matcherName,
@@ -39,21 +35,27 @@ async function toBeTruthy(matcherName, receiver, receiverType, expected, arg, qu
39
35
  expected
40
36
  };
41
37
  }
42
- const notFound = received === import_matcherHint.kNoElementsFoundError ? received : void 0;
43
38
  let printedReceived;
44
39
  let printedExpected;
45
40
  if (pass) {
46
41
  printedExpected = `Expected: not ${expected}`;
47
- printedReceived = `Received: ${notFound ? import_matcherHint.kNoElementsFoundError : expected}`;
42
+ printedReceived = errorMessage ? "" : `Received: ${expected}`;
48
43
  } else {
49
44
  printedExpected = `Expected: ${expected}`;
50
- printedReceived = `Received: ${notFound ? import_matcherHint.kNoElementsFoundError : received}`;
45
+ printedReceived = errorMessage ? "" : `Received: ${received}`;
51
46
  }
52
47
  const message = () => {
53
- const header = (0, import_matcherHint.matcherHint)(this, receiver, matcherName, "locator", arg, matcherOptions, timedOut ? timeout : void 0);
54
- const logText = (0, import_util.callLogText)(log);
55
- return `${header}${printedExpected}
56
- ${printedReceived}${logText}`;
48
+ return (0, import_matcherHint.formatMatcherMessage)(this, {
49
+ matcherName,
50
+ expectation: arg,
51
+ locator,
52
+ timeout,
53
+ timedOut,
54
+ printedExpected,
55
+ printedReceived,
56
+ errorMessage,
57
+ log
58
+ });
57
59
  };
58
60
  return {
59
61
  message,
@@ -26,15 +26,10 @@ var import_util = require("../util");
26
26
  var import_matcherHint = require("./matcherHint");
27
27
  const EXPECTED_LABEL = "Expected";
28
28
  const RECEIVED_LABEL = "Received";
29
- async function toEqual(matcherName, receiver, receiverType, query, expected, options = {}) {
30
- (0, import_util.expectTypes)(receiver, [receiverType], matcherName);
31
- const matcherOptions = {
32
- comment: options.contains ? "" : "deep equality",
33
- isNot: this.isNot,
34
- promise: this.promise
35
- };
29
+ async function toEqual(matcherName, locator, receiverType, query, expected, options = {}) {
30
+ (0, import_util.expectTypes)(locator, [receiverType], matcherName);
36
31
  const timeout = options.timeout ?? this.timeout;
37
- const { matches: pass, received, log, timedOut } = await query(!!this.isNot, timeout);
32
+ const { matches: pass, received, log, timedOut, errorMessage } = await query(!!this.isNot, timeout);
38
33
  if (pass === !this.isNot) {
39
34
  return {
40
35
  name: matcherName,
@@ -48,7 +43,9 @@ async function toEqual(matcherName, receiver, receiverType, query, expected, opt
48
43
  let printedDiff;
49
44
  if (pass) {
50
45
  printedExpected = `Expected: not ${this.utils.printExpected(expected)}`;
51
- printedReceived = `Received: ${this.utils.printReceived(received)}`;
46
+ printedReceived = errorMessage ? "" : `Received: ${this.utils.printReceived(received)}`;
47
+ } else if (errorMessage) {
48
+ printedExpected = `Expected: ${this.utils.printExpected(expected)}`;
52
49
  } else if (Array.isArray(expected) && Array.isArray(received)) {
53
50
  const normalizedExpected = expected.map((exp, index) => {
54
51
  const rec = received[index];
@@ -73,10 +70,18 @@ async function toEqual(matcherName, receiver, receiverType, query, expected, opt
73
70
  );
74
71
  }
75
72
  const message = () => {
76
- const header = (0, import_matcherHint.matcherHint)(this, receiver, matcherName, "locator", void 0, matcherOptions, timedOut ? timeout : void 0);
77
- const details = printedDiff || `${printedExpected}
78
- ${printedReceived}`;
79
- return `${header}${details}${(0, import_util.callLogText)(log)}`;
73
+ return (0, import_matcherHint.formatMatcherMessage)(this, {
74
+ matcherName,
75
+ expectation: "expected",
76
+ locator,
77
+ timeout,
78
+ timedOut,
79
+ printedExpected,
80
+ printedReceived,
81
+ printedDiff,
82
+ errorMessage,
83
+ log
84
+ });
80
85
  };
81
86
  return {
82
87
  actual: received,
@@ -22,27 +22,11 @@ __export(toHaveURL_exports, {
22
22
  });
23
23
  module.exports = __toCommonJS(toHaveURL_exports);
24
24
  var import_utils = require("playwright-core/lib/utils");
25
- var import_utils2 = require("playwright-core/lib/utils");
26
25
  var import_expect = require("./expect");
27
26
  var import_matcherHint = require("./matcherHint");
28
27
  var import_expectBundle = require("../common/expectBundle");
29
28
  async function toHaveURLWithPredicate(page, expected, options) {
30
29
  const matcherName = "toHaveURL";
31
- const expression = "page";
32
- const matcherOptions = {
33
- isNot: this.isNot,
34
- promise: this.promise
35
- };
36
- if (typeof expected !== "function") {
37
- throw new Error(
38
- [
39
- // Always display `expected` in expectation place
40
- (0, import_matcherHint.matcherHint)(this, void 0, matcherName, expression, void 0, matcherOptions),
41
- `${import_utils2.colors.bold("Matcher error")}: ${(0, import_expectBundle.EXPECTED_COLOR)("expected")} value must be a string, regular expression, or predicate`,
42
- this.utils.printWithType("Expected", expected, this.utils.printExpected)
43
- ].join("\n\n")
44
- );
45
- }
46
30
  const timeout = options?.timeout ?? this.timeout;
47
31
  const baseURL = page.context()._options.baseURL;
48
32
  let conditionSucceeded = false;
@@ -74,7 +58,6 @@ async function toHaveURLWithPredicate(page, expected, options) {
74
58
  message: () => toHaveURLMessage(
75
59
  this,
76
60
  matcherName,
77
- expression,
78
61
  expected,
79
62
  lastCheckedURLString,
80
63
  this.isNot,
@@ -85,19 +68,14 @@ async function toHaveURLWithPredicate(page, expected, options) {
85
68
  timeout
86
69
  };
87
70
  }
88
- function toHaveURLMessage(state, matcherName, expression, expected, received, pass, didTimeout, timeout) {
89
- const matcherOptions = {
90
- isNot: state.isNot,
91
- promise: state.promise
92
- };
71
+ function toHaveURLMessage(state, matcherName, expected, received, pass, timedOut, timeout) {
93
72
  const receivedString = received || "";
94
- const messagePrefix = (0, import_matcherHint.matcherHint)(state, void 0, matcherName, expression, void 0, matcherOptions, didTimeout ? timeout : void 0);
95
73
  let printedReceived;
96
74
  let printedExpected;
97
75
  let printedDiff;
98
76
  if (typeof expected === "function") {
99
- printedExpected = `Expected predicate to ${!state.isNot ? "succeed" : "fail"}`;
100
- printedReceived = `Received string: ${(0, import_expectBundle.printReceived)(receivedString)}`;
77
+ printedExpected = `Expected: predicate to ${!state.isNot ? "succeed" : "fail"}`;
78
+ printedReceived = `Received: ${(0, import_expectBundle.printReceived)(receivedString)}`;
101
79
  } else {
102
80
  if (pass) {
103
81
  printedExpected = `Expected pattern: not ${state.utils.printExpected(expected)}`;
@@ -108,8 +86,15 @@ function toHaveURLMessage(state, matcherName, expression, expected, received, pa
108
86
  printedDiff = state.utils.printDiffOrStringify(expected, receivedString, labelExpected, "Received string", false);
109
87
  }
110
88
  }
111
- const resultDetails = printedDiff ? printedDiff : printedExpected + "\n" + printedReceived;
112
- return messagePrefix + resultDetails;
89
+ return (0, import_matcherHint.formatMatcherMessage)(state, {
90
+ matcherName,
91
+ expectation: "expected",
92
+ timeout,
93
+ timedOut,
94
+ printedExpected,
95
+ printedReceived,
96
+ printedDiff
97
+ });
113
98
  }
114
99
  // Annotate the CommonJS export names for ESM import in node:
115
100
  0 && (module.exports = {
@@ -35,11 +35,10 @@ var import_fs = __toESM(require("fs"));
35
35
  var import_path = __toESM(require("path"));
36
36
  var import_utils = require("playwright-core/lib/utils");
37
37
  var import_matcherHint = require("./matcherHint");
38
- var import_expectBundle = require("../common/expectBundle");
39
38
  var import_util = require("../util");
40
39
  var import_expect = require("./expect");
41
40
  var import_globals = require("../common/globals");
42
- async function toMatchAriaSnapshot(receiver, expectedParam, options = {}) {
41
+ async function toMatchAriaSnapshot(locator, expectedParam, options = {}) {
43
42
  const matcherName = "toMatchAriaSnapshot";
44
43
  const testInfo = (0, import_globals.currentTestInfo)();
45
44
  if (!testInfo)
@@ -47,10 +46,6 @@ async function toMatchAriaSnapshot(receiver, expectedParam, options = {}) {
47
46
  if (testInfo._projectInternal.ignoreSnapshots)
48
47
  return { pass: !this.isNot, message: () => "", name: "toMatchAriaSnapshot", expected: "" };
49
48
  const updateSnapshots = testInfo.config.updateSnapshots;
50
- const matcherOptions = {
51
- isNot: this.isNot,
52
- promise: this.promise
53
- };
54
49
  let expected;
55
50
  let timeout;
56
51
  let expectedPath;
@@ -75,36 +70,36 @@ async function toMatchAriaSnapshot(receiver, expectedParam, options = {}) {
75
70
  }
76
71
  }
77
72
  expected = unshift(expected);
78
- const { matches: pass, received, log, timedOut } = await receiver._expect("to.match.aria", { expectedValue: expected, isNot: this.isNot, timeout });
73
+ const { matches: pass, received, log, timedOut, errorMessage } = await locator._expect("to.match.aria", { expectedValue: expected, isNot: this.isNot, timeout });
79
74
  const typedReceived = received;
80
- const messagePrefix = (0, import_matcherHint.matcherHint)(this, receiver, matcherName, "locator", void 0, matcherOptions, timedOut ? timeout : void 0);
81
- const notFound = typedReceived === import_matcherHint.kNoElementsFoundError;
82
- if (notFound) {
83
- return {
84
- pass: this.isNot,
85
- message: () => messagePrefix + `Expected: ${this.utils.printExpected(expected)}
86
- Received: ${(0, import_expectBundle.EXPECTED_COLOR)("<element not found>")}` + (0, import_util.callLogText)(log),
87
- name: "toMatchAriaSnapshot",
88
- expected
89
- };
90
- }
91
- const receivedText = typedReceived.raw;
92
75
  const message = () => {
93
- if (pass) {
94
- if (notFound)
95
- return messagePrefix + `Expected: not ${this.utils.printExpected(expected)}
96
- Received: ${receivedText}` + (0, import_util.callLogText)(log);
97
- const printedReceived = (0, import_expect.printReceivedStringContainExpectedSubstring)(receivedText, receivedText.indexOf(expected), expected.length);
98
- return messagePrefix + `Expected: not ${this.utils.printExpected(expected)}
99
- Received: ${printedReceived}` + (0, import_util.callLogText)(log);
76
+ let printedExpected;
77
+ let printedReceived;
78
+ let printedDiff;
79
+ if (errorMessage) {
80
+ printedExpected = `Expected: ${this.isNot ? "not " : ""}${this.utils.printExpected(expected)}`;
81
+ } else if (pass) {
82
+ const receivedString = (0, import_expect.printReceivedStringContainExpectedSubstring)(typedReceived.raw, typedReceived.raw.indexOf(expected), expected.length);
83
+ printedExpected = `Expected: not ${this.utils.printExpected(expected)}`;
84
+ printedReceived = `Received: ${receivedString}`;
100
85
  } else {
101
- const labelExpected = `Expected`;
102
- if (notFound)
103
- return messagePrefix + `${labelExpected}: ${this.utils.printExpected(expected)}
104
- Received: ${receivedText}` + (0, import_util.callLogText)(log);
105
- return messagePrefix + this.utils.printDiffOrStringify(expected, receivedText, labelExpected, "Received", false) + (0, import_util.callLogText)(log);
86
+ printedDiff = this.utils.printDiffOrStringify(expected, typedReceived.raw, "Expected", "Received", false);
106
87
  }
88
+ return (0, import_matcherHint.formatMatcherMessage)(this, {
89
+ matcherName,
90
+ expectation: "expected",
91
+ locator,
92
+ timeout,
93
+ timedOut,
94
+ printedExpected,
95
+ printedReceived,
96
+ printedDiff,
97
+ errorMessage,
98
+ log
99
+ });
107
100
  };
101
+ if (errorMessage)
102
+ return { pass: this.isNot, message, name: "toMatchAriaSnapshot", expected };
108
103
  if (!this.isNot) {
109
104
  if (updateSnapshots === "all" || updateSnapshots === "changed" && pass === this.isNot || generateMissingBaseline) {
110
105
  if (expectedPath) {
@@ -162,7 +162,7 @@ class SnapshotHelper {
162
162
  step?._attachToStep({ name: (0, import_util.addSuffixToFilePath)(this.attachmentBaseName, "-diff"), contentType: this.mimeType, path: this.diffPath });
163
163
  }
164
164
  if (log?.length)
165
- output.push((0, import_util.callLogText)(log));
165
+ output.push((0, import_matcherHint.callLogText)(log));
166
166
  else
167
167
  output.push("");
168
168
  return this.createMatcherResult(output.join("\n"), false, log);
@@ -216,8 +216,7 @@ function toMatchSnapshot(received, nameOrOptions = {}, optOptions = {}) {
216
216
  const result = helper.comparator(received, expected, helper.options);
217
217
  if (!result)
218
218
  return helper.handleMatching();
219
- const receiver = (0, import_utils.isString)(received) ? "string" : "Buffer";
220
- const header = (0, import_matcherHint.matcherHint)(this, void 0, "toMatchSnapshot", receiver, void 0, void 0);
219
+ const header = (0, import_matcherHint.formatMatcherMessage)(this, { matcherName: "toMatchSnapshot", receiver: (0, import_utils.isString)(received) ? "string" : "Buffer", expectation: "expected" });
221
220
  return helper.handleDifferent(received, expected, void 0, result.diff, header, result.errorMessage, void 0, this._stepInfo);
222
221
  }
223
222
  function toHaveScreenshotStepTitle(nameOrOptions = {}, optOptions = {}) {
@@ -271,11 +270,10 @@ async function toHaveScreenshot(pageOrLocator, nameOrOptions = {}, optOptions =
271
270
  }
272
271
  if (helper.updateSnapshots === "none" && !hasSnapshot)
273
272
  return helper.createMatcherResult(`A snapshot doesn't exist at ${helper.expectedPath}.`, false);
274
- const receiver = locator ? "locator" : "page";
275
273
  if (!hasSnapshot) {
276
274
  const { actual: actual2, previous: previous2, diff: diff2, errorMessage: errorMessage2, log: log2, timedOut: timedOut2 } = await page._expectScreenshot(expectScreenshotOptions);
277
275
  if (errorMessage2) {
278
- const header2 = (0, import_matcherHint.matcherHint)(this, locator, "toHaveScreenshot", receiver, void 0, void 0, timedOut2 ? timeout : void 0);
276
+ const header2 = (0, import_matcherHint.formatMatcherMessage)(this, { matcherName: "toHaveScreenshot", locator, expectation: "expected", timeout, timedOut: timedOut2 });
279
277
  return helper.handleDifferent(actual2, void 0, previous2, diff2, header2, errorMessage2, log2, this._stepInfo);
280
278
  }
281
279
  return helper.handleMissing(actual2, this._stepInfo);
@@ -283,22 +281,27 @@ async function toHaveScreenshot(pageOrLocator, nameOrOptions = {}, optOptions =
283
281
  const expected = await import_fs.default.promises.readFile(helper.expectedPath);
284
282
  expectScreenshotOptions.expected = helper.updateSnapshots === "all" ? void 0 : expected;
285
283
  const { actual, previous, diff, errorMessage, log, timedOut } = await page._expectScreenshot(expectScreenshotOptions);
286
- const writeFiles = () => {
287
- writeFileSync(helper.expectedPath, actual);
288
- writeFileSync(helper.actualPath, actual);
284
+ const writeFiles = (actualBuffer) => {
285
+ writeFileSync(helper.expectedPath, actualBuffer);
286
+ writeFileSync(helper.actualPath, actualBuffer);
289
287
  console.log(helper.expectedPath + " is re-generated, writing actual.");
290
288
  return helper.createMatcherResult(helper.expectedPath + " running with --update-snapshots, writing actual.", true);
291
289
  };
292
290
  if (!errorMessage) {
293
291
  if (helper.updateSnapshots === "all" && actual && (0, import_utils.compareBuffersOrStrings)(actual, expected)) {
294
292
  console.log(helper.expectedPath + " is re-generated, writing actual.");
295
- return writeFiles();
293
+ return writeFiles(actual);
296
294
  }
297
295
  return helper.handleMatching();
298
296
  }
299
- if (helper.updateSnapshots === "changed" || helper.updateSnapshots === "all")
300
- return writeFiles();
301
- const header = (0, import_matcherHint.matcherHint)(this, void 0, "toHaveScreenshot", receiver, void 0, void 0, timedOut ? timeout : void 0);
297
+ if (helper.updateSnapshots === "changed" || helper.updateSnapshots === "all") {
298
+ if (actual)
299
+ return writeFiles(actual);
300
+ let header2 = (0, import_matcherHint.formatMatcherMessage)(this, { matcherName: "toHaveScreenshot", locator, expectation: "expected", timeout, timedOut });
301
+ header2 += " Failed to re-generate expected.\n";
302
+ return helper.handleDifferent(actual, expectScreenshotOptions.expected, previous, diff, header2, errorMessage, log, this._stepInfo);
303
+ }
304
+ const header = (0, import_matcherHint.formatMatcherMessage)(this, { matcherName: "toHaveScreenshot", locator, expectation: "expected", timeout, timedOut });
302
305
  return helper.handleDifferent(actual, expectScreenshotOptions.expected, previous, diff, header, errorMessage, log, this._stepInfo);
303
306
  }
304
307
  function writeFileSync(aPath, content) {
@@ -21,26 +21,20 @@ __export(toMatchText_exports, {
21
21
  toMatchText: () => toMatchText
22
22
  });
23
23
  module.exports = __toCommonJS(toMatchText_exports);
24
- var import_utils = require("playwright-core/lib/utils");
25
24
  var import_util = require("../util");
26
25
  var import_expect = require("./expect");
27
26
  var import_matcherHint = require("./matcherHint");
28
27
  var import_expectBundle = require("../common/expectBundle");
29
28
  async function toMatchText(matcherName, receiver, receiverType, query, expected, options = {}) {
30
29
  (0, import_util.expectTypes)(receiver, [receiverType], matcherName);
31
- const matcherOptions = {
32
- isNot: this.isNot,
33
- promise: this.promise
34
- };
30
+ const locator = receiverType === "Locator" ? receiver : void 0;
35
31
  if (!(typeof expected === "string") && !(expected && typeof expected.test === "function")) {
36
- throw new Error([
37
- (0, import_matcherHint.matcherHint)(this, receiverType === "Locator" ? receiver : void 0, matcherName, options.receiverLabel ?? receiver, expected, matcherOptions),
38
- `${import_utils.colors.bold("Matcher error")}: ${(0, import_expectBundle.EXPECTED_COLOR)("expected")} value must be a string or regular expression`,
39
- this.utils.printWithType("Expected", expected, this.utils.printExpected)
40
- ].join("\n\n"));
32
+ const errorMessage2 = `Error: ${(0, import_expectBundle.EXPECTED_COLOR)("expected")} value must be a string or regular expression
33
+ ${this.utils.printWithType("Expected", expected, this.utils.printExpected)}`;
34
+ throw new Error((0, import_matcherHint.formatMatcherMessage)(this, { locator, matcherName, expectation: "expected", errorMessage: errorMessage2 }));
41
35
  }
42
36
  const timeout = options.timeout ?? this.timeout;
43
- const { matches: pass, received, log, timedOut } = await query(!!this.isNot, timeout);
37
+ const { matches: pass, received, log, timedOut, errorMessage } = await query(!!this.isNot, timeout);
44
38
  if (pass === !this.isNot) {
45
39
  return {
46
40
  name: matcherName,
@@ -49,45 +43,45 @@ async function toMatchText(matcherName, receiver, receiverType, query, expected,
49
43
  expected
50
44
  };
51
45
  }
52
- const stringSubstring = options.matchSubstring ? "substring" : "string";
46
+ const expectedSuffix = typeof expected === "string" ? options.matchSubstring ? " substring" : "" : " pattern";
47
+ const receivedSuffix = typeof expected === "string" ? options.matchSubstring ? " string" : "" : " string";
53
48
  const receivedString = received || "";
54
- const messagePrefix = (0, import_matcherHint.matcherHint)(this, receiverType === "Locator" ? receiver : void 0, matcherName, options.receiverLabel ?? "locator", void 0, matcherOptions, timedOut ? timeout : void 0);
55
- const notFound = received === import_matcherHint.kNoElementsFoundError;
56
49
  let printedReceived;
57
50
  let printedExpected;
58
51
  let printedDiff;
59
52
  if (pass) {
60
53
  if (typeof expected === "string") {
61
- if (notFound) {
62
- printedExpected = `Expected ${stringSubstring}: not ${this.utils.printExpected(expected)}`;
63
- printedReceived = `Received: ${received}`;
64
- } else {
65
- printedExpected = `Expected ${stringSubstring}: not ${this.utils.printExpected(expected)}`;
54
+ printedExpected = `Expected${expectedSuffix}: not ${this.utils.printExpected(expected)}`;
55
+ if (!errorMessage) {
66
56
  const formattedReceived = (0, import_expect.printReceivedStringContainExpectedSubstring)(receivedString, receivedString.indexOf(expected), expected.length);
67
- printedReceived = `Received string: ${formattedReceived}`;
57
+ printedReceived = `Received${receivedSuffix}: ${formattedReceived}`;
68
58
  }
69
59
  } else {
70
- if (notFound) {
71
- printedExpected = `Expected pattern: not ${this.utils.printExpected(expected)}`;
72
- printedReceived = `Received: ${received}`;
73
- } else {
74
- printedExpected = `Expected pattern: not ${this.utils.printExpected(expected)}`;
60
+ printedExpected = `Expected${expectedSuffix}: not ${this.utils.printExpected(expected)}`;
61
+ if (!errorMessage) {
75
62
  const formattedReceived = (0, import_expect.printReceivedStringContainExpectedResult)(receivedString, typeof expected.exec === "function" ? expected.exec(receivedString) : null);
76
- printedReceived = `Received string: ${formattedReceived}`;
63
+ printedReceived = `Received${receivedSuffix}: ${formattedReceived}`;
77
64
  }
78
65
  }
79
66
  } else {
80
- const labelExpected = `Expected ${typeof expected === "string" ? stringSubstring : "pattern"}`;
81
- if (notFound) {
82
- printedExpected = `${labelExpected}: ${this.utils.printExpected(expected)}`;
83
- printedReceived = `Received: ${received}`;
84
- } else {
85
- printedDiff = this.utils.printDiffOrStringify(expected, receivedString, labelExpected, "Received string", false);
86
- }
67
+ if (errorMessage)
68
+ printedExpected = `Expected${expectedSuffix}: ${this.utils.printExpected(expected)}`;
69
+ else
70
+ printedDiff = this.utils.printDiffOrStringify(expected, receivedString, `Expected${expectedSuffix}`, `Received${receivedSuffix}`, false);
87
71
  }
88
72
  const message = () => {
89
- const resultDetails = printedDiff ? printedDiff : printedExpected + "\n" + printedReceived;
90
- return messagePrefix + resultDetails + (0, import_util.callLogText)(log);
73
+ return (0, import_matcherHint.formatMatcherMessage)(this, {
74
+ matcherName,
75
+ expectation: "expected",
76
+ locator,
77
+ timeout,
78
+ timedOut,
79
+ printedExpected,
80
+ printedReceived,
81
+ printedDiff,
82
+ log,
83
+ errorMessage
84
+ });
91
85
  };
92
86
  return {
93
87
  name: matcherName,
@@ -0,0 +1,16 @@
1
+ "use strict";
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
6
+ var __copyProps = (to, from, except, desc) => {
7
+ if (from && typeof from === "object" || typeof from === "function") {
8
+ for (let key of __getOwnPropNames(from))
9
+ if (!__hasOwnProp.call(to, key) && key !== except)
10
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
11
+ }
12
+ return to;
13
+ };
14
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
15
+ var actions_d_exports = {};
16
+ module.exports = __toCommonJS(actions_d_exports);