UNPKG

@revoloo/cypress6

Version:

Cypress.io end to end testing tool

173 lines (143 loc) 4.73 kB
const _ = require('lodash') const Promise = require('bluebird') const $dom = require('../../../dom') const $utils = require('../../../cypress/utils') const $errUtils = require('../../../cypress/error_utils') const $elements = require('../../../dom/elements') const checkOrUncheck = (Cypress, cy, type, subject, values = [], userOptions = {}) => { // we're not handling conversion of values to strings // in case we've received numbers // if we're not an array but we are an object // reassign userOptions to values if (!_.isArray(values) && _.isObject(values)) { userOptions = values values = [] } else { // make sure we're an array of values values = [].concat(values) } // keep an array of subjects which // are potentially reduced down // to new filtered subjects const matchingElements = [] const options = _.defaults({}, userOptions, { $el: subject, log: true, force: false, }) const isNoop = ($el) => { return type === 'check' ? $el.prop('checked') : !$el.prop('checked') } const isAcceptableElement = ($el) => { return type === 'check' ? $el.is(':checkbox,:radio') : $el.is(':checkbox') } // does our el have a value // in the values array? // or values array is empty const elHasMatchingValue = ($el) => { const value = $elements.getNativeProp($el.get(0), 'value') return (values.length === 0) || values.includes(value) } // blow up if any member of the subject // isnt a checkbox or radio const checkOrUncheckEl = (el) => { const $el = $dom.wrap(el) if (!isAcceptableElement($el)) { const node = $dom.stringify($el) const word = $utils.plural(options.$el, 'contains', 'is') const phrase = type === 'check' ? ' and `:radio`' : '' $errUtils.throwErrByPath('check_uncheck.invalid_element', { onFail: options._log, args: { node, word, phrase, cmd: type }, }) } const isElActionable = elHasMatchingValue($el) if (isElActionable) { matchingElements.push(el) } const consoleProps = { 'Applied To': $dom.getElements($el), 'Elements': $el.length, } if (options.log && isElActionable) { // figure out the userOptions which actually change the behavior of clicks const deltaOptions = $utils.filterOutOptions(options) options._log = Cypress.log({ message: deltaOptions, $el, timeout: options.timeout, consoleProps () { return _.extend(consoleProps, { Options: deltaOptions, }) }, }) options._log.snapshot('before', { next: 'after' }) // if the checkbox was already checked // then notify the user of this note // and bail if (isNoop($el)) { if (!options.force) { // still ensure visibility even if the command is noop cy.ensureVisibility($el, options._log) } if (options._log) { const inputType = $el.is(':radio') ? 'radio' : 'checkbox' consoleProps.Note = `This ${inputType} was already ${type}ed. No operation took place.` options._log.snapshot().end() } return null } } // if we didnt pass in any values or our // el's value is in the array then check it if (isElActionable) { return cy.now('click', $el, { $el, log: false, verify: false, _log: options._log, force: options.force, timeout: options.timeout, interval: options.interval, waitForAnimations: options.waitForAnimations, animationDistanceThreshold: options.animationDistanceThreshold, scrollBehavior: options.scrollBehavior, }).then(() => { if (options._log) { options._log.snapshot().end() } return null }) } } // return our original subject when our promise resolves return Promise .resolve(options.$el.toArray()) .each(checkOrUncheckEl) .then(() => { // filter down our $el to the // matching elements options.$el = options.$el.filter(matchingElements) const verifyAssertions = () => { return cy.verifyUpcomingAssertions(options.$el, options, { onRetry: verifyAssertions, }) } return verifyAssertions() }) } module.exports = function (Commands, Cypress, cy) { return Commands.addAll({ prevSubject: 'element' }, { check (subject, values, options) { return checkOrUncheck.call(this, Cypress, cy, 'check', subject, values, options) }, uncheck (subject, values, options) { return checkOrUncheck.call(this, Cypress, cy, 'uncheck', subject, values, options) }, }) }