| b69ab31 | | | 1 | /** |
| b69ab31 | | | 2 | * Copyright (c) Meta Platforms, Inc. and affiliates. |
| b69ab31 | | | 3 | * |
| b69ab31 | | | 4 | * This source code is licensed under the MIT license found in the |
| b69ab31 | | | 5 | * LICENSE file in the root directory of this source tree. |
| b69ab31 | | | 6 | */ |
| b69ab31 | | | 7 | |
| b69ab31 | | | 8 | import {gc} from 'shared/testUtils'; |
| b69ab31 | | | 9 | import {Timer} from '../timer'; |
| b69ab31 | | | 10 | |
| b69ab31 | | | 11 | describe('Timer', () => { |
| b69ab31 | | | 12 | beforeEach(() => { |
| b69ab31 | | | 13 | jest.useFakeTimers(); |
| b69ab31 | | | 14 | }); |
| b69ab31 | | | 15 | afterEach(() => { |
| b69ab31 | | | 16 | jest.useRealTimers(); |
| b69ab31 | | | 17 | }); |
| b69ab31 | | | 18 | |
| b69ab31 | | | 19 | it('can enable and disable', () => { |
| b69ab31 | | | 20 | const callback = jest.fn(); |
| b69ab31 | | | 21 | const timer = new Timer(callback, 100); |
| b69ab31 | | | 22 | |
| b69ab31 | | | 23 | timer.enabled = true; |
| b69ab31 | | | 24 | jest.advanceTimersByTime(250); |
| b69ab31 | | | 25 | expect(callback).toHaveBeenCalledTimes(2); |
| b69ab31 | | | 26 | |
| b69ab31 | | | 27 | timer.enabled = false; |
| b69ab31 | | | 28 | jest.advanceTimersByTime(500); |
| b69ab31 | | | 29 | expect(callback).toHaveBeenCalledTimes(2); |
| b69ab31 | | | 30 | |
| b69ab31 | | | 31 | timer.enabled = true; |
| b69ab31 | | | 32 | jest.advanceTimersByTime(200); |
| b69ab31 | | | 33 | expect(callback).toHaveBeenCalledTimes(4); |
| b69ab31 | | | 34 | }); |
| b69ab31 | | | 35 | |
| b69ab31 | | | 36 | it('error once cancels the timer', () => { |
| b69ab31 | | | 37 | const callback = jest.fn(() => { |
| b69ab31 | | | 38 | throw new Error('x'); |
| b69ab31 | | | 39 | }); |
| b69ab31 | | | 40 | |
| b69ab31 | | | 41 | // Initially enabled. |
| b69ab31 | | | 42 | const timer = new Timer(callback, 100, true); |
| b69ab31 | | | 43 | expect(timer.enabled).toBe(true); |
| b69ab31 | | | 44 | |
| b69ab31 | | | 45 | // Try to call 3 times, but the first time it will throw. |
| b69ab31 | | | 46 | try { |
| b69ab31 | | | 47 | jest.advanceTimersByTime(350); |
| b69ab31 | | | 48 | } catch (_e) {} |
| b69ab31 | | | 49 | |
| b69ab31 | | | 50 | // After throw the timer is disabled. |
| b69ab31 | | | 51 | expect(timer.enabled).toBe(false); |
| b69ab31 | | | 52 | expect(callback).toHaveBeenCalledTimes(1); |
| b69ab31 | | | 53 | }); |
| b69ab31 | | | 54 | |
| b69ab31 | | | 55 | it('returning false stops the timer', () => { |
| b69ab31 | | | 56 | let count = 0; |
| b69ab31 | | | 57 | const callback = jest.fn(() => { |
| b69ab31 | | | 58 | count += 1; |
| b69ab31 | | | 59 | return count < 3; |
| b69ab31 | | | 60 | }); |
| b69ab31 | | | 61 | const timer = new Timer(callback, 100, true); |
| b69ab31 | | | 62 | expect(timer.enabled).toBe(true); |
| b69ab31 | | | 63 | jest.advanceTimersByTime(250); |
| b69ab31 | | | 64 | expect(timer.enabled).toBe(true); |
| b69ab31 | | | 65 | jest.advanceTimersByTime(500); |
| b69ab31 | | | 66 | expect(timer.enabled).toBe(false); |
| b69ab31 | | | 67 | expect(callback).toHaveBeenCalledTimes(3); |
| b69ab31 | | | 68 | }); |
| b69ab31 | | | 69 | |
| b69ab31 | | | 70 | it('dispose cancels the timer forever', () => { |
| b69ab31 | | | 71 | const callback = jest.fn(); |
| b69ab31 | | | 72 | const timer = new Timer(callback, 100); |
| b69ab31 | | | 73 | |
| b69ab31 | | | 74 | timer.enabled = true; |
| b69ab31 | | | 75 | jest.advanceTimersByTime(50); |
| b69ab31 | | | 76 | |
| b69ab31 | | | 77 | timer.dispose(); |
| b69ab31 | | | 78 | |
| b69ab31 | | | 79 | // Cannot be re-enabled. |
| b69ab31 | | | 80 | timer.enabled = true; |
| b69ab31 | | | 81 | jest.advanceTimersByTime(500); |
| b69ab31 | | | 82 | expect(timer.enabled).toBe(false); |
| b69ab31 | | | 83 | expect(callback).toHaveBeenCalledTimes(0); |
| b69ab31 | | | 84 | }); |
| b69ab31 | | | 85 | |
| b69ab31 | | | 86 | it('GC cancels the timer forever', async () => { |
| b69ab31 | | | 87 | const callback = jest.fn(); |
| b69ab31 | | | 88 | let timer: Timer | null = new Timer(callback, 100, true); |
| b69ab31 | | | 89 | expect(timer.enabled).toBe(true); |
| b69ab31 | | | 90 | |
| b69ab31 | | | 91 | // GC the timer. |
| b69ab31 | | | 92 | // eslint-disable-next-line @typescript-eslint/no-unused-vars |
| b69ab31 | | | 93 | timer = null; |
| b69ab31 | | | 94 | await gc(); |
| b69ab31 | | | 95 | |
| b69ab31 | | | 96 | // Callback should not be called after the time is gone. |
| b69ab31 | | | 97 | jest.advanceTimersByTime(500); |
| b69ab31 | | | 98 | expect(callback).toHaveBeenCalledTimes(0); |
| b69ab31 | | | 99 | }); |
| b69ab31 | | | 100 | }); |