ScuttleBot

Source Blame History 311 lines
f7eb47b… lmata 1 "use strict";
f7eb47b… lmata 2 var __defProp = Object.defineProperty;
f7eb47b… lmata 3 var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
f7eb47b… lmata 4 var __getOwnPropNames = Object.getOwnPropertyNames;
f7eb47b… lmata 5 var __hasOwnProp = Object.prototype.hasOwnProperty;
f7eb47b… lmata 6 var __export = (target, all) => {
f7eb47b… lmata 7 for (var name in all)
f7eb47b… lmata 8 __defProp(target, name, { get: all[name], enumerable: true });
f7eb47b… lmata 9 };
f7eb47b… lmata 10 var __copyProps = (to, from, except, desc) => {
f7eb47b… lmata 11 if (from && typeof from === "object" || typeof from === "function") {
f7eb47b… lmata 12 for (let key of __getOwnPropNames(from))
f7eb47b… lmata 13 if (!__hasOwnProp.call(to, key) && key !== except)
f7eb47b… lmata 14 __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
f7eb47b… lmata 15 }
f7eb47b… lmata 16 return to;
f7eb47b… lmata 17 };
f7eb47b… lmata 18 var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
f7eb47b… lmata 19 var expect_exports = {};
f7eb47b… lmata 20 __export(expect_exports, {
f7eb47b… lmata 21 expect: () => expect,
f7eb47b… lmata 22 mergeExpects: () => mergeExpects
f7eb47b… lmata 23 });
f7eb47b… lmata 24 module.exports = __toCommonJS(expect_exports);
f7eb47b… lmata 25 var import_utils = require("playwright-core/lib/utils");
f7eb47b… lmata 26 var import_matcherHint = require("./matcherHint");
f7eb47b… lmata 27 var import_matchers = require("./matchers");
f7eb47b… lmata 28 var import_toMatchAriaSnapshot = require("./toMatchAriaSnapshot");
f7eb47b… lmata 29 var import_toMatchSnapshot = require("./toMatchSnapshot");
f7eb47b… lmata 30 var import_expectBundle = require("../common/expectBundle");
f7eb47b… lmata 31 var import_globals = require("../common/globals");
f7eb47b… lmata 32 var import_util = require("../util");
f7eb47b… lmata 33 var import_testInfo = require("../worker/testInfo");
f7eb47b… lmata 34 function createMatchers(actual, info, prefix) {
f7eb47b… lmata 35 return new Proxy((0, import_expectBundle.expect)(actual), new ExpectMetaInfoProxyHandler(actual, info, prefix));
f7eb47b… lmata 36 }
f7eb47b… lmata 37 const userMatchersSymbol = Symbol("userMatchers");
f7eb47b… lmata 38 function qualifiedMatcherName(qualifier, matcherName) {
f7eb47b… lmata 39 return qualifier.join(":") + "$" + matcherName;
f7eb47b… lmata 40 }
f7eb47b… lmata 41 function createExpect(info, prefix, userMatchers) {
f7eb47b… lmata 42 const expectInstance = new Proxy(import_expectBundle.expect, {
f7eb47b… lmata 43 apply: function(target, thisArg, argumentsList) {
f7eb47b… lmata 44 const [actual, messageOrOptions] = argumentsList;
f7eb47b… lmata 45 const message = (0, import_utils.isString)(messageOrOptions) ? messageOrOptions : messageOrOptions?.message || info.message;
f7eb47b… lmata 46 const newInfo = { ...info, message };
f7eb47b… lmata 47 if (newInfo.poll) {
f7eb47b… lmata 48 if (typeof actual !== "function")
f7eb47b… lmata 49 throw new Error("`expect.poll()` accepts only function as a first argument");
f7eb47b… lmata 50 newInfo.poll.generator = actual;
f7eb47b… lmata 51 }
f7eb47b… lmata 52 return createMatchers(actual, newInfo, prefix);
f7eb47b… lmata 53 },
f7eb47b… lmata 54 get: function(target, property) {
f7eb47b… lmata 55 if (property === "configure")
f7eb47b… lmata 56 return configure;
f7eb47b… lmata 57 if (property === "extend") {
f7eb47b… lmata 58 return (matchers) => {
f7eb47b… lmata 59 const qualifier = [...prefix, (0, import_utils.createGuid)()];
f7eb47b… lmata 60 const wrappedMatchers = {};
f7eb47b… lmata 61 for (const [name, matcher] of Object.entries(matchers)) {
f7eb47b… lmata 62 wrappedMatchers[name] = wrapPlaywrightMatcherToPassNiceThis(matcher);
f7eb47b… lmata 63 const key = qualifiedMatcherName(qualifier, name);
f7eb47b… lmata 64 wrappedMatchers[key] = wrappedMatchers[name];
f7eb47b… lmata 65 Object.defineProperty(wrappedMatchers[key], "name", { value: name });
f7eb47b… lmata 66 }
f7eb47b… lmata 67 import_expectBundle.expect.extend(wrappedMatchers);
f7eb47b… lmata 68 return createExpect(info, qualifier, { ...userMatchers, ...matchers });
f7eb47b… lmata 69 };
f7eb47b… lmata 70 }
f7eb47b… lmata 71 if (property === "soft") {
f7eb47b… lmata 72 return (actual, messageOrOptions) => {
f7eb47b… lmata 73 return configure({ soft: true })(actual, messageOrOptions);
f7eb47b… lmata 74 };
f7eb47b… lmata 75 }
f7eb47b… lmata 76 if (property === userMatchersSymbol)
f7eb47b… lmata 77 return userMatchers;
f7eb47b… lmata 78 if (property === "poll") {
f7eb47b… lmata 79 return (actual, messageOrOptions) => {
f7eb47b… lmata 80 const poll = (0, import_utils.isString)(messageOrOptions) ? {} : messageOrOptions || {};
f7eb47b… lmata 81 return configure({ _poll: poll })(actual, messageOrOptions);
f7eb47b… lmata 82 };
f7eb47b… lmata 83 }
f7eb47b… lmata 84 return import_expectBundle.expect[property];
f7eb47b… lmata 85 }
f7eb47b… lmata 86 });
f7eb47b… lmata 87 const configure = (configuration) => {
f7eb47b… lmata 88 const newInfo = { ...info };
f7eb47b… lmata 89 if ("message" in configuration)
f7eb47b… lmata 90 newInfo.message = configuration.message;
f7eb47b… lmata 91 if ("timeout" in configuration)
f7eb47b… lmata 92 newInfo.timeout = configuration.timeout;
f7eb47b… lmata 93 if ("soft" in configuration)
f7eb47b… lmata 94 newInfo.isSoft = configuration.soft;
f7eb47b… lmata 95 if ("_poll" in configuration) {
f7eb47b… lmata 96 newInfo.poll = configuration._poll ? { ...info.poll, generator: () => {
f7eb47b… lmata 97 } } : void 0;
f7eb47b… lmata 98 if (typeof configuration._poll === "object") {
f7eb47b… lmata 99 newInfo.poll.timeout = configuration._poll.timeout ?? newInfo.poll.timeout;
f7eb47b… lmata 100 newInfo.poll.intervals = configuration._poll.intervals ?? newInfo.poll.intervals;
f7eb47b… lmata 101 }
f7eb47b… lmata 102 }
f7eb47b… lmata 103 return createExpect(newInfo, prefix, userMatchers);
f7eb47b… lmata 104 };
f7eb47b… lmata 105 return expectInstance;
f7eb47b… lmata 106 }
f7eb47b… lmata 107 let matcherCallContext;
f7eb47b… lmata 108 function setMatcherCallContext(context) {
f7eb47b… lmata 109 matcherCallContext = context;
f7eb47b… lmata 110 }
f7eb47b… lmata 111 function takeMatcherCallContext() {
f7eb47b… lmata 112 try {
f7eb47b… lmata 113 return matcherCallContext;
f7eb47b… lmata 114 } finally {
f7eb47b… lmata 115 matcherCallContext = void 0;
f7eb47b… lmata 116 }
f7eb47b… lmata 117 }
f7eb47b… lmata 118 const defaultExpectTimeout = 5e3;
f7eb47b… lmata 119 function wrapPlaywrightMatcherToPassNiceThis(matcher) {
f7eb47b… lmata 120 return function(...args) {
f7eb47b… lmata 121 const { isNot, promise, utils } = this;
f7eb47b… lmata 122 const context = takeMatcherCallContext();
f7eb47b… lmata 123 const timeout = context?.expectInfo.timeout ?? context?.testInfo?._projectInternal?.expect?.timeout ?? defaultExpectTimeout;
f7eb47b… lmata 124 const newThis = {
f7eb47b… lmata 125 isNot,
f7eb47b… lmata 126 promise,
f7eb47b… lmata 127 utils,
f7eb47b… lmata 128 timeout,
f7eb47b… lmata 129 _stepInfo: context?.step
f7eb47b… lmata 130 };
f7eb47b… lmata 131 newThis.equals = throwUnsupportedExpectMatcherError;
f7eb47b… lmata 132 return matcher.call(newThis, ...args);
f7eb47b… lmata 133 };
f7eb47b… lmata 134 }
f7eb47b… lmata 135 function throwUnsupportedExpectMatcherError() {
f7eb47b… lmata 136 throw new Error("It looks like you are using custom expect matchers that are not compatible with Playwright. See https://aka.ms/playwright/expect-compatibility");
f7eb47b… lmata 137 }
f7eb47b… lmata 138 import_expectBundle.expect.setState({ expand: false });
f7eb47b… lmata 139 const customAsyncMatchers = {
f7eb47b… lmata 140 toBeAttached: import_matchers.toBeAttached,
f7eb47b… lmata 141 toBeChecked: import_matchers.toBeChecked,
f7eb47b… lmata 142 toBeDisabled: import_matchers.toBeDisabled,
f7eb47b… lmata 143 toBeEditable: import_matchers.toBeEditable,
f7eb47b… lmata 144 toBeEmpty: import_matchers.toBeEmpty,
f7eb47b… lmata 145 toBeEnabled: import_matchers.toBeEnabled,
f7eb47b… lmata 146 toBeFocused: import_matchers.toBeFocused,
f7eb47b… lmata 147 toBeHidden: import_matchers.toBeHidden,
f7eb47b… lmata 148 toBeInViewport: import_matchers.toBeInViewport,
f7eb47b… lmata 149 toBeOK: import_matchers.toBeOK,
f7eb47b… lmata 150 toBeVisible: import_matchers.toBeVisible,
f7eb47b… lmata 151 toContainText: import_matchers.toContainText,
f7eb47b… lmata 152 toContainClass: import_matchers.toContainClass,
f7eb47b… lmata 153 toHaveAccessibleDescription: import_matchers.toHaveAccessibleDescription,
f7eb47b… lmata 154 toHaveAccessibleName: import_matchers.toHaveAccessibleName,
f7eb47b… lmata 155 toHaveAccessibleErrorMessage: import_matchers.toHaveAccessibleErrorMessage,
f7eb47b… lmata 156 toHaveAttribute: import_matchers.toHaveAttribute,
f7eb47b… lmata 157 toHaveClass: import_matchers.toHaveClass,
f7eb47b… lmata 158 toHaveCount: import_matchers.toHaveCount,
f7eb47b… lmata 159 toHaveCSS: import_matchers.toHaveCSS,
f7eb47b… lmata 160 toHaveId: import_matchers.toHaveId,
f7eb47b… lmata 161 toHaveJSProperty: import_matchers.toHaveJSProperty,
f7eb47b… lmata 162 toHaveRole: import_matchers.toHaveRole,
f7eb47b… lmata 163 toHaveText: import_matchers.toHaveText,
f7eb47b… lmata 164 toHaveTitle: import_matchers.toHaveTitle,
f7eb47b… lmata 165 toHaveURL: import_matchers.toHaveURL,
f7eb47b… lmata 166 toHaveValue: import_matchers.toHaveValue,
f7eb47b… lmata 167 toHaveValues: import_matchers.toHaveValues,
f7eb47b… lmata 168 toHaveScreenshot: import_toMatchSnapshot.toHaveScreenshot,
f7eb47b… lmata 169 toMatchAriaSnapshot: import_toMatchAriaSnapshot.toMatchAriaSnapshot,
f7eb47b… lmata 170 toPass: import_matchers.toPass
f7eb47b… lmata 171 };
f7eb47b… lmata 172 const customMatchers = {
f7eb47b… lmata 173 ...customAsyncMatchers,
f7eb47b… lmata 174 toMatchSnapshot: import_toMatchSnapshot.toMatchSnapshot
f7eb47b… lmata 175 };
f7eb47b… lmata 176 class ExpectMetaInfoProxyHandler {
f7eb47b… lmata 177 constructor(actual, info, prefix) {
f7eb47b… lmata 178 this._actual = actual;
f7eb47b… lmata 179 this._info = { ...info };
f7eb47b… lmata 180 this._prefix = prefix;
f7eb47b… lmata 181 }
f7eb47b… lmata 182 get(target, matcherName, receiver) {
f7eb47b… lmata 183 if (matcherName === "toThrowError")
f7eb47b… lmata 184 matcherName = "toThrow";
f7eb47b… lmata 185 let matcher = Reflect.get(target, matcherName, receiver);
f7eb47b… lmata 186 if (typeof matcherName !== "string")
f7eb47b… lmata 187 return matcher;
f7eb47b… lmata 188 let resolvedMatcherName = matcherName;
f7eb47b… lmata 189 for (let i = this._prefix.length; i > 0; i--) {
f7eb47b… lmata 190 const qualifiedName = qualifiedMatcherName(this._prefix.slice(0, i), matcherName);
f7eb47b… lmata 191 if (Reflect.has(target, qualifiedName)) {
f7eb47b… lmata 192 matcher = Reflect.get(target, qualifiedName, receiver);
f7eb47b… lmata 193 resolvedMatcherName = qualifiedName;
f7eb47b… lmata 194 break;
f7eb47b… lmata 195 }
f7eb47b… lmata 196 }
f7eb47b… lmata 197 if (matcher === void 0)
f7eb47b… lmata 198 throw new Error(`expect: Property '${matcherName}' not found.`);
f7eb47b… lmata 199 if (typeof matcher !== "function") {
f7eb47b… lmata 200 if (matcherName === "not")
f7eb47b… lmata 201 this._info.isNot = !this._info.isNot;
f7eb47b… lmata 202 return new Proxy(matcher, this);
f7eb47b… lmata 203 }
f7eb47b… lmata 204 if (this._info.poll) {
f7eb47b… lmata 205 if (customAsyncMatchers[matcherName] || matcherName === "resolves" || matcherName === "rejects")
f7eb47b… lmata 206 throw new Error(`\`expect.poll()\` does not support "${matcherName}" matcher.`);
f7eb47b… lmata 207 matcher = (...args) => pollMatcher(resolvedMatcherName, this._info, this._prefix, ...args);
f7eb47b… lmata 208 }
f7eb47b… lmata 209 return (...args) => {
f7eb47b… lmata 210 const testInfo = (0, import_globals.currentTestInfo)();
f7eb47b… lmata 211 setMatcherCallContext({ expectInfo: this._info, testInfo });
f7eb47b… lmata 212 if (!testInfo)
f7eb47b… lmata 213 return matcher.call(target, ...args);
f7eb47b… lmata 214 const customMessage = this._info.message || "";
f7eb47b… lmata 215 const suffixes = (0, import_matchers.computeMatcherTitleSuffix)(matcherName, this._actual, args);
f7eb47b… lmata 216 const defaultTitle = `${this._info.poll ? "poll " : ""}${this._info.isSoft ? "soft " : ""}${this._info.isNot ? "not " : ""}${matcherName}${suffixes.short || ""}`;
f7eb47b… lmata 217 const shortTitle = customMessage || `Expect ${(0, import_utils.escapeWithQuotes)(defaultTitle, '"')}`;
f7eb47b… lmata 218 const longTitle = shortTitle + (suffixes.long || "");
f7eb47b… lmata 219 const apiName = `expect${this._info.poll ? ".poll " : ""}${this._info.isSoft ? ".soft " : ""}${this._info.isNot ? ".not" : ""}.${matcherName}${suffixes.short || ""}`;
f7eb47b… lmata 220 const stackFrames = (0, import_util.filteredStackTrace)((0, import_utils.captureRawStack)());
f7eb47b… lmata 221 const stepInfo = {
f7eb47b… lmata 222 category: "expect",
f7eb47b… lmata 223 apiName,
f7eb47b… lmata 224 title: longTitle,
f7eb47b… lmata 225 shortTitle,
f7eb47b… lmata 226 params: args[0] ? { expected: args[0] } : void 0,
f7eb47b… lmata 227 infectParentStepsWithError: this._info.isSoft
f7eb47b… lmata 228 };
f7eb47b… lmata 229 const step = testInfo._addStep(stepInfo);
f7eb47b… lmata 230 const reportStepError = (e) => {
f7eb47b… lmata 231 const jestError = (0, import_matcherHint.isJestError)(e) ? e : null;
f7eb47b… lmata 232 const expectError = jestError ? new import_matcherHint.ExpectError(jestError, customMessage, stackFrames) : void 0;
f7eb47b… lmata 233 if (jestError?.matcherResult.suggestedRebaseline) {
f7eb47b… lmata 234 step.complete({ suggestedRebaseline: jestError?.matcherResult.suggestedRebaseline });
f7eb47b… lmata 235 return;
f7eb47b… lmata 236 }
f7eb47b… lmata 237 const error = expectError ?? e;
f7eb47b… lmata 238 step.complete({ error });
f7eb47b… lmata 239 if (this._info.isSoft)
f7eb47b… lmata 240 testInfo._failWithError(error);
f7eb47b… lmata 241 else
f7eb47b… lmata 242 throw error;
f7eb47b… lmata 243 };
f7eb47b… lmata 244 const finalizer = () => {
f7eb47b… lmata 245 step.complete({});
f7eb47b… lmata 246 };
f7eb47b… lmata 247 try {
f7eb47b… lmata 248 setMatcherCallContext({ expectInfo: this._info, testInfo, step: step.info });
f7eb47b… lmata 249 const callback = () => matcher.call(target, ...args);
f7eb47b… lmata 250 const result = (0, import_utils.currentZone)().with("stepZone", step).run(callback);
f7eb47b… lmata 251 if (result instanceof Promise)
f7eb47b… lmata 252 return result.then(finalizer).catch(reportStepError);
f7eb47b… lmata 253 finalizer();
f7eb47b… lmata 254 return result;
f7eb47b… lmata 255 } catch (e) {
f7eb47b… lmata 256 void reportStepError(e);
f7eb47b… lmata 257 }
f7eb47b… lmata 258 };
f7eb47b… lmata 259 }
f7eb47b… lmata 260 }
f7eb47b… lmata 261 async function pollMatcher(qualifiedMatcherName2, info, prefix, ...args) {
f7eb47b… lmata 262 const testInfo = (0, import_globals.currentTestInfo)();
f7eb47b… lmata 263 const poll = info.poll;
f7eb47b… lmata 264 const timeout = poll.timeout ?? info.timeout ?? testInfo?._projectInternal?.expect?.timeout ?? defaultExpectTimeout;
f7eb47b… lmata 265 const { deadline, timeoutMessage } = testInfo ? testInfo._deadlineForMatcher(timeout) : import_testInfo.TestInfoImpl._defaultDeadlineForMatcher(timeout);
f7eb47b… lmata 266 const result = await (0, import_utils.pollAgainstDeadline)(async () => {
f7eb47b… lmata 267 if (testInfo && (0, import_globals.currentTestInfo)() !== testInfo)
f7eb47b… lmata 268 return { continuePolling: false, result: void 0 };
f7eb47b… lmata 269 const innerInfo = {
f7eb47b… lmata 270 ...info,
f7eb47b… lmata 271 isSoft: false,
f7eb47b… lmata 272 // soft is outside of poll, not inside
f7eb47b… lmata 273 poll: void 0
f7eb47b… lmata 274 };
f7eb47b… lmata 275 const value = await poll.generator();
f7eb47b… lmata 276 try {
f7eb47b… lmata 277 let matchers = createMatchers(value, innerInfo, prefix);
f7eb47b… lmata 278 if (info.isNot)
f7eb47b… lmata 279 matchers = matchers.not;
f7eb47b… lmata 280 matchers[qualifiedMatcherName2](...args);
f7eb47b… lmata 281 return { continuePolling: false, result: void 0 };
f7eb47b… lmata 282 } catch (error) {
f7eb47b… lmata 283 return { continuePolling: true, result: error };
f7eb47b… lmata 284 }
f7eb47b… lmata 285 }, deadline, poll.intervals ?? [100, 250, 500, 1e3]);
f7eb47b… lmata 286 if (result.timedOut) {
f7eb47b… lmata 287 const message = result.result ? [
f7eb47b… lmata 288 result.result.message,
f7eb47b… lmata 289 "",
f7eb47b… lmata 290 `Call Log:`,
f7eb47b… lmata 291 `- ${timeoutMessage}`
f7eb47b… lmata 292 ].join("\n") : timeoutMessage;
f7eb47b… lmata 293 throw new Error(message);
f7eb47b… lmata 294 }
f7eb47b… lmata 295 }
f7eb47b… lmata 296 const expect = createExpect({}, [], {}).extend(customMatchers);
f7eb47b… lmata 297 function mergeExpects(...expects) {
f7eb47b… lmata 298 let merged = expect;
f7eb47b… lmata 299 for (const e of expects) {
f7eb47b… lmata 300 const internals = e[userMatchersSymbol];
f7eb47b… lmata 301 if (!internals)
f7eb47b… lmata 302 continue;
f7eb47b… lmata 303 merged = merged.extend(internals);
f7eb47b… lmata 304 }
f7eb47b… lmata 305 return merged;
f7eb47b… lmata 306 }
f7eb47b… lmata 307 // Annotate the CommonJS export names for ESM import in node:
f7eb47b… lmata 308 0 && (module.exports = {
f7eb47b… lmata 309 expect,
f7eb47b… lmata 310 mergeExpects
f7eb47b… lmata 311 });

Keyboard Shortcuts

Open search /
Next entry (timeline) j
Previous entry (timeline) k
Open focused entry Enter
Show this help ?
Toggle theme Top nav button