diff --git a/cypress/component/advanced/timers/README.md b/cypress/component/advanced/timers/README.md index 6dd03da2..350f7c69 100644 --- a/cypress/component/advanced/timers/README.md +++ b/cypress/component/advanced/timers/README.md @@ -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. diff --git a/cypress/component/advanced/timers/card-spec.js b/cypress/component/advanced/timers/card-spec.js index 23f75c93..d439e17f 100644 --- a/cypress/component/advanced/timers/card-spec.js +++ b/cypress/component/advanced/timers/card-spec.js @@ -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() + 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() + cy.get('@selected', { timeout: 5100 }).should('have.been.calledWith', null) +}) + it('should accept selections', () => { const onSelect = cy.stub() mount() diff --git a/cypress/component/advanced/timers/card-without-effect-spec.js b/cypress/component/advanced/timers/card-without-effect-spec.js index b74e6251..e98556ef 100644 --- a/cypress/component/advanced/timers/card-without-effect-spec.js +++ b/cypress/component/advanced/timers/card-without-effect-spec.js @@ -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() + cy.tick(100).then(() => { expect(onSelect).to.not.have.been.called }) diff --git a/cypress/component/advanced/timers/card.jsx b/cypress/component/advanced/timers/card.jsx index d1b4b66f..82bd9ba7 100644 --- a/cypress/component/advanced/timers/card.jsx +++ b/cypress/component/advanced/timers/card.jsx @@ -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 => (