|
| 1 | +import React from 'react' |
| 2 | +import {render, Simulate} from '../' |
| 3 | + |
| 4 | +class StopWatch extends React.Component { |
| 5 | + state = {lapse: 0, running: false} |
| 6 | + handleRunClick = () => { |
| 7 | + this.setState(state => { |
| 8 | + if (state.running) { |
| 9 | + clearInterval(this.timer) |
| 10 | + } else { |
| 11 | + const startTime = Date.now() - this.state.lapse |
| 12 | + this.timer = setInterval(() => { |
| 13 | + this.setState({lapse: Date.now() - startTime}) |
| 14 | + }) |
| 15 | + } |
| 16 | + return {running: !state.running} |
| 17 | + }) |
| 18 | + } |
| 19 | + handleClearClick = () => { |
| 20 | + clearInterval(this.timer) |
| 21 | + this.setState({lapse: 0, running: false}) |
| 22 | + } |
| 23 | + componentWillUnmount() { |
| 24 | + clearInterval(this.timer) |
| 25 | + } |
| 26 | + render() { |
| 27 | + const {lapse, running} = this.state |
| 28 | + return ( |
| 29 | + <div> |
| 30 | + <span>{lapse}ms</span> |
| 31 | + <button onClick={this.handleRunClick} data-testid="start-stop-button"> |
| 32 | + {running ? 'Stop' : 'Start'} |
| 33 | + </button> |
| 34 | + <button onClick={this.handleClearClick} data-testid="clear-button"> |
| 35 | + Clear |
| 36 | + </button> |
| 37 | + </div> |
| 38 | + ) |
| 39 | + } |
| 40 | +} |
| 41 | + |
| 42 | +const wait = time => new Promise(resolve => setTimeout(resolve, time)) |
| 43 | + |
| 44 | +test('unmounts a component', async () => { |
| 45 | + jest.spyOn(console, 'error').mockImplementation(() => {}) |
| 46 | + const {unmount, queryByTestId, container} = render(<StopWatch />) |
| 47 | + Simulate.click(queryByTestId('start-stop-button')) |
| 48 | + unmount() |
| 49 | + // hey there reader! You don't need to have an assertion like this one |
| 50 | + // this is just me making sure that the unmount function works. |
| 51 | + // You don't need to do this in your apps. Just rely on the fact that this works. |
| 52 | + expect(container.innerHTML).toBe('') |
| 53 | + // just wait to see if the interval is cleared or not |
| 54 | + // if it's not, then we'll call setState on an unmounted component |
| 55 | + // and get an error. |
| 56 | + await wait() |
| 57 | + // eslint-disable-next-line no-console |
| 58 | + expect(console.error).not.toHaveBeenCalled() |
| 59 | +}) |
0 commit comments