@khanacademy/wonder-blocks-timing 1.2.3 → 2.0.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/es/index.js +151 -48
- package/dist/index.js +309 -159
- package/docs.md +28 -18
- package/package.json +4 -4
- package/src/components/__tests__/action-scheduler-provider.test.js +3 -3
- package/src/components/action-scheduler-provider.js +2 -2
- package/src/components/with-action-scheduler.js +8 -4
- package/src/hooks/__tests__/use-timeout.test.js +336 -0
- package/src/hooks/use-timeout.js +70 -0
- package/src/hooks/use-timeout.stories.mdx +152 -0
- package/src/index.js +2 -0
- package/src/util/__tests__/action-scheduler.test.js +103 -88
- package/src/util/__tests__/animation-frame.test.js +29 -20
- package/src/util/__tests__/interval.test.js +51 -25
- package/src/util/__tests__/timeout.test.js +35 -20
- package/src/util/action-scheduler.js +41 -16
- package/src/util/animation-frame.js +26 -13
- package/src/util/interval.js +19 -13
- package/src/util/policies.js +10 -0
- package/src/util/timeout.js +23 -13
- package/src/util/types.js +26 -26
|
@@ -0,0 +1,152 @@
|
|
|
1
|
+
import {Meta, Story, Source, Canvas} from "@storybook/addon-docs";
|
|
2
|
+
|
|
3
|
+
import {Body, HeadingSmall} from "@khanacademy/wonder-blocks-typography";
|
|
4
|
+
import {View} from "@khanacademy/wonder-blocks-core";
|
|
5
|
+
import Button from "@khanacademy/wonder-blocks-button";
|
|
6
|
+
|
|
7
|
+
import {ClearPolicy, SchedulePolicy} from "../util/policies.js";
|
|
8
|
+
import {useTimeout} from "./use-timeout.js";
|
|
9
|
+
|
|
10
|
+
<Meta
|
|
11
|
+
title="Timing/useTimeout"
|
|
12
|
+
parameters={{
|
|
13
|
+
chromatic: {
|
|
14
|
+
disableSnapshot: true,
|
|
15
|
+
},
|
|
16
|
+
}}
|
|
17
|
+
/>
|
|
18
|
+
|
|
19
|
+
# `useTimeout`
|
|
20
|
+
|
|
21
|
+
`useTimeout` is a hook that provides a convenient API for setting and clearing
|
|
22
|
+
a timeout. It is defined as follows:
|
|
23
|
+
|
|
24
|
+
```ts
|
|
25
|
+
function useTimeout(
|
|
26
|
+
action: () => mixed,
|
|
27
|
+
timeoutMs: number,
|
|
28
|
+
options?: {|
|
|
29
|
+
schedulePolicy?: "schedule-immediately" | "schedule-on-demand",
|
|
30
|
+
clearPolicy?: "resolve-on-clear" | "cancel-on-clear",
|
|
31
|
+
|},
|
|
32
|
+
): ITimeout;
|
|
33
|
+
|
|
34
|
+
interface ITimeout {
|
|
35
|
+
get isSet(): boolean;
|
|
36
|
+
set(): void;
|
|
37
|
+
clear(policy?: ClearPolicy): void;
|
|
38
|
+
}
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
By default the timeout will be set immediately up creation. The `options` parameter can
|
|
42
|
+
be used to control when when the timeout is schedule and whether or not `action` should be
|
|
43
|
+
called when the timeout is cleared.
|
|
44
|
+
|
|
45
|
+
Notes:
|
|
46
|
+
|
|
47
|
+
- Because `clear` takes a param, it's import that you don't pass it directly to an event handler,
|
|
48
|
+
e.g. `<Button onClick={clear} />` will not work as expected.
|
|
49
|
+
- Calling `set` after the timeout has expired will restart the timeout.
|
|
50
|
+
- Updating the second paramter, `timeoutMs`, will also restart the timeout.
|
|
51
|
+
- When the component using this hooks is unmounted, the timeout will automatically be cleared.
|
|
52
|
+
- Calling `set` after the timeout is set but before it expires means that the timeout will be
|
|
53
|
+
reset and will call `action`, `timeoutMs` after the most recent call to `set` was made.
|
|
54
|
+
|
|
55
|
+
export const Immediately = () => {
|
|
56
|
+
const [callCount, setCallCount] = React.useState(0);
|
|
57
|
+
const callback = React.useCallback(() => {
|
|
58
|
+
setCallCount((callCount) => callCount + 1);
|
|
59
|
+
}, []);
|
|
60
|
+
const {isSet, set, clear} = useTimeout(callback, 1000);
|
|
61
|
+
return (
|
|
62
|
+
<View>
|
|
63
|
+
<View>isSet = {isSet.toString()}</View>
|
|
64
|
+
<View>callCount = {callCount}</View>
|
|
65
|
+
<View style={{flexDirection: "row"}}>
|
|
66
|
+
<Button onClick={set}>Set timeout</Button>
|
|
67
|
+
<Button onClick={clear}>Clear timeout</Button>
|
|
68
|
+
</View>
|
|
69
|
+
</View>
|
|
70
|
+
);
|
|
71
|
+
};
|
|
72
|
+
|
|
73
|
+
<Canvas>
|
|
74
|
+
<Story name="Immediately">
|
|
75
|
+
<Immediately />
|
|
76
|
+
</Story>
|
|
77
|
+
</Canvas>
|
|
78
|
+
|
|
79
|
+
```jsx
|
|
80
|
+
const Immediately = () => {
|
|
81
|
+
const [callCount, setCallCount] = React.useState(0);
|
|
82
|
+
const callback = React.useCallback(() => {
|
|
83
|
+
setCallCount((callCount) => callCount + 1);
|
|
84
|
+
}, []);
|
|
85
|
+
const {isSet, set, clear} = useTimeout(callback, 1000);
|
|
86
|
+
return (
|
|
87
|
+
<View>
|
|
88
|
+
<View>isSet = {isSet.toString()}</View>
|
|
89
|
+
<View>callCount = {callCount}</View>
|
|
90
|
+
<View style={{flexDirection: "row"}}>
|
|
91
|
+
<Button onClick={() => set()}>Set timeout</Button>
|
|
92
|
+
<Button onClick={() => clear()}>Clear timeout</Button>
|
|
93
|
+
</View>
|
|
94
|
+
</View>
|
|
95
|
+
);
|
|
96
|
+
};
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
export const OnDemandAndResolveOnClear = () => {
|
|
100
|
+
const [callCount, setCallCount] = React.useState(0);
|
|
101
|
+
const callback = React.useCallback(() => {
|
|
102
|
+
console.log("action called");
|
|
103
|
+
setCallCount((callCount) => callCount + 1);
|
|
104
|
+
}, []);
|
|
105
|
+
const {isSet, set, clear} = useTimeout(callback, 1000, {
|
|
106
|
+
clearPolicy: ClearPolicy.Resolve,
|
|
107
|
+
schedulePolicy: SchedulePolicy.OnDemand,
|
|
108
|
+
});
|
|
109
|
+
return (
|
|
110
|
+
<View>
|
|
111
|
+
<View>isSet = {isSet.toString()}</View>
|
|
112
|
+
<View>callCount = {callCount}</View>
|
|
113
|
+
<View style={{flexDirection: "row"}}>
|
|
114
|
+
<Button onClick={() => set()}>Set timeout</Button>
|
|
115
|
+
<Button onClick={() => clear()}>Clear timeout</Button>
|
|
116
|
+
</View>
|
|
117
|
+
</View>
|
|
118
|
+
);
|
|
119
|
+
};
|
|
120
|
+
|
|
121
|
+
<Canvas>
|
|
122
|
+
<Story name="OnDemandAndResolveOnClear">
|
|
123
|
+
<OnDemandAndResolveOnClear />
|
|
124
|
+
</Story>
|
|
125
|
+
</Canvas>
|
|
126
|
+
|
|
127
|
+
```jsx
|
|
128
|
+
const OnDemandAndResolveOnClear = () => {
|
|
129
|
+
const [callCount, setCallCount] = React.useState(0);
|
|
130
|
+
const callback = React.useCallback(() => {
|
|
131
|
+
setCallCount((callCount) => callCount + 1);
|
|
132
|
+
}, []);
|
|
133
|
+
const {isSet, set, clear} = useTimeout(
|
|
134
|
+
callback,
|
|
135
|
+
1000,
|
|
136
|
+
{
|
|
137
|
+
clearPolicy: ClearPolicy.Resolve,
|
|
138
|
+
schedulePolicy: SchedulePolicy.OnDemand,
|
|
139
|
+
},
|
|
140
|
+
);
|
|
141
|
+
return (
|
|
142
|
+
<View>
|
|
143
|
+
<View>isSet = {isSet.toString()}</View>
|
|
144
|
+
<View>callCount = {callCount}</View>
|
|
145
|
+
<View style={{flexDirection: "row"}}>
|
|
146
|
+
<Button onClick={() => set()}>Set timeout</Button>
|
|
147
|
+
<Button onClick={() => clear()}>Clear timeout</Button>
|
|
148
|
+
</View>
|
|
149
|
+
</View>
|
|
150
|
+
);
|
|
151
|
+
};
|
|
152
|
+
```
|
package/src/index.js
CHANGED
|
@@ -3,6 +3,7 @@ import ActionScheduler from "../action-scheduler.js";
|
|
|
3
3
|
import Timeout from "../timeout.js";
|
|
4
4
|
import Interval from "../interval.js";
|
|
5
5
|
import AnimationFrame from "../animation-frame.js";
|
|
6
|
+
import {SchedulePolicy, ClearPolicy} from "../policies.js";
|
|
6
7
|
|
|
7
8
|
jest.mock("../timeout.js");
|
|
8
9
|
jest.mock("../interval.js");
|
|
@@ -38,55 +39,54 @@ describe("ActionScheduler", () => {
|
|
|
38
39
|
expect(result).toBeDefined();
|
|
39
40
|
});
|
|
40
41
|
|
|
41
|
-
it("should pass
|
|
42
|
+
it("should pass schedule policy to Timeout", () => {
|
|
42
43
|
// Arrange
|
|
43
44
|
const actionScheduler = new ActionScheduler();
|
|
44
45
|
const action = jest.fn();
|
|
46
|
+
const options = {
|
|
47
|
+
schedulePolicy: SchedulePolicy.Immediately,
|
|
48
|
+
};
|
|
45
49
|
|
|
46
50
|
// Act
|
|
47
|
-
actionScheduler.timeout(action, 42,
|
|
51
|
+
actionScheduler.timeout(action, 42, options);
|
|
48
52
|
|
|
49
53
|
// Assert
|
|
50
|
-
expect(Timeout).toHaveBeenCalledWith(
|
|
54
|
+
expect(Timeout).toHaveBeenCalledWith(
|
|
55
|
+
action,
|
|
56
|
+
42,
|
|
57
|
+
SchedulePolicy.Immediately,
|
|
58
|
+
);
|
|
51
59
|
});
|
|
52
60
|
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
false,
|
|
62
|
-
true,
|
|
63
|
-
);
|
|
61
|
+
it("should pass clear policy to timeout.clear on clearAll", () => {
|
|
62
|
+
// Arrange
|
|
63
|
+
const actionScheduler = new ActionScheduler();
|
|
64
|
+
const action = jest.fn();
|
|
65
|
+
const options = {
|
|
66
|
+
clearPolicy: ClearPolicy.Resolve,
|
|
67
|
+
};
|
|
68
|
+
const testTimeout = actionScheduler.timeout(action, 42, options);
|
|
64
69
|
|
|
65
|
-
|
|
66
|
-
|
|
70
|
+
// Act
|
|
71
|
+
actionScheduler.clearAll();
|
|
67
72
|
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
73
|
+
// Assert
|
|
74
|
+
// $FlowIgnore[method-unbinding]
|
|
75
|
+
expect(testTimeout.clear).toHaveBeenCalledWith(ClearPolicy.Resolve);
|
|
76
|
+
});
|
|
72
77
|
|
|
73
|
-
|
|
78
|
+
describe("when scheduler is disabled", () => {
|
|
79
|
+
it("should return a noop timeout", () => {
|
|
74
80
|
// Arrange
|
|
75
81
|
const actionScheduler = new ActionScheduler();
|
|
76
82
|
const action = jest.fn();
|
|
77
|
-
const testTimeout = actionScheduler.timeout(
|
|
78
|
-
action,
|
|
79
|
-
42,
|
|
80
|
-
false,
|
|
81
|
-
false,
|
|
82
|
-
);
|
|
83
83
|
|
|
84
84
|
// Act
|
|
85
|
-
actionScheduler.
|
|
85
|
+
actionScheduler.disable();
|
|
86
|
+
const result = actionScheduler.timeout(action, 42);
|
|
86
87
|
|
|
87
88
|
// Assert
|
|
88
|
-
|
|
89
|
-
expect(testTimeout.clear).toHaveBeenCalledWith(false);
|
|
89
|
+
expect(result).toBe(ActionScheduler.NoopAction);
|
|
90
90
|
});
|
|
91
91
|
});
|
|
92
92
|
});
|
|
@@ -104,55 +104,56 @@ describe("ActionScheduler", () => {
|
|
|
104
104
|
expect(result).toBeDefined();
|
|
105
105
|
});
|
|
106
106
|
|
|
107
|
-
it("should pass
|
|
107
|
+
it("should pass schedule policy to Interval", () => {
|
|
108
108
|
// Arrange
|
|
109
109
|
const actionScheduler = new ActionScheduler();
|
|
110
110
|
const action = jest.fn();
|
|
111
|
+
const options = {
|
|
112
|
+
schedulePolicy: SchedulePolicy.Immediately,
|
|
113
|
+
};
|
|
111
114
|
|
|
112
115
|
// Act
|
|
113
|
-
actionScheduler.interval(action, 42,
|
|
116
|
+
actionScheduler.interval(action, 42, options);
|
|
114
117
|
|
|
115
118
|
// Assert
|
|
116
|
-
expect(Interval).toHaveBeenCalledWith(
|
|
119
|
+
expect(Interval).toHaveBeenCalledWith(
|
|
120
|
+
action,
|
|
121
|
+
42,
|
|
122
|
+
SchedulePolicy.Immediately,
|
|
123
|
+
);
|
|
117
124
|
});
|
|
118
125
|
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
false,
|
|
128
|
-
true,
|
|
129
|
-
);
|
|
126
|
+
it("should pass clear policy to interval.clear on clearAll", () => {
|
|
127
|
+
// Arrange
|
|
128
|
+
const actionScheduler = new ActionScheduler();
|
|
129
|
+
const action = jest.fn();
|
|
130
|
+
const options = {
|
|
131
|
+
clearPolicy: ClearPolicy.Resolve,
|
|
132
|
+
};
|
|
133
|
+
const testInterval = actionScheduler.interval(action, 42, options);
|
|
130
134
|
|
|
131
|
-
|
|
132
|
-
|
|
135
|
+
// Act
|
|
136
|
+
actionScheduler.clearAll();
|
|
133
137
|
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
+
// Assert
|
|
139
|
+
// $FlowIgnore[method-unbinding]
|
|
140
|
+
expect(testInterval.clear).toHaveBeenCalledWith(
|
|
141
|
+
ClearPolicy.Resolve,
|
|
142
|
+
);
|
|
143
|
+
});
|
|
138
144
|
|
|
139
|
-
|
|
145
|
+
describe("when scheduler is disabled", () => {
|
|
146
|
+
it("should return a noop interval", () => {
|
|
140
147
|
// Arrange
|
|
141
148
|
const actionScheduler = new ActionScheduler();
|
|
142
149
|
const action = jest.fn();
|
|
143
|
-
const testInterval = actionScheduler.interval(
|
|
144
|
-
action,
|
|
145
|
-
42,
|
|
146
|
-
false,
|
|
147
|
-
false,
|
|
148
|
-
);
|
|
149
150
|
|
|
150
151
|
// Act
|
|
151
|
-
actionScheduler.
|
|
152
|
+
actionScheduler.disable();
|
|
153
|
+
const result = actionScheduler.interval(action, 42);
|
|
152
154
|
|
|
153
155
|
// Assert
|
|
154
|
-
|
|
155
|
-
expect(testInterval.clear).toHaveBeenCalledWith(false);
|
|
156
|
+
expect(result).toBe(ActionScheduler.NoopAction);
|
|
156
157
|
});
|
|
157
158
|
});
|
|
158
159
|
});
|
|
@@ -170,53 +171,53 @@ describe("ActionScheduler", () => {
|
|
|
170
171
|
expect(result).toBeDefined();
|
|
171
172
|
});
|
|
172
173
|
|
|
173
|
-
it("should pass
|
|
174
|
+
it("should pass schedule policy to AnimationFrame", () => {
|
|
174
175
|
// Arrange
|
|
175
176
|
const actionScheduler = new ActionScheduler();
|
|
176
177
|
const action = jest.fn();
|
|
178
|
+
const options = {
|
|
179
|
+
schedulePolicy: SchedulePolicy.Immediately,
|
|
180
|
+
};
|
|
177
181
|
|
|
178
182
|
// Act
|
|
179
|
-
actionScheduler.animationFrame(action,
|
|
183
|
+
actionScheduler.animationFrame(action, options);
|
|
180
184
|
|
|
181
185
|
// Assert
|
|
182
|
-
expect(AnimationFrame).toHaveBeenCalledWith(
|
|
186
|
+
expect(AnimationFrame).toHaveBeenCalledWith(
|
|
187
|
+
action,
|
|
188
|
+
SchedulePolicy.Immediately,
|
|
189
|
+
);
|
|
183
190
|
});
|
|
184
191
|
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
true,
|
|
194
|
-
);
|
|
192
|
+
it("should pass clear policy to animationFrame.clear on clearAll", () => {
|
|
193
|
+
// Arrange
|
|
194
|
+
const actionScheduler = new ActionScheduler();
|
|
195
|
+
const action = jest.fn();
|
|
196
|
+
const options = {
|
|
197
|
+
clearPolicy: ClearPolicy.Resolve,
|
|
198
|
+
};
|
|
199
|
+
const testFrame = actionScheduler.animationFrame(action, options);
|
|
195
200
|
|
|
196
|
-
|
|
197
|
-
|
|
201
|
+
// Act
|
|
202
|
+
actionScheduler.clearAll();
|
|
198
203
|
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
204
|
+
// Assert
|
|
205
|
+
// $FlowIgnore[method-unbinding]
|
|
206
|
+
expect(testFrame.clear).toHaveBeenCalledWith(ClearPolicy.Resolve);
|
|
207
|
+
});
|
|
203
208
|
|
|
204
|
-
|
|
209
|
+
describe("when scheduler is disabled", () => {
|
|
210
|
+
it("should return a noop interval", () => {
|
|
205
211
|
// Arrange
|
|
206
212
|
const actionScheduler = new ActionScheduler();
|
|
207
213
|
const action = jest.fn();
|
|
208
|
-
const testFrame = actionScheduler.animationFrame(
|
|
209
|
-
action,
|
|
210
|
-
false,
|
|
211
|
-
false,
|
|
212
|
-
);
|
|
213
214
|
|
|
214
215
|
// Act
|
|
215
|
-
actionScheduler.
|
|
216
|
+
actionScheduler.disable();
|
|
217
|
+
const result = actionScheduler.animationFrame(action);
|
|
216
218
|
|
|
217
219
|
// Assert
|
|
218
|
-
|
|
219
|
-
expect(testFrame.clear).toHaveBeenCalledWith(false);
|
|
220
|
+
expect(result).toBe(ActionScheduler.NoopAction);
|
|
220
221
|
});
|
|
221
222
|
});
|
|
222
223
|
});
|
|
@@ -263,4 +264,18 @@ describe("ActionScheduler", () => {
|
|
|
263
264
|
expect(animationFrame.clear).toHaveBeenCalledTimes(1);
|
|
264
265
|
});
|
|
265
266
|
});
|
|
267
|
+
|
|
268
|
+
describe("#disable", () => {
|
|
269
|
+
it("should clear all scheduled actions", () => {
|
|
270
|
+
// Arrange
|
|
271
|
+
const actionScheduler = new ActionScheduler();
|
|
272
|
+
const clearAllSpy = jest.spyOn(actionScheduler, "clearAll");
|
|
273
|
+
|
|
274
|
+
// Act
|
|
275
|
+
actionScheduler.disable();
|
|
276
|
+
|
|
277
|
+
// Assert
|
|
278
|
+
expect(clearAllSpy).toHaveBeenCalledTimes(1);
|
|
279
|
+
});
|
|
280
|
+
});
|
|
266
281
|
});
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
// @flow
|
|
2
2
|
import AnimationFrame from "../animation-frame.js";
|
|
3
|
+
import {SchedulePolicy, ClearPolicy} from "../policies.js";
|
|
3
4
|
|
|
4
5
|
describe("AnimationFrame", () => {
|
|
5
6
|
beforeEach(() => {
|
|
@@ -8,14 +9,12 @@ describe("AnimationFrame", () => {
|
|
|
8
9
|
// Jest doesn't fake out the animation frame API, so we're going to do
|
|
9
10
|
// it here and map it to timeouts, that way we can use the fake timer
|
|
10
11
|
// API to test our animation frame things.
|
|
11
|
-
jest.spyOn(
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
"cancelAnimationFrame",
|
|
18
|
-
).mockImplementation((id, ...args) => clearTimeout(id));
|
|
12
|
+
jest.spyOn(global, "requestAnimationFrame").mockImplementation(
|
|
13
|
+
(fn, ...args) => setTimeout(fn, 0),
|
|
14
|
+
);
|
|
15
|
+
jest.spyOn(global, "cancelAnimationFrame").mockImplementation(
|
|
16
|
+
(id, ...args) => clearTimeout(id),
|
|
17
|
+
);
|
|
19
18
|
});
|
|
20
19
|
|
|
21
20
|
afterEach(() => {
|
|
@@ -45,12 +44,12 @@ describe("AnimationFrame", () => {
|
|
|
45
44
|
);
|
|
46
45
|
});
|
|
47
46
|
|
|
48
|
-
it("requests an animation frame when
|
|
47
|
+
it("requests an animation frame when schedule policy is SchedulePolicy.Immediately", () => {
|
|
49
48
|
// Arrange
|
|
50
49
|
|
|
51
50
|
// Act
|
|
52
51
|
// eslint-disable-next-line no-new
|
|
53
|
-
new AnimationFrame(() => {},
|
|
52
|
+
new AnimationFrame(() => {}, SchedulePolicy.Immediately);
|
|
54
53
|
|
|
55
54
|
// Assert
|
|
56
55
|
expect(requestAnimationFrame).toHaveBeenCalledTimes(1);
|
|
@@ -60,7 +59,8 @@ describe("AnimationFrame", () => {
|
|
|
60
59
|
describe("isSet", () => {
|
|
61
60
|
it("is false when the request has not been set", () => {
|
|
62
61
|
// Arrange
|
|
63
|
-
const animationFrame = new AnimationFrame(() => {},
|
|
62
|
+
const animationFrame = new AnimationFrame(() => {},
|
|
63
|
+
SchedulePolicy.OnDemand);
|
|
64
64
|
|
|
65
65
|
// Act
|
|
66
66
|
const result = animationFrame.isSet;
|
|
@@ -144,7 +144,10 @@ describe("AnimationFrame", () => {
|
|
|
144
144
|
it("should set the timeout again if it has already executed", () => {
|
|
145
145
|
// Arrange
|
|
146
146
|
const action = jest.fn();
|
|
147
|
-
const animationFrame = new AnimationFrame(
|
|
147
|
+
const animationFrame = new AnimationFrame(
|
|
148
|
+
action,
|
|
149
|
+
SchedulePolicy.OnDemand,
|
|
150
|
+
);
|
|
148
151
|
animationFrame.set();
|
|
149
152
|
jest.runOnlyPendingTimers();
|
|
150
153
|
|
|
@@ -171,7 +174,7 @@ describe("AnimationFrame", () => {
|
|
|
171
174
|
expect(action).not.toHaveBeenCalled();
|
|
172
175
|
});
|
|
173
176
|
|
|
174
|
-
it("should invoke the action if
|
|
177
|
+
it("should invoke the action if clear policy is ClearPolicy.Resolve", () => {
|
|
175
178
|
// Arrange
|
|
176
179
|
jest.spyOn(performance, "now").mockReturnValue(42);
|
|
177
180
|
const action = jest.fn();
|
|
@@ -179,7 +182,7 @@ describe("AnimationFrame", () => {
|
|
|
179
182
|
animationFrame.set();
|
|
180
183
|
|
|
181
184
|
// Act
|
|
182
|
-
animationFrame.clear(
|
|
185
|
+
animationFrame.clear(ClearPolicy.Resolve);
|
|
183
186
|
jest.runOnlyPendingTimers();
|
|
184
187
|
|
|
185
188
|
// Assert
|
|
@@ -187,26 +190,32 @@ describe("AnimationFrame", () => {
|
|
|
187
190
|
expect(action).toHaveBeenCalledWith(42);
|
|
188
191
|
});
|
|
189
192
|
|
|
190
|
-
it("should not invoke the action if
|
|
193
|
+
it("should not invoke the action if clear policy is ClearPolicy.Cancel", () => {
|
|
191
194
|
// Arrange
|
|
192
195
|
const action = jest.fn();
|
|
193
|
-
const animationFrame = new AnimationFrame(
|
|
196
|
+
const animationFrame = new AnimationFrame(
|
|
197
|
+
action,
|
|
198
|
+
SchedulePolicy.Immediately,
|
|
199
|
+
);
|
|
194
200
|
|
|
195
201
|
// Act
|
|
196
|
-
animationFrame.clear(
|
|
202
|
+
animationFrame.clear(ClearPolicy.Cancel);
|
|
197
203
|
jest.runOnlyPendingTimers();
|
|
198
204
|
|
|
199
205
|
// Assert
|
|
200
206
|
expect(action).not.toHaveBeenCalled();
|
|
201
207
|
});
|
|
202
208
|
|
|
203
|
-
it("should not invoke the action if timeout is not pending", () => {
|
|
209
|
+
it("should not invoke the action if timeout is not pending and clear policy is ClearPolicy.Resolve", () => {
|
|
204
210
|
// Arrange
|
|
205
211
|
const action = jest.fn();
|
|
206
|
-
const animationFrame = new AnimationFrame(
|
|
212
|
+
const animationFrame = new AnimationFrame(
|
|
213
|
+
action,
|
|
214
|
+
SchedulePolicy.OnDemand,
|
|
215
|
+
);
|
|
207
216
|
|
|
208
217
|
// Act
|
|
209
|
-
animationFrame.clear(
|
|
218
|
+
animationFrame.clear(ClearPolicy.Resolve);
|
|
210
219
|
jest.runOnlyPendingTimers();
|
|
211
220
|
|
|
212
221
|
// Assert
|