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 => (