Skip to content

Commit

Permalink
Do not mutate options argument.
Browse files Browse the repository at this point in the history
  • Loading branch information
sainthkh committed Dec 4, 2019
1 parent 0cedf1d commit 7292ec8
Show file tree
Hide file tree
Showing 26 changed files with 731 additions and 682 deletions.
42 changes: 20 additions & 22 deletions packages/driver/src/cy/commands/actions/check.coffee
Original file line number Diff line number Diff line change
Expand Up @@ -18,14 +18,12 @@ checkOrUncheck = (type, subject, values = [], options = {}) ->
## make sure we're an array of values
values = [].concat(values)

userOptions = Object.assign({}, options)

## keep an array of subjects which
## are potentially reduced down
## to new filtered subjects
matchingElements = []

_.defaults options,
opts = _.defaults {}, options,
$el: subject
log: true
force: false
Expand Down Expand Up @@ -58,10 +56,10 @@ checkOrUncheck = (type, subject, values = [], options = {}) ->

if not isAcceptableElement($el)
node = $dom.stringify($el)
word = $utils.plural(options.$el, "contains", "is")
word = $utils.plural(opts.$el, "contains", "is")
phrase = if type is "check" then " and :radio" else ""
$utils.throwErrByPath "check_uncheck.invalid_element", {
onFail: options._log
onFail: opts._log
args: { node, word, phrase, cmd: type }
}

Expand All @@ -75,33 +73,33 @@ checkOrUncheck = (type, subject, values = [], options = {}) ->
"Elements": $el.length
}

if options.log and isElActionable
if opts.log and isElActionable

## figure out the options which actually change the behavior of clicks
deltaOptions = $utils.filterOutOptions(options)
deltaOptions = $utils.filterOutOptions(opts)

options._log = Cypress.log
options: userOptions
opts._log = Cypress.log
options: options
$el: $el
consoleProps: ->
_.extend consoleProps, {
Options: deltaOptions
}

options._log.snapshot("before", {next: "after"})
opts._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
if !opts.force
## still ensure visibility even if the command is noop
cy.ensureVisibility($el, options._log)
if options._log
cy.ensureVisibility($el, opts._log)
if opts._log
inputType = if $el.is(":radio") then "radio" else "checkbox"
consoleProps.Note = "This #{inputType} was already #{type}ed. No operation took place."
options._log.snapshot().end()
opts._log.snapshot().end()

return null

Expand All @@ -112,26 +110,26 @@ checkOrUncheck = (type, subject, values = [], options = {}) ->
$el: $el
log: false
verify: false
_log: options._log
force: options.force
timeout: options.timeout
interval: options.interval
_log: opts._log
force: opts.force
timeout: opts.timeout
interval: opts.interval
}).then ->
options._log.snapshot().end() if options._log
opts._log.snapshot().end() if opts._log

return null

## return our original subject when our promise resolves
Promise
.resolve(options.$el.toArray())
.resolve(opts.$el.toArray())
.each(checkOrUncheckEl)
.then ->
## filter down our $el to the
## matching elements
options.$el = options.$el.filter(matchingElements)
opts.$el = opts.$el.filter(matchingElements)

do verifyAssertions = =>
cy.verifyUpcomingAssertions(options.$el, options, {
cy.verifyUpcomingAssertions(opts.$el, opts, {
onRetry: verifyAssertions
})

Expand Down
59 changes: 29 additions & 30 deletions packages/driver/src/cy/commands/actions/click.js
Original file line number Diff line number Diff line change
Expand Up @@ -41,14 +41,13 @@ module.exports = (Commands, Cypress, cy, state, config) => {

({ options, position, x, y } = $actionability.getPositionFromArguments(positionOrX, y, options))

const userOptions = Object.assign({}, options)
const message = $utils.stringify([
position ? `position: ${position}` : undefined,
x ? `x: ${x}` : undefined,
y ? `y: ${y}` : undefined,
])

_.defaults(options, {
const opts = _.defaults({}, options, {
$el: subject,
log: true,
verify: true,
Expand All @@ -65,33 +64,33 @@ module.exports = (Commands, Cypress, cy, state, config) => {

// throw if we're trying to click multiple elements
// and we did not pass the multiple flag
if ((options.multiple === false) && (options.$el.length > 1)) {
if ((opts.multiple === false) && (opts.$el.length > 1)) {
$utils.throwErrByPath('click.multiple_elements', {
args: { cmd: eventName, num: options.$el.length },
args: { cmd: eventName, num: opts.$el.length },
})
}

const perform = (el) => {
let deltaOptions
const $el = $dom.wrap(el)

if (options.log) {
if (opts.log) {
// figure out the options which actually change the behavior of clicks
deltaOptions = $utils.filterOutOptions(options, defaultOptions)
deltaOptions = $utils.filterOutOptions(opts, defaultOptions)

options._log = Cypress.log({
opts._log = Cypress.log({
message,
options: userOptions,
options,
$el,
})

options._log.snapshot('before', { next: 'after' })
opts._log.snapshot('before', { next: 'after' })
}

if (options.errorOnSelect && $el.is('select')) {
if (opts.errorOnSelect && $el.is('select')) {
$utils.throwErrByPath('click.on_select_element', {
args: { cmd: eventName },
onFail: options._log,
onFail: opts._log,
})
}

Expand All @@ -105,19 +104,19 @@ module.exports = (Commands, Cypress, cy, state, config) => {

const elClicked = domEvents.moveEvents.el

if (options._log) {
consoleObj = options._log.invoke('consoleProps')
if (opts._log) {
consoleObj = opts._log.invoke('consoleProps')
}

const consoleProps = function () {
consoleObj = _.defaults(consoleObj != null ? consoleObj : {}, {
'Applied To': $dom.getElements(options.$el),
'Elements': options.$el.length,
'Applied To': $dom.getElements(opts.$el),
'Elements': opts.$el.length,
'Coords': _.pick(fromElWindow, 'x', 'y'), // always absolute
'Options': deltaOptions,
})

if (options.$el.get(0) !== elClicked) {
if (opts.$el.get(0) !== elClicked) {
// only do this if $elToClick isnt $el
consoleObj['Actual Element Clicked'] = $dom.getElements($(elClicked))
}
Expand All @@ -131,18 +130,18 @@ module.exports = (Commands, Cypress, cy, state, config) => {
.delay($actionability.delay, 'click')
.then(() => {
// display the red dot at these coords
if (options._log) {
if (opts._log) {
// because we snapshot and output a command per click
// we need to manually snapshot + end them
options._log.set({ coords: fromAutWindow, consoleProps })
opts._log.set({ coords: fromAutWindow, consoleProps })
}

// we need to split this up because we want the coordinates
// to mutate our passed in options._log but we dont necessary
// to mutate our passed in opts._log but we dont necessary
// want to snapshot and end our command if we're a different
// action like (cy.type) and we're borrowing the click action
if (options._log && options.log) {
return options._log.snapshot().end()
if (opts._log && opts.log) {
return opts._log.snapshot().end()
}
})
.return(null)
Expand All @@ -152,15 +151,15 @@ module.exports = (Commands, Cypress, cy, state, config) => {
// because we're issuing the clicks synchonrously
// once we establish the coordinates and the element
// passes all of the internal checks
return $actionability.verify(cy, $el, options, {
return $actionability.verify(cy, $el, opts, {
onScroll ($el, type) {
return Cypress.action('cy:scrolled', $el, type)
},

onReady ($elToClick, coords) {
const { fromElViewport, fromElWindow, fromAutWindow } = coords

const forceEl = options.force && $elToClick.get(0)
const forceEl = opts.force && $elToClick.get(0)

const moveEvents = mouse.move(fromElViewport, forceEl)

Expand All @@ -177,26 +176,26 @@ module.exports = (Commands, Cypress, cy, state, config) => {
.catch((err) => {
// snapshot only on click failure
err.onFail = function () {
if (options._log) {
return options._log.snapshot()
if (opts._log) {
return opts._log.snapshot()
}
}

// if we give up on waiting for actionability then
// lets throw this error and log the command
return $utils.throwErr(err, { onFail: options._log })
return $utils.throwErr(err, { onFail: opts._log })
})
}

return Promise
.each(options.$el.toArray(), perform)
.each(opts.$el.toArray(), perform)
.then(() => {
if (options.verify === false) {
return options.$el
if (opts.verify === false) {
return opts.$el
}

const verifyAssertions = () => {
return cy.verifyUpcomingAssertions(options.$el, options, {
return cy.verifyUpcomingAssertions(opts.$el, opts, {
onRetry: verifyAssertions,
})
}
Expand Down
Loading

0 comments on commit 7292ec8

Please sign in to comment.