screenshot/test_1
This commit is contained in:
371
node_modules/playwright/lib/matchers/expect.js
generated
vendored
Normal file
371
node_modules/playwright/lib/matchers/expect.js
generated
vendored
Normal file
@@ -0,0 +1,371 @@
|
||||
"use strict";
|
||||
|
||||
Object.defineProperty(exports, "__esModule", {
|
||||
value: true
|
||||
});
|
||||
exports.expect = void 0;
|
||||
exports.mergeExpects = mergeExpects;
|
||||
exports.printReceivedStringContainExpectedSubstring = exports.printReceivedStringContainExpectedResult = void 0;
|
||||
var _utils = require("playwright-core/lib/utils");
|
||||
var _matcherHint = require("./matcherHint");
|
||||
var _matchers = require("./matchers");
|
||||
var _toMatchAriaSnapshot = require("./toMatchAriaSnapshot");
|
||||
var _toMatchSnapshot = require("./toMatchSnapshot");
|
||||
var _expectBundle = require("../common/expectBundle");
|
||||
var _globals = require("../common/globals");
|
||||
var _util = require("../util");
|
||||
var _testInfo = require("../worker/testInfo");
|
||||
/**
|
||||
* Copyright Microsoft Corporation. All rights reserved.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
// #region
|
||||
// Mirrored from https://github.com/facebook/jest/blob/f13abff8df9a0e1148baf3584bcde6d1b479edc7/packages/expect/src/print.ts
|
||||
/**
|
||||
* Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved.
|
||||
*
|
||||
* This source code is licensed under the MIT license found here
|
||||
* https://github.com/facebook/jest/blob/1547740bbc26400d69f4576bf35645163e942829/LICENSE
|
||||
*/
|
||||
|
||||
// Format substring but do not enclose in double quote marks.
|
||||
// The replacement is compatible with pretty-format package.
|
||||
const printSubstring = val => val.replace(/"|\\/g, '\\$&');
|
||||
const printReceivedStringContainExpectedSubstring = (received, start, length // not end
|
||||
) => (0, _expectBundle.RECEIVED_COLOR)('"' + printSubstring(received.slice(0, start)) + (0, _expectBundle.INVERTED_COLOR)(printSubstring(received.slice(start, start + length))) + printSubstring(received.slice(start + length)) + '"');
|
||||
exports.printReceivedStringContainExpectedSubstring = printReceivedStringContainExpectedSubstring;
|
||||
const printReceivedStringContainExpectedResult = (received, result) => result === null ? (0, _expectBundle.printReceived)(received) : printReceivedStringContainExpectedSubstring(received, result.index, result[0].length);
|
||||
|
||||
// #endregion
|
||||
exports.printReceivedStringContainExpectedResult = printReceivedStringContainExpectedResult;
|
||||
function createMatchers(actual, info, prefix) {
|
||||
return new Proxy((0, _expectBundle.expect)(actual), new ExpectMetaInfoProxyHandler(info, prefix));
|
||||
}
|
||||
const userMatchersSymbol = Symbol('userMatchers');
|
||||
function qualifiedMatcherName(qualifier, matcherName) {
|
||||
return qualifier.join(':') + '$' + matcherName;
|
||||
}
|
||||
function createExpect(info, prefix, userMatchers) {
|
||||
const expectInstance = new Proxy(_expectBundle.expect, {
|
||||
apply: function (target, thisArg, argumentsList) {
|
||||
const [actual, messageOrOptions] = argumentsList;
|
||||
const message = (0, _utils.isString)(messageOrOptions) ? messageOrOptions : (messageOrOptions === null || messageOrOptions === void 0 ? void 0 : messageOrOptions.message) || info.message;
|
||||
const newInfo = {
|
||||
...info,
|
||||
message
|
||||
};
|
||||
if (newInfo.poll) {
|
||||
if (typeof actual !== 'function') throw new Error('`expect.poll()` accepts only function as a first argument');
|
||||
newInfo.poll.generator = actual;
|
||||
}
|
||||
return createMatchers(actual, newInfo, prefix);
|
||||
},
|
||||
get: function (target, property) {
|
||||
if (property === 'configure') return configure;
|
||||
if (property === 'extend') {
|
||||
return matchers => {
|
||||
const qualifier = [...prefix, (0, _utils.createGuid)()];
|
||||
const wrappedMatchers = {};
|
||||
for (const [name, matcher] of Object.entries(matchers)) {
|
||||
wrappedMatchers[name] = wrapPlaywrightMatcherToPassNiceThis(matcher);
|
||||
const key = qualifiedMatcherName(qualifier, name);
|
||||
wrappedMatchers[key] = wrappedMatchers[name];
|
||||
Object.defineProperty(wrappedMatchers[key], 'name', {
|
||||
value: name
|
||||
});
|
||||
}
|
||||
_expectBundle.expect.extend(wrappedMatchers);
|
||||
return createExpect(info, qualifier, {
|
||||
...userMatchers,
|
||||
...matchers
|
||||
});
|
||||
};
|
||||
}
|
||||
if (property === 'soft') {
|
||||
return (actual, messageOrOptions) => {
|
||||
return configure({
|
||||
soft: true
|
||||
})(actual, messageOrOptions);
|
||||
};
|
||||
}
|
||||
if (property === userMatchersSymbol) return userMatchers;
|
||||
if (property === 'poll') {
|
||||
return (actual, messageOrOptions) => {
|
||||
const poll = (0, _utils.isString)(messageOrOptions) ? {} : messageOrOptions || {};
|
||||
return configure({
|
||||
_poll: poll
|
||||
})(actual, messageOrOptions);
|
||||
};
|
||||
}
|
||||
return _expectBundle.expect[property];
|
||||
}
|
||||
});
|
||||
const configure = configuration => {
|
||||
const newInfo = {
|
||||
...info
|
||||
};
|
||||
if ('message' in configuration) newInfo.message = configuration.message;
|
||||
if ('timeout' in configuration) newInfo.timeout = configuration.timeout;
|
||||
if ('soft' in configuration) newInfo.isSoft = configuration.soft;
|
||||
if ('_poll' in configuration) {
|
||||
newInfo.poll = configuration._poll ? {
|
||||
...info.poll,
|
||||
generator: () => {}
|
||||
} : undefined;
|
||||
if (typeof configuration._poll === 'object') {
|
||||
var _configuration$_poll$, _configuration$_poll$2;
|
||||
newInfo.poll.timeout = (_configuration$_poll$ = configuration._poll.timeout) !== null && _configuration$_poll$ !== void 0 ? _configuration$_poll$ : newInfo.poll.timeout;
|
||||
newInfo.poll.intervals = (_configuration$_poll$2 = configuration._poll.intervals) !== null && _configuration$_poll$2 !== void 0 ? _configuration$_poll$2 : newInfo.poll.intervals;
|
||||
}
|
||||
}
|
||||
return createExpect(newInfo, prefix, userMatchers);
|
||||
};
|
||||
return expectInstance;
|
||||
}
|
||||
|
||||
// Expect wraps matchers, so there is no way to pass this information to the raw Playwright matcher.
|
||||
// Rely on sync call sequence to seed each matcher call with the context.
|
||||
|
||||
let matcherCallContext;
|
||||
function setMatcherCallContext(context) {
|
||||
matcherCallContext = context;
|
||||
}
|
||||
function takeMatcherCallContext() {
|
||||
try {
|
||||
return matcherCallContext;
|
||||
} finally {
|
||||
// Any subsequent matcher following the first is assumed to be an unsupported legacy asymmetric matcher.
|
||||
// Lacking call context in these scenarios is not particularly important.
|
||||
matcherCallContext = undefined;
|
||||
}
|
||||
}
|
||||
const defaultExpectTimeout = 5000;
|
||||
function wrapPlaywrightMatcherToPassNiceThis(matcher) {
|
||||
return function (...args) {
|
||||
var _ref, _context$expectInfo$t, _context$testInfo;
|
||||
const {
|
||||
isNot,
|
||||
promise,
|
||||
utils
|
||||
} = this;
|
||||
const context = takeMatcherCallContext();
|
||||
const timeout = (_ref = (_context$expectInfo$t = context === null || context === void 0 ? void 0 : context.expectInfo.timeout) !== null && _context$expectInfo$t !== void 0 ? _context$expectInfo$t : context === null || context === void 0 || (_context$testInfo = context.testInfo) === null || _context$testInfo === void 0 || (_context$testInfo = _context$testInfo._projectInternal) === null || _context$testInfo === void 0 || (_context$testInfo = _context$testInfo.expect) === null || _context$testInfo === void 0 ? void 0 : _context$testInfo.timeout) !== null && _ref !== void 0 ? _ref : defaultExpectTimeout;
|
||||
const newThis = {
|
||||
isNot,
|
||||
promise,
|
||||
utils,
|
||||
timeout,
|
||||
_stepInfo: context === null || context === void 0 ? void 0 : context.step
|
||||
};
|
||||
newThis.equals = throwUnsupportedExpectMatcherError;
|
||||
return matcher.call(newThis, ...args);
|
||||
};
|
||||
}
|
||||
function throwUnsupportedExpectMatcherError() {
|
||||
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');
|
||||
}
|
||||
_expectBundle.expect.setState({
|
||||
expand: false
|
||||
});
|
||||
const customAsyncMatchers = {
|
||||
toBeAttached: _matchers.toBeAttached,
|
||||
toBeChecked: _matchers.toBeChecked,
|
||||
toBeDisabled: _matchers.toBeDisabled,
|
||||
toBeEditable: _matchers.toBeEditable,
|
||||
toBeEmpty: _matchers.toBeEmpty,
|
||||
toBeEnabled: _matchers.toBeEnabled,
|
||||
toBeFocused: _matchers.toBeFocused,
|
||||
toBeHidden: _matchers.toBeHidden,
|
||||
toBeInViewport: _matchers.toBeInViewport,
|
||||
toBeOK: _matchers.toBeOK,
|
||||
toBeVisible: _matchers.toBeVisible,
|
||||
toContainText: _matchers.toContainText,
|
||||
toHaveAccessibleDescription: _matchers.toHaveAccessibleDescription,
|
||||
toHaveAccessibleName: _matchers.toHaveAccessibleName,
|
||||
toHaveAccessibleErrorMessage: _matchers.toHaveAccessibleErrorMessage,
|
||||
toHaveAttribute: _matchers.toHaveAttribute,
|
||||
toHaveClass: _matchers.toHaveClass,
|
||||
toHaveCount: _matchers.toHaveCount,
|
||||
toHaveCSS: _matchers.toHaveCSS,
|
||||
toHaveId: _matchers.toHaveId,
|
||||
toHaveJSProperty: _matchers.toHaveJSProperty,
|
||||
toHaveRole: _matchers.toHaveRole,
|
||||
toHaveText: _matchers.toHaveText,
|
||||
toHaveTitle: _matchers.toHaveTitle,
|
||||
toHaveURL: _matchers.toHaveURL,
|
||||
toHaveValue: _matchers.toHaveValue,
|
||||
toHaveValues: _matchers.toHaveValues,
|
||||
toHaveScreenshot: _toMatchSnapshot.toHaveScreenshot,
|
||||
toMatchAriaSnapshot: _toMatchAriaSnapshot.toMatchAriaSnapshot,
|
||||
toPass: _matchers.toPass
|
||||
};
|
||||
const customMatchers = {
|
||||
...customAsyncMatchers,
|
||||
toMatchSnapshot: _toMatchSnapshot.toMatchSnapshot
|
||||
};
|
||||
class ExpectMetaInfoProxyHandler {
|
||||
constructor(info, prefix) {
|
||||
this._info = void 0;
|
||||
this._prefix = void 0;
|
||||
this._info = {
|
||||
...info
|
||||
};
|
||||
this._prefix = prefix;
|
||||
}
|
||||
get(target, matcherName, receiver) {
|
||||
let matcher = Reflect.get(target, matcherName, receiver);
|
||||
if (typeof matcherName !== 'string') return matcher;
|
||||
let resolvedMatcherName = matcherName;
|
||||
for (let i = this._prefix.length; i > 0; i--) {
|
||||
const qualifiedName = qualifiedMatcherName(this._prefix.slice(0, i), matcherName);
|
||||
if (Reflect.has(target, qualifiedName)) {
|
||||
matcher = Reflect.get(target, qualifiedName, receiver);
|
||||
resolvedMatcherName = qualifiedName;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (matcher === undefined) throw new Error(`expect: Property '${matcherName}' not found.`);
|
||||
if (typeof matcher !== 'function') {
|
||||
if (matcherName === 'not') this._info.isNot = !this._info.isNot;
|
||||
return new Proxy(matcher, this);
|
||||
}
|
||||
if (this._info.poll) {
|
||||
if (customAsyncMatchers[matcherName] || matcherName === 'resolves' || matcherName === 'rejects') throw new Error(`\`expect.poll()\` does not support "${matcherName}" matcher.`);
|
||||
matcher = (...args) => pollMatcher(resolvedMatcherName, this._info, this._prefix, ...args);
|
||||
}
|
||||
return (...args) => {
|
||||
const testInfo = (0, _globals.currentTestInfo)();
|
||||
setMatcherCallContext({
|
||||
expectInfo: this._info,
|
||||
testInfo
|
||||
});
|
||||
if (!testInfo) return matcher.call(target, ...args);
|
||||
const customMessage = this._info.message || '';
|
||||
const argsSuffix = computeArgsSuffix(matcherName, args);
|
||||
const defaultTitle = `expect${this._info.poll ? '.poll' : ''}${this._info.isSoft ? '.soft' : ''}${this._info.isNot ? '.not' : ''}.${matcherName}${argsSuffix}`;
|
||||
const title = customMessage || defaultTitle;
|
||||
|
||||
// This looks like it is unnecessary, but it isn't - we need to filter
|
||||
// out all the frames that belong to the test runner from caught runtime errors.
|
||||
const stackFrames = (0, _util.filteredStackTrace)((0, _utils.captureRawStack)());
|
||||
|
||||
// toPass and poll matchers can contain other steps, expects and API calls,
|
||||
// so they behave like a retriable step.
|
||||
const stepInfo = {
|
||||
category: matcherName === 'toPass' || this._info.poll ? 'step' : 'expect',
|
||||
title: (0, _util.trimLongString)(title, 1024),
|
||||
params: args[0] ? {
|
||||
expected: args[0]
|
||||
} : undefined,
|
||||
infectParentStepsWithError: this._info.isSoft
|
||||
};
|
||||
const step = testInfo._addStep(stepInfo);
|
||||
const reportStepError = e => {
|
||||
const jestError = (0, _matcherHint.isJestError)(e) ? e : null;
|
||||
const error = jestError ? new _matcherHint.ExpectError(jestError, customMessage, stackFrames) : e;
|
||||
if (jestError !== null && jestError !== void 0 && jestError.matcherResult.suggestedRebaseline) {
|
||||
// NOTE: this is a workaround for the fact that we can't pass the suggested rebaseline
|
||||
// for passing matchers. See toMatchAriaSnapshot for a counterpart.
|
||||
step.complete({
|
||||
suggestedRebaseline: jestError === null || jestError === void 0 ? void 0 : jestError.matcherResult.suggestedRebaseline
|
||||
});
|
||||
return;
|
||||
}
|
||||
step.complete({
|
||||
error
|
||||
});
|
||||
if (this._info.isSoft) testInfo._failWithError(error);else throw error;
|
||||
};
|
||||
const finalizer = () => {
|
||||
step.complete({});
|
||||
};
|
||||
try {
|
||||
setMatcherCallContext({
|
||||
expectInfo: this._info,
|
||||
testInfo,
|
||||
step: step.info
|
||||
});
|
||||
const callback = () => matcher.call(target, ...args);
|
||||
const result = (0, _utils.currentZone)().with('stepZone', step).run(callback);
|
||||
if (result instanceof Promise) {
|
||||
const promise = result.then(finalizer).catch(reportStepError);
|
||||
return testInfo._floatingPromiseScope.wrapPromiseAPIResult(promise);
|
||||
}
|
||||
finalizer();
|
||||
return result;
|
||||
} catch (e) {
|
||||
reportStepError(e);
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
async function pollMatcher(qualifiedMatcherName, info, prefix, ...args) {
|
||||
var _ref2, _ref3, _poll$timeout, _testInfo$_projectInt, _poll$intervals;
|
||||
const testInfo = (0, _globals.currentTestInfo)();
|
||||
const poll = info.poll;
|
||||
const timeout = (_ref2 = (_ref3 = (_poll$timeout = poll.timeout) !== null && _poll$timeout !== void 0 ? _poll$timeout : info.timeout) !== null && _ref3 !== void 0 ? _ref3 : testInfo === null || testInfo === void 0 || (_testInfo$_projectInt = testInfo._projectInternal) === null || _testInfo$_projectInt === void 0 || (_testInfo$_projectInt = _testInfo$_projectInt.expect) === null || _testInfo$_projectInt === void 0 ? void 0 : _testInfo$_projectInt.timeout) !== null && _ref2 !== void 0 ? _ref2 : defaultExpectTimeout;
|
||||
const {
|
||||
deadline,
|
||||
timeoutMessage
|
||||
} = testInfo ? testInfo._deadlineForMatcher(timeout) : _testInfo.TestInfoImpl._defaultDeadlineForMatcher(timeout);
|
||||
const result = await (0, _utils.pollAgainstDeadline)(async () => {
|
||||
if (testInfo && (0, _globals.currentTestInfo)() !== testInfo) return {
|
||||
continuePolling: false,
|
||||
result: undefined
|
||||
};
|
||||
const innerInfo = {
|
||||
...info,
|
||||
isSoft: false,
|
||||
// soft is outside of poll, not inside
|
||||
poll: undefined
|
||||
};
|
||||
const value = await poll.generator();
|
||||
try {
|
||||
let matchers = createMatchers(value, innerInfo, prefix);
|
||||
if (info.isNot) matchers = matchers.not;
|
||||
matchers[qualifiedMatcherName](...args);
|
||||
return {
|
||||
continuePolling: false,
|
||||
result: undefined
|
||||
};
|
||||
} catch (error) {
|
||||
return {
|
||||
continuePolling: true,
|
||||
result: error
|
||||
};
|
||||
}
|
||||
}, deadline, (_poll$intervals = poll.intervals) !== null && _poll$intervals !== void 0 ? _poll$intervals : [100, 250, 500, 1000]);
|
||||
if (result.timedOut) {
|
||||
const message = result.result ? [result.result.message, '', `Call Log:`, `- ${timeoutMessage}`].join('\n') : timeoutMessage;
|
||||
throw new Error(message);
|
||||
}
|
||||
}
|
||||
function computeArgsSuffix(matcherName, args) {
|
||||
let value = '';
|
||||
if (matcherName === 'toHaveScreenshot') value = (0, _toMatchSnapshot.toHaveScreenshotStepTitle)(...args);
|
||||
return value ? `(${value})` : '';
|
||||
}
|
||||
const expect = exports.expect = createExpect({}, [], {}).extend(customMatchers);
|
||||
function mergeExpects(...expects) {
|
||||
let merged = expect;
|
||||
for (const e of expects) {
|
||||
const internals = e[userMatchersSymbol];
|
||||
if (!internals)
|
||||
// non-playwright expects mutate the global expect, so we don't need to do anything special
|
||||
continue;
|
||||
merged = merged.extend(internals);
|
||||
}
|
||||
return merged;
|
||||
}
|
||||
49
node_modules/playwright/lib/matchers/matcherHint.js
generated
vendored
Normal file
49
node_modules/playwright/lib/matchers/matcherHint.js
generated
vendored
Normal file
@@ -0,0 +1,49 @@
|
||||
"use strict";
|
||||
|
||||
Object.defineProperty(exports, "__esModule", {
|
||||
value: true
|
||||
});
|
||||
exports.ExpectError = void 0;
|
||||
exports.isJestError = isJestError;
|
||||
exports.kNoElementsFoundError = void 0;
|
||||
exports.matcherHint = matcherHint;
|
||||
var _utils = require("playwright-core/lib/utils");
|
||||
/**
|
||||
* Copyright Microsoft Corporation. All rights reserved.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
const kNoElementsFoundError = exports.kNoElementsFoundError = '<element(s) not found>';
|
||||
function matcherHint(state, locator, matcherName, expression, actual, matcherOptions, timeout) {
|
||||
let header = state.utils.matcherHint(matcherName, expression, actual, matcherOptions).replace(/ \/\/ deep equality/, '') + '\n\n';
|
||||
if (timeout) header = _utils.colors.red(`Timed out ${timeout}ms waiting for `) + header;
|
||||
if (locator) header += `Locator: ${String(locator)}\n`;
|
||||
return header;
|
||||
}
|
||||
class ExpectError extends Error {
|
||||
constructor(jestError, customMessage, stackFrames) {
|
||||
super('');
|
||||
// Copy to erase the JestMatcherError constructor name from the console.log(error).
|
||||
this.matcherResult = void 0;
|
||||
this.name = jestError.name;
|
||||
this.message = jestError.message;
|
||||
this.matcherResult = jestError.matcherResult;
|
||||
if (customMessage) this.message = customMessage + '\n\n' + this.message;
|
||||
this.stack = this.name + ': ' + this.message + '\n' + (0, _utils.stringifyStackFrames)(stackFrames).join('\n');
|
||||
}
|
||||
}
|
||||
exports.ExpectError = ExpectError;
|
||||
function isJestError(e) {
|
||||
return e instanceof Error && 'matcherResult' in e;
|
||||
}
|
||||
475
node_modules/playwright/lib/matchers/matchers.js
generated
vendored
Normal file
475
node_modules/playwright/lib/matchers/matchers.js
generated
vendored
Normal file
@@ -0,0 +1,475 @@
|
||||
"use strict";
|
||||
|
||||
Object.defineProperty(exports, "__esModule", {
|
||||
value: true
|
||||
});
|
||||
exports.toBeAttached = toBeAttached;
|
||||
exports.toBeChecked = toBeChecked;
|
||||
exports.toBeDisabled = toBeDisabled;
|
||||
exports.toBeEditable = toBeEditable;
|
||||
exports.toBeEmpty = toBeEmpty;
|
||||
exports.toBeEnabled = toBeEnabled;
|
||||
exports.toBeFocused = toBeFocused;
|
||||
exports.toBeHidden = toBeHidden;
|
||||
exports.toBeInViewport = toBeInViewport;
|
||||
exports.toBeOK = toBeOK;
|
||||
exports.toBeVisible = toBeVisible;
|
||||
exports.toContainText = toContainText;
|
||||
exports.toHaveAccessibleDescription = toHaveAccessibleDescription;
|
||||
exports.toHaveAccessibleErrorMessage = toHaveAccessibleErrorMessage;
|
||||
exports.toHaveAccessibleName = toHaveAccessibleName;
|
||||
exports.toHaveAttribute = toHaveAttribute;
|
||||
exports.toHaveCSS = toHaveCSS;
|
||||
exports.toHaveClass = toHaveClass;
|
||||
exports.toHaveCount = toHaveCount;
|
||||
exports.toHaveId = toHaveId;
|
||||
exports.toHaveJSProperty = toHaveJSProperty;
|
||||
exports.toHaveRole = toHaveRole;
|
||||
exports.toHaveText = toHaveText;
|
||||
exports.toHaveTitle = toHaveTitle;
|
||||
exports.toHaveURL = toHaveURL;
|
||||
exports.toHaveValue = toHaveValue;
|
||||
exports.toHaveValues = toHaveValues;
|
||||
exports.toPass = toPass;
|
||||
var _utils = require("playwright-core/lib/utils");
|
||||
var _util = require("../util");
|
||||
var _toBeTruthy = require("./toBeTruthy");
|
||||
var _toEqual = require("./toEqual");
|
||||
var _toHaveURL = require("./toHaveURL");
|
||||
var _toMatchText = require("./toMatchText");
|
||||
var _config = require("../common/config");
|
||||
var _globals = require("../common/globals");
|
||||
var _testInfo = require("../worker/testInfo");
|
||||
/**
|
||||
* Copyright Microsoft Corporation. All rights reserved.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
function toBeAttached(locator, options) {
|
||||
const attached = !options || options.attached === undefined || options.attached;
|
||||
const expected = attached ? 'attached' : 'detached';
|
||||
const arg = attached ? '' : '{ attached: false }';
|
||||
return _toBeTruthy.toBeTruthy.call(this, 'toBeAttached', locator, 'Locator', expected, arg, async (isNot, timeout) => {
|
||||
return await locator._expect(attached ? 'to.be.attached' : 'to.be.detached', {
|
||||
isNot,
|
||||
timeout
|
||||
});
|
||||
}, options);
|
||||
}
|
||||
function toBeChecked(locator, options) {
|
||||
const checked = options === null || options === void 0 ? void 0 : options.checked;
|
||||
const indeterminate = options === null || options === void 0 ? void 0 : options.indeterminate;
|
||||
const expectedValue = {
|
||||
checked,
|
||||
indeterminate
|
||||
};
|
||||
let expected;
|
||||
let arg;
|
||||
if (options !== null && options !== void 0 && options.indeterminate) {
|
||||
expected = 'indeterminate';
|
||||
arg = `{ indeterminate: true }`;
|
||||
} else {
|
||||
expected = (options === null || options === void 0 ? void 0 : options.checked) === false ? 'unchecked' : 'checked';
|
||||
arg = (options === null || options === void 0 ? void 0 : options.checked) === false ? `{ checked: false }` : '';
|
||||
}
|
||||
return _toBeTruthy.toBeTruthy.call(this, 'toBeChecked', locator, 'Locator', expected, arg, async (isNot, timeout) => {
|
||||
return await locator._expect('to.be.checked', {
|
||||
isNot,
|
||||
timeout,
|
||||
expectedValue
|
||||
});
|
||||
}, options);
|
||||
}
|
||||
function toBeDisabled(locator, options) {
|
||||
return _toBeTruthy.toBeTruthy.call(this, 'toBeDisabled', locator, 'Locator', 'disabled', '', async (isNot, timeout) => {
|
||||
return await locator._expect('to.be.disabled', {
|
||||
isNot,
|
||||
timeout
|
||||
});
|
||||
}, options);
|
||||
}
|
||||
function toBeEditable(locator, options) {
|
||||
const editable = !options || options.editable === undefined || options.editable;
|
||||
const expected = editable ? 'editable' : 'readOnly';
|
||||
const arg = editable ? '' : '{ editable: false }';
|
||||
return _toBeTruthy.toBeTruthy.call(this, 'toBeEditable', locator, 'Locator', expected, arg, async (isNot, timeout) => {
|
||||
return await locator._expect(editable ? 'to.be.editable' : 'to.be.readonly', {
|
||||
isNot,
|
||||
timeout
|
||||
});
|
||||
}, options);
|
||||
}
|
||||
function toBeEmpty(locator, options) {
|
||||
return _toBeTruthy.toBeTruthy.call(this, 'toBeEmpty', locator, 'Locator', 'empty', '', async (isNot, timeout) => {
|
||||
return await locator._expect('to.be.empty', {
|
||||
isNot,
|
||||
timeout
|
||||
});
|
||||
}, options);
|
||||
}
|
||||
function toBeEnabled(locator, options) {
|
||||
const enabled = !options || options.enabled === undefined || options.enabled;
|
||||
const expected = enabled ? 'enabled' : 'disabled';
|
||||
const arg = enabled ? '' : '{ enabled: false }';
|
||||
return _toBeTruthy.toBeTruthy.call(this, 'toBeEnabled', locator, 'Locator', expected, arg, async (isNot, timeout) => {
|
||||
return await locator._expect(enabled ? 'to.be.enabled' : 'to.be.disabled', {
|
||||
isNot,
|
||||
timeout
|
||||
});
|
||||
}, options);
|
||||
}
|
||||
function toBeFocused(locator, options) {
|
||||
return _toBeTruthy.toBeTruthy.call(this, 'toBeFocused', locator, 'Locator', 'focused', '', async (isNot, timeout) => {
|
||||
return await locator._expect('to.be.focused', {
|
||||
isNot,
|
||||
timeout
|
||||
});
|
||||
}, options);
|
||||
}
|
||||
function toBeHidden(locator, options) {
|
||||
return _toBeTruthy.toBeTruthy.call(this, 'toBeHidden', locator, 'Locator', 'hidden', '', async (isNot, timeout) => {
|
||||
return await locator._expect('to.be.hidden', {
|
||||
isNot,
|
||||
timeout
|
||||
});
|
||||
}, options);
|
||||
}
|
||||
function toBeVisible(locator, options) {
|
||||
const visible = !options || options.visible === undefined || options.visible;
|
||||
const expected = visible ? 'visible' : 'hidden';
|
||||
const arg = visible ? '' : '{ visible: false }';
|
||||
return _toBeTruthy.toBeTruthy.call(this, 'toBeVisible', locator, 'Locator', expected, arg, async (isNot, timeout) => {
|
||||
return await locator._expect(visible ? 'to.be.visible' : 'to.be.hidden', {
|
||||
isNot,
|
||||
timeout
|
||||
});
|
||||
}, options);
|
||||
}
|
||||
function toBeInViewport(locator, options) {
|
||||
return _toBeTruthy.toBeTruthy.call(this, 'toBeInViewport', locator, 'Locator', 'in viewport', '', async (isNot, timeout) => {
|
||||
return await locator._expect('to.be.in.viewport', {
|
||||
isNot,
|
||||
expectedNumber: options === null || options === void 0 ? void 0 : options.ratio,
|
||||
timeout
|
||||
});
|
||||
}, options);
|
||||
}
|
||||
function toContainText(locator, expected, options = {}) {
|
||||
if (Array.isArray(expected)) {
|
||||
return _toEqual.toEqual.call(this, 'toContainText', locator, 'Locator', async (isNot, timeout) => {
|
||||
const expectedText = (0, _utils.serializeExpectedTextValues)(expected, {
|
||||
matchSubstring: true,
|
||||
normalizeWhiteSpace: true,
|
||||
ignoreCase: options.ignoreCase
|
||||
});
|
||||
return await locator._expect('to.contain.text.array', {
|
||||
expectedText,
|
||||
isNot,
|
||||
useInnerText: options.useInnerText,
|
||||
timeout
|
||||
});
|
||||
}, expected, {
|
||||
...options,
|
||||
contains: true
|
||||
});
|
||||
} else {
|
||||
return _toMatchText.toMatchText.call(this, 'toContainText', locator, 'Locator', async (isNot, timeout) => {
|
||||
const expectedText = (0, _utils.serializeExpectedTextValues)([expected], {
|
||||
matchSubstring: true,
|
||||
normalizeWhiteSpace: true,
|
||||
ignoreCase: options.ignoreCase
|
||||
});
|
||||
return await locator._expect('to.have.text', {
|
||||
expectedText,
|
||||
isNot,
|
||||
useInnerText: options.useInnerText,
|
||||
timeout
|
||||
});
|
||||
}, expected, options);
|
||||
}
|
||||
}
|
||||
function toHaveAccessibleDescription(locator, expected, options) {
|
||||
return _toMatchText.toMatchText.call(this, 'toHaveAccessibleDescription', locator, 'Locator', async (isNot, timeout) => {
|
||||
const expectedText = (0, _utils.serializeExpectedTextValues)([expected], {
|
||||
ignoreCase: options === null || options === void 0 ? void 0 : options.ignoreCase,
|
||||
normalizeWhiteSpace: true
|
||||
});
|
||||
return await locator._expect('to.have.accessible.description', {
|
||||
expectedText,
|
||||
isNot,
|
||||
timeout
|
||||
});
|
||||
}, expected, options);
|
||||
}
|
||||
function toHaveAccessibleName(locator, expected, options) {
|
||||
return _toMatchText.toMatchText.call(this, 'toHaveAccessibleName', locator, 'Locator', async (isNot, timeout) => {
|
||||
const expectedText = (0, _utils.serializeExpectedTextValues)([expected], {
|
||||
ignoreCase: options === null || options === void 0 ? void 0 : options.ignoreCase,
|
||||
normalizeWhiteSpace: true
|
||||
});
|
||||
return await locator._expect('to.have.accessible.name', {
|
||||
expectedText,
|
||||
isNot,
|
||||
timeout
|
||||
});
|
||||
}, expected, options);
|
||||
}
|
||||
function toHaveAccessibleErrorMessage(locator, expected, options) {
|
||||
return _toMatchText.toMatchText.call(this, 'toHaveAccessibleErrorMessage', locator, 'Locator', async (isNot, timeout) => {
|
||||
const expectedText = (0, _utils.serializeExpectedTextValues)([expected], {
|
||||
ignoreCase: options === null || options === void 0 ? void 0 : options.ignoreCase,
|
||||
normalizeWhiteSpace: true
|
||||
});
|
||||
return await locator._expect('to.have.accessible.error.message', {
|
||||
expectedText: expectedText,
|
||||
isNot,
|
||||
timeout
|
||||
});
|
||||
}, expected, options);
|
||||
}
|
||||
function toHaveAttribute(locator, name, expected, options) {
|
||||
if (!options) {
|
||||
// Update params for the case toHaveAttribute(name, options);
|
||||
if (typeof expected === 'object' && !(0, _utils.isRegExp)(expected)) {
|
||||
options = expected;
|
||||
expected = undefined;
|
||||
}
|
||||
}
|
||||
if (expected === undefined) {
|
||||
return _toBeTruthy.toBeTruthy.call(this, 'toHaveAttribute', locator, 'Locator', 'have attribute', '', async (isNot, timeout) => {
|
||||
return await locator._expect('to.have.attribute', {
|
||||
expressionArg: name,
|
||||
isNot,
|
||||
timeout
|
||||
});
|
||||
}, options);
|
||||
}
|
||||
return _toMatchText.toMatchText.call(this, 'toHaveAttribute', locator, 'Locator', async (isNot, timeout) => {
|
||||
var _options;
|
||||
const expectedText = (0, _utils.serializeExpectedTextValues)([expected], {
|
||||
ignoreCase: (_options = options) === null || _options === void 0 ? void 0 : _options.ignoreCase
|
||||
});
|
||||
return await locator._expect('to.have.attribute.value', {
|
||||
expressionArg: name,
|
||||
expectedText,
|
||||
isNot,
|
||||
timeout
|
||||
});
|
||||
}, expected, options);
|
||||
}
|
||||
function toHaveClass(locator, expected, options) {
|
||||
if (Array.isArray(expected)) {
|
||||
return _toEqual.toEqual.call(this, 'toHaveClass', locator, 'Locator', async (isNot, timeout) => {
|
||||
const expectedText = (0, _utils.serializeExpectedTextValues)(expected);
|
||||
return await locator._expect('to.have.class.array', {
|
||||
expectedText,
|
||||
isNot,
|
||||
timeout
|
||||
});
|
||||
}, expected, options);
|
||||
} else {
|
||||
return _toMatchText.toMatchText.call(this, 'toHaveClass', locator, 'Locator', async (isNot, timeout) => {
|
||||
const expectedText = (0, _utils.serializeExpectedTextValues)([expected]);
|
||||
return await locator._expect('to.have.class', {
|
||||
expectedText,
|
||||
isNot,
|
||||
timeout
|
||||
});
|
||||
}, expected, options);
|
||||
}
|
||||
}
|
||||
function toHaveCount(locator, expected, options) {
|
||||
return _toEqual.toEqual.call(this, 'toHaveCount', locator, 'Locator', async (isNot, timeout) => {
|
||||
return await locator._expect('to.have.count', {
|
||||
expectedNumber: expected,
|
||||
isNot,
|
||||
timeout
|
||||
});
|
||||
}, expected, options);
|
||||
}
|
||||
function toHaveCSS(locator, name, expected, options) {
|
||||
return _toMatchText.toMatchText.call(this, 'toHaveCSS', locator, 'Locator', async (isNot, timeout) => {
|
||||
const expectedText = (0, _utils.serializeExpectedTextValues)([expected]);
|
||||
return await locator._expect('to.have.css', {
|
||||
expressionArg: name,
|
||||
expectedText,
|
||||
isNot,
|
||||
timeout
|
||||
});
|
||||
}, expected, options);
|
||||
}
|
||||
function toHaveId(locator, expected, options) {
|
||||
return _toMatchText.toMatchText.call(this, 'toHaveId', locator, 'Locator', async (isNot, timeout) => {
|
||||
const expectedText = (0, _utils.serializeExpectedTextValues)([expected]);
|
||||
return await locator._expect('to.have.id', {
|
||||
expectedText,
|
||||
isNot,
|
||||
timeout
|
||||
});
|
||||
}, expected, options);
|
||||
}
|
||||
function toHaveJSProperty(locator, name, expected, options) {
|
||||
return _toEqual.toEqual.call(this, 'toHaveJSProperty', locator, 'Locator', async (isNot, timeout) => {
|
||||
return await locator._expect('to.have.property', {
|
||||
expressionArg: name,
|
||||
expectedValue: expected,
|
||||
isNot,
|
||||
timeout
|
||||
});
|
||||
}, expected, options);
|
||||
}
|
||||
function toHaveRole(locator, expected, options) {
|
||||
if (!(0, _utils.isString)(expected)) throw new Error(`"role" argument in toHaveRole must be a string`);
|
||||
return _toMatchText.toMatchText.call(this, 'toHaveRole', locator, 'Locator', async (isNot, timeout) => {
|
||||
const expectedText = (0, _utils.serializeExpectedTextValues)([expected]);
|
||||
return await locator._expect('to.have.role', {
|
||||
expectedText,
|
||||
isNot,
|
||||
timeout
|
||||
});
|
||||
}, expected, options);
|
||||
}
|
||||
function toHaveText(locator, expected, options = {}) {
|
||||
if (Array.isArray(expected)) {
|
||||
return _toEqual.toEqual.call(this, 'toHaveText', locator, 'Locator', async (isNot, timeout) => {
|
||||
const expectedText = (0, _utils.serializeExpectedTextValues)(expected, {
|
||||
normalizeWhiteSpace: true,
|
||||
ignoreCase: options.ignoreCase
|
||||
});
|
||||
return await locator._expect('to.have.text.array', {
|
||||
expectedText,
|
||||
isNot,
|
||||
useInnerText: options === null || options === void 0 ? void 0 : options.useInnerText,
|
||||
timeout
|
||||
});
|
||||
}, expected, options);
|
||||
} else {
|
||||
return _toMatchText.toMatchText.call(this, 'toHaveText', locator, 'Locator', async (isNot, timeout) => {
|
||||
const expectedText = (0, _utils.serializeExpectedTextValues)([expected], {
|
||||
normalizeWhiteSpace: true,
|
||||
ignoreCase: options.ignoreCase
|
||||
});
|
||||
return await locator._expect('to.have.text', {
|
||||
expectedText,
|
||||
isNot,
|
||||
useInnerText: options === null || options === void 0 ? void 0 : options.useInnerText,
|
||||
timeout
|
||||
});
|
||||
}, expected, options);
|
||||
}
|
||||
}
|
||||
function toHaveValue(locator, expected, options) {
|
||||
return _toMatchText.toMatchText.call(this, 'toHaveValue', locator, 'Locator', async (isNot, timeout) => {
|
||||
const expectedText = (0, _utils.serializeExpectedTextValues)([expected]);
|
||||
return await locator._expect('to.have.value', {
|
||||
expectedText,
|
||||
isNot,
|
||||
timeout
|
||||
});
|
||||
}, expected, options);
|
||||
}
|
||||
function toHaveValues(locator, expected, options) {
|
||||
return _toEqual.toEqual.call(this, 'toHaveValues', locator, 'Locator', async (isNot, timeout) => {
|
||||
const expectedText = (0, _utils.serializeExpectedTextValues)(expected);
|
||||
return await locator._expect('to.have.values', {
|
||||
expectedText,
|
||||
isNot,
|
||||
timeout
|
||||
});
|
||||
}, expected, options);
|
||||
}
|
||||
function toHaveTitle(page, expected, options = {}) {
|
||||
const locator = page.locator(':root');
|
||||
return _toMatchText.toMatchText.call(this, 'toHaveTitle', locator, 'Locator', async (isNot, timeout) => {
|
||||
const expectedText = (0, _utils.serializeExpectedTextValues)([expected], {
|
||||
normalizeWhiteSpace: true
|
||||
});
|
||||
return await locator._expect('to.have.title', {
|
||||
expectedText,
|
||||
isNot,
|
||||
timeout
|
||||
});
|
||||
}, expected, options);
|
||||
}
|
||||
function toHaveURL(page, expected, options) {
|
||||
// Ports don't support predicates. Keep separate server and client codepaths
|
||||
if (typeof expected === 'function') return _toHaveURL.toHaveURLWithPredicate.call(this, page, expected, options);
|
||||
const baseURL = page.context()._options.baseURL;
|
||||
expected = typeof expected === 'string' ? (0, _utils.constructURLBasedOnBaseURL)(baseURL, expected) : expected;
|
||||
const locator = page.locator(':root');
|
||||
return _toMatchText.toMatchText.call(this, 'toHaveURL', locator, 'Locator', async (isNot, timeout) => {
|
||||
const expectedText = (0, _utils.serializeExpectedTextValues)([expected], {
|
||||
ignoreCase: options === null || options === void 0 ? void 0 : options.ignoreCase
|
||||
});
|
||||
return await locator._expect('to.have.url', {
|
||||
expectedText,
|
||||
isNot,
|
||||
timeout
|
||||
});
|
||||
}, expected, options);
|
||||
}
|
||||
async function toBeOK(response) {
|
||||
const matcherName = 'toBeOK';
|
||||
(0, _util.expectTypes)(response, ['APIResponse'], matcherName);
|
||||
const contentType = response.headers()['content-type'];
|
||||
const isTextEncoding = contentType && (0, _utils.isTextualMimeType)(contentType);
|
||||
const [log, text] = this.isNot === response.ok() ? await Promise.all([response._fetchLog(), isTextEncoding ? response.text() : null]) : [];
|
||||
const message = () => this.utils.matcherHint(matcherName, undefined, '', {
|
||||
isNot: this.isNot
|
||||
}) + (0, _util.callLogText)(log) + (text === null ? '' : `\nResponse text:\n${_utils.colors.dim((text === null || text === void 0 ? void 0 : text.substring(0, 1000)) || '')}`);
|
||||
const pass = response.ok();
|
||||
return {
|
||||
message,
|
||||
pass
|
||||
};
|
||||
}
|
||||
async function toPass(callback, options = {}) {
|
||||
var _testInfo$_projectInt, _testInfo$_projectInt2;
|
||||
const testInfo = (0, _globals.currentTestInfo)();
|
||||
const timeout = (0, _config.takeFirst)(options.timeout, testInfo === null || testInfo === void 0 || (_testInfo$_projectInt = testInfo._projectInternal.expect) === null || _testInfo$_projectInt === void 0 || (_testInfo$_projectInt = _testInfo$_projectInt.toPass) === null || _testInfo$_projectInt === void 0 ? void 0 : _testInfo$_projectInt.timeout, 0);
|
||||
const intervals = (0, _config.takeFirst)(options.intervals, testInfo === null || testInfo === void 0 || (_testInfo$_projectInt2 = testInfo._projectInternal.expect) === null || _testInfo$_projectInt2 === void 0 || (_testInfo$_projectInt2 = _testInfo$_projectInt2.toPass) === null || _testInfo$_projectInt2 === void 0 ? void 0 : _testInfo$_projectInt2.intervals, [100, 250, 500, 1000]);
|
||||
const {
|
||||
deadline,
|
||||
timeoutMessage
|
||||
} = testInfo ? testInfo._deadlineForMatcher(timeout) : _testInfo.TestInfoImpl._defaultDeadlineForMatcher(timeout);
|
||||
const result = await (0, _utils.pollAgainstDeadline)(async () => {
|
||||
if (testInfo && (0, _globals.currentTestInfo)() !== testInfo) return {
|
||||
continuePolling: false,
|
||||
result: undefined
|
||||
};
|
||||
try {
|
||||
await callback();
|
||||
return {
|
||||
continuePolling: !!this.isNot,
|
||||
result: undefined
|
||||
};
|
||||
} catch (e) {
|
||||
return {
|
||||
continuePolling: !this.isNot,
|
||||
result: e
|
||||
};
|
||||
}
|
||||
}, deadline, intervals);
|
||||
if (result.timedOut) {
|
||||
const message = result.result ? [result.result.message, '', `Call Log:`, `- ${timeoutMessage}`].join('\n') : timeoutMessage;
|
||||
return {
|
||||
message: () => message,
|
||||
pass: !!this.isNot
|
||||
};
|
||||
}
|
||||
return {
|
||||
pass: !this.isNot,
|
||||
message: () => ''
|
||||
};
|
||||
}
|
||||
71
node_modules/playwright/lib/matchers/toBeTruthy.js
generated
vendored
Normal file
71
node_modules/playwright/lib/matchers/toBeTruthy.js
generated
vendored
Normal file
@@ -0,0 +1,71 @@
|
||||
"use strict";
|
||||
|
||||
Object.defineProperty(exports, "__esModule", {
|
||||
value: true
|
||||
});
|
||||
exports.toBeTruthy = toBeTruthy;
|
||||
var _util = require("../util");
|
||||
var _matcherHint = require("./matcherHint");
|
||||
/**
|
||||
* Copyright Microsoft Corporation. All rights reserved.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
async function toBeTruthy(matcherName, receiver, receiverType, expected, arg, query, options = {}) {
|
||||
var _options$timeout;
|
||||
(0, _util.expectTypes)(receiver, [receiverType], matcherName);
|
||||
const matcherOptions = {
|
||||
isNot: this.isNot,
|
||||
promise: this.promise
|
||||
};
|
||||
const timeout = (_options$timeout = options.timeout) !== null && _options$timeout !== void 0 ? _options$timeout : this.timeout;
|
||||
const {
|
||||
matches: pass,
|
||||
log,
|
||||
timedOut,
|
||||
received
|
||||
} = await query(!!this.isNot, timeout);
|
||||
if (pass === !this.isNot) {
|
||||
return {
|
||||
name: matcherName,
|
||||
message: () => '',
|
||||
pass,
|
||||
expected
|
||||
};
|
||||
}
|
||||
const notFound = received === _matcherHint.kNoElementsFoundError ? received : undefined;
|
||||
let printedReceived;
|
||||
let printedExpected;
|
||||
if (pass) {
|
||||
printedExpected = `Expected: not ${expected}`;
|
||||
printedReceived = `Received: ${notFound ? _matcherHint.kNoElementsFoundError : expected}`;
|
||||
} else {
|
||||
printedExpected = `Expected: ${expected}`;
|
||||
printedReceived = `Received: ${notFound ? _matcherHint.kNoElementsFoundError : received}`;
|
||||
}
|
||||
const message = () => {
|
||||
const header = (0, _matcherHint.matcherHint)(this, receiver, matcherName, 'locator', arg, matcherOptions, timedOut ? timeout : undefined);
|
||||
const logText = (0, _util.callLogText)(log);
|
||||
return `${header}${printedExpected}\n${printedReceived}${logText}`;
|
||||
};
|
||||
return {
|
||||
message,
|
||||
pass,
|
||||
actual: received,
|
||||
name: matcherName,
|
||||
expected,
|
||||
log,
|
||||
timeout: timedOut ? timeout : undefined
|
||||
};
|
||||
}
|
||||
85
node_modules/playwright/lib/matchers/toEqual.js
generated
vendored
Normal file
85
node_modules/playwright/lib/matchers/toEqual.js
generated
vendored
Normal file
@@ -0,0 +1,85 @@
|
||||
"use strict";
|
||||
|
||||
Object.defineProperty(exports, "__esModule", {
|
||||
value: true
|
||||
});
|
||||
exports.toEqual = toEqual;
|
||||
var _utils = require("playwright-core/lib/utils");
|
||||
var _util = require("../util");
|
||||
var _matcherHint = require("./matcherHint");
|
||||
/**
|
||||
* Copyright Microsoft Corporation. All rights reserved.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
// Omit colon and one or more spaces, so can call getLabelPrinter.
|
||||
const EXPECTED_LABEL = 'Expected';
|
||||
const RECEIVED_LABEL = 'Received';
|
||||
async function toEqual(matcherName, receiver, receiverType, query, expected, options = {}) {
|
||||
var _options$timeout;
|
||||
(0, _util.expectTypes)(receiver, [receiverType], matcherName);
|
||||
const matcherOptions = {
|
||||
comment: options.contains ? '' : 'deep equality',
|
||||
isNot: this.isNot,
|
||||
promise: this.promise
|
||||
};
|
||||
const timeout = (_options$timeout = options.timeout) !== null && _options$timeout !== void 0 ? _options$timeout : this.timeout;
|
||||
const {
|
||||
matches: pass,
|
||||
received,
|
||||
log,
|
||||
timedOut
|
||||
} = await query(!!this.isNot, timeout);
|
||||
if (pass === !this.isNot) {
|
||||
return {
|
||||
name: matcherName,
|
||||
message: () => '',
|
||||
pass,
|
||||
expected
|
||||
};
|
||||
}
|
||||
let printedReceived;
|
||||
let printedExpected;
|
||||
let printedDiff;
|
||||
if (pass) {
|
||||
printedExpected = `Expected: not ${this.utils.printExpected(expected)}`;
|
||||
printedReceived = `Received: ${this.utils.printReceived(received)}`;
|
||||
} else if (Array.isArray(expected) && Array.isArray(received)) {
|
||||
const normalizedExpected = expected.map((exp, index) => {
|
||||
const rec = received[index];
|
||||
if ((0, _utils.isRegExp)(exp)) return exp.test(rec) ? rec : exp;
|
||||
return exp;
|
||||
});
|
||||
printedDiff = this.utils.printDiffOrStringify(normalizedExpected, received, EXPECTED_LABEL, RECEIVED_LABEL, false);
|
||||
} else {
|
||||
printedDiff = this.utils.printDiffOrStringify(expected, received, EXPECTED_LABEL, RECEIVED_LABEL, false);
|
||||
}
|
||||
const message = () => {
|
||||
const header = (0, _matcherHint.matcherHint)(this, receiver, matcherName, 'locator', undefined, matcherOptions, timedOut ? timeout : undefined);
|
||||
const details = printedDiff || `${printedExpected}\n${printedReceived}`;
|
||||
return `${header}${details}${(0, _util.callLogText)(log)}`;
|
||||
};
|
||||
// Passing the actual and expected objects so that a custom reporter
|
||||
// could access them, for example in order to display a custom visual diff,
|
||||
// or create a different error message
|
||||
return {
|
||||
actual: received,
|
||||
expected,
|
||||
message,
|
||||
name: matcherName,
|
||||
pass,
|
||||
log,
|
||||
timeout: timedOut ? timeout : undefined
|
||||
};
|
||||
}
|
||||
96
node_modules/playwright/lib/matchers/toHaveURL.js
generated
vendored
Normal file
96
node_modules/playwright/lib/matchers/toHaveURL.js
generated
vendored
Normal file
@@ -0,0 +1,96 @@
|
||||
"use strict";
|
||||
|
||||
Object.defineProperty(exports, "__esModule", {
|
||||
value: true
|
||||
});
|
||||
exports.toHaveURLWithPredicate = toHaveURLWithPredicate;
|
||||
var _utils = require("playwright-core/lib/utils");
|
||||
var _expect = require("./expect");
|
||||
var _matcherHint = require("./matcherHint");
|
||||
var _expectBundle = require("../common/expectBundle");
|
||||
/**
|
||||
* Copyright (c) Microsoft Corporation.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
async function toHaveURLWithPredicate(page, expected, options) {
|
||||
var _options$timeout;
|
||||
const matcherName = 'toHaveURL';
|
||||
const expression = 'page';
|
||||
const matcherOptions = {
|
||||
isNot: this.isNot,
|
||||
promise: this.promise
|
||||
};
|
||||
if (typeof expected !== 'function') {
|
||||
throw new Error([
|
||||
// Always display `expected` in expectation place
|
||||
(0, _matcherHint.matcherHint)(this, undefined, matcherName, expression, undefined, matcherOptions), `${_utils.colors.bold('Matcher error')}: ${(0, _expectBundle.EXPECTED_COLOR)('expected')} value must be a string, regular expression, or predicate`, this.utils.printWithType('Expected', expected, this.utils.printExpected)].join('\n\n'));
|
||||
}
|
||||
const timeout = (_options$timeout = options === null || options === void 0 ? void 0 : options.timeout) !== null && _options$timeout !== void 0 ? _options$timeout : this.timeout;
|
||||
const baseURL = page.context()._options.baseURL;
|
||||
let conditionSucceeded = false;
|
||||
let lastCheckedURLString = undefined;
|
||||
try {
|
||||
await page.mainFrame().waitForURL(url => {
|
||||
lastCheckedURLString = url.toString();
|
||||
if (options !== null && options !== void 0 && options.ignoreCase) {
|
||||
return !this.isNot === (0, _utils.urlMatches)(baseURL === null || baseURL === void 0 ? void 0 : baseURL.toLocaleLowerCase(), lastCheckedURLString.toLocaleLowerCase(), expected);
|
||||
}
|
||||
return !this.isNot === (0, _utils.urlMatches)(baseURL, lastCheckedURLString, expected);
|
||||
}, {
|
||||
timeout
|
||||
});
|
||||
conditionSucceeded = true;
|
||||
} catch (e) {
|
||||
conditionSucceeded = false;
|
||||
}
|
||||
if (conditionSucceeded) return {
|
||||
name: matcherName,
|
||||
pass: !this.isNot,
|
||||
message: () => ''
|
||||
};
|
||||
return {
|
||||
name: matcherName,
|
||||
pass: this.isNot,
|
||||
message: () => toHaveURLMessage(this, matcherName, expression, expected, lastCheckedURLString, this.isNot, true, timeout),
|
||||
actual: lastCheckedURLString,
|
||||
timeout
|
||||
};
|
||||
}
|
||||
function toHaveURLMessage(state, matcherName, expression, expected, received, pass, didTimeout, timeout) {
|
||||
const matcherOptions = {
|
||||
isNot: state.isNot,
|
||||
promise: state.promise
|
||||
};
|
||||
const receivedString = received || '';
|
||||
const messagePrefix = (0, _matcherHint.matcherHint)(state, undefined, matcherName, expression, undefined, matcherOptions, didTimeout ? timeout : undefined);
|
||||
let printedReceived;
|
||||
let printedExpected;
|
||||
let printedDiff;
|
||||
if (typeof expected === 'function') {
|
||||
printedExpected = `Expected predicate to ${!state.isNot ? 'succeed' : 'fail'}`;
|
||||
printedReceived = `Received string: ${(0, _expectBundle.printReceived)(receivedString)}`;
|
||||
} else {
|
||||
if (pass) {
|
||||
printedExpected = `Expected pattern: not ${state.utils.printExpected(expected)}`;
|
||||
const formattedReceived = (0, _expect.printReceivedStringContainExpectedResult)(receivedString, null);
|
||||
printedReceived = `Received string: ${formattedReceived}`;
|
||||
} else {
|
||||
const labelExpected = `Expected ${typeof expected === 'string' ? 'string' : 'pattern'}`;
|
||||
printedDiff = state.utils.printDiffOrStringify(expected, receivedString, labelExpected, 'Received string', false);
|
||||
}
|
||||
}
|
||||
const resultDetails = printedDiff ? printedDiff : printedExpected + '\n' + printedReceived;
|
||||
return messagePrefix + resultDetails;
|
||||
}
|
||||
194
node_modules/playwright/lib/matchers/toMatchAriaSnapshot.js
generated
vendored
Normal file
194
node_modules/playwright/lib/matchers/toMatchAriaSnapshot.js
generated
vendored
Normal file
@@ -0,0 +1,194 @@
|
||||
"use strict";
|
||||
|
||||
Object.defineProperty(exports, "__esModule", {
|
||||
value: true
|
||||
});
|
||||
exports.toMatchAriaSnapshot = toMatchAriaSnapshot;
|
||||
var _fs = _interopRequireDefault(require("fs"));
|
||||
var _path = _interopRequireDefault(require("path"));
|
||||
var _utils = require("playwright-core/lib/utils");
|
||||
var _matcherHint = require("./matcherHint");
|
||||
var _expectBundle = require("../common/expectBundle");
|
||||
var _util = require("../util");
|
||||
var _expect = require("./expect");
|
||||
var _globals = require("../common/globals");
|
||||
function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
|
||||
/**
|
||||
* Copyright Microsoft Corporation. All rights reserved.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
async function toMatchAriaSnapshot(receiver, expectedParam, options = {}) {
|
||||
var _testInfo$_projectInt;
|
||||
const matcherName = 'toMatchAriaSnapshot';
|
||||
const testInfo = (0, _globals.currentTestInfo)();
|
||||
if (!testInfo) throw new Error(`toMatchAriaSnapshot() must be called during the test`);
|
||||
if (testInfo._projectInternal.ignoreSnapshots) return {
|
||||
pass: !this.isNot,
|
||||
message: () => '',
|
||||
name: 'toMatchAriaSnapshot',
|
||||
expected: ''
|
||||
};
|
||||
const updateSnapshots = testInfo.config.updateSnapshots;
|
||||
const pathTemplate = (_testInfo$_projectInt = testInfo._projectInternal.expect) === null || _testInfo$_projectInt === void 0 || (_testInfo$_projectInt = _testInfo$_projectInt.toMatchAriaSnapshot) === null || _testInfo$_projectInt === void 0 ? void 0 : _testInfo$_projectInt.pathTemplate;
|
||||
const defaultTemplate = '{snapshotDir}/{testFileDir}/{testFileName}-snapshots/{arg}{ext}';
|
||||
const matcherOptions = {
|
||||
isNot: this.isNot,
|
||||
promise: this.promise
|
||||
};
|
||||
let expected;
|
||||
let timeout;
|
||||
let expectedPath;
|
||||
if ((0, _utils.isString)(expectedParam)) {
|
||||
var _options$timeout;
|
||||
expected = expectedParam;
|
||||
timeout = (_options$timeout = options.timeout) !== null && _options$timeout !== void 0 ? _options$timeout : this.timeout;
|
||||
} else {
|
||||
var _expectedParam$timeou;
|
||||
if (expectedParam !== null && expectedParam !== void 0 && expectedParam.name) {
|
||||
const ext = expectedParam.name.endsWith('.aria.yml') ? '.aria.yml' : undefined;
|
||||
expectedPath = testInfo._resolveSnapshotPath(pathTemplate, defaultTemplate, [(0, _util.sanitizeFilePathBeforeExtension)(expectedParam.name, ext)]);
|
||||
} else {
|
||||
let snapshotNames = testInfo[snapshotNamesSymbol];
|
||||
if (!snapshotNames) {
|
||||
snapshotNames = {
|
||||
anonymousSnapshotIndex: 0
|
||||
};
|
||||
testInfo[snapshotNamesSymbol] = snapshotNames;
|
||||
}
|
||||
const fullTitleWithoutSpec = [...testInfo.titlePath.slice(1), ++snapshotNames.anonymousSnapshotIndex].join(' ');
|
||||
expectedPath = testInfo._resolveSnapshotPath(pathTemplate, defaultTemplate, [(0, _utils.sanitizeForFilePath)((0, _util.trimLongString)(fullTitleWithoutSpec))], '.aria.yml');
|
||||
// in 1.51, we changed the default template to use .aria.yml extension
|
||||
// for backwards compatibility, we check for the legacy .yml extension
|
||||
if (!(await (0, _util.fileExistsAsync)(expectedPath))) {
|
||||
const legacyPath = testInfo._resolveSnapshotPath(pathTemplate, defaultTemplate, [(0, _utils.sanitizeForFilePath)((0, _util.trimLongString)(fullTitleWithoutSpec))], '.yml');
|
||||
if (await (0, _util.fileExistsAsync)(legacyPath)) expectedPath = legacyPath;
|
||||
}
|
||||
}
|
||||
expected = await _fs.default.promises.readFile(expectedPath, 'utf8').catch(() => '');
|
||||
timeout = (_expectedParam$timeou = expectedParam === null || expectedParam === void 0 ? void 0 : expectedParam.timeout) !== null && _expectedParam$timeou !== void 0 ? _expectedParam$timeou : this.timeout;
|
||||
}
|
||||
const generateMissingBaseline = updateSnapshots === 'missing' && !expected;
|
||||
if (generateMissingBaseline) {
|
||||
if (this.isNot) {
|
||||
const message = `Matchers using ".not" can't generate new baselines`;
|
||||
return {
|
||||
pass: this.isNot,
|
||||
message: () => message,
|
||||
name: 'toMatchAriaSnapshot'
|
||||
};
|
||||
} else {
|
||||
// When generating new baseline, run entire pipeline against impossible match.
|
||||
expected = `- none "Generating new baseline"`;
|
||||
}
|
||||
}
|
||||
expected = unshift(expected);
|
||||
const {
|
||||
matches: pass,
|
||||
received,
|
||||
log,
|
||||
timedOut
|
||||
} = await receiver._expect('to.match.aria', {
|
||||
expectedValue: expected,
|
||||
isNot: this.isNot,
|
||||
timeout
|
||||
});
|
||||
const typedReceived = received;
|
||||
const messagePrefix = (0, _matcherHint.matcherHint)(this, receiver, matcherName, 'locator', undefined, matcherOptions, timedOut ? timeout : undefined);
|
||||
const notFound = typedReceived === _matcherHint.kNoElementsFoundError;
|
||||
if (notFound) {
|
||||
return {
|
||||
pass: this.isNot,
|
||||
message: () => messagePrefix + `Expected: ${this.utils.printExpected(expected)}\nReceived: ${(0, _expectBundle.EXPECTED_COLOR)('<element not found>')}` + (0, _util.callLogText)(log),
|
||||
name: 'toMatchAriaSnapshot',
|
||||
expected
|
||||
};
|
||||
}
|
||||
const receivedText = typedReceived.raw;
|
||||
const message = () => {
|
||||
if (pass) {
|
||||
if (notFound) return messagePrefix + `Expected: not ${this.utils.printExpected(expected)}\nReceived: ${receivedText}` + (0, _util.callLogText)(log);
|
||||
const printedReceived = (0, _expect.printReceivedStringContainExpectedSubstring)(receivedText, receivedText.indexOf(expected), expected.length);
|
||||
return messagePrefix + `Expected: not ${this.utils.printExpected(expected)}\nReceived: ${printedReceived}` + (0, _util.callLogText)(log);
|
||||
} else {
|
||||
const labelExpected = `Expected`;
|
||||
if (notFound) return messagePrefix + `${labelExpected}: ${this.utils.printExpected(expected)}\nReceived: ${receivedText}` + (0, _util.callLogText)(log);
|
||||
return messagePrefix + this.utils.printDiffOrStringify(expected, receivedText, labelExpected, 'Received', false) + (0, _util.callLogText)(log);
|
||||
}
|
||||
};
|
||||
if (!this.isNot) {
|
||||
if (updateSnapshots === 'all' || updateSnapshots === 'changed' && pass === this.isNot || generateMissingBaseline) {
|
||||
if (expectedPath) {
|
||||
await _fs.default.promises.mkdir(_path.default.dirname(expectedPath), {
|
||||
recursive: true
|
||||
});
|
||||
await _fs.default.promises.writeFile(expectedPath, typedReceived.regex, 'utf8');
|
||||
const relativePath = _path.default.relative(process.cwd(), expectedPath);
|
||||
if (updateSnapshots === 'missing') {
|
||||
const message = `A snapshot doesn't exist at ${relativePath}, writing actual.`;
|
||||
testInfo._hasNonRetriableError = true;
|
||||
testInfo._failWithError(new Error(message));
|
||||
} else {
|
||||
const message = `A snapshot is generated at ${relativePath}.`;
|
||||
/* eslint-disable no-console */
|
||||
console.log(message);
|
||||
}
|
||||
return {
|
||||
pass: true,
|
||||
message: () => '',
|
||||
name: 'toMatchAriaSnapshot'
|
||||
};
|
||||
} else {
|
||||
const suggestedRebaseline = `\`\n${(0, _utils.escapeTemplateString)(indent(typedReceived.regex, '{indent} '))}\n{indent}\``;
|
||||
if (updateSnapshots === 'missing') {
|
||||
const message = 'A snapshot is not provided, generating new baseline.';
|
||||
testInfo._hasNonRetriableError = true;
|
||||
testInfo._failWithError(new Error(message));
|
||||
}
|
||||
// TODO: ideally, we should return "pass: true" here because this matcher passes
|
||||
// when regenerating baselines. However, we can only access suggestedRebaseline in case
|
||||
// of an error, so we fail here and workaround it in the expect implementation.
|
||||
return {
|
||||
pass: false,
|
||||
message: () => '',
|
||||
name: 'toMatchAriaSnapshot',
|
||||
suggestedRebaseline
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
return {
|
||||
name: matcherName,
|
||||
expected,
|
||||
message,
|
||||
pass,
|
||||
actual: received,
|
||||
log,
|
||||
timeout: timedOut ? timeout : undefined
|
||||
};
|
||||
}
|
||||
function unshift(snapshot) {
|
||||
const lines = snapshot.split('\n');
|
||||
let whitespacePrefixLength = 100;
|
||||
for (const line of lines) {
|
||||
if (!line.trim()) continue;
|
||||
const match = line.match(/^(\s*)/);
|
||||
if (match && match[1].length < whitespacePrefixLength) whitespacePrefixLength = match[1].length;
|
||||
}
|
||||
return lines.filter(t => t.trim()).map(line => line.substring(whitespacePrefixLength)).join('\n');
|
||||
}
|
||||
function indent(snapshot, indent) {
|
||||
return snapshot.split('\n').map(line => indent + line).join('\n');
|
||||
}
|
||||
const snapshotNamesSymbol = Symbol('snapshotNames');
|
||||
412
node_modules/playwright/lib/matchers/toMatchSnapshot.js
generated
vendored
Normal file
412
node_modules/playwright/lib/matchers/toMatchSnapshot.js
generated
vendored
Normal file
@@ -0,0 +1,412 @@
|
||||
"use strict";
|
||||
|
||||
Object.defineProperty(exports, "__esModule", {
|
||||
value: true
|
||||
});
|
||||
exports.toHaveScreenshot = toHaveScreenshot;
|
||||
exports.toHaveScreenshotStepTitle = toHaveScreenshotStepTitle;
|
||||
exports.toMatchSnapshot = toMatchSnapshot;
|
||||
var _fs = _interopRequireDefault(require("fs"));
|
||||
var _path = _interopRequireDefault(require("path"));
|
||||
var _utils = require("playwright-core/lib/utils");
|
||||
var _utilsBundle = require("playwright-core/lib/utilsBundle");
|
||||
var _util = require("../util");
|
||||
var _matcherHint = require("./matcherHint");
|
||||
var _globals = require("../common/globals");
|
||||
function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
|
||||
/**
|
||||
* Copyright Microsoft Corporation. All rights reserved.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
const snapshotNamesSymbol = Symbol('snapshotNames');
|
||||
// Keep in sync with above (begin).
|
||||
const NonConfigProperties = ['clip', 'fullPage', 'mask', 'maskColor', 'omitBackground', 'timeout'];
|
||||
// Keep in sync with above (end).
|
||||
|
||||
class SnapshotHelper {
|
||||
constructor(testInfo, matcherName, locator, anonymousSnapshotExtension, configOptions, nameOrOptions, optOptions) {
|
||||
var _mime$getType;
|
||||
this.testInfo = void 0;
|
||||
this.attachmentBaseName = void 0;
|
||||
this.legacyExpectedPath = void 0;
|
||||
this.previousPath = void 0;
|
||||
this.expectedPath = void 0;
|
||||
this.actualPath = void 0;
|
||||
this.diffPath = void 0;
|
||||
this.mimeType = void 0;
|
||||
this.kind = void 0;
|
||||
this.updateSnapshots = void 0;
|
||||
this.comparator = void 0;
|
||||
this.options = void 0;
|
||||
this.matcherName = void 0;
|
||||
this.locator = void 0;
|
||||
let name;
|
||||
if (Array.isArray(nameOrOptions) || typeof nameOrOptions === 'string') {
|
||||
name = nameOrOptions;
|
||||
this.options = {
|
||||
...optOptions
|
||||
};
|
||||
} else {
|
||||
const {
|
||||
name: nameFromOptions,
|
||||
...options
|
||||
} = nameOrOptions;
|
||||
this.options = options;
|
||||
name = nameFromOptions;
|
||||
}
|
||||
let snapshotNames = testInfo[snapshotNamesSymbol];
|
||||
if (!testInfo[snapshotNamesSymbol]) {
|
||||
snapshotNames = {
|
||||
anonymousSnapshotIndex: 0,
|
||||
namedSnapshotIndex: {}
|
||||
};
|
||||
testInfo[snapshotNamesSymbol] = snapshotNames;
|
||||
}
|
||||
let expectedPathSegments;
|
||||
let outputBasePath;
|
||||
if (!name) {
|
||||
// Consider the use case below. We should save actual to different paths.
|
||||
// Therefore we auto-increment |anonymousSnapshotIndex|.
|
||||
//
|
||||
// expect.toMatchSnapshot('a.png')
|
||||
// // noop
|
||||
// expect.toMatchSnapshot('a.png')
|
||||
const fullTitleWithoutSpec = [...testInfo.titlePath.slice(1), ++snapshotNames.anonymousSnapshotIndex].join(' ');
|
||||
// Note: expected path must not ever change for backwards compatibility.
|
||||
expectedPathSegments = [(0, _utils.sanitizeForFilePath)((0, _util.trimLongString)(fullTitleWithoutSpec)) + '.' + anonymousSnapshotExtension];
|
||||
// Trim the output file paths more aggressively to avoid hitting Windows filesystem limits.
|
||||
const sanitizedName = (0, _utils.sanitizeForFilePath)((0, _util.trimLongString)(fullTitleWithoutSpec, _util.windowsFilesystemFriendlyLength)) + '.' + anonymousSnapshotExtension;
|
||||
outputBasePath = testInfo._getOutputPath(sanitizedName);
|
||||
this.attachmentBaseName = sanitizedName;
|
||||
} else {
|
||||
// We intentionally do not sanitize user-provided array of segments, assuming
|
||||
// it is a file system path. See https://github.com/microsoft/playwright/pull/9156.
|
||||
// Note: expected path must not ever change for backwards compatibility.
|
||||
expectedPathSegments = Array.isArray(name) ? name : [(0, _util.sanitizeFilePathBeforeExtension)(name)];
|
||||
const joinedName = Array.isArray(name) ? name.join(_path.default.sep) : (0, _util.sanitizeFilePathBeforeExtension)((0, _util.trimLongString)(name, _util.windowsFilesystemFriendlyLength));
|
||||
snapshotNames.namedSnapshotIndex[joinedName] = (snapshotNames.namedSnapshotIndex[joinedName] || 0) + 1;
|
||||
const index = snapshotNames.namedSnapshotIndex[joinedName];
|
||||
const sanitizedName = index > 1 ? (0, _util.addSuffixToFilePath)(joinedName, `-${index - 1}`) : joinedName;
|
||||
outputBasePath = testInfo._getOutputPath(sanitizedName);
|
||||
this.attachmentBaseName = sanitizedName;
|
||||
}
|
||||
const defaultTemplate = '{snapshotDir}/{testFileDir}/{testFileName}-snapshots/{arg}{-projectName}{-snapshotSuffix}{ext}';
|
||||
this.expectedPath = testInfo._resolveSnapshotPath(configOptions.pathTemplate, defaultTemplate, expectedPathSegments);
|
||||
this.legacyExpectedPath = (0, _util.addSuffixToFilePath)(outputBasePath, '-expected');
|
||||
this.previousPath = (0, _util.addSuffixToFilePath)(outputBasePath, '-previous');
|
||||
this.actualPath = (0, _util.addSuffixToFilePath)(outputBasePath, '-actual');
|
||||
this.diffPath = (0, _util.addSuffixToFilePath)(outputBasePath, '-diff');
|
||||
const filteredConfigOptions = {
|
||||
...configOptions
|
||||
};
|
||||
for (const prop of NonConfigProperties) delete filteredConfigOptions[prop];
|
||||
this.options = {
|
||||
...filteredConfigOptions,
|
||||
...this.options
|
||||
};
|
||||
|
||||
// While comparator is not a part of the public API, it is translated here.
|
||||
if (this.options._comparator) {
|
||||
this.options.comparator = this.options._comparator;
|
||||
delete this.options._comparator;
|
||||
}
|
||||
if (this.options.maxDiffPixels !== undefined && this.options.maxDiffPixels < 0) throw new Error('`maxDiffPixels` option value must be non-negative integer');
|
||||
if (this.options.maxDiffPixelRatio !== undefined && (this.options.maxDiffPixelRatio < 0 || this.options.maxDiffPixelRatio > 1)) throw new Error('`maxDiffPixelRatio` option value must be between 0 and 1');
|
||||
this.matcherName = matcherName;
|
||||
this.locator = locator;
|
||||
this.updateSnapshots = testInfo.config.updateSnapshots;
|
||||
this.mimeType = (_mime$getType = _utilsBundle.mime.getType(_path.default.basename(this.expectedPath))) !== null && _mime$getType !== void 0 ? _mime$getType : 'application/octet-string';
|
||||
this.comparator = (0, _utils.getComparator)(this.mimeType);
|
||||
this.testInfo = testInfo;
|
||||
this.kind = this.mimeType.startsWith('image/') ? 'Screenshot' : 'Snapshot';
|
||||
}
|
||||
createMatcherResult(message, pass, log) {
|
||||
const unfiltered = {
|
||||
name: this.matcherName,
|
||||
expected: this.expectedPath,
|
||||
actual: this.actualPath,
|
||||
diff: this.diffPath,
|
||||
pass,
|
||||
message: () => message,
|
||||
log
|
||||
};
|
||||
return Object.fromEntries(Object.entries(unfiltered).filter(([_, v]) => v !== undefined));
|
||||
}
|
||||
handleMissingNegated() {
|
||||
const isWriteMissingMode = this.updateSnapshots !== 'none';
|
||||
const message = `A snapshot doesn't exist at ${this.expectedPath}${isWriteMissingMode ? ', matchers using ".not" won\'t write them automatically.' : '.'}`;
|
||||
// NOTE: 'isNot' matcher implies inversed value.
|
||||
return this.createMatcherResult(message, true);
|
||||
}
|
||||
handleDifferentNegated() {
|
||||
// NOTE: 'isNot' matcher implies inversed value.
|
||||
return this.createMatcherResult('', false);
|
||||
}
|
||||
handleMatchingNegated() {
|
||||
const message = [_utils.colors.red(`${this.kind} comparison failed:`), '', indent('Expected result should be different from the actual one.', ' ')].join('\n');
|
||||
// NOTE: 'isNot' matcher implies inversed value.
|
||||
return this.createMatcherResult(message, true);
|
||||
}
|
||||
handleMissing(actual, step) {
|
||||
const isWriteMissingMode = this.updateSnapshots !== 'none';
|
||||
if (isWriteMissingMode) writeFileSync(this.expectedPath, actual);
|
||||
step === null || step === void 0 || step._attachToStep({
|
||||
name: (0, _util.addSuffixToFilePath)(this.attachmentBaseName, '-expected'),
|
||||
contentType: this.mimeType,
|
||||
path: this.expectedPath
|
||||
});
|
||||
writeFileSync(this.actualPath, actual);
|
||||
step === null || step === void 0 || step._attachToStep({
|
||||
name: (0, _util.addSuffixToFilePath)(this.attachmentBaseName, '-actual'),
|
||||
contentType: this.mimeType,
|
||||
path: this.actualPath
|
||||
});
|
||||
const message = `A snapshot doesn't exist at ${this.expectedPath}${isWriteMissingMode ? ', writing actual.' : '.'}`;
|
||||
if (this.updateSnapshots === 'all' || this.updateSnapshots === 'changed') {
|
||||
/* eslint-disable no-console */
|
||||
console.log(message);
|
||||
return this.createMatcherResult(message, true);
|
||||
}
|
||||
if (this.updateSnapshots === 'missing') {
|
||||
this.testInfo._hasNonRetriableError = true;
|
||||
this.testInfo._failWithError(new Error(message));
|
||||
return this.createMatcherResult('', true);
|
||||
}
|
||||
return this.createMatcherResult(message, false);
|
||||
}
|
||||
handleDifferent(actual, expected, previous, diff, header, diffError, log, step) {
|
||||
const output = [`${header}${indent(diffError, ' ')}`];
|
||||
if (expected !== undefined) {
|
||||
// Copy the expectation inside the `test-results/` folder for backwards compatibility,
|
||||
// so that one can upload `test-results/` directory and have all the data inside.
|
||||
writeFileSync(this.legacyExpectedPath, expected);
|
||||
step === null || step === void 0 || step._attachToStep({
|
||||
name: (0, _util.addSuffixToFilePath)(this.attachmentBaseName, '-expected'),
|
||||
contentType: this.mimeType,
|
||||
path: this.expectedPath
|
||||
});
|
||||
output.push(`\nExpected: ${_utils.colors.yellow(this.expectedPath)}`);
|
||||
}
|
||||
if (previous !== undefined) {
|
||||
writeFileSync(this.previousPath, previous);
|
||||
step === null || step === void 0 || step._attachToStep({
|
||||
name: (0, _util.addSuffixToFilePath)(this.attachmentBaseName, '-previous'),
|
||||
contentType: this.mimeType,
|
||||
path: this.previousPath
|
||||
});
|
||||
output.push(`Previous: ${_utils.colors.yellow(this.previousPath)}`);
|
||||
}
|
||||
if (actual !== undefined) {
|
||||
writeFileSync(this.actualPath, actual);
|
||||
step === null || step === void 0 || step._attachToStep({
|
||||
name: (0, _util.addSuffixToFilePath)(this.attachmentBaseName, '-actual'),
|
||||
contentType: this.mimeType,
|
||||
path: this.actualPath
|
||||
});
|
||||
output.push(`Received: ${_utils.colors.yellow(this.actualPath)}`);
|
||||
}
|
||||
if (diff !== undefined) {
|
||||
writeFileSync(this.diffPath, diff);
|
||||
step === null || step === void 0 || step._attachToStep({
|
||||
name: (0, _util.addSuffixToFilePath)(this.attachmentBaseName, '-diff'),
|
||||
contentType: this.mimeType,
|
||||
path: this.diffPath
|
||||
});
|
||||
output.push(` Diff: ${_utils.colors.yellow(this.diffPath)}`);
|
||||
}
|
||||
if (log !== null && log !== void 0 && log.length) output.push((0, _util.callLogText)(log));else output.push('');
|
||||
return this.createMatcherResult(output.join('\n'), false, log);
|
||||
}
|
||||
handleMatching() {
|
||||
return this.createMatcherResult('', true);
|
||||
}
|
||||
}
|
||||
function toMatchSnapshot(received, nameOrOptions = {}, optOptions = {}) {
|
||||
var _testInfo$_projectInt;
|
||||
const testInfo = (0, _globals.currentTestInfo)();
|
||||
if (!testInfo) throw new Error(`toMatchSnapshot() must be called during the test`);
|
||||
if (received instanceof Promise) throw new Error('An unresolved Promise was passed to toMatchSnapshot(), make sure to resolve it by adding await to it.');
|
||||
if (testInfo._projectInternal.ignoreSnapshots) return {
|
||||
pass: !this.isNot,
|
||||
message: () => '',
|
||||
name: 'toMatchSnapshot',
|
||||
expected: nameOrOptions
|
||||
};
|
||||
const configOptions = ((_testInfo$_projectInt = testInfo._projectInternal.expect) === null || _testInfo$_projectInt === void 0 ? void 0 : _testInfo$_projectInt.toMatchSnapshot) || {};
|
||||
const helper = new SnapshotHelper(testInfo, 'toMatchSnapshot', undefined, determineFileExtension(received), configOptions, nameOrOptions, optOptions);
|
||||
if (this.isNot) {
|
||||
if (!_fs.default.existsSync(helper.expectedPath)) return helper.handleMissingNegated();
|
||||
const isDifferent = !!helper.comparator(received, _fs.default.readFileSync(helper.expectedPath), helper.options);
|
||||
return isDifferent ? helper.handleDifferentNegated() : helper.handleMatchingNegated();
|
||||
}
|
||||
if (!_fs.default.existsSync(helper.expectedPath)) return helper.handleMissing(received, this._stepInfo);
|
||||
const expected = _fs.default.readFileSync(helper.expectedPath);
|
||||
if (helper.updateSnapshots === 'all') {
|
||||
if (!(0, _utils.compareBuffersOrStrings)(received, expected)) return helper.handleMatching();
|
||||
writeFileSync(helper.expectedPath, received);
|
||||
/* eslint-disable no-console */
|
||||
console.log(helper.expectedPath + ' is not the same, writing actual.');
|
||||
return helper.createMatcherResult(helper.expectedPath + ' running with --update-snapshots, writing actual.', true);
|
||||
}
|
||||
if (helper.updateSnapshots === 'changed') {
|
||||
const result = helper.comparator(received, expected, helper.options);
|
||||
if (!result) return helper.handleMatching();
|
||||
writeFileSync(helper.expectedPath, received);
|
||||
/* eslint-disable no-console */
|
||||
console.log(helper.expectedPath + ' does not match, writing actual.');
|
||||
return helper.createMatcherResult(helper.expectedPath + ' running with --update-snapshots, writing actual.', true);
|
||||
}
|
||||
const result = helper.comparator(received, expected, helper.options);
|
||||
if (!result) return helper.handleMatching();
|
||||
const receiver = (0, _utils.isString)(received) ? 'string' : 'Buffer';
|
||||
const header = (0, _matcherHint.matcherHint)(this, undefined, 'toMatchSnapshot', receiver, undefined, undefined);
|
||||
return helper.handleDifferent(received, expected, undefined, result.diff, header, result.errorMessage, undefined, this._stepInfo);
|
||||
}
|
||||
function toHaveScreenshotStepTitle(nameOrOptions = {}, optOptions = {}) {
|
||||
let name;
|
||||
if (typeof nameOrOptions === 'object' && !Array.isArray(nameOrOptions)) name = nameOrOptions.name;else name = nameOrOptions;
|
||||
return Array.isArray(name) ? name.join(_path.default.sep) : name || '';
|
||||
}
|
||||
async function toHaveScreenshot(pageOrLocator, nameOrOptions = {}, optOptions = {}) {
|
||||
var _testInfo$_projectInt2, _helper$options$timeo, _helper$options$anima, _helper$options$caret, _helper$options$scale;
|
||||
const testInfo = (0, _globals.currentTestInfo)();
|
||||
if (!testInfo) throw new Error(`toHaveScreenshot() must be called during the test`);
|
||||
if (testInfo._projectInternal.ignoreSnapshots) return {
|
||||
pass: !this.isNot,
|
||||
message: () => '',
|
||||
name: 'toHaveScreenshot',
|
||||
expected: nameOrOptions
|
||||
};
|
||||
(0, _util.expectTypes)(pageOrLocator, ['Page', 'Locator'], 'toHaveScreenshot');
|
||||
const [page, locator] = pageOrLocator.constructor.name === 'Page' ? [pageOrLocator, undefined] : [pageOrLocator.page(), pageOrLocator];
|
||||
const configOptions = ((_testInfo$_projectInt2 = testInfo._projectInternal.expect) === null || _testInfo$_projectInt2 === void 0 ? void 0 : _testInfo$_projectInt2.toHaveScreenshot) || {};
|
||||
const helper = new SnapshotHelper(testInfo, 'toHaveScreenshot', locator, 'png', configOptions, nameOrOptions, optOptions);
|
||||
if (!helper.expectedPath.toLowerCase().endsWith('.png')) throw new Error(`Screenshot name "${_path.default.basename(helper.expectedPath)}" must have '.png' extension`);
|
||||
(0, _util.expectTypes)(pageOrLocator, ['Page', 'Locator'], 'toHaveScreenshot');
|
||||
const style = await loadScreenshotStyles(helper.options.stylePath);
|
||||
const timeout = (_helper$options$timeo = helper.options.timeout) !== null && _helper$options$timeo !== void 0 ? _helper$options$timeo : this.timeout;
|
||||
const expectScreenshotOptions = {
|
||||
locator,
|
||||
animations: (_helper$options$anima = helper.options.animations) !== null && _helper$options$anima !== void 0 ? _helper$options$anima : 'disabled',
|
||||
caret: (_helper$options$caret = helper.options.caret) !== null && _helper$options$caret !== void 0 ? _helper$options$caret : 'hide',
|
||||
clip: helper.options.clip,
|
||||
fullPage: helper.options.fullPage,
|
||||
mask: helper.options.mask,
|
||||
maskColor: helper.options.maskColor,
|
||||
omitBackground: helper.options.omitBackground,
|
||||
scale: (_helper$options$scale = helper.options.scale) !== null && _helper$options$scale !== void 0 ? _helper$options$scale : 'css',
|
||||
style,
|
||||
isNot: !!this.isNot,
|
||||
timeout,
|
||||
comparator: helper.options.comparator,
|
||||
maxDiffPixels: helper.options.maxDiffPixels,
|
||||
maxDiffPixelRatio: helper.options.maxDiffPixelRatio,
|
||||
threshold: helper.options.threshold
|
||||
};
|
||||
const hasSnapshot = _fs.default.existsSync(helper.expectedPath);
|
||||
if (this.isNot) {
|
||||
if (!hasSnapshot) return helper.handleMissingNegated();
|
||||
|
||||
// Having `errorMessage` means we timed out while waiting
|
||||
// for screenshots not to match, so screenshots
|
||||
// are actually the same in the end.
|
||||
expectScreenshotOptions.expected = await _fs.default.promises.readFile(helper.expectedPath);
|
||||
const isDifferent = !(await page._expectScreenshot(expectScreenshotOptions)).errorMessage;
|
||||
return isDifferent ? helper.handleDifferentNegated() : helper.handleMatchingNegated();
|
||||
}
|
||||
|
||||
// Fast path: there's no screenshot and we don't intend to update it.
|
||||
if (helper.updateSnapshots === 'none' && !hasSnapshot) return helper.createMatcherResult(`A snapshot doesn't exist at ${helper.expectedPath}.`, false);
|
||||
const receiver = locator ? 'locator' : 'page';
|
||||
if (!hasSnapshot) {
|
||||
// Regenerate a new screenshot by waiting until two screenshots are the same.
|
||||
const {
|
||||
actual,
|
||||
previous,
|
||||
diff,
|
||||
errorMessage,
|
||||
log,
|
||||
timedOut
|
||||
} = await page._expectScreenshot(expectScreenshotOptions);
|
||||
// We tried re-generating new snapshot but failed.
|
||||
// This can be due to e.g. spinning animation, so we want to show it as a diff.
|
||||
if (errorMessage) {
|
||||
const header = (0, _matcherHint.matcherHint)(this, locator, 'toHaveScreenshot', receiver, undefined, undefined, timedOut ? timeout : undefined);
|
||||
return helper.handleDifferent(actual, undefined, previous, diff, header, errorMessage, log, this._stepInfo);
|
||||
}
|
||||
|
||||
// We successfully generated new screenshot.
|
||||
return helper.handleMissing(actual, this._stepInfo);
|
||||
}
|
||||
|
||||
// General case:
|
||||
// - snapshot exists
|
||||
// - regular matcher (i.e. not a `.not`)
|
||||
const expected = await _fs.default.promises.readFile(helper.expectedPath);
|
||||
expectScreenshotOptions.expected = helper.updateSnapshots === 'all' ? undefined : expected;
|
||||
const {
|
||||
actual,
|
||||
previous,
|
||||
diff,
|
||||
errorMessage,
|
||||
log,
|
||||
timedOut
|
||||
} = await page._expectScreenshot(expectScreenshotOptions);
|
||||
const writeFiles = () => {
|
||||
writeFileSync(helper.expectedPath, actual);
|
||||
writeFileSync(helper.actualPath, actual);
|
||||
/* eslint-disable no-console */
|
||||
console.log(helper.expectedPath + ' is re-generated, writing actual.');
|
||||
return helper.createMatcherResult(helper.expectedPath + ' running with --update-snapshots, writing actual.', true);
|
||||
};
|
||||
if (!errorMessage) {
|
||||
// Screenshot is matching, but is not necessarily the same as the expected.
|
||||
if (helper.updateSnapshots === 'all' && actual && (0, _utils.compareBuffersOrStrings)(actual, expected)) {
|
||||
console.log(helper.expectedPath + ' is re-generated, writing actual.');
|
||||
return writeFiles();
|
||||
}
|
||||
return helper.handleMatching();
|
||||
}
|
||||
if (helper.updateSnapshots === 'changed' || helper.updateSnapshots === 'all') return writeFiles();
|
||||
const header = (0, _matcherHint.matcherHint)(this, undefined, 'toHaveScreenshot', receiver, undefined, undefined, timedOut ? timeout : undefined);
|
||||
return helper.handleDifferent(actual, expectScreenshotOptions.expected, previous, diff, header, errorMessage, log, this._stepInfo);
|
||||
}
|
||||
function writeFileSync(aPath, content) {
|
||||
_fs.default.mkdirSync(_path.default.dirname(aPath), {
|
||||
recursive: true
|
||||
});
|
||||
_fs.default.writeFileSync(aPath, content);
|
||||
}
|
||||
function indent(lines, tab) {
|
||||
return lines.replace(/^(?=.+$)/gm, tab);
|
||||
}
|
||||
function determineFileExtension(file) {
|
||||
if (typeof file === 'string') return 'txt';
|
||||
if (compareMagicBytes(file, [0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a])) return 'png';
|
||||
if (compareMagicBytes(file, [0xff, 0xd8, 0xff])) return 'jpg';
|
||||
return 'dat';
|
||||
}
|
||||
function compareMagicBytes(file, magicBytes) {
|
||||
return Buffer.compare(Buffer.from(magicBytes), file.slice(0, magicBytes.length)) === 0;
|
||||
}
|
||||
async function loadScreenshotStyles(stylePath) {
|
||||
if (!stylePath) return;
|
||||
const stylePaths = Array.isArray(stylePath) ? stylePath : [stylePath];
|
||||
const styles = await Promise.all(stylePaths.map(async stylePath => {
|
||||
const text = await _fs.default.promises.readFile(stylePath, 'utf8');
|
||||
return text.trim();
|
||||
}));
|
||||
return styles.join('\n').trim() || undefined;
|
||||
}
|
||||
103
node_modules/playwright/lib/matchers/toMatchText.js
generated
vendored
Normal file
103
node_modules/playwright/lib/matchers/toMatchText.js
generated
vendored
Normal file
@@ -0,0 +1,103 @@
|
||||
"use strict";
|
||||
|
||||
Object.defineProperty(exports, "__esModule", {
|
||||
value: true
|
||||
});
|
||||
exports.toMatchText = toMatchText;
|
||||
var _utils = require("playwright-core/lib/utils");
|
||||
var _util = require("../util");
|
||||
var _expect = require("./expect");
|
||||
var _matcherHint = require("./matcherHint");
|
||||
var _expectBundle = require("../common/expectBundle");
|
||||
/**
|
||||
* Copyright Microsoft Corporation. All rights reserved.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
async function toMatchText(matcherName, receiver, receiverType, query, expected, options = {}) {
|
||||
var _options$timeout;
|
||||
(0, _util.expectTypes)(receiver, [receiverType], matcherName);
|
||||
const matcherOptions = {
|
||||
isNot: this.isNot,
|
||||
promise: this.promise
|
||||
};
|
||||
if (!(typeof expected === 'string') && !(expected && typeof expected.test === 'function')) {
|
||||
// Same format as jest's matcherErrorMessage
|
||||
throw new Error([(0, _matcherHint.matcherHint)(this, receiver, matcherName, receiver, expected, matcherOptions), `${_utils.colors.bold('Matcher error')}: ${(0, _expectBundle.EXPECTED_COLOR)('expected')} value must be a string or regular expression`, this.utils.printWithType('Expected', expected, this.utils.printExpected)].join('\n\n'));
|
||||
}
|
||||
const timeout = (_options$timeout = options.timeout) !== null && _options$timeout !== void 0 ? _options$timeout : this.timeout;
|
||||
const {
|
||||
matches: pass,
|
||||
received,
|
||||
log,
|
||||
timedOut
|
||||
} = await query(!!this.isNot, timeout);
|
||||
if (pass === !this.isNot) {
|
||||
return {
|
||||
name: matcherName,
|
||||
message: () => '',
|
||||
pass,
|
||||
expected
|
||||
};
|
||||
}
|
||||
const stringSubstring = options.matchSubstring ? 'substring' : 'string';
|
||||
const receivedString = received || '';
|
||||
const messagePrefix = (0, _matcherHint.matcherHint)(this, receiver, matcherName, 'locator', undefined, matcherOptions, timedOut ? timeout : undefined);
|
||||
const notFound = received === _matcherHint.kNoElementsFoundError;
|
||||
let printedReceived;
|
||||
let printedExpected;
|
||||
let printedDiff;
|
||||
if (pass) {
|
||||
if (typeof expected === 'string') {
|
||||
if (notFound) {
|
||||
printedExpected = `Expected ${stringSubstring}: not ${this.utils.printExpected(expected)}`;
|
||||
printedReceived = `Received: ${received}`;
|
||||
} else {
|
||||
printedExpected = `Expected ${stringSubstring}: not ${this.utils.printExpected(expected)}`;
|
||||
const formattedReceived = (0, _expect.printReceivedStringContainExpectedSubstring)(receivedString, receivedString.indexOf(expected), expected.length);
|
||||
printedReceived = `Received string: ${formattedReceived}`;
|
||||
}
|
||||
} else {
|
||||
if (notFound) {
|
||||
printedExpected = `Expected pattern: not ${this.utils.printExpected(expected)}`;
|
||||
printedReceived = `Received: ${received}`;
|
||||
} else {
|
||||
printedExpected = `Expected pattern: not ${this.utils.printExpected(expected)}`;
|
||||
const formattedReceived = (0, _expect.printReceivedStringContainExpectedResult)(receivedString, typeof expected.exec === 'function' ? expected.exec(receivedString) : null);
|
||||
printedReceived = `Received string: ${formattedReceived}`;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
const labelExpected = `Expected ${typeof expected === 'string' ? stringSubstring : 'pattern'}`;
|
||||
if (notFound) {
|
||||
printedExpected = `${labelExpected}: ${this.utils.printExpected(expected)}`;
|
||||
printedReceived = `Received: ${received}`;
|
||||
} else {
|
||||
printedDiff = this.utils.printDiffOrStringify(expected, receivedString, labelExpected, 'Received string', false);
|
||||
}
|
||||
}
|
||||
const message = () => {
|
||||
const resultDetails = printedDiff ? printedDiff : printedExpected + '\n' + printedReceived;
|
||||
return messagePrefix + resultDetails + (0, _util.callLogText)(log);
|
||||
};
|
||||
return {
|
||||
name: matcherName,
|
||||
expected,
|
||||
message,
|
||||
pass,
|
||||
actual: received,
|
||||
log,
|
||||
timeout: timedOut ? timeout : undefined
|
||||
};
|
||||
}
|
||||
Reference in New Issue
Block a user