Skip to content

Commit

Permalink
feat: add .else() command (#9)
Browse files Browse the repository at this point in the history
  • Loading branch information
bahmutov committed Aug 31, 2022
1 parent 06329d4 commit 0d84a27
Show file tree
Hide file tree
Showing 5 changed files with 155 additions and 10 deletions.
1 change: 1 addition & 0 deletions .gitignore
@@ -1,2 +1,3 @@
node_modules/
cypress/videos/
cypress/screenshots/
12 changes: 12 additions & 0 deletions README.md
Expand Up @@ -54,6 +54,18 @@ You can use assertions with `not`
cy.get('#enrolled').if('not.checked').check()
```

## else command

You can chain `.else()` command that is only executed if the `.if()` is skipped.

```js
cy.contains('Accept cookies')
.if('visible')
.click()
.else()
.log('no cookie banner')
```

## Debugging

This module uses [debug](https://github.com/debug-js/debug#readme) module to output verbose browser console messages when needed. To turn the logging on, open the browser's DevTools console and set the local storage entry:
Expand Down
38 changes: 38 additions & 0 deletions cypress/e2e/checked.cy.js
Expand Up @@ -12,4 +12,42 @@ describe('checkbox', () => {
cy.visit('cypress/checkbox.html')
cy.get('#agreed').if('not.checked').check()
})

context('with else() branches', () => {
it('logs a message when nothing to check', () => {
cy.visit('cypress/checkbox.html')
cy.get('#agreed')
.if('not.checked')
.check()
.else()
.log('**already agreed**')
})

it('handles if().else() short chain', () => {
cy.visit('cypress/checkbox.html')
cy.get('#enrolled').if('checked').else().check()
cy.get('#enrolled').should('be.checked')
})

it('checks the button if not checked', () => {
cy.visit('cypress/checkbox.html')
cy.get('#enrolled')
.if('checked')
// .log('**already enrolled**')
.else()
.check()
cy.get('#enrolled').should('be.checked')
})

it.skip('passes the subject to the else() branch', () => {
cy.visit('cypress/checkbox.html')
cy.get('#enrolled')
.if('checked')
.log('**already enrolled**')
// the checkbox should be passed into .else()
.else()
.check()
cy.get('#enrolled').should('be.checked')
})
})
})
35 changes: 35 additions & 0 deletions cypress/e2e/else.cy.js
@@ -0,0 +1,35 @@
/// <reference types="cypress" />

import '../../src'

describe('else branch', () => {
it('takes the if branch', () => {
cy.wrap(42).if('equal', 42).log('if branch').else().log('else branch')
})

it('takes the else branch', () => {
cy.wrap(42).if('equal', 1).log('if branch').else().log('else branch')
})

context('with checks', () => {
it('calls actions in the if branch', () => {
cy.wrap(42)
.if('equal', 42)
.then(cy.spy().as('if'))
.else()
.then(cy.spy().as('else'))
cy.get('@if').should('have.been.calledOnce')
cy.get('@else').should('not.be.called')
})

it('calls actions in the else branch', () => {
cy.wrap(42)
.if('equal', 1)
.then(cy.spy().as('if'))
.else()
.then(cy.spy().as('else'))
cy.get('@else').should('have.been.calledOnce')
cy.get('@if').should('not.be.called')
})
})
})
79 changes: 69 additions & 10 deletions src/index.js
@@ -1,5 +1,19 @@
const debug = require('debug')('cypress-if')

function skipRestOfTheChain(cmd) {
while (cmd) {
if (cmd.attributes.type === 'parent' && cmd.attributes.name !== 'log') {
// stop checking because found new chain
debug('found parent command "%s"', cmd.attributes.name)
cmd = null
} else {
debug('skipping "%s"', cmd.attributes.name)
cmd.attributes.skip = true
cmd = cmd.attributes.next
}
}
}

Cypress.Commands.add(
'if',
{ prevSubject: true },
Expand Down Expand Up @@ -40,29 +54,74 @@ Cypress.Commands.add(
nextCommand.attributes.name,
)
// cy.log(`**skipping ${cmd.attributes.next.attributes.name}**`)
debug('skipping "%s"', nextCommand.attributes.name)
debug(nextCommand.attributes)
nextCommand.attributes.skip = true

nextCommand = nextCommand.attributes.next
if (nextCommand && nextCommand.attributes.type === 'parent') {
debug(
'stop skipping commands, see a parent command "%s"',
nextCommand.attributes.name,
)
if (nextCommand.attributes.name === 'else') {
debug('else branch starts right away')
nextCommand = null
} else {
debug('skipping "%s"', nextCommand.attributes.name)
debug(nextCommand.attributes)
nextCommand.attributes.skip = true

nextCommand = nextCommand.attributes.next
if (nextCommand) {
if (nextCommand.attributes.type === 'parent') {
debug(
'stop skipping commands, see a parent command "%s"',
nextCommand.attributes.name,
)
nextCommand = null
} else if (nextCommand.attributes.name === 'else') {
debug('stop skipping command on "else" command')
nextCommand = null
}
}
}
}

if (subject) {
cy.wrap(subject, { log: false })
}
return
} else {
// skip possible "else" branch
debug('skipping a possible "else" branch')
let nextCommand = cmd.attributes.next
while (nextCommand) {
debug(
'next command "%s" type "%s"',
nextCommand.attributes.name,
nextCommand.attributes.type,
nextCommand.attributes,
)
if (nextCommand.attributes.type === 'parent') {
// ignore the "cy.log" - even if it is a parent
if (nextCommand.attributes.name !== 'log') {
// stop checking because found new chain
nextCommand = null
} else {
nextCommand = nextCommand.attributes.next
}
} else if (nextCommand.attributes.name === 'else') {
// found the "else" command, start skipping
debug('found the "else" branch command start')
skipRestOfTheChain(nextCommand)
nextCommand = null
} else {
nextCommand = nextCommand.attributes.next
}
}
}
return subject
},
)

Cypress.Commands.add('else', { prevSubject: true }, (subject) => {
debug('else command, subject', subject)
if (subject) {
cy.wrap(subject, { log: false })
}
})

Cypress.Commands.overwrite('get', function (get, selector) {
// can we see the next command already?
const cmd = cy.state('current')
Expand Down

0 comments on commit 0d84a27

Please sign in to comment.