Skip to content
This repository was archived by the owner on Mar 5, 2022. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions cypress/component/advanced/timers/README.md
Original file line number Diff line number Diff line change
@@ -1 +1,3 @@
example from https://reactjs.org/docs/testing-recipes.html#timers

Your code might use timer-based functions like setTimeout to schedule more work in the future. In this example, a multiple choice panel waits for a selection and advances, timing out if a selection isn’t made in 5 seconds.
38 changes: 35 additions & 3 deletions cypress/component/advanced/timers/card-spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,19 +3,51 @@ import Card from './card.jsx'
import React from 'react'
import { mount } from 'cypress-react-unit-test'

// NOTE: seems our clock control does not work with effect hooks
it.skip('should select null after timing out', () => {
// looking at the clock control from component's hook
// https://github.com/bahmutov/cypress-react-unit-test/issues/200
it('should select null after timing out (fast)', () => {
const onSelect = cy.stub()
// https://on.cypress.io/clock
cy.clock()

mount(<Card onSelect={onSelect} />)
cy.get('button').should('have.length', 4)

// component calls "onSelect" stub after 5 seconds of inactivity
cy.tick(100).then(() => {
// not yet
expect(onSelect).to.not.have.been.called
})
cy.tick(1000).then(() => {
// not yet
expect(onSelect).to.not.have.been.called
})
cy.tick(5000).then(() => {
cy.tick(1000).then(() => {
// not yet
expect(onSelect).to.not.have.been.called
})
cy.tick(1000).then(() => {
// not yet
expect(onSelect).to.not.have.been.called
})
cy.tick(1000).then(() => {
// not yet
expect(onSelect).to.not.have.been.called
})
cy.log('5 seconds passed')
cy.tick(1000).then(() => {
// NOW
expect(onSelect).to.have.been.calledWith(null)
})
})

it('should select null after timing out (slow)', () => {
// without synthetic clock we must wait for the real delay
const onSelect = cy.stub().as('selected')
mount(<Card onSelect={onSelect} />)
cy.get('@selected', { timeout: 5100 }).should('have.been.calledWith', null)
})

it('should accept selections', () => {
const onSelect = cy.stub()
mount(<Card onSelect={onSelect} />)
Expand Down
2 changes: 2 additions & 0 deletions cypress/component/advanced/timers/card-without-effect-spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,10 @@ import { unmountComponentAtNode } from 'react-dom'

it('should select null after timing out', () => {
const onSelect = cy.stub()
// https://on.cypress.io/clock
cy.clock()
mount(<Card onSelect={onSelect} />)

cy.tick(100).then(() => {
expect(onSelect).to.not.have.been.called
})
Expand Down
4 changes: 4 additions & 0 deletions cypress/component/advanced/timers/card.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,17 @@ import React, { useEffect } from 'react'
export default function Card(props) {
useEffect(() => {
const timeoutID = setTimeout(() => {
console.log('after timeout')
props.onSelect(null)
}, 5000)

return () => {
console.log('clearing timeout')
clearTimeout(timeoutID)
}
}, [props.onSelect])

console.log('inside Card')
return [1, 2, 3, 4].map(choice => (
<button
key={choice}
Expand Down
29 changes: 18 additions & 11 deletions lib/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -100,17 +100,24 @@ export const mount = (jsx: React.ReactElement, options: MountOptions = {}) => {
}
}

return cy
.wrap(CypressTestComponent, { log: false })
.as(options.alias || displayName)
.then(() => {
if (logInstance) {
logInstance.snapshot('mounted')
logInstance.end()
}

return undefined
})
return (
cy
.wrap(CypressTestComponent, { log: false })
.as(options.alias || displayName)
// by waiting, we give the component's hook a chance to run
// https://github.com/bahmutov/cypress-react-unit-test/issues/200
.wait(1, { log: false })
.then(() => {
if (logInstance) {
logInstance.snapshot('mounted')
logInstance.end()
}

// by returning undefined we keep the previous subject
// which is the mounted component
return undefined
})
)
})
}

Expand Down