matchers.js 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360
  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 __export = (target, all) => {
  7. for (var name in all)
  8. __defProp(target, name, { get: all[name], enumerable: true });
  9. };
  10. var __copyProps = (to, from, except, desc) => {
  11. if (from && typeof from === "object" || typeof from === "function") {
  12. for (let key of __getOwnPropNames(from))
  13. if (!__hasOwnProp.call(to, key) && key !== except)
  14. __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
  15. }
  16. return to;
  17. };
  18. var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
  19. var matchers_exports = {};
  20. __export(matchers_exports, {
  21. toBeAttached: () => toBeAttached,
  22. toBeChecked: () => toBeChecked,
  23. toBeDisabled: () => toBeDisabled,
  24. toBeEditable: () => toBeEditable,
  25. toBeEmpty: () => toBeEmpty,
  26. toBeEnabled: () => toBeEnabled,
  27. toBeFocused: () => toBeFocused,
  28. toBeHidden: () => toBeHidden,
  29. toBeInViewport: () => toBeInViewport,
  30. toBeOK: () => toBeOK,
  31. toBeVisible: () => toBeVisible,
  32. toContainClass: () => toContainClass,
  33. toContainText: () => toContainText,
  34. toHaveAccessibleDescription: () => toHaveAccessibleDescription,
  35. toHaveAccessibleErrorMessage: () => toHaveAccessibleErrorMessage,
  36. toHaveAccessibleName: () => toHaveAccessibleName,
  37. toHaveAttribute: () => toHaveAttribute,
  38. toHaveCSS: () => toHaveCSS,
  39. toHaveClass: () => toHaveClass,
  40. toHaveCount: () => toHaveCount,
  41. toHaveId: () => toHaveId,
  42. toHaveJSProperty: () => toHaveJSProperty,
  43. toHaveRole: () => toHaveRole,
  44. toHaveText: () => toHaveText,
  45. toHaveTitle: () => toHaveTitle,
  46. toHaveURL: () => toHaveURL,
  47. toHaveValue: () => toHaveValue,
  48. toHaveValues: () => toHaveValues,
  49. toPass: () => toPass
  50. });
  51. module.exports = __toCommonJS(matchers_exports);
  52. var import_utils = require("playwright-core/lib/utils");
  53. var import_utils2 = require("playwright-core/lib/utils");
  54. var import_util = require("../util");
  55. var import_toBeTruthy = require("./toBeTruthy");
  56. var import_toEqual = require("./toEqual");
  57. var import_toHaveURL = require("./toHaveURL");
  58. var import_toMatchText = require("./toMatchText");
  59. var import_config = require("../common/config");
  60. var import_globals = require("../common/globals");
  61. var import_testInfo = require("../worker/testInfo");
  62. function toBeAttached(locator, options) {
  63. const attached = !options || options.attached === void 0 || options.attached;
  64. const expected = attached ? "attached" : "detached";
  65. const arg = attached ? "" : "{ attached: false }";
  66. return import_toBeTruthy.toBeTruthy.call(this, "toBeAttached", locator, "Locator", expected, arg, async (isNot, timeout) => {
  67. return await locator._expect(attached ? "to.be.attached" : "to.be.detached", { isNot, timeout });
  68. }, options);
  69. }
  70. function toBeChecked(locator, options) {
  71. const checked = options?.checked;
  72. const indeterminate = options?.indeterminate;
  73. const expectedValue = {
  74. checked,
  75. indeterminate
  76. };
  77. let expected;
  78. let arg;
  79. if (options?.indeterminate) {
  80. expected = "indeterminate";
  81. arg = `{ indeterminate: true }`;
  82. } else {
  83. expected = options?.checked === false ? "unchecked" : "checked";
  84. arg = options?.checked === false ? `{ checked: false }` : "";
  85. }
  86. return import_toBeTruthy.toBeTruthy.call(this, "toBeChecked", locator, "Locator", expected, arg, async (isNot, timeout) => {
  87. return await locator._expect("to.be.checked", { isNot, timeout, expectedValue });
  88. }, options);
  89. }
  90. function toBeDisabled(locator, options) {
  91. return import_toBeTruthy.toBeTruthy.call(this, "toBeDisabled", locator, "Locator", "disabled", "", async (isNot, timeout) => {
  92. return await locator._expect("to.be.disabled", { isNot, timeout });
  93. }, options);
  94. }
  95. function toBeEditable(locator, options) {
  96. const editable = !options || options.editable === void 0 || options.editable;
  97. const expected = editable ? "editable" : "readOnly";
  98. const arg = editable ? "" : "{ editable: false }";
  99. return import_toBeTruthy.toBeTruthy.call(this, "toBeEditable", locator, "Locator", expected, arg, async (isNot, timeout) => {
  100. return await locator._expect(editable ? "to.be.editable" : "to.be.readonly", { isNot, timeout });
  101. }, options);
  102. }
  103. function toBeEmpty(locator, options) {
  104. return import_toBeTruthy.toBeTruthy.call(this, "toBeEmpty", locator, "Locator", "empty", "", async (isNot, timeout) => {
  105. return await locator._expect("to.be.empty", { isNot, timeout });
  106. }, options);
  107. }
  108. function toBeEnabled(locator, options) {
  109. const enabled = !options || options.enabled === void 0 || options.enabled;
  110. const expected = enabled ? "enabled" : "disabled";
  111. const arg = enabled ? "" : "{ enabled: false }";
  112. return import_toBeTruthy.toBeTruthy.call(this, "toBeEnabled", locator, "Locator", expected, arg, async (isNot, timeout) => {
  113. return await locator._expect(enabled ? "to.be.enabled" : "to.be.disabled", { isNot, timeout });
  114. }, options);
  115. }
  116. function toBeFocused(locator, options) {
  117. return import_toBeTruthy.toBeTruthy.call(this, "toBeFocused", locator, "Locator", "focused", "", async (isNot, timeout) => {
  118. return await locator._expect("to.be.focused", { isNot, timeout });
  119. }, options);
  120. }
  121. function toBeHidden(locator, options) {
  122. return import_toBeTruthy.toBeTruthy.call(this, "toBeHidden", locator, "Locator", "hidden", "", async (isNot, timeout) => {
  123. return await locator._expect("to.be.hidden", { isNot, timeout });
  124. }, options);
  125. }
  126. function toBeVisible(locator, options) {
  127. const visible = !options || options.visible === void 0 || options.visible;
  128. const expected = visible ? "visible" : "hidden";
  129. const arg = visible ? "" : "{ visible: false }";
  130. return import_toBeTruthy.toBeTruthy.call(this, "toBeVisible", locator, "Locator", expected, arg, async (isNot, timeout) => {
  131. return await locator._expect(visible ? "to.be.visible" : "to.be.hidden", { isNot, timeout });
  132. }, options);
  133. }
  134. function toBeInViewport(locator, options) {
  135. return import_toBeTruthy.toBeTruthy.call(this, "toBeInViewport", locator, "Locator", "in viewport", "", async (isNot, timeout) => {
  136. return await locator._expect("to.be.in.viewport", { isNot, expectedNumber: options?.ratio, timeout });
  137. }, options);
  138. }
  139. function toContainText(locator, expected, options = {}) {
  140. if (Array.isArray(expected)) {
  141. return import_toEqual.toEqual.call(this, "toContainText", locator, "Locator", async (isNot, timeout) => {
  142. const expectedText = (0, import_utils.serializeExpectedTextValues)(expected, { matchSubstring: true, normalizeWhiteSpace: true, ignoreCase: options.ignoreCase });
  143. return await locator._expect("to.contain.text.array", { expectedText, isNot, useInnerText: options.useInnerText, timeout });
  144. }, expected, { ...options, contains: true });
  145. } else {
  146. return import_toMatchText.toMatchText.call(this, "toContainText", locator, "Locator", async (isNot, timeout) => {
  147. const expectedText = (0, import_utils.serializeExpectedTextValues)([expected], { matchSubstring: true, normalizeWhiteSpace: true, ignoreCase: options.ignoreCase });
  148. return await locator._expect("to.have.text", { expectedText, isNot, useInnerText: options.useInnerText, timeout });
  149. }, expected, options);
  150. }
  151. }
  152. function toHaveAccessibleDescription(locator, expected, options) {
  153. return import_toMatchText.toMatchText.call(this, "toHaveAccessibleDescription", locator, "Locator", async (isNot, timeout) => {
  154. const expectedText = (0, import_utils.serializeExpectedTextValues)([expected], { ignoreCase: options?.ignoreCase, normalizeWhiteSpace: true });
  155. return await locator._expect("to.have.accessible.description", { expectedText, isNot, timeout });
  156. }, expected, options);
  157. }
  158. function toHaveAccessibleName(locator, expected, options) {
  159. return import_toMatchText.toMatchText.call(this, "toHaveAccessibleName", locator, "Locator", async (isNot, timeout) => {
  160. const expectedText = (0, import_utils.serializeExpectedTextValues)([expected], { ignoreCase: options?.ignoreCase, normalizeWhiteSpace: true });
  161. return await locator._expect("to.have.accessible.name", { expectedText, isNot, timeout });
  162. }, expected, options);
  163. }
  164. function toHaveAccessibleErrorMessage(locator, expected, options) {
  165. return import_toMatchText.toMatchText.call(this, "toHaveAccessibleErrorMessage", locator, "Locator", async (isNot, timeout) => {
  166. const expectedText = (0, import_utils.serializeExpectedTextValues)([expected], { ignoreCase: options?.ignoreCase, normalizeWhiteSpace: true });
  167. return await locator._expect("to.have.accessible.error.message", { expectedText, isNot, timeout });
  168. }, expected, options);
  169. }
  170. function toHaveAttribute(locator, name, expected, options) {
  171. if (!options) {
  172. if (typeof expected === "object" && !(0, import_utils.isRegExp)(expected)) {
  173. options = expected;
  174. expected = void 0;
  175. }
  176. }
  177. if (expected === void 0) {
  178. return import_toBeTruthy.toBeTruthy.call(this, "toHaveAttribute", locator, "Locator", "have attribute", "", async (isNot, timeout) => {
  179. return await locator._expect("to.have.attribute", { expressionArg: name, isNot, timeout });
  180. }, options);
  181. }
  182. return import_toMatchText.toMatchText.call(this, "toHaveAttribute", locator, "Locator", async (isNot, timeout) => {
  183. const expectedText = (0, import_utils.serializeExpectedTextValues)([expected], { ignoreCase: options?.ignoreCase });
  184. return await locator._expect("to.have.attribute.value", { expressionArg: name, expectedText, isNot, timeout });
  185. }, expected, options);
  186. }
  187. function toHaveClass(locator, expected, options) {
  188. if (Array.isArray(expected)) {
  189. return import_toEqual.toEqual.call(this, "toHaveClass", locator, "Locator", async (isNot, timeout) => {
  190. const expectedText = (0, import_utils.serializeExpectedTextValues)(expected);
  191. return await locator._expect("to.have.class.array", { expectedText, isNot, timeout });
  192. }, expected, options, true);
  193. } else {
  194. return import_toMatchText.toMatchText.call(this, "toHaveClass", locator, "Locator", async (isNot, timeout) => {
  195. const expectedText = (0, import_utils.serializeExpectedTextValues)([expected]);
  196. return await locator._expect("to.have.class", { expectedText, isNot, timeout });
  197. }, expected, options);
  198. }
  199. }
  200. function toContainClass(locator, expected, options) {
  201. if (Array.isArray(expected)) {
  202. if (expected.some((e) => (0, import_utils.isRegExp)(e)))
  203. throw new Error(`"expected" argument in toContainClass cannot contain RegExp values`);
  204. return import_toEqual.toEqual.call(this, "toContainClass", locator, "Locator", async (isNot, timeout) => {
  205. const expectedText = (0, import_utils.serializeExpectedTextValues)(expected);
  206. return await locator._expect("to.contain.class.array", { expectedText, isNot, timeout });
  207. }, expected, options, true);
  208. } else {
  209. if ((0, import_utils.isRegExp)(expected))
  210. throw new Error(`"expected" argument in toContainClass cannot be a RegExp value`);
  211. return import_toMatchText.toMatchText.call(this, "toContainClass", locator, "Locator", async (isNot, timeout) => {
  212. const expectedText = (0, import_utils.serializeExpectedTextValues)([expected]);
  213. return await locator._expect("to.contain.class", { expectedText, isNot, timeout });
  214. }, expected, options);
  215. }
  216. }
  217. function toHaveCount(locator, expected, options) {
  218. return import_toEqual.toEqual.call(this, "toHaveCount", locator, "Locator", async (isNot, timeout) => {
  219. return await locator._expect("to.have.count", { expectedNumber: expected, isNot, timeout });
  220. }, expected, options);
  221. }
  222. function toHaveCSS(locator, name, expected, options) {
  223. return import_toMatchText.toMatchText.call(this, "toHaveCSS", locator, "Locator", async (isNot, timeout) => {
  224. const expectedText = (0, import_utils.serializeExpectedTextValues)([expected]);
  225. return await locator._expect("to.have.css", { expressionArg: name, expectedText, isNot, timeout });
  226. }, expected, options);
  227. }
  228. function toHaveId(locator, expected, options) {
  229. return import_toMatchText.toMatchText.call(this, "toHaveId", locator, "Locator", async (isNot, timeout) => {
  230. const expectedText = (0, import_utils.serializeExpectedTextValues)([expected]);
  231. return await locator._expect("to.have.id", { expectedText, isNot, timeout });
  232. }, expected, options);
  233. }
  234. function toHaveJSProperty(locator, name, expected, options) {
  235. return import_toEqual.toEqual.call(this, "toHaveJSProperty", locator, "Locator", async (isNot, timeout) => {
  236. return await locator._expect("to.have.property", { expressionArg: name, expectedValue: expected, isNot, timeout });
  237. }, expected, options);
  238. }
  239. function toHaveRole(locator, expected, options) {
  240. if (!(0, import_utils.isString)(expected))
  241. throw new Error(`"role" argument in toHaveRole must be a string`);
  242. return import_toMatchText.toMatchText.call(this, "toHaveRole", locator, "Locator", async (isNot, timeout) => {
  243. const expectedText = (0, import_utils.serializeExpectedTextValues)([expected]);
  244. return await locator._expect("to.have.role", { expectedText, isNot, timeout });
  245. }, expected, options);
  246. }
  247. function toHaveText(locator, expected, options = {}) {
  248. if (Array.isArray(expected)) {
  249. return import_toEqual.toEqual.call(this, "toHaveText", locator, "Locator", async (isNot, timeout) => {
  250. const expectedText = (0, import_utils.serializeExpectedTextValues)(expected, { normalizeWhiteSpace: true, ignoreCase: options.ignoreCase });
  251. return await locator._expect("to.have.text.array", { expectedText, isNot, useInnerText: options?.useInnerText, timeout });
  252. }, expected, options);
  253. } else {
  254. return import_toMatchText.toMatchText.call(this, "toHaveText", locator, "Locator", async (isNot, timeout) => {
  255. const expectedText = (0, import_utils.serializeExpectedTextValues)([expected], { normalizeWhiteSpace: true, ignoreCase: options.ignoreCase });
  256. return await locator._expect("to.have.text", { expectedText, isNot, useInnerText: options?.useInnerText, timeout });
  257. }, expected, options);
  258. }
  259. }
  260. function toHaveValue(locator, expected, options) {
  261. return import_toMatchText.toMatchText.call(this, "toHaveValue", locator, "Locator", async (isNot, timeout) => {
  262. const expectedText = (0, import_utils.serializeExpectedTextValues)([expected]);
  263. return await locator._expect("to.have.value", { expectedText, isNot, timeout });
  264. }, expected, options);
  265. }
  266. function toHaveValues(locator, expected, options) {
  267. return import_toEqual.toEqual.call(this, "toHaveValues", locator, "Locator", async (isNot, timeout) => {
  268. const expectedText = (0, import_utils.serializeExpectedTextValues)(expected);
  269. return await locator._expect("to.have.values", { expectedText, isNot, timeout });
  270. }, expected, options);
  271. }
  272. function toHaveTitle(page, expected, options = {}) {
  273. return import_toMatchText.toMatchText.call(this, "toHaveTitle", page, "Page", async (isNot, timeout) => {
  274. const expectedText = (0, import_utils.serializeExpectedTextValues)([expected], { normalizeWhiteSpace: true });
  275. return await page.mainFrame()._expect("to.have.title", { expectedText, isNot, timeout });
  276. }, expected, { receiverLabel: "page", ...options });
  277. }
  278. function toHaveURL(page, expected, options) {
  279. if (typeof expected === "function")
  280. return import_toHaveURL.toHaveURLWithPredicate.call(this, page, expected, options);
  281. const baseURL = page.context()._options.baseURL;
  282. expected = typeof expected === "string" ? (0, import_utils.constructURLBasedOnBaseURL)(baseURL, expected) : expected;
  283. return import_toMatchText.toMatchText.call(this, "toHaveURL", page, "Page", async (isNot, timeout) => {
  284. const expectedText = (0, import_utils.serializeExpectedTextValues)([expected], { ignoreCase: options?.ignoreCase });
  285. return await page.mainFrame()._expect("to.have.url", { expectedText, isNot, timeout });
  286. }, expected, { receiverLabel: "page", ...options });
  287. }
  288. async function toBeOK(response) {
  289. const matcherName = "toBeOK";
  290. (0, import_util.expectTypes)(response, ["APIResponse"], matcherName);
  291. const contentType = response.headers()["content-type"];
  292. const isTextEncoding = contentType && (0, import_utils.isTextualMimeType)(contentType);
  293. const [log, text] = this.isNot === response.ok() ? await Promise.all([
  294. response._fetchLog(),
  295. isTextEncoding ? response.text() : null
  296. ]) : [];
  297. const message = () => this.utils.matcherHint(matcherName, void 0, "", { isNot: this.isNot }) + (0, import_util.callLogText)(log) + (text === null ? "" : `
  298. Response text:
  299. ${import_utils2.colors.dim(text?.substring(0, 1e3) || "")}`);
  300. const pass = response.ok();
  301. return { message, pass };
  302. }
  303. async function toPass(callback, options = {}) {
  304. const testInfo = (0, import_globals.currentTestInfo)();
  305. const timeout = (0, import_config.takeFirst)(options.timeout, testInfo?._projectInternal.expect?.toPass?.timeout, 0);
  306. const intervals = (0, import_config.takeFirst)(options.intervals, testInfo?._projectInternal.expect?.toPass?.intervals, [100, 250, 500, 1e3]);
  307. const { deadline, timeoutMessage } = testInfo ? testInfo._deadlineForMatcher(timeout) : import_testInfo.TestInfoImpl._defaultDeadlineForMatcher(timeout);
  308. const result = await (0, import_utils.pollAgainstDeadline)(async () => {
  309. if (testInfo && (0, import_globals.currentTestInfo)() !== testInfo)
  310. return { continuePolling: false, result: void 0 };
  311. try {
  312. await callback();
  313. return { continuePolling: !!this.isNot, result: void 0 };
  314. } catch (e) {
  315. return { continuePolling: !this.isNot, result: e };
  316. }
  317. }, deadline, intervals);
  318. if (result.timedOut) {
  319. const message = result.result ? [
  320. result.result.message,
  321. "",
  322. `Call Log:`,
  323. `- ${timeoutMessage}`
  324. ].join("\n") : timeoutMessage;
  325. return { message: () => message, pass: !!this.isNot };
  326. }
  327. return { pass: !this.isNot, message: () => "" };
  328. }
  329. // Annotate the CommonJS export names for ESM import in node:
  330. 0 && (module.exports = {
  331. toBeAttached,
  332. toBeChecked,
  333. toBeDisabled,
  334. toBeEditable,
  335. toBeEmpty,
  336. toBeEnabled,
  337. toBeFocused,
  338. toBeHidden,
  339. toBeInViewport,
  340. toBeOK,
  341. toBeVisible,
  342. toContainClass,
  343. toContainText,
  344. toHaveAccessibleDescription,
  345. toHaveAccessibleErrorMessage,
  346. toHaveAccessibleName,
  347. toHaveAttribute,
  348. toHaveCSS,
  349. toHaveClass,
  350. toHaveCount,
  351. toHaveId,
  352. toHaveJSProperty,
  353. toHaveRole,
  354. toHaveText,
  355. toHaveTitle,
  356. toHaveURL,
  357. toHaveValue,
  358. toHaveValues,
  359. toPass
  360. });