UNPKG

@revoloo/cypress6

Version:

Cypress.io end to end testing tool

181 lines (145 loc) 4.89 kB
const _ = require('lodash') const $dom = require('../../../dom') const $utils = require('../../../cypress/utils') const $errUtils = require('../../../cypress/error_utils') const $elements = require('../../../dom/elements') module.exports = (Commands, Cypress, cy) => { return Commands.addAll({ prevSubject: ['element', 'window'] }, { focus (subject, options = {}) { const userOptions = options // we should throw errors by default! // but allow them to be silenced options = _.defaults({}, userOptions, { $el: subject, error: true, log: true, verify: true, }) const isWin = $dom.isWindow(options.$el) if (isWin) { // get this into a jquery object options.$el = $dom.wrap(options.$el) } if (options.log) { options._log = Cypress.log({ $el: options.$el, timeout: options.timeout, consoleProps () { return { 'Applied To': $dom.getElements(options.$el) } }, }) } const el = options.$el.get(0) // the body is not really focusable, but it // can have focus on initial page load. // this is instead a noop. // TODO: throw on body instead (breaking change) const isBody = $dom.isJquery(options.$el) && $elements.isElement(options.$el.get(0)) && $elements.isBody(options.$el.get(0)) // http://www.w3.org/$R/html5/editing.html#specially-focusable // ensure there is only 1 dom element in the subject // make sure its allowed to be focusable if (!(isWin || isBody || $dom.isFocusable(options.$el))) { if (options.error === false) { return } const node = $dom.stringify(options.$el) $errUtils.throwErrByPath('focus.invalid_element', { onFail: options._log, args: { node }, }) } if (options.$el.length && options.$el.length > 1) { if (options.error === false) { return } $errUtils.throwErrByPath('focus.multiple_elements', { onFail: options._log, args: { num: options.$el.length }, }) } cy.fireFocus(el) const verifyAssertions = () => { return cy.verifyUpcomingAssertions(options.$el, options, { onRetry: verifyAssertions, }) } return verifyAssertions() }, blur (subject, options = {}) { const userOptions = options // we should throw errors by default! // but allow them to be silenced options = _.defaults({}, userOptions, { $el: subject, $focused: cy.getFocused(), error: true, log: true, verify: true, force: false, }) const { $focused } = options const isWin = $dom.isWindow(options.$el) if (isWin) { // get this into a jquery object options.$el = $dom.wrap(options.$el) } const isBody = options.$el.is('body') if (options.log) { // figure out the options which actually change the behavior of clicks const deltaOptions = $utils.filterOutOptions(options) options._log = Cypress.log({ $el: options.$el, message: deltaOptions, timeout: options.timeout, consoleProps () { return { 'Applied To': $dom.getElements(options.$el) } }, }) } if (options.$el.length && options.$el.length > 1) { if (options.error === false) { return } $errUtils.throwErrByPath('blur.multiple_elements', { onFail: options._log, args: { num: options.$el.length }, }) } // if we haven't forced the blur, and we don't currently // have a focused element OR we aren't the window or body then error if (options.force !== true && !$focused && !isWin && !isBody) { if (options.error === false) { return } $errUtils.throwErrByPath('blur.no_focused_element', { onFail: options._log }) } // if we're currently window dont check for the wrong // focused element because window will not show up // as $focused if (options.force !== true && !isWin && !isBody && options.$el.get(0) !== $focused.get(0) ) { if (options.error === false) { return } const node = $dom.stringify($focused) $errUtils.throwErrByPath('blur.wrong_focused_element', { onFail: options._log, args: { node }, }) } const el = options.$el.get(0) cy.fireBlur(el) const verifyAssertions = () => { return cy.verifyUpcomingAssertions(options.$el, options, { onRetry: verifyAssertions, }) } return verifyAssertions() }, }) }