This commit is contained in:
Iliyan Angelov
2025-09-14 23:24:25 +03:00
commit c67067a2a4
71311 changed files with 6800714 additions and 0 deletions

View File

@@ -0,0 +1,5 @@
# CHANGELOG
The changelog is automatically updated using
[semantic-release](https://github.com/semantic-release/semantic-release). You
can see it on the [releases page](../../releases).

View File

@@ -0,0 +1,20 @@
The MIT License (MIT)
Copyright (c) 2017 Kent C. Dodds
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

1491
frontend/node_modules/@testing-library/jest-dom/README.md generated vendored Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,6 @@
"use strict";
var extensions = _interopRequireWildcard(require("./matchers"));
function _getRequireWildcardCache(nodeInterop) { if (typeof WeakMap !== "function") return null; var cacheBabelInterop = new WeakMap(); var cacheNodeInterop = new WeakMap(); return (_getRequireWildcardCache = function (nodeInterop) { return nodeInterop ? cacheNodeInterop : cacheBabelInterop; })(nodeInterop); }
function _interopRequireWildcard(obj, nodeInterop) { if (!nodeInterop && obj && obj.__esModule) { return obj; } if (obj === null || typeof obj !== "object" && typeof obj !== "function") { return { default: obj }; } var cache = _getRequireWildcardCache(nodeInterop); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (key !== "default" && Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj.default = obj; if (cache) { cache.set(obj, newObj); } return newObj; }
expect.extend(extensions);

View File

@@ -0,0 +1,3 @@
"use strict";
require("./extend-expect");

View File

@@ -0,0 +1,192 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
Object.defineProperty(exports, "toBeChecked", {
enumerable: true,
get: function () {
return _toBeChecked.toBeChecked;
}
});
Object.defineProperty(exports, "toBeDisabled", {
enumerable: true,
get: function () {
return _toBeDisabled.toBeDisabled;
}
});
Object.defineProperty(exports, "toBeEmpty", {
enumerable: true,
get: function () {
return _toBeEmpty.toBeEmpty;
}
});
Object.defineProperty(exports, "toBeEmptyDOMElement", {
enumerable: true,
get: function () {
return _toBeEmptyDomElement.toBeEmptyDOMElement;
}
});
Object.defineProperty(exports, "toBeEnabled", {
enumerable: true,
get: function () {
return _toBeDisabled.toBeEnabled;
}
});
Object.defineProperty(exports, "toBeInTheDOM", {
enumerable: true,
get: function () {
return _toBeInTheDom.toBeInTheDOM;
}
});
Object.defineProperty(exports, "toBeInTheDocument", {
enumerable: true,
get: function () {
return _toBeInTheDocument.toBeInTheDocument;
}
});
Object.defineProperty(exports, "toBeInvalid", {
enumerable: true,
get: function () {
return _toBeInvalid.toBeInvalid;
}
});
Object.defineProperty(exports, "toBePartiallyChecked", {
enumerable: true,
get: function () {
return _toBePartiallyChecked.toBePartiallyChecked;
}
});
Object.defineProperty(exports, "toBeRequired", {
enumerable: true,
get: function () {
return _toBeRequired.toBeRequired;
}
});
Object.defineProperty(exports, "toBeValid", {
enumerable: true,
get: function () {
return _toBeInvalid.toBeValid;
}
});
Object.defineProperty(exports, "toBeVisible", {
enumerable: true,
get: function () {
return _toBeVisible.toBeVisible;
}
});
Object.defineProperty(exports, "toContainElement", {
enumerable: true,
get: function () {
return _toContainElement.toContainElement;
}
});
Object.defineProperty(exports, "toContainHTML", {
enumerable: true,
get: function () {
return _toContainHtml.toContainHTML;
}
});
Object.defineProperty(exports, "toHaveAccessibleDescription", {
enumerable: true,
get: function () {
return _toHaveAccessibleDescription.toHaveAccessibleDescription;
}
});
Object.defineProperty(exports, "toHaveAccessibleErrorMessage", {
enumerable: true,
get: function () {
return _toHaveAccessibleErrormessage.toHaveAccessibleErrorMessage;
}
});
Object.defineProperty(exports, "toHaveAccessibleName", {
enumerable: true,
get: function () {
return _toHaveAccessibleName.toHaveAccessibleName;
}
});
Object.defineProperty(exports, "toHaveAttribute", {
enumerable: true,
get: function () {
return _toHaveAttribute.toHaveAttribute;
}
});
Object.defineProperty(exports, "toHaveClass", {
enumerable: true,
get: function () {
return _toHaveClass.toHaveClass;
}
});
Object.defineProperty(exports, "toHaveDescription", {
enumerable: true,
get: function () {
return _toHaveDescription.toHaveDescription;
}
});
Object.defineProperty(exports, "toHaveDisplayValue", {
enumerable: true,
get: function () {
return _toHaveDisplayValue.toHaveDisplayValue;
}
});
Object.defineProperty(exports, "toHaveErrorMessage", {
enumerable: true,
get: function () {
return _toHaveErrormessage.toHaveErrorMessage;
}
});
Object.defineProperty(exports, "toHaveFocus", {
enumerable: true,
get: function () {
return _toHaveFocus.toHaveFocus;
}
});
Object.defineProperty(exports, "toHaveFormValues", {
enumerable: true,
get: function () {
return _toHaveFormValues.toHaveFormValues;
}
});
Object.defineProperty(exports, "toHaveStyle", {
enumerable: true,
get: function () {
return _toHaveStyle.toHaveStyle;
}
});
Object.defineProperty(exports, "toHaveTextContent", {
enumerable: true,
get: function () {
return _toHaveTextContent.toHaveTextContent;
}
});
Object.defineProperty(exports, "toHaveValue", {
enumerable: true,
get: function () {
return _toHaveValue.toHaveValue;
}
});
var _toBeInTheDom = require("./to-be-in-the-dom");
var _toBeInTheDocument = require("./to-be-in-the-document");
var _toBeEmpty = require("./to-be-empty");
var _toBeEmptyDomElement = require("./to-be-empty-dom-element");
var _toContainElement = require("./to-contain-element");
var _toContainHtml = require("./to-contain-html");
var _toHaveTextContent = require("./to-have-text-content");
var _toHaveAccessibleDescription = require("./to-have-accessible-description");
var _toHaveAccessibleErrormessage = require("./to-have-accessible-errormessage");
var _toHaveAccessibleName = require("./to-have-accessible-name");
var _toHaveAttribute = require("./to-have-attribute");
var _toHaveClass = require("./to-have-class");
var _toHaveStyle = require("./to-have-style");
var _toHaveFocus = require("./to-have-focus");
var _toHaveFormValues = require("./to-have-form-values");
var _toBeVisible = require("./to-be-visible");
var _toBeDisabled = require("./to-be-disabled");
var _toBeRequired = require("./to-be-required");
var _toBeInvalid = require("./to-be-invalid");
var _toHaveValue = require("./to-have-value");
var _toHaveDisplayValue = require("./to-have-display-value");
var _toBeChecked = require("./to-be-checked");
var _toBePartiallyChecked = require("./to-be-partially-checked");
var _toHaveDescription = require("./to-have-description");
var _toHaveErrormessage = require("./to-have-errormessage");

View File

@@ -0,0 +1,46 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.toBeChecked = toBeChecked;
var _ariaQuery = require("aria-query");
var _utils = require("./utils");
function toBeChecked(element) {
(0, _utils.checkHtmlElement)(element, toBeChecked, this);
const isValidInput = () => {
return element.tagName.toLowerCase() === 'input' && ['checkbox', 'radio'].includes(element.type);
};
const isValidAriaElement = () => {
return roleSupportsChecked(element.getAttribute('role')) && ['true', 'false'].includes(element.getAttribute('aria-checked'));
};
if (!isValidInput() && !isValidAriaElement()) {
return {
pass: false,
message: () => `only inputs with type="checkbox" or type="radio" or elements with ${supportedRolesSentence()} and a valid aria-checked attribute can be used with .toBeChecked(). Use .toHaveValue() instead`
};
}
const isChecked = () => {
if (isValidInput()) return element.checked;
return element.getAttribute('aria-checked') === 'true';
};
return {
pass: isChecked(),
message: () => {
const is = isChecked() ? 'is' : 'is not';
return [this.utils.matcherHint(`${this.isNot ? '.not' : ''}.toBeChecked`, 'element', ''), '', `Received element ${is} checked:`, ` ${this.utils.printReceived(element.cloneNode(false))}`].join('\n');
}
};
}
function supportedRolesSentence() {
return (0, _utils.toSentence)(supportedRoles().map(role => `role="${role}"`), {
lastWordConnector: ' or '
});
}
function supportedRoles() {
return _ariaQuery.roles.keys().filter(roleSupportsChecked);
}
function roleSupportsChecked(role) {
var _roles$get;
return ((_roles$get = _ariaQuery.roles.get(role)) == null ? void 0 : _roles$get.props['aria-checked']) !== undefined;
}

View File

@@ -0,0 +1,70 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.toBeDisabled = toBeDisabled;
exports.toBeEnabled = toBeEnabled;
var _utils = require("./utils");
// form elements that support 'disabled'
const FORM_TAGS = ['fieldset', 'input', 'select', 'optgroup', 'option', 'button', 'textarea'];
/*
* According to specification:
* If <fieldset> is disabled, the form controls that are its descendants,
* except descendants of its first optional <legend> element, are disabled
*
* https://html.spec.whatwg.org/multipage/form-elements.html#concept-fieldset-disabled
*
* This method tests whether element is first legend child of fieldset parent
*/
function isFirstLegendChildOfFieldset(element, parent) {
return (0, _utils.getTag)(element) === 'legend' && (0, _utils.getTag)(parent) === 'fieldset' && element.isSameNode(Array.from(parent.children).find(child => (0, _utils.getTag)(child) === 'legend'));
}
function isElementDisabledByParent(element, parent) {
return isElementDisabled(parent) && !isFirstLegendChildOfFieldset(element, parent);
}
function isCustomElement(tag) {
return tag.includes('-');
}
/*
* Only certain form elements and custom elements can actually be disabled:
* https://html.spec.whatwg.org/multipage/semantics-other.html#disabled-elements
*/
function canElementBeDisabled(element) {
const tag = (0, _utils.getTag)(element);
return FORM_TAGS.includes(tag) || isCustomElement(tag);
}
function isElementDisabled(element) {
return canElementBeDisabled(element) && element.hasAttribute('disabled');
}
function isAncestorDisabled(element) {
const parent = element.parentElement;
return Boolean(parent) && (isElementDisabledByParent(element, parent) || isAncestorDisabled(parent));
}
function isElementOrAncestorDisabled(element) {
return canElementBeDisabled(element) && (isElementDisabled(element) || isAncestorDisabled(element));
}
function toBeDisabled(element) {
(0, _utils.checkHtmlElement)(element, toBeDisabled, this);
const isDisabled = isElementOrAncestorDisabled(element);
return {
pass: isDisabled,
message: () => {
const is = isDisabled ? 'is' : 'is not';
return [this.utils.matcherHint(`${this.isNot ? '.not' : ''}.toBeDisabled`, 'element', ''), '', `Received element ${is} disabled:`, ` ${this.utils.printReceived(element.cloneNode(false))}`].join('\n');
}
};
}
function toBeEnabled(element) {
(0, _utils.checkHtmlElement)(element, toBeEnabled, this);
const isEnabled = !isElementOrAncestorDisabled(element);
return {
pass: isEnabled,
message: () => {
const is = isEnabled ? 'is' : 'is not';
return [this.utils.matcherHint(`${this.isNot ? '.not' : ''}.toBeEnabled`, 'element', ''), '', `Received element ${is} enabled:`, ` ${this.utils.printReceived(element.cloneNode(false))}`].join('\n');
}
};
}

View File

@@ -0,0 +1,29 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.toBeEmptyDOMElement = toBeEmptyDOMElement;
var _utils = require("./utils");
function toBeEmptyDOMElement(element) {
(0, _utils.checkHtmlElement)(element, toBeEmptyDOMElement, this);
return {
pass: isEmptyElement(element),
message: () => {
return [this.utils.matcherHint(`${this.isNot ? '.not' : ''}.toBeEmptyDOMElement`, 'element', ''), '', 'Received:', ` ${this.utils.printReceived(element.innerHTML)}`].join('\n');
}
};
}
/**
* Identifies if an element doesn't contain child nodes (excluding comments)
* Node.COMMENT_NODE can't be used because of the following issue
* https://github.com/jsdom/jsdom/issues/2220
*
* @param {*} element an HtmlElement or SVGElement
* @return {*} true if the element only contains comments or none
*/
function isEmptyElement(element) {
const nonCommentChildNodes = [...element.childNodes].filter(node => node.nodeType !== 8);
return nonCommentChildNodes.length === 0;
}

View File

@@ -0,0 +1,17 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.toBeEmpty = toBeEmpty;
var _utils = require("./utils");
function toBeEmpty(element) {
(0, _utils.deprecate)('toBeEmpty', 'Please use instead toBeEmptyDOMElement for finding empty nodes in the DOM.');
(0, _utils.checkHtmlElement)(element, toBeEmpty, this);
return {
pass: element.innerHTML === '',
message: () => {
return [this.utils.matcherHint(`${this.isNot ? '.not' : ''}.toBeEmpty`, 'element', ''), '', 'Received:', ` ${this.utils.printReceived(element.innerHTML)}`].join('\n');
}
};
}

View File

@@ -0,0 +1,29 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.toBeInTheDocument = toBeInTheDocument;
var _utils = require("./utils");
function toBeInTheDocument(element) {
if (element !== null || !this.isNot) {
(0, _utils.checkHtmlElement)(element, toBeInTheDocument, this);
}
const pass = element === null ? false : element.ownerDocument === element.getRootNode({
composed: true
});
const errorFound = () => {
return `expected document not to contain element, found ${this.utils.stringify(element.cloneNode(true))} instead`;
};
const errorNotFound = () => {
return `element could not be found in the document`;
};
return {
pass,
message: () => {
return [this.utils.matcherHint(`${this.isNot ? '.not' : ''}.toBeInTheDocument`, 'element', ''), '',
// eslint-disable-next-line @babel/new-cap
this.utils.RECEIVED_COLOR(this.isNot ? errorFound() : errorNotFound())].join('\n');
}
};
}

View File

@@ -0,0 +1,22 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.toBeInTheDOM = toBeInTheDOM;
var _utils = require("./utils");
function toBeInTheDOM(element, container) {
(0, _utils.deprecate)('toBeInTheDOM', 'Please use toBeInTheDocument for searching the entire document and toContainElement for searching a specific container.');
if (element) {
(0, _utils.checkHtmlElement)(element, toBeInTheDOM, this);
}
if (container) {
(0, _utils.checkHtmlElement)(container, toBeInTheDOM, this);
}
return {
pass: container ? container.contains(element) : !!element,
message: () => {
return [this.utils.matcherHint(`${this.isNot ? '.not' : ''}.toBeInTheDOM`, 'element', ''), '', 'Received:', ` ${this.utils.printReceived(element ? element.cloneNode(false) : element)}`].join('\n');
}
};
}

View File

@@ -0,0 +1,45 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.toBeInvalid = toBeInvalid;
exports.toBeValid = toBeValid;
var _utils = require("./utils");
const FORM_TAGS = ['form', 'input', 'select', 'textarea'];
function isElementHavingAriaInvalid(element) {
return element.hasAttribute('aria-invalid') && element.getAttribute('aria-invalid') !== 'false';
}
function isSupportsValidityMethod(element) {
return FORM_TAGS.includes((0, _utils.getTag)(element));
}
function isElementInvalid(element) {
const isHaveAriaInvalid = isElementHavingAriaInvalid(element);
if (isSupportsValidityMethod(element)) {
return isHaveAriaInvalid || !element.checkValidity();
} else {
return isHaveAriaInvalid;
}
}
function toBeInvalid(element) {
(0, _utils.checkHtmlElement)(element, toBeInvalid, this);
const isInvalid = isElementInvalid(element);
return {
pass: isInvalid,
message: () => {
const is = isInvalid ? 'is' : 'is not';
return [this.utils.matcherHint(`${this.isNot ? '.not' : ''}.toBeInvalid`, 'element', ''), '', `Received element ${is} currently invalid:`, ` ${this.utils.printReceived(element.cloneNode(false))}`].join('\n');
}
};
}
function toBeValid(element) {
(0, _utils.checkHtmlElement)(element, toBeValid, this);
const isValid = !isElementInvalid(element);
return {
pass: isValid,
message: () => {
const is = isValid ? 'is' : 'is not';
return [this.utils.matcherHint(`${this.isNot ? '.not' : ''}.toBeValid`, 'element', ''), '', `Received element ${is} currently valid:`, ` ${this.utils.printReceived(element.cloneNode(false))}`].join('\n');
}
};
}

View File

@@ -0,0 +1,36 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.toBePartiallyChecked = toBePartiallyChecked;
var _utils = require("./utils");
function toBePartiallyChecked(element) {
(0, _utils.checkHtmlElement)(element, toBePartiallyChecked, this);
const isValidInput = () => {
return element.tagName.toLowerCase() === 'input' && element.type === 'checkbox';
};
const isValidAriaElement = () => {
return element.getAttribute('role') === 'checkbox';
};
if (!isValidInput() && !isValidAriaElement()) {
return {
pass: false,
message: () => 'only inputs with type="checkbox" or elements with role="checkbox" and a valid aria-checked attribute can be used with .toBePartiallyChecked(). Use .toHaveValue() instead'
};
}
const isPartiallyChecked = () => {
const isAriaMixed = element.getAttribute('aria-checked') === 'mixed';
if (isValidInput()) {
return element.indeterminate || isAriaMixed;
}
return isAriaMixed;
};
return {
pass: isPartiallyChecked(),
message: () => {
const is = isPartiallyChecked() ? 'is' : 'is not';
return [this.utils.matcherHint(`${this.isNot ? '.not' : ''}.toBePartiallyChecked`, 'element', ''), '', `Received element ${is} partially checked:`, ` ${this.utils.printReceived(element.cloneNode(false))}`].join('\n');
}
};
}

View File

@@ -0,0 +1,32 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.toBeRequired = toBeRequired;
var _utils = require("./utils");
// form elements that support 'required'
const FORM_TAGS = ['select', 'textarea'];
const ARIA_FORM_TAGS = ['input', 'select', 'textarea'];
const UNSUPPORTED_INPUT_TYPES = ['color', 'hidden', 'range', 'submit', 'image', 'reset'];
const SUPPORTED_ARIA_ROLES = ['combobox', 'gridcell', 'radiogroup', 'spinbutton', 'tree'];
function isRequiredOnFormTagsExceptInput(element) {
return FORM_TAGS.includes((0, _utils.getTag)(element)) && element.hasAttribute('required');
}
function isRequiredOnSupportedInput(element) {
return (0, _utils.getTag)(element) === 'input' && element.hasAttribute('required') && (element.hasAttribute('type') && !UNSUPPORTED_INPUT_TYPES.includes(element.getAttribute('type')) || !element.hasAttribute('type'));
}
function isElementRequiredByARIA(element) {
return element.hasAttribute('aria-required') && element.getAttribute('aria-required') === 'true' && (ARIA_FORM_TAGS.includes((0, _utils.getTag)(element)) || element.hasAttribute('role') && SUPPORTED_ARIA_ROLES.includes(element.getAttribute('role')));
}
function toBeRequired(element) {
(0, _utils.checkHtmlElement)(element, toBeRequired, this);
const isRequired = isRequiredOnFormTagsExceptInput(element) || isRequiredOnSupportedInput(element) || isElementRequiredByARIA(element);
return {
pass: isRequired,
message: () => {
const is = isRequired ? 'is' : 'is not';
return [this.utils.matcherHint(`${this.isNot ? '.not' : ''}.toBeRequired`, 'element', ''), '', `Received element ${is} required:`, ` ${this.utils.printReceived(element.cloneNode(false))}`].join('\n');
}
};
}

View File

@@ -0,0 +1,44 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.toBeVisible = toBeVisible;
var _utils = require("./utils");
function isStyleVisible(element) {
const {
getComputedStyle
} = element.ownerDocument.defaultView;
const {
display,
visibility,
opacity
} = getComputedStyle(element);
return display !== 'none' && visibility !== 'hidden' && visibility !== 'collapse' && opacity !== '0' && opacity !== 0;
}
function isAttributeVisible(element, previousElement) {
let detailsVisibility;
if (previousElement) {
detailsVisibility = element.nodeName === 'DETAILS' && previousElement.nodeName !== 'SUMMARY' ? element.hasAttribute('open') : true;
} else {
detailsVisibility = element.nodeName === 'DETAILS' ? element.hasAttribute('open') : true;
}
return !element.hasAttribute('hidden') && detailsVisibility;
}
function isElementVisible(element, previousElement) {
return isStyleVisible(element) && isAttributeVisible(element, previousElement) && (!element.parentElement || isElementVisible(element.parentElement, element));
}
function toBeVisible(element) {
(0, _utils.checkHtmlElement)(element, toBeVisible, this);
const isInDocument = element.ownerDocument === element.getRootNode({
composed: true
});
const isVisible = isInDocument && isElementVisible(element);
return {
pass: isVisible,
message: () => {
const is = isVisible ? 'is' : 'is not';
return [this.utils.matcherHint(`${this.isNot ? '.not' : ''}.toBeVisible`, 'element', ''), '', `Received element ${is} visible${isInDocument ? '' : ' (element is not in the document)'}:`, ` ${this.utils.printReceived(element.cloneNode(false))}`].join('\n');
}
};
}

View File

@@ -0,0 +1,22 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.toContainElement = toContainElement;
var _utils = require("./utils");
function toContainElement(container, element) {
(0, _utils.checkHtmlElement)(container, toContainElement, this);
if (element !== null) {
(0, _utils.checkHtmlElement)(element, toContainElement, this);
}
return {
pass: container.contains(element),
message: () => {
return [this.utils.matcherHint(`${this.isNot ? '.not' : ''}.toContainElement`, 'element', 'element'), '',
// eslint-disable-next-line @babel/new-cap
this.utils.RECEIVED_COLOR(`${this.utils.stringify(container.cloneNode(false))} ${this.isNot ? 'contains:' : 'does not contain:'} ${this.utils.stringify(element ? element.cloneNode(false) : element)}
`)].join('\n');
}
};
}

View File

@@ -0,0 +1,26 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.toContainHTML = toContainHTML;
var _utils = require("./utils");
function getNormalizedHtml(container, htmlText) {
const div = container.ownerDocument.createElement('div');
div.innerHTML = htmlText;
return div.innerHTML;
}
function toContainHTML(container, htmlText) {
(0, _utils.checkHtmlElement)(container, toContainHTML, this);
if (typeof htmlText !== 'string') {
throw new Error(`.toContainHTML() expects a string value, got ${htmlText}`);
}
return {
pass: container.outerHTML.includes(getNormalizedHtml(container, htmlText)),
message: () => {
return [this.utils.matcherHint(`${this.isNot ? '.not' : ''}.toContainHTML`, 'element', ''), 'Expected:',
// eslint-disable-next-line @babel/new-cap
` ${this.utils.EXPECTED_COLOR(htmlText)}`, 'Received:', ` ${this.utils.printReceived(container.cloneNode(true))}`].join('\n');
}
};
}

View File

@@ -0,0 +1,28 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.toHaveAccessibleDescription = toHaveAccessibleDescription;
var _domAccessibilityApi = require("dom-accessibility-api");
var _utils = require("./utils");
function toHaveAccessibleDescription(htmlElement, expectedAccessibleDescription) {
(0, _utils.checkHtmlElement)(htmlElement, toHaveAccessibleDescription, this);
const actualAccessibleDescription = (0, _domAccessibilityApi.computeAccessibleDescription)(htmlElement);
const missingExpectedValue = arguments.length === 1;
let pass = false;
if (missingExpectedValue) {
// When called without an expected value we only want to validate that the element has an
// accessible description, whatever it may be.
pass = actualAccessibleDescription !== '';
} else {
pass = expectedAccessibleDescription instanceof RegExp ? expectedAccessibleDescription.test(actualAccessibleDescription) : this.equals(actualAccessibleDescription, expectedAccessibleDescription);
}
return {
pass,
message: () => {
const to = this.isNot ? 'not to' : 'to';
return (0, _utils.getMessage)(this, this.utils.matcherHint(`${this.isNot ? '.not' : ''}.${toHaveAccessibleDescription.name}`, 'element', ''), `Expected element ${to} have accessible description`, expectedAccessibleDescription, 'Received', actualAccessibleDescription);
}
};
}

View File

@@ -0,0 +1,50 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.toHaveAccessibleErrorMessage = toHaveAccessibleErrorMessage;
var _utils = require("./utils");
const ariaInvalidName = 'aria-invalid';
const validStates = ['false'];
// See `aria-errormessage` spec at https://www.w3.org/TR/wai-aria-1.2/#aria-errormessage
function toHaveAccessibleErrorMessage(htmlElement, expectedAccessibleErrorMessage) {
var _htmlElement$ownerDoc, _htmlElement$ownerDoc2;
(0, _utils.checkHtmlElement)(htmlElement, toHaveAccessibleErrorMessage, this);
const to = this.isNot ? 'not to' : 'to';
const method = this.isNot ? '.not.toHaveAccessibleErrorMessage' : '.toHaveAccessibleErrorMessage';
// Enforce Valid Id
const errormessageId = htmlElement.getAttribute('aria-errormessage');
const errormessageIdInvalid = !!errormessageId && /\s+/.test(errormessageId);
if (errormessageIdInvalid) {
return {
pass: false,
message: () => {
return (0, _utils.getMessage)(this, this.utils.matcherHint(method, 'element'), "Expected element's `aria-errormessage` attribute to be empty or a single, valid ID", '', 'Received', `aria-errormessage="${errormessageId}"`);
}
};
}
// See `aria-invalid` spec at https://www.w3.org/TR/wai-aria-1.2/#aria-invalid
const ariaInvalidVal = htmlElement.getAttribute(ariaInvalidName);
const fieldValid = !htmlElement.hasAttribute(ariaInvalidName) || validStates.includes(ariaInvalidVal);
// Enforce Valid `aria-invalid` Attribute
if (fieldValid) {
return {
pass: false,
message: () => {
return (0, _utils.getMessage)(this, this.utils.matcherHint(method, 'element'), 'Expected element to be marked as invalid with attribute', `${ariaInvalidName}="${String(true)}"`, 'Received', htmlElement.hasAttribute('aria-invalid') ? `${ariaInvalidName}="${htmlElement.getAttribute(ariaInvalidName)}` : null);
}
};
}
const error = (0, _utils.normalize)((_htmlElement$ownerDoc = (_htmlElement$ownerDoc2 = htmlElement.ownerDocument.getElementById(errormessageId)) == null ? void 0 : _htmlElement$ownerDoc2.textContent) != null ? _htmlElement$ownerDoc : '');
return {
pass: expectedAccessibleErrorMessage === undefined ? Boolean(error) : expectedAccessibleErrorMessage instanceof RegExp ? expectedAccessibleErrorMessage.test(error) : this.equals(error, expectedAccessibleErrorMessage),
message: () => {
return (0, _utils.getMessage)(this, this.utils.matcherHint(method, 'element'), `Expected element ${to} have accessible error message`, expectedAccessibleErrorMessage != null ? expectedAccessibleErrorMessage : '', 'Received', error);
}
};
}

View File

@@ -0,0 +1,28 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.toHaveAccessibleName = toHaveAccessibleName;
var _domAccessibilityApi = require("dom-accessibility-api");
var _utils = require("./utils");
function toHaveAccessibleName(htmlElement, expectedAccessibleName) {
(0, _utils.checkHtmlElement)(htmlElement, toHaveAccessibleName, this);
const actualAccessibleName = (0, _domAccessibilityApi.computeAccessibleName)(htmlElement);
const missingExpectedValue = arguments.length === 1;
let pass = false;
if (missingExpectedValue) {
// When called without an expected value we only want to validate that the element has an
// accessible name, whatever it may be.
pass = actualAccessibleName !== '';
} else {
pass = expectedAccessibleName instanceof RegExp ? expectedAccessibleName.test(actualAccessibleName) : this.equals(actualAccessibleName, expectedAccessibleName);
}
return {
pass,
message: () => {
const to = this.isNot ? 'not to' : 'to';
return (0, _utils.getMessage)(this, this.utils.matcherHint(`${this.isNot ? '.not' : ''}.${toHaveAccessibleName.name}`, 'element', ''), `Expected element ${to} have accessible name`, expectedAccessibleName, 'Received', actualAccessibleName);
}
};
}

View File

@@ -0,0 +1,31 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.toHaveAttribute = toHaveAttribute;
var _utils = require("./utils");
function printAttribute(stringify, name, value) {
return value === undefined ? name : `${name}=${stringify(value)}`;
}
function getAttributeComment(stringify, name, value) {
return value === undefined ? `element.hasAttribute(${stringify(name)})` : `element.getAttribute(${stringify(name)}) === ${stringify(value)}`;
}
function toHaveAttribute(htmlElement, name, expectedValue) {
(0, _utils.checkHtmlElement)(htmlElement, toHaveAttribute, this);
const isExpectedValuePresent = expectedValue !== undefined;
const hasAttribute = htmlElement.hasAttribute(name);
const receivedValue = htmlElement.getAttribute(name);
return {
pass: isExpectedValuePresent ? hasAttribute && this.equals(receivedValue, expectedValue) : hasAttribute,
message: () => {
const to = this.isNot ? 'not to' : 'to';
const receivedAttribute = hasAttribute ? printAttribute(this.utils.stringify, name, receivedValue) : null;
const matcher = this.utils.matcherHint(`${this.isNot ? '.not' : ''}.toHaveAttribute`, 'element', this.utils.printExpected(name), {
secondArgument: isExpectedValuePresent ? this.utils.printExpected(expectedValue) : undefined,
comment: getAttributeComment(this.utils.stringify, name, expectedValue)
});
return (0, _utils.getMessage)(this, matcher, `Expected the element ${to} have attribute`, printAttribute(this.utils.stringify, name, expectedValue), 'Received', receivedAttribute);
}
};
}

View File

@@ -0,0 +1,61 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.toHaveClass = toHaveClass;
var _utils = require("./utils");
function getExpectedClassNamesAndOptions(params) {
const lastParam = params.pop();
let expectedClassNames, options;
if (typeof lastParam === 'object') {
expectedClassNames = params;
options = lastParam;
} else {
expectedClassNames = params.concat(lastParam);
options = {
exact: false
};
}
return {
expectedClassNames,
options
};
}
function splitClassNames(str) {
if (!str) {
return [];
}
return str.split(/\s+/).filter(s => s.length > 0);
}
function isSubset(subset, superset) {
return subset.every(item => superset.includes(item));
}
function toHaveClass(htmlElement, ...params) {
(0, _utils.checkHtmlElement)(htmlElement, toHaveClass, this);
const {
expectedClassNames,
options
} = getExpectedClassNamesAndOptions(params);
const received = splitClassNames(htmlElement.getAttribute('class'));
const expected = expectedClassNames.reduce((acc, className) => acc.concat(splitClassNames(className)), []);
if (options.exact) {
return {
pass: isSubset(expected, received) && expected.length === received.length,
message: () => {
const to = this.isNot ? 'not to' : 'to';
return (0, _utils.getMessage)(this, this.utils.matcherHint(`${this.isNot ? '.not' : ''}.toHaveClass`, 'element', this.utils.printExpected(expected.join(' '))), `Expected the element ${to} have EXACTLY defined classes`, expected.join(' '), 'Received', received.join(' '));
}
};
}
return expected.length > 0 ? {
pass: isSubset(expected, received),
message: () => {
const to = this.isNot ? 'not to' : 'to';
return (0, _utils.getMessage)(this, this.utils.matcherHint(`${this.isNot ? '.not' : ''}.toHaveClass`, 'element', this.utils.printExpected(expected.join(' '))), `Expected the element ${to} have class`, expected.join(' '), 'Received', received.join(' '));
}
} : {
pass: this.isNot ? received.length > 0 : false,
message: () => this.isNot ? (0, _utils.getMessage)(this, this.utils.matcherHint('.not.toHaveClass', 'element', ''), 'Expected the element to have classes', '(none)', 'Received', received.join(' ')) : [this.utils.matcherHint(`.toHaveClass`, 'element'), 'At least one expected class must be provided.'].join('\n')
};
}

View File

@@ -0,0 +1,28 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.toHaveDescription = toHaveDescription;
var _utils = require("./utils");
// See algoritm: https://www.w3.org/TR/accname-1.1/#mapping_additional_nd_description
function toHaveDescription(htmlElement, checkWith) {
(0, _utils.deprecate)('toHaveDescription', 'Please use toHaveAccessibleDescription.');
(0, _utils.checkHtmlElement)(htmlElement, toHaveDescription, this);
const expectsDescription = checkWith !== undefined;
const descriptionIDRaw = htmlElement.getAttribute('aria-describedby') || '';
const descriptionIDs = descriptionIDRaw.split(/\s+/).filter(Boolean);
let description = '';
if (descriptionIDs.length > 0) {
const document = htmlElement.ownerDocument;
const descriptionEls = descriptionIDs.map(descriptionID => document.getElementById(descriptionID)).filter(Boolean);
description = (0, _utils.normalize)(descriptionEls.map(el => el.textContent).join(' '));
}
return {
pass: expectsDescription ? checkWith instanceof RegExp ? checkWith.test(description) : this.equals(description, checkWith) : Boolean(description),
message: () => {
const to = this.isNot ? 'not to' : 'to';
return (0, _utils.getMessage)(this, this.utils.matcherHint(`${this.isNot ? '.not' : ''}.toHaveDescription`, 'element', ''), `Expected the element ${to} have description`, this.utils.printExpected(checkWith), 'Received', this.utils.printReceived(description));
}
};
}

View File

@@ -0,0 +1,32 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.toHaveDisplayValue = toHaveDisplayValue;
var _utils = require("./utils");
function toHaveDisplayValue(htmlElement, expectedValue) {
(0, _utils.checkHtmlElement)(htmlElement, toHaveDisplayValue, this);
const tagName = htmlElement.tagName.toLowerCase();
if (!['select', 'input', 'textarea'].includes(tagName)) {
throw new Error('.toHaveDisplayValue() currently supports only input, textarea or select elements, try with another matcher instead.');
}
if (tagName === 'input' && ['radio', 'checkbox'].includes(htmlElement.type)) {
throw new Error(`.toHaveDisplayValue() currently does not support input[type="${htmlElement.type}"], try with another matcher instead.`);
}
const values = getValues(tagName, htmlElement);
const expectedValues = getExpectedValues(expectedValue);
const numberOfMatchesWithValues = expectedValues.filter(expected => values.some(value => expected instanceof RegExp ? expected.test(value) : this.equals(value, String(expected)))).length;
const matchedWithAllValues = numberOfMatchesWithValues === values.length;
const matchedWithAllExpectedValues = numberOfMatchesWithValues === expectedValues.length;
return {
pass: matchedWithAllValues && matchedWithAllExpectedValues,
message: () => (0, _utils.getMessage)(this, this.utils.matcherHint(`${this.isNot ? '.not' : ''}.toHaveDisplayValue`, 'element', ''), `Expected element ${this.isNot ? 'not ' : ''}to have display value`, expectedValue, 'Received', values)
};
}
function getValues(tagName, htmlElement) {
return tagName === 'select' ? Array.from(htmlElement).filter(option => option.selected).map(option => option.textContent) : [htmlElement.value];
}
function getExpectedValues(expectedValue) {
return expectedValue instanceof Array ? expectedValue : [expectedValue];
}

View File

@@ -0,0 +1,37 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.toHaveErrorMessage = toHaveErrorMessage;
var _utils = require("./utils");
// See aria-errormessage spec https://www.w3.org/TR/wai-aria-1.2/#aria-errormessage
function toHaveErrorMessage(htmlElement, checkWith) {
(0, _utils.deprecate)('toHaveErrorMessage', 'Please use toHaveAccessibleErrorMessage.');
(0, _utils.checkHtmlElement)(htmlElement, toHaveErrorMessage, this);
if (!htmlElement.hasAttribute('aria-invalid') || htmlElement.getAttribute('aria-invalid') === 'false') {
const not = this.isNot ? '.not' : '';
return {
pass: false,
message: () => {
return (0, _utils.getMessage)(this, this.utils.matcherHint(`${not}.toHaveErrorMessage`, 'element', ''), `Expected the element to have invalid state indicated by`, 'aria-invalid="true"', 'Received', htmlElement.hasAttribute('aria-invalid') ? `aria-invalid="${htmlElement.getAttribute('aria-invalid')}"` : this.utils.printReceived(''));
}
};
}
const expectsErrorMessage = checkWith !== undefined;
const errormessageIDRaw = htmlElement.getAttribute('aria-errormessage') || '';
const errormessageIDs = errormessageIDRaw.split(/\s+/).filter(Boolean);
let errormessage = '';
if (errormessageIDs.length > 0) {
const document = htmlElement.ownerDocument;
const errormessageEls = errormessageIDs.map(errormessageID => document.getElementById(errormessageID)).filter(Boolean);
errormessage = (0, _utils.normalize)(errormessageEls.map(el => el.textContent).join(' '));
}
return {
pass: expectsErrorMessage ? checkWith instanceof RegExp ? checkWith.test(errormessage) : this.equals(errormessage, checkWith) : Boolean(errormessage),
message: () => {
const to = this.isNot ? 'not to' : 'to';
return (0, _utils.getMessage)(this, this.utils.matcherHint(`${this.isNot ? '.not' : ''}.toHaveErrorMessage`, 'element', ''), `Expected the element ${to} have error message`, this.utils.printExpected(checkWith), 'Received', this.utils.printReceived(errormessage));
}
};
}

View File

@@ -0,0 +1,16 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.toHaveFocus = toHaveFocus;
var _utils = require("./utils");
function toHaveFocus(element) {
(0, _utils.checkHtmlElement)(element, toHaveFocus, this);
return {
pass: element.ownerDocument.activeElement === element,
message: () => {
return [this.utils.matcherHint(`${this.isNot ? '.not' : ''}.toHaveFocus`, 'element', ''), '', ...(this.isNot ? ['Received element is focused:', ` ${this.utils.printReceived(element)}`] : ['Expected element with focus:', ` ${this.utils.printExpected(element)}`, 'Received element with focus:', ` ${this.utils.printReceived(element.ownerDocument.activeElement)}`])].join('\n');
}
};
}

View File

@@ -0,0 +1,76 @@
"use strict";
var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.toHaveFormValues = toHaveFormValues;
var _extends2 = _interopRequireDefault(require("@babel/runtime/helpers/extends"));
var _isEqualWith = _interopRequireDefault(require("lodash/isEqualWith"));
var _uniq = _interopRequireDefault(require("lodash/uniq"));
var _css = _interopRequireDefault(require("css.escape"));
var _utils = require("./utils");
// Returns the combined value of several elements that have the same name
// e.g. radio buttons or groups of checkboxes
function getMultiElementValue(elements) {
const types = (0, _uniq.default)(elements.map(element => element.type));
if (types.length !== 1) {
throw new Error('Multiple form elements with the same name must be of the same type');
}
switch (types[0]) {
case 'radio':
{
const theChosenOne = elements.find(radio => radio.checked);
return theChosenOne ? theChosenOne.value : undefined;
}
case 'checkbox':
return elements.filter(checkbox => checkbox.checked).map(checkbox => checkbox.value);
default:
// NOTE: Not even sure this is a valid use case, but just in case...
return elements.map(element => element.value);
}
}
function getFormValue(container, name) {
const elements = [...container.querySelectorAll(`[name="${(0, _css.default)(name)}"]`)];
/* istanbul ignore if */
if (elements.length === 0) {
return undefined; // shouldn't happen, but just in case
}
switch (elements.length) {
case 1:
return (0, _utils.getSingleElementValue)(elements[0]);
default:
return getMultiElementValue(elements);
}
}
// Strips the `[]` suffix off a form value name
function getPureName(name) {
return /\[\]$/.test(name) ? name.slice(0, -2) : name;
}
function getAllFormValues(container) {
const names = Array.from(container.elements).map(element => element.name);
return names.reduce((obj, name) => (0, _extends2.default)({}, obj, {
[getPureName(name)]: getFormValue(container, name)
}), {});
}
function toHaveFormValues(formElement, expectedValues) {
(0, _utils.checkHtmlElement)(formElement, toHaveFormValues, this);
if (!formElement.elements) {
// TODO: Change condition to use instanceof against the appropriate element classes instead
throw new Error('toHaveFormValues must be called on a form or a fieldset');
}
const formValues = getAllFormValues(formElement);
return {
pass: Object.entries(expectedValues).every(([name, expectedValue]) => (0, _isEqualWith.default)(formValues[name], expectedValue, _utils.compareArraysAsSet)),
message: () => {
const to = this.isNot ? 'not to' : 'to';
const matcher = `${this.isNot ? '.not' : ''}.toHaveFormValues`;
const commonKeyValues = Object.keys(formValues).filter(key => expectedValues.hasOwnProperty(key)).reduce((obj, key) => (0, _extends2.default)({}, obj, {
[key]: formValues[key]
}), {});
return [this.utils.matcherHint(matcher, 'element', ''), `Expected the element ${to} have form values`, this.utils.diff(expectedValues, commonKeyValues)].join('\n\n');
}
};
}

View File

@@ -0,0 +1,53 @@
"use strict";
var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.toHaveStyle = toHaveStyle;
var _chalk = _interopRequireDefault(require("chalk"));
var _utils = require("./utils");
function getStyleDeclaration(document, css) {
const styles = {};
// The next block is necessary to normalize colors
const copy = document.createElement('div');
Object.keys(css).forEach(property => {
copy.style[property] = css[property];
styles[property] = copy.style[property];
});
return styles;
}
function isSubset(styles, computedStyle) {
return !!Object.keys(styles).length && Object.entries(styles).every(([prop, value]) => computedStyle[prop] === value || computedStyle.getPropertyValue(prop.toLowerCase()) === value);
}
function printoutStyles(styles) {
return Object.keys(styles).sort().map(prop => `${prop}: ${styles[prop]};`).join('\n');
}
// Highlights only style rules that were expected but were not found in the
// received computed styles
function expectedDiff(diffFn, expected, computedStyles) {
const received = Array.from(computedStyles).filter(prop => expected[prop] !== undefined).reduce((obj, prop) => Object.assign(obj, {
[prop]: computedStyles.getPropertyValue(prop)
}), {});
const diffOutput = diffFn(printoutStyles(expected), printoutStyles(received));
// Remove the "+ Received" annotation because this is a one-way diff
return diffOutput.replace(`${_chalk.default.red('+ Received')}\n`, '');
}
function toHaveStyle(htmlElement, css) {
(0, _utils.checkHtmlElement)(htmlElement, toHaveStyle, this);
const parsedCSS = typeof css === 'object' ? css : (0, _utils.parseCSS)(css, toHaveStyle, this);
const {
getComputedStyle
} = htmlElement.ownerDocument.defaultView;
const expected = getStyleDeclaration(htmlElement.ownerDocument, parsedCSS);
const received = getComputedStyle(htmlElement);
return {
pass: isSubset(expected, received),
message: () => {
const matcher = `${this.isNot ? '.not' : ''}.toHaveStyle`;
return [this.utils.matcherHint(matcher, 'element', ''), expectedDiff(this.utils.diff, expected, received)].join('\n\n');
}
};
}

View File

@@ -0,0 +1,22 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.toHaveTextContent = toHaveTextContent;
var _utils = require("./utils");
function toHaveTextContent(node, checkWith, options = {
normalizeWhitespace: true
}) {
(0, _utils.checkNode)(node, toHaveTextContent, this);
const textContent = options.normalizeWhitespace ? (0, _utils.normalize)(node.textContent) : node.textContent.replace(/\u00a0/g, ' '); // Replace &nbsp; with normal spaces
const checkingWithEmptyString = textContent !== '' && checkWith === '';
return {
pass: !checkingWithEmptyString && (0, _utils.matches)(textContent, checkWith),
message: () => {
const to = this.isNot ? 'not to' : 'to';
return (0, _utils.getMessage)(this, this.utils.matcherHint(`${this.isNot ? '.not' : ''}.toHaveTextContent`, 'element', ''), checkingWithEmptyString ? `Checking with empty string will always match, use .toBeEmptyDOMElement() instead` : `Expected element ${to} have text content`, checkWith, 'Received', textContent);
}
};
}

View File

@@ -0,0 +1,31 @@
"use strict";
var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.toHaveValue = toHaveValue;
var _isEqualWith = _interopRequireDefault(require("lodash/isEqualWith"));
var _utils = require("./utils");
function toHaveValue(htmlElement, expectedValue) {
(0, _utils.checkHtmlElement)(htmlElement, toHaveValue, this);
if (htmlElement.tagName.toLowerCase() === 'input' && ['checkbox', 'radio'].includes(htmlElement.type)) {
throw new Error('input with type=checkbox or type=radio cannot be used with .toHaveValue(). Use .toBeChecked() for type=checkbox or .toHaveFormValues() instead');
}
const receivedValue = (0, _utils.getSingleElementValue)(htmlElement);
const expectsValue = expectedValue !== undefined;
let expectedTypedValue = expectedValue;
let receivedTypedValue = receivedValue;
if (expectedValue == receivedValue && expectedValue !== receivedValue) {
expectedTypedValue = `${expectedValue} (${typeof expectedValue})`;
receivedTypedValue = `${receivedValue} (${typeof receivedValue})`;
}
return {
pass: expectsValue ? (0, _isEqualWith.default)(receivedValue, expectedValue, _utils.compareArraysAsSet) : Boolean(receivedValue),
message: () => {
const to = this.isNot ? 'not to' : 'to';
const matcher = this.utils.matcherHint(`${this.isNot ? '.not' : ''}.toHaveValue`, 'element', expectedValue);
return (0, _utils.getMessage)(this, matcher, `Expected the element ${to} have value`, expectsValue ? expectedTypedValue : '(any)', 'Received', receivedTypedValue);
}
};
}

View File

@@ -0,0 +1,188 @@
"use strict";
var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.NodeTypeError = exports.HtmlElementTypeError = void 0;
exports.checkHtmlElement = checkHtmlElement;
exports.checkNode = checkNode;
exports.compareArraysAsSet = compareArraysAsSet;
exports.deprecate = deprecate;
exports.getMessage = getMessage;
exports.getSingleElementValue = getSingleElementValue;
exports.getTag = getTag;
exports.matches = matches;
exports.normalize = normalize;
exports.parseCSS = parseCSS;
exports.toSentence = toSentence;
var _redent = _interopRequireDefault(require("redent"));
var _isEqual = _interopRequireDefault(require("lodash/isEqual"));
var _cssTools = require("@adobe/css-tools");
class GenericTypeError extends Error {
constructor(expectedString, received, matcherFn, context) {
super();
/* istanbul ignore next */
if (Error.captureStackTrace) {
Error.captureStackTrace(this, matcherFn);
}
let withType = '';
try {
withType = context.utils.printWithType('Received', received, context.utils.printReceived);
} catch (e) {
// Can throw for Document:
// https://github.com/jsdom/jsdom/issues/2304
}
this.message = [context.utils.matcherHint(`${context.isNot ? '.not' : ''}.${matcherFn.name}`, 'received', ''), '',
// eslint-disable-next-line @babel/new-cap
`${context.utils.RECEIVED_COLOR('received')} value must ${expectedString}.`, withType].join('\n');
}
}
class HtmlElementTypeError extends GenericTypeError {
constructor(...args) {
super('be an HTMLElement or an SVGElement', ...args);
}
}
exports.HtmlElementTypeError = HtmlElementTypeError;
class NodeTypeError extends GenericTypeError {
constructor(...args) {
super('be a Node', ...args);
}
}
exports.NodeTypeError = NodeTypeError;
function checkHasWindow(htmlElement, ErrorClass, ...args) {
if (!htmlElement || !htmlElement.ownerDocument || !htmlElement.ownerDocument.defaultView) {
throw new ErrorClass(htmlElement, ...args);
}
}
function checkNode(node, ...args) {
checkHasWindow(node, NodeTypeError, ...args);
const window = node.ownerDocument.defaultView;
if (!(node instanceof window.Node)) {
throw new NodeTypeError(node, ...args);
}
}
function checkHtmlElement(htmlElement, ...args) {
checkHasWindow(htmlElement, HtmlElementTypeError, ...args);
const window = htmlElement.ownerDocument.defaultView;
if (!(htmlElement instanceof window.HTMLElement) && !(htmlElement instanceof window.SVGElement)) {
throw new HtmlElementTypeError(htmlElement, ...args);
}
}
class InvalidCSSError extends Error {
constructor(received, matcherFn, context) {
super();
/* istanbul ignore next */
if (Error.captureStackTrace) {
Error.captureStackTrace(this, matcherFn);
}
this.message = [received.message, '',
// eslint-disable-next-line @babel/new-cap
context.utils.RECEIVED_COLOR(`Failing css:`),
// eslint-disable-next-line @babel/new-cap
context.utils.RECEIVED_COLOR(`${received.css}`)].join('\n');
}
}
function parseCSS(css, ...args) {
const ast = (0, _cssTools.parse)(`selector { ${css} }`, {
silent: true
}).stylesheet;
if (ast.parsingErrors && ast.parsingErrors.length > 0) {
const {
reason,
line
} = ast.parsingErrors[0];
throw new InvalidCSSError({
css,
message: `Syntax error parsing expected css: ${reason} on line: ${line}`
}, ...args);
}
const parsedRules = ast.rules[0].declarations.filter(d => d.type === 'declaration').reduce((obj, {
property,
value
}) => Object.assign(obj, {
[property]: value
}), {});
return parsedRules;
}
function display(context, value) {
return typeof value === 'string' ? value : context.utils.stringify(value);
}
function getMessage(context, matcher, expectedLabel, expectedValue, receivedLabel, receivedValue) {
return [`${matcher}\n`,
// eslint-disable-next-line @babel/new-cap
`${expectedLabel}:\n${context.utils.EXPECTED_COLOR((0, _redent.default)(display(context, expectedValue), 2))}`,
// eslint-disable-next-line @babel/new-cap
`${receivedLabel}:\n${context.utils.RECEIVED_COLOR((0, _redent.default)(display(context, receivedValue), 2))}`].join('\n');
}
function matches(textToMatch, matcher) {
if (matcher instanceof RegExp) {
return matcher.test(textToMatch);
} else {
return textToMatch.includes(String(matcher));
}
}
function deprecate(name, replacementText) {
// Notify user that they are using deprecated functionality.
// eslint-disable-next-line no-console
console.warn(`Warning: ${name} has been deprecated and will be removed in future updates.`, replacementText);
}
function normalize(text) {
return text.replace(/\s+/g, ' ').trim();
}
function getTag(element) {
return element.tagName && element.tagName.toLowerCase();
}
function getSelectValue({
multiple,
options
}) {
const selectedOptions = [...options].filter(option => option.selected);
if (multiple) {
return [...selectedOptions].map(opt => opt.value);
}
/* istanbul ignore if */
if (selectedOptions.length === 0) {
return undefined; // Couldn't make this happen, but just in case
}
return selectedOptions[0].value;
}
function getInputValue(inputElement) {
switch (inputElement.type) {
case 'number':
return inputElement.value === '' ? null : Number(inputElement.value);
case 'checkbox':
return inputElement.checked;
default:
return inputElement.value;
}
}
function getSingleElementValue(element) {
/* istanbul ignore if */
if (!element) {
return undefined;
}
switch (element.tagName.toLowerCase()) {
case 'input':
return getInputValue(element);
case 'select':
return getSelectValue(element);
default:
return element.value;
}
}
function compareArraysAsSet(a, b) {
if (Array.isArray(a) && Array.isArray(b)) {
return (0, _isEqual.default)(new Set(a), new Set(b));
}
return undefined;
}
function toSentence(array, {
wordConnector = ', ',
lastWordConnector = ' and '
} = {}) {
return [array.slice(0, -1).join(wordConnector), array[array.length - 1]].join(array.length > 1 ? lastWordConnector : '');
}

View File

@@ -0,0 +1,2 @@
// eslint-disable-next-line
require('./dist/extend-expect')

View File

@@ -0,0 +1,2 @@
const matchers = require('./dist/matchers')
module.exports = matchers

View File

@@ -0,0 +1,80 @@
{
"name": "@testing-library/jest-dom",
"version": "5.17.0",
"description": "Custom jest matchers to test the state of the DOM",
"main": "dist/index.js",
"engines": {
"node": ">=8",
"npm": ">=6",
"yarn": ">=1"
},
"scripts": {
"build": "kcd-scripts build",
"format": "kcd-scripts format",
"lint": "kcd-scripts lint",
"setup": "npm install && npm run validate -s",
"test": "kcd-scripts test",
"test:update": "npm test -- --updateSnapshot --coverage",
"validate": "kcd-scripts validate"
},
"files": [
"dist",
"extend-expect.js",
"matchers.js"
],
"keywords": [
"testing",
"dom",
"jest",
"jsdom"
],
"author": "Ernesto Garcia <gnapse@gmail.com> (http://gnapse.github.io)",
"license": "MIT",
"dependencies": {
"@babel/runtime": "^7.9.2",
"@types/testing-library__jest-dom": "^5.9.1",
"aria-query": "^5.0.0",
"chalk": "^3.0.0",
"@adobe/css-tools": "^4.0.1",
"css.escape": "^1.5.1",
"dom-accessibility-api": "^0.5.6",
"lodash": "^4.17.15",
"redent": "^3.0.0"
},
"devDependencies": {
"jest-environment-jsdom-sixteen": "^1.0.3",
"jest-watch-select-projects": "^2.0.0",
"jsdom": "^16.2.1",
"kcd-scripts": "^11.1.0",
"pretty-format": "^25.1.0"
},
"eslintConfig": {
"extends": "./node_modules/kcd-scripts/eslint.js",
"rules": {
"@babel/no-invalid-this": "off"
},
"overrides": [
{
"files": [
"src/__tests__/*.js"
],
"rules": {
"max-lines-per-function": "off"
}
}
]
},
"eslintIgnore": [
"node_modules",
"coverage",
"dist"
],
"repository": {
"type": "git",
"url": "https://github.com/testing-library/jest-dom"
},
"bugs": {
"url": "https://github.com/testing-library/jest-dom/issues"
},
"homepage": "https://github.com/testing-library/jest-dom#readme"
}