From d7c50a87d11b922ea44ade4dfc4ddc650bd42087 Mon Sep 17 00:00:00 2001 From: Jason Staten Date: Sat, 2 Nov 2019 21:25:41 -0600 Subject: [PATCH] feat: flush intervals by 50 ms default --- src/__tests__/stopwatch.js | 104 ++++++++++++++++++++++--------------- src/pure.js | 20 ++++--- 2 files changed, 74 insertions(+), 50 deletions(-) diff --git a/src/__tests__/stopwatch.js b/src/__tests__/stopwatch.js index d4cd606..51771fc 100644 --- a/src/__tests__/stopwatch.js +++ b/src/__tests__/stopwatch.js @@ -1,56 +1,74 @@ -import React from 'react' -import {render, fireEvent} from '../' +import angular from 'angular' +import 'angular-mocks' +import {render, fireEvent, wait} from '../' + +class StopWatch { + lapse = 0 + running = false + + constructor($interval) { + this.$interval = $interval + } -class StopWatch extends React.Component { - state = {lapse: 0, running: false} handleRunClick = () => { - this.setState(state => { - if (state.running) { - clearInterval(this.timer) - } else { - const startTime = Date.now() - this.state.lapse - this.timer = setInterval(() => { - this.setState({lapse: Date.now() - startTime}) - }) - } - return {running: !state.running} - }) + if (this.running) { + clearInterval(this.timer) + } else { + const startTime = Date.now() - this.lapse + this.timer = this.$interval(() => { + this.lapse = Date.now() - startTime + }) + } + this.running = !this.running } + handleClearClick = () => { - clearInterval(this.timer) - this.setState({lapse: 0, running: false}) + this.$interval.cancel(this.timer) + this.lapse = 0 + this.running = false } - componentWillUnmount() { - clearInterval(this.timer) - } - render() { - const {lapse, running} = this.state - return ( -
- {lapse}ms - - -
- ) + + $onDestroy() { + this.$interval.cancel(this.timer) } } -const wait = time => new Promise(resolve => setTimeout(resolve, time)) +const template = ` +
+ {{$ctrl.lapse}}ms + + +
+` + +beforeEach(() => { + angular.module('atl', []) + angular.mock.module('atl') + angular.module('atl').component('atlStopwatch', { + template, + controller: StopWatch, + }) +}) test('unmounts a component', async () => { - jest.spyOn(console, 'error').mockImplementation(() => {}) - const {unmount, getByText, container} = render() + const {$scope, unmount, getByText, getByTestId} = render( + ``, + ) + const elapsedTime = getByTestId('elapsed') + + expect(elapsedTime).toHaveTextContent('0ms') + fireEvent.click(getByText('Start')) + // Ensure it starts + getByText('Stop') + + await wait() + + expect(elapsedTime.textContent).not.toEqual('0ms') + unmount() - // hey there reader! You don't need to have an assertion like this one - // this is just me making sure that the unmount function works. - // You don't need to do this in your apps. Just rely on the fact that this works. - expect(container.innerHTML).toBe('') - // just wait to see if the interval is cleared or not - // if it's not, then we'll call setState on an unmounted component - // and get an error. - // eslint-disable-next-line no-console - await wait(() => expect(console.error).not.toHaveBeenCalled()) + + expect($scope.$$destroyed).toBe(true) }) diff --git a/src/pure.js b/src/pure.js index b91c578..dfa6f46 100644 --- a/src/pure.js +++ b/src/pure.js @@ -59,6 +59,9 @@ function render(ui, {container, baseElement = container, queries, scope} = {}) { return template.content }, $scope, + unmount: () => { + $scope.$destroy() + }, ...getQueriesForElement(baseElement, queries), } } @@ -79,6 +82,7 @@ function cleanupAtContainer(container) { function cleanupScope(scope) { scope.$destroy() + mountedScopes.delete(scope) } function getAngularService(name) { @@ -112,16 +116,18 @@ Object.keys(dtlFireEvent).forEach(key => { fireEvent.mouseEnter = fireEvent.mouseOver fireEvent.mouseLeave = fireEvent.mouseOut -function flush() { +function flush(millis = 50) { const $browser = getAngularService('$browser') - if ($browser.deferredFns.length) { - $browser.defer.flush() - } + const $rootScope = getAngularService('$rootScope') + const $interval = getAngularService('$interval') + $interval.flush(millis) + $browser.defer.flush(millis) + $rootScope.$digest() } -function wait(callback, options) { - dtlWait(() => { - flush() +function wait(callback, options = {}) { + return dtlWait(() => { + flush(options.interval) if (callback) { callback() } -- 2.45.2