playwright 1.56.0-alpha-2025-09-10 → 1.56.0-alpha-2025-09-11

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/lib/index.js CHANGED
@@ -240,7 +240,8 @@ const playwrightFixtures = {
240
240
  if (!testInfo2 || data.apiName.includes("setTestIdAttribute") || data.apiName === "tracing.groupEnd")
241
241
  return;
242
242
  const zone = (0, import_utils.currentZone)().data("stepZone");
243
- if (zone && zone.category === "expect") {
243
+ const isExpectCall = data.apiName === "locator._expect" || data.apiName === "frame._expect" || data.apiName === "page._expectScreenshot";
244
+ if (zone && zone.category === "expect" && isExpectCall) {
244
245
  if (zone.apiName)
245
246
  data.apiName = zone.apiName;
246
247
  if (zone.title)
@@ -225,9 +225,8 @@ class ExpectMetaInfoProxyHandler {
225
225
  const title = customMessage || `Expect ${(0, import_utils.escapeWithQuotes)(defaultTitle, '"')}`;
226
226
  const apiName = `expect${this._info.poll ? ".poll " : ""}${this._info.isSoft ? ".soft " : ""}${this._info.isNot ? ".not" : ""}.${matcherName}${argsSuffix}`;
227
227
  const stackFrames = (0, import_util.filteredStackTrace)((0, import_utils.captureRawStack)());
228
- const category = matcherName === "toPass" || this._info.poll ? "test.step" : "expect";
229
228
  const stepInfo = {
230
- category,
229
+ category: "expect",
231
230
  apiName,
232
231
  title,
233
232
  params: args[0] ? { expected: args[0] } : void 0,
@@ -19,24 +19,42 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
19
19
  var matcherHint_exports = {};
20
20
  __export(matcherHint_exports, {
21
21
  ExpectError: () => ExpectError,
22
- isJestError: () => isJestError,
23
- matcherHint: () => matcherHint
22
+ callLogText: () => callLogText,
23
+ formatMatcherMessage: () => formatMatcherMessage,
24
+ isJestError: () => isJestError
24
25
  });
25
26
  module.exports = __toCommonJS(matcherHint_exports);
26
27
  var import_utils = require("playwright-core/lib/utils");
27
- function matcherHint(state, locator, matcherName, expression, actual, matcherOptions, timeout, expectedReceivedString, preventExtraStatIndent = false) {
28
- let header = state.utils.matcherHint(matcherName, expression, actual, matcherOptions).replace(/ \/\/ deep equality/, "") + " failed\n\n";
29
- const extraSpace = preventExtraStatIndent ? "" : " ";
30
- if (locator)
31
- header += `Locator: ${extraSpace}${String(locator)}
32
- `;
33
- if (expectedReceivedString)
34
- header += `${expectedReceivedString}
28
+ var import_expectBundle = require("../common/expectBundle");
29
+ function formatMatcherMessage(state, details) {
30
+ const receiver = details.receiver ?? (details.locator ? "locator" : "page");
31
+ let message = (0, import_expectBundle.DIM_COLOR)("expect(") + (0, import_expectBundle.RECEIVED_COLOR)(receiver) + (0, import_expectBundle.DIM_COLOR)(")" + (state.promise ? "." + state.promise : "") + (state.isNot ? ".not" : "") + ".") + details.matcherName + (0, import_expectBundle.DIM_COLOR)("(") + (0, import_expectBundle.EXPECTED_COLOR)(details.expectation) + (0, import_expectBundle.DIM_COLOR)(")") + " failed\n\n";
32
+ const diffLines = details.printedDiff?.split("\n");
33
+ if (diffLines?.length === 2) {
34
+ details.printedExpected = diffLines[0];
35
+ details.printedReceived = diffLines[1];
36
+ details.printedDiff = void 0;
37
+ }
38
+ const align = !details.errorMessage && details.printedExpected?.startsWith("Expected:") && (!details.printedReceived || details.printedReceived.startsWith("Received:"));
39
+ if (details.locator)
40
+ message += `Locator: ${align ? " " : ""}${String(details.locator)}
35
41
  `;
36
- if (timeout)
37
- header += `Timeout: ${extraSpace}${timeout}ms
42
+ if (details.printedExpected)
43
+ message += details.printedExpected + "\n";
44
+ if (details.printedReceived)
45
+ message += details.printedReceived + "\n";
46
+ if (details.timedOut && details.timeout)
47
+ message += `Timeout: ${align ? " " : ""}${details.timeout}ms
38
48
  `;
39
- return header;
49
+ if (details.printedDiff)
50
+ message += details.printedDiff + "\n";
51
+ if (details.errorMessage) {
52
+ message += details.errorMessage;
53
+ if (!details.errorMessage.endsWith("\n"))
54
+ message += "\n";
55
+ }
56
+ message += callLogText(details.log);
57
+ return message;
40
58
  }
41
59
  class ExpectError extends Error {
42
60
  constructor(jestError, customMessage, stackFrames) {
@@ -52,9 +70,18 @@ class ExpectError extends Error {
52
70
  function isJestError(e) {
53
71
  return e instanceof Error && "matcherResult" in e;
54
72
  }
73
+ const callLogText = (log) => {
74
+ if (!log || !log.some((l) => !!l))
75
+ return "";
76
+ return `
77
+ Call log:
78
+ ${(0, import_expectBundle.DIM_COLOR)(log.join("\n"))}
79
+ `;
80
+ };
55
81
  // Annotate the CommonJS export names for ESM import in node:
56
82
  0 && (module.exports = {
57
83
  ExpectError,
58
- isJestError,
59
- matcherHint
84
+ callLogText,
85
+ formatMatcherMessage,
86
+ isJestError
60
87
  });
@@ -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) {
@@ -189,7 +190,7 @@ function toHaveClass(locator, expected, options) {
189
190
  return import_toEqual.toEqual.call(this, "toHaveClass", locator, "Locator", async (isNot, timeout) => {
190
191
  const expectedText = (0, import_utils.serializeExpectedTextValues)(expected);
191
192
  return await locator._expect("to.have.class.array", { expectedText, isNot, timeout });
192
- }, expected, options, true);
193
+ }, expected, options);
193
194
  } else {
194
195
  return import_toMatchText.toMatchText.call(this, "toHaveClass", locator, "Locator", async (isNot, timeout) => {
195
196
  const expectedText = (0, import_utils.serializeExpectedTextValues)([expected]);
@@ -204,7 +205,7 @@ function toContainClass(locator, expected, options) {
204
205
  return import_toEqual.toEqual.call(this, "toContainClass", locator, "Locator", async (isNot, timeout) => {
205
206
  const expectedText = (0, import_utils.serializeExpectedTextValues)(expected);
206
207
  return await locator._expect("to.contain.class.array", { expectedText, isNot, timeout });
207
- }, expected, options, true);
208
+ }, expected, options);
208
209
  } else {
209
210
  if ((0, import_utils.isRegExp)(expected))
210
211
  throw new Error(`"expected" argument in toContainClass cannot be a RegExp value`);
@@ -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();
@@ -24,12 +24,8 @@ module.exports = __toCommonJS(toBeTruthy_exports);
24
24
  var import_util = require("../util");
25
25
  var import_matcherHint = require("./matcherHint");
26
26
  var import_browserBackend = require("../mcp/test/browserBackend");
27
- async function toBeTruthy(matcherName, receiver, receiverType, expected, arg, query, options = {}) {
28
- (0, import_util.expectTypes)(receiver, [receiverType], matcherName);
29
- const matcherOptions = {
30
- isNot: this.isNot,
31
- promise: this.promise
32
- };
27
+ async function toBeTruthy(matcherName, locator, receiverType, expected, arg, query, options = {}) {
28
+ (0, import_util.expectTypes)(locator, [receiverType], matcherName);
33
29
  const timeout = options.timeout ?? this.timeout;
34
30
  const { matches: pass, log, timedOut, received, errorMessage } = await query(!!this.isNot, timeout);
35
31
  if (pass === !this.isNot) {
@@ -44,18 +40,25 @@ async function toBeTruthy(matcherName, receiver, receiverType, expected, arg, qu
44
40
  let printedExpected;
45
41
  if (pass) {
46
42
  printedExpected = `Expected: not ${expected}`;
47
- printedReceived = errorMessage ?? `Received: ${expected}`;
43
+ printedReceived = errorMessage ? "" : `Received: ${expected}`;
48
44
  } else {
49
45
  printedExpected = `Expected: ${expected}`;
50
- printedReceived = errorMessage ?? `Received: ${received}`;
46
+ printedReceived = errorMessage ? "" : `Received: ${received}`;
51
47
  }
52
48
  const message = () => {
53
- const header = (0, import_matcherHint.matcherHint)(this, receiver, matcherName, "locator", arg, matcherOptions, timedOut ? timeout : void 0, `${printedExpected}
54
- ${printedReceived}`);
55
- const logText = (0, import_util.callLogText)(log);
56
- return `${header}${logText}`;
49
+ return (0, import_matcherHint.formatMatcherMessage)(this, {
50
+ matcherName,
51
+ expectation: arg,
52
+ locator,
53
+ timeout,
54
+ timedOut,
55
+ printedExpected,
56
+ printedReceived,
57
+ errorMessage,
58
+ log
59
+ });
57
60
  };
58
- await (0, import_browserBackend.runBrowserBackendOnError)(receiver.page(), message);
61
+ await (0, import_browserBackend.runBrowserBackendOnError)(locator.page(), message);
59
62
  return {
60
63
  message,
61
64
  pass,
@@ -27,13 +27,8 @@ var import_matcherHint = require("./matcherHint");
27
27
  var import_browserBackend = require("../mcp/test/browserBackend");
28
28
  const EXPECTED_LABEL = "Expected";
29
29
  const RECEIVED_LABEL = "Received";
30
- async function toEqual(matcherName, receiver, receiverType, query, expected, options = {}, messagePreventExtraStatIndent) {
31
- (0, import_util.expectTypes)(receiver, [receiverType], matcherName);
32
- const matcherOptions = {
33
- comment: options.contains ? "" : "deep equality",
34
- isNot: this.isNot,
35
- promise: this.promise
36
- };
30
+ async function toEqual(matcherName, locator, receiverType, query, expected, options = {}) {
31
+ (0, import_util.expectTypes)(locator, [receiverType], matcherName);
37
32
  const timeout = options.timeout ?? this.timeout;
38
33
  const { matches: pass, received, log, timedOut, errorMessage } = await query(!!this.isNot, timeout);
39
34
  if (pass === !this.isNot) {
@@ -49,10 +44,9 @@ async function toEqual(matcherName, receiver, receiverType, query, expected, opt
49
44
  let printedDiff;
50
45
  if (pass) {
51
46
  printedExpected = `Expected: not ${this.utils.printExpected(expected)}`;
52
- printedReceived = errorMessage ?? `Received: ${this.utils.printReceived(received)}`;
47
+ printedReceived = errorMessage ? "" : `Received: ${this.utils.printReceived(received)}`;
53
48
  } else if (errorMessage) {
54
49
  printedExpected = `Expected: ${this.utils.printExpected(expected)}`;
55
- printedReceived = errorMessage;
56
50
  } else if (Array.isArray(expected) && Array.isArray(received)) {
57
51
  const normalizedExpected = expected.map((exp, index) => {
58
52
  const rec = received[index];
@@ -77,12 +71,20 @@ async function toEqual(matcherName, receiver, receiverType, query, expected, opt
77
71
  );
78
72
  }
79
73
  const message = () => {
80
- const details = printedDiff || `${printedExpected}
81
- ${printedReceived}`;
82
- const header = (0, import_matcherHint.matcherHint)(this, receiver, matcherName, "locator", void 0, matcherOptions, timedOut ? timeout : void 0, details, messagePreventExtraStatIndent);
83
- return `${header}${(0, import_util.callLogText)(log)}`;
74
+ return (0, import_matcherHint.formatMatcherMessage)(this, {
75
+ matcherName,
76
+ expectation: "expected",
77
+ locator,
78
+ timeout,
79
+ timedOut,
80
+ printedExpected,
81
+ printedReceived,
82
+ printedDiff,
83
+ errorMessage,
84
+ log
85
+ });
84
86
  };
85
- await (0, import_browserBackend.runBrowserBackendOnError)(receiver.page(), message);
87
+ await (0, import_browserBackend.runBrowserBackendOnError)(locator.page(), message);
86
88
  return {
87
89
  actual: received,
88
90
  expected,
@@ -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, void 0, void 0, true),
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, void 0, true);
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 = {
@@ -38,7 +38,7 @@ var import_matcherHint = require("./matcherHint");
38
38
  var import_util = require("../util");
39
39
  var import_expect = require("./expect");
40
40
  var import_globals = require("../common/globals");
41
- async function toMatchAriaSnapshot(receiver, expectedParam, options = {}) {
41
+ async function toMatchAriaSnapshot(locator, expectedParam, options = {}) {
42
42
  const matcherName = "toMatchAriaSnapshot";
43
43
  const testInfo = (0, import_globals.currentTestInfo)();
44
44
  if (!testInfo)
@@ -46,10 +46,6 @@ async function toMatchAriaSnapshot(receiver, expectedParam, options = {}) {
46
46
  if (testInfo._projectInternal.ignoreSnapshots)
47
47
  return { pass: !this.isNot, message: () => "", name: "toMatchAriaSnapshot", expected: "" };
48
48
  const updateSnapshots = testInfo.config.updateSnapshots;
49
- const matcherOptions = {
50
- isNot: this.isNot,
51
- promise: this.promise
52
- };
53
49
  let expected;
54
50
  let timeout;
55
51
  let expectedPath;
@@ -74,33 +70,36 @@ async function toMatchAriaSnapshot(receiver, expectedParam, options = {}) {
74
70
  }
75
71
  }
76
72
  expected = unshift(expected);
77
- const { matches: pass, received, log, timedOut, errorMessage } = 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 });
78
74
  const typedReceived = received;
79
- const matcherHintWithExpect = (expectedReceivedString) => {
80
- return (0, import_matcherHint.matcherHint)(this, receiver, matcherName, "locator", void 0, matcherOptions, timedOut ? timeout : void 0, expectedReceivedString);
81
- };
82
- if (errorMessage) {
83
- return {
84
- pass: this.isNot,
85
- message: () => matcherHintWithExpect(`Expected: ${this.utils.printExpected(expected)}
86
- ${errorMessage}`) + (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
- const receivedString = (0, import_expect.printReceivedStringContainExpectedSubstring)(receivedText, receivedText.indexOf(expected), expected.length);
95
- const expectedReceivedString = `Expected: not ${this.utils.printExpected(expected)}
96
- Received: ${receivedString}`;
97
- return matcherHintWithExpect(expectedReceivedString) + (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}`;
98
85
  } else {
99
- const labelExpected = `Expected`;
100
- const expectedReceivedString = this.utils.printDiffOrStringify(expected, receivedText, labelExpected, "Received", false);
101
- return matcherHintWithExpect(expectedReceivedString) + (0, import_util.callLogText)(log);
86
+ printedDiff = this.utils.printDiffOrStringify(expected, typedReceived.raw, "Expected", "Received", false);
102
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
+ });
103
100
  };
101
+ if (errorMessage)
102
+ return { pass: this.isNot, message, name: "toMatchAriaSnapshot", expected };
104
103
  if (!this.isNot) {
105
104
  if (updateSnapshots === "all" || updateSnapshots === "changed" && pass === this.isNot || generateMissingBaseline) {
106
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, 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);
@@ -299,11 +297,11 @@ async function toHaveScreenshot(pageOrLocator, nameOrOptions = {}, optOptions =
299
297
  if (helper.updateSnapshots === "changed" || helper.updateSnapshots === "all") {
300
298
  if (actual)
301
299
  return writeFiles(actual);
302
- let header2 = (0, import_matcherHint.matcherHint)(this, void 0, "toHaveScreenshot", receiver, void 0, void 0, timedOut ? timeout : void 0);
300
+ let header2 = (0, import_matcherHint.formatMatcherMessage)(this, { matcherName: "toHaveScreenshot", locator, expectation: "expected", timeout, timedOut });
303
301
  header2 += " Failed to re-generate expected.\n";
304
302
  return helper.handleDifferent(actual, expectScreenshotOptions.expected, previous, diff, header2, errorMessage, log, this._stepInfo);
305
303
  }
306
- const header = (0, import_matcherHint.matcherHint)(this, void 0, "toHaveScreenshot", receiver, void 0, void 0, timedOut ? timeout : void 0);
304
+ const header = (0, import_matcherHint.formatMatcherMessage)(this, { matcherName: "toHaveScreenshot", locator, expectation: "expected", timeout, timedOut });
307
305
  return helper.handleDifferent(actual, expectScreenshotOptions.expected, previous, diff, header, errorMessage, log, this._stepInfo);
308
306
  }
309
307
  function writeFileSync(aPath, content) {
@@ -21,7 +21,6 @@ __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");
@@ -29,16 +28,11 @@ var import_expectBundle = require("../common/expectBundle");
29
28
  var import_browserBackend = require("../mcp/test/browserBackend");
30
29
  async function toMatchText(matcherName, receiver, receiverType, query, expected, options = {}) {
31
30
  (0, import_util.expectTypes)(receiver, [receiverType], matcherName);
32
- const matcherOptions = {
33
- isNot: this.isNot,
34
- promise: this.promise
35
- };
31
+ const locator = receiverType === "Locator" ? receiver : void 0;
36
32
  if (!(typeof expected === "string") && !(expected && typeof expected.test === "function")) {
37
- throw new Error([
38
- (0, import_matcherHint.matcherHint)(this, receiverType === "Locator" ? receiver : void 0, matcherName, options.receiverLabel ?? receiver, expected, matcherOptions, void 0, void 0, true),
39
- `${import_utils.colors.bold("Matcher error")}: ${(0, import_expectBundle.EXPECTED_COLOR)("expected")} value must be a string or regular expression`,
40
- this.utils.printWithType("Expected", expected, this.utils.printExpected)
41
- ].join("\n\n"));
33
+ const errorMessage2 = `Error: ${(0, import_expectBundle.EXPECTED_COLOR)("expected")} value must be a string or regular expression
34
+ ${this.utils.printWithType("Expected", expected, this.utils.printExpected)}`;
35
+ throw new Error((0, import_matcherHint.formatMatcherMessage)(this, { locator, matcherName, expectation: "expected", errorMessage: errorMessage2 }));
42
36
  }
43
37
  const timeout = options.timeout ?? this.timeout;
44
38
  const { matches: pass, received, log, timedOut, errorMessage } = await query(!!this.isNot, timeout);
@@ -50,45 +44,48 @@ async function toMatchText(matcherName, receiver, receiverType, query, expected,
50
44
  expected
51
45
  };
52
46
  }
53
- const stringSubstring = options.matchSubstring ? "substring" : "string";
47
+ const expectedSuffix = typeof expected === "string" ? options.matchSubstring ? " substring" : "" : " pattern";
48
+ const receivedSuffix = typeof expected === "string" ? options.matchSubstring ? " string" : "" : " string";
54
49
  const receivedString = received || "";
55
50
  let printedReceived;
56
51
  let printedExpected;
57
52
  let printedDiff;
58
53
  if (pass) {
59
54
  if (typeof expected === "string") {
60
- printedExpected = `Expected ${stringSubstring}: not ${this.utils.printExpected(expected)}`;
61
- if (errorMessage) {
62
- printedReceived = errorMessage;
63
- } else {
55
+ printedExpected = `Expected${expectedSuffix}: not ${this.utils.printExpected(expected)}`;
56
+ if (!errorMessage) {
64
57
  const formattedReceived = (0, import_expect.printReceivedStringContainExpectedSubstring)(receivedString, receivedString.indexOf(expected), expected.length);
65
- printedReceived = `Received string: ${formattedReceived}`;
58
+ printedReceived = `Received${receivedSuffix}: ${formattedReceived}`;
66
59
  }
67
60
  } else {
68
- printedExpected = `Expected pattern: not ${this.utils.printExpected(expected)}`;
69
- if (errorMessage) {
70
- printedReceived = errorMessage;
71
- } else {
61
+ printedExpected = `Expected${expectedSuffix}: not ${this.utils.printExpected(expected)}`;
62
+ if (!errorMessage) {
72
63
  const formattedReceived = (0, import_expect.printReceivedStringContainExpectedResult)(receivedString, typeof expected.exec === "function" ? expected.exec(receivedString) : null);
73
- printedReceived = `Received string: ${formattedReceived}`;
64
+ printedReceived = `Received${receivedSuffix}: ${formattedReceived}`;
74
65
  }
75
66
  }
76
67
  } else {
77
- const labelExpected = `Expected ${typeof expected === "string" ? stringSubstring : "pattern"}`;
78
- if (errorMessage) {
79
- printedExpected = `${labelExpected}: ${this.utils.printExpected(expected)}`;
80
- printedReceived = errorMessage;
81
- } else {
82
- printedDiff = this.utils.printDiffOrStringify(expected, receivedString, labelExpected, "Received string", false);
83
- }
68
+ if (errorMessage)
69
+ printedExpected = `Expected${expectedSuffix}: ${this.utils.printExpected(expected)}`;
70
+ else
71
+ printedDiff = this.utils.printDiffOrStringify(expected, receivedString, `Expected${expectedSuffix}`, `Received${receivedSuffix}`, false);
84
72
  }
85
73
  const message = () => {
86
- const resultDetails = printedDiff ? printedDiff : printedExpected + "\n" + printedReceived;
87
- const hints = (0, import_matcherHint.matcherHint)(this, receiverType === "Locator" ? receiver : void 0, matcherName, options.receiverLabel ?? "locator", void 0, matcherOptions, timedOut ? timeout : void 0, resultDetails, true);
88
- return hints + (0, import_util.callLogText)(log);
74
+ return (0, import_matcherHint.formatMatcherMessage)(this, {
75
+ matcherName,
76
+ expectation: "expected",
77
+ locator,
78
+ timeout,
79
+ timedOut,
80
+ printedExpected,
81
+ printedReceived,
82
+ printedDiff,
83
+ log,
84
+ errorMessage
85
+ });
89
86
  };
90
- if (receiverType === "Locator")
91
- await (0, import_browserBackend.runBrowserBackendOnError)(receiver.page(), message);
87
+ if (locator)
88
+ await (0, import_browserBackend.runBrowserBackendOnError)(locator.page(), message);
92
89
  return {
93
90
  name: matcherName,
94
91
  expected,
@@ -43,7 +43,6 @@ class BrowserServerBackend {
43
43
  }
44
44
  this._sessionLog = this._config.saveSession ? await import_sessionLog.SessionLog.create(this._config, rootPath) : void 0;
45
45
  this._context = new import_context.Context({
46
- tools: this._tools,
47
46
  config: this._config,
48
47
  browserContextFactory: this._browserContextFactory,
49
48
  sessionLog: this._sessionLog,
@@ -30,6 +30,7 @@ var config_exports = {};
30
30
  __export(config_exports, {
31
31
  commaSeparatedList: () => commaSeparatedList,
32
32
  configFromCLIOptions: () => configFromCLIOptions,
33
+ defaultConfig: () => defaultConfig,
33
34
  dotenvFileLoader: () => dotenvFileLoader,
34
35
  headerParser: () => headerParser,
35
36
  numberParser: () => numberParser,
@@ -307,6 +308,7 @@ function sanitizeForFilePath(s) {
307
308
  0 && (module.exports = {
308
309
  commaSeparatedList,
309
310
  configFromCLIOptions,
311
+ defaultConfig,
310
312
  dotenvFileLoader,
311
313
  headerParser,
312
314
  numberParser,
@@ -42,7 +42,6 @@ class Context {
42
42
  constructor(options) {
43
43
  this._tabs = [];
44
44
  this._abortController = new AbortController();
45
- this.tools = options.tools;
46
45
  this.config = options.config;
47
46
  this.sessionLog = options.sessionLog;
48
47
  this.options = options;
@@ -51,7 +51,8 @@ class Tab extends import_events.EventEmitter {
51
51
  this.setModalState({
52
52
  type: "fileChooser",
53
53
  description: "File chooser",
54
- fileChooser: chooser
54
+ fileChooser: chooser,
55
+ clearedBy: "browser_file_upload"
55
56
  });
56
57
  });
57
58
  page.on("dialog", (dialog) => this._dialogShown(dialog));
@@ -82,7 +83,8 @@ class Tab extends import_events.EventEmitter {
82
83
  this.setModalState({
83
84
  type: "dialog",
84
85
  description: `"${dialog.type()}" dialog with message "${dialog.message()}"`,
85
- dialog
86
+ dialog,
87
+ clearedBy: "browser_handle_dialog"
86
88
  });
87
89
  }
88
90
  async _downloadStarted(download) {
@@ -241,10 +243,8 @@ function renderModalStates(context, modalStates) {
241
243
  const result = ["### Modal state"];
242
244
  if (modalStates.length === 0)
243
245
  result.push("- There is no modal state present");
244
- for (const state of modalStates) {
245
- const tool = context.tools.filter((tool2) => "clearsModalState" in tool2).find((tool2) => tool2.clearsModalState === state.type);
246
- result.push(`- [${state.description}]: can be handled by the "${tool?.schema.name}" tool`);
247
- }
246
+ for (const state of modalStates)
247
+ result.push(`- [${state.description}]: can be handled by the "${state.clearedBy}" tool`);
248
248
  return result;
249
249
  }
250
250
  const tabSymbol = Symbol("tabSymbol");