You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
94 lines
3.2 KiB
94 lines
3.2 KiB
"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'); |
|
} |
|
}; |
|
} |