@khanacademy/wonder-blocks-timing 5.0.1 → 5.0.2

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/CHANGELOG.md CHANGED
@@ -1,5 +1,11 @@
1
1
  # @khanacademy/wonder-blocks-timing
2
2
 
3
+ ## 5.0.2
4
+
5
+ ### Patch Changes
6
+
7
+ - 02a1b298: Make sure we don't package tsconfig and tsbuildinfo files
8
+
3
9
  ## 5.0.1
4
10
 
5
11
  ### Patch Changes
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@khanacademy/wonder-blocks-timing",
3
3
  "private": false,
4
- "version": "5.0.1",
4
+ "version": "5.0.2",
5
5
  "design": "v1",
6
6
  "publishConfig": {
7
7
  "access": "public"
@@ -1,36 +0,0 @@
1
- import * as React from "react";
2
- import {render} from "@testing-library/react";
3
-
4
- import ActionSchedulerProvider from "../action-scheduler-provider";
5
- import ActionScheduler from "../../util/action-scheduler";
6
-
7
- jest.mock("../../util/action-scheduler");
8
-
9
- describe("ActionSchedulerProvider", () => {
10
- it("should render children with action scheduler instance", () => {
11
- // Arrange
12
- const childrenMock = jest.fn().mockReturnValueOnce(null);
13
-
14
- // Act
15
- render(
16
- <ActionSchedulerProvider>{childrenMock}</ActionSchedulerProvider>,
17
- );
18
-
19
- // Assert
20
- expect(childrenMock).toHaveBeenCalledWith(expect.any(ActionScheduler));
21
- });
22
-
23
- it("should call disable on the action scheduler at unmount", () => {
24
- // Arrange
25
- const childrenMock = jest.fn().mockReturnValueOnce(null);
26
- const {unmount} = render(
27
- <ActionSchedulerProvider>{childrenMock}</ActionSchedulerProvider>,
28
- );
29
-
30
- // Act
31
- unmount();
32
-
33
- // Assert
34
- expect(childrenMock.mock.calls[0][0].disable).toHaveBeenCalledTimes(1);
35
- });
36
- });
@@ -1,22 +0,0 @@
1
- import * as React from "react";
2
- import {render, screen} from "@testing-library/react";
3
-
4
- import withActionScheduler from "../with-action-scheduler";
5
-
6
- import type {WithActionSchedulerProps} from "../../util/types";
7
-
8
- describe("withActionScheduler", () => {
9
- it("should provide wrapped component with IScheduleActions instance", () => {
10
- // Arrange
11
- const Component = (props: WithActionSchedulerProps) => (
12
- <>{props.schedule != null ? "true" : "false"}</>
13
- );
14
-
15
- // Act
16
- const WithScheduler = withActionScheduler(Component);
17
- render(<WithScheduler />);
18
-
19
- // Assert
20
- expect(screen.getByText("true")).toBeInTheDocument();
21
- });
22
- });
@@ -1,35 +0,0 @@
1
- import * as React from "react";
2
- import ActionScheduler from "../util/action-scheduler";
3
-
4
- import type {IScheduleActions} from "../util/types";
5
-
6
- type Props = {
7
- /**
8
- * A function that, when given an instance of `IScheduleActions` will
9
- * render a `React.Node`.
10
- */
11
- children: (arg1: IScheduleActions) => React.ReactNode;
12
- };
13
-
14
- /**
15
- * A provider component that passes our action scheduling API to its children
16
- * and ensures that all scheduled actions are cleared on unmount.
17
- *
18
- * ```jsx
19
- * <ActionSchedulerProvider>
20
- * {schedule => this.renderThingThatNeedsTimers(schedule)}
21
- * </ActionSchedulerProvider>
22
- * ```
23
- */
24
- export default class ActionSchedulerProvider extends React.Component<Props> {
25
- componentWillUnmount() {
26
- this._actionScheduler.disable();
27
- }
28
-
29
- _actionScheduler: ActionScheduler = new ActionScheduler();
30
-
31
- render(): React.ReactNode {
32
- const {children} = this.props;
33
- return children(this._actionScheduler);
34
- }
35
- }
@@ -1,36 +0,0 @@
1
- import * as React from "react";
2
-
3
- import ActionSchedulerProvider from "./action-scheduler-provider";
4
-
5
- import type {IScheduleActions, WithActionSchedulerProps} from "../util/types";
6
-
7
- type WithoutActionScheduler<T> = Omit<T, "schedule">;
8
-
9
- /**
10
- * A higher order component that attaches the given component to an
11
- * `IScheduleActions` instance. Any actions scheduled will automatically be
12
- * cleared on unmount.
13
- *
14
- * @template TOwnProps The own props of the component being rendered, without
15
- * the additional action scheduler prop. To attach the additional prop to
16
- * these props use the `WithActionScheduler` type.
17
- */
18
- export default function withActionScheduler<
19
- Props extends WithActionSchedulerProps,
20
- >(WrappedComponent: React.ComponentType<Props>) {
21
- const displayName = `withActionScheduler(${
22
- WrappedComponent.displayName || WrappedComponent.name
23
- })`;
24
-
25
- const C = (props: WithoutActionScheduler<Props>) => (
26
- <ActionSchedulerProvider>
27
- {(schedule: IScheduleActions) => (
28
- <WrappedComponent {...(props as Props)} schedule={schedule} />
29
- )}
30
- </ActionSchedulerProvider>
31
- );
32
-
33
- C.displayName = displayName;
34
-
35
- return C;
36
- }
@@ -1,520 +0,0 @@
1
- import {renderHook, act} from "@testing-library/react-hooks";
2
- import {SchedulePolicy, ClearPolicy, ActionPolicy} from "../../util/policies";
3
-
4
- import {useInterval} from "../use-interval";
5
-
6
- describe("useInterval", () => {
7
- beforeEach(() => {
8
- jest.useFakeTimers();
9
- });
10
-
11
- afterEach(() => {
12
- jest.restoreAllMocks();
13
- });
14
-
15
- it("throws if the action is not a function", () => {
16
- // Arrange
17
-
18
- // Act
19
- const {result} = renderHook(() => useInterval(null as any, 1000));
20
-
21
- // Assert
22
- expect(result.error).toEqual(Error("Action must be a function"));
23
- });
24
-
25
- it("throws if the period is less than 1", () => {
26
- // Arrange
27
-
28
- // Act
29
- const {result} = renderHook(() => useInterval(() => {}, 0));
30
-
31
- // Assert
32
- expect(result.error).toEqual(Error("Interval period must be >= 1"));
33
- });
34
-
35
- it("sets an interval when schedule policy is SchedulePolicy.Immediately", () => {
36
- // Arrange
37
- const intervalSpy = jest.spyOn(global, "setInterval");
38
-
39
- // Act
40
- renderHook(() => useInterval(() => {}, 1000));
41
-
42
- // Assert
43
- expect(intervalSpy).toHaveBeenCalledTimes(1);
44
- });
45
-
46
- it("should call the action before unmounting when clear policy is Resolve", () => {
47
- const action = jest.fn();
48
- const {unmount} = renderHook(() =>
49
- useInterval(action, 1000, {
50
- clearPolicy: ClearPolicy.Resolve,
51
- }),
52
- );
53
-
54
- act(() => {
55
- unmount();
56
- });
57
-
58
- expect(action).toHaveBeenCalled();
59
- });
60
-
61
- it("should call the current action", () => {
62
- // Arrange
63
- const action1 = jest.fn();
64
- const action2 = jest.fn();
65
- const {rerender} = renderHook(
66
- ({action}: any) => useInterval(action, 500),
67
- {
68
- initialProps: {action: action1},
69
- },
70
- );
71
-
72
- // Act
73
- rerender({action: action2});
74
- jest.advanceTimersByTime(501);
75
-
76
- // Assert
77
- expect(action2).toHaveBeenCalledTimes(1);
78
- });
79
-
80
- it("should only call setInterval once even if action changes", () => {
81
- // Arrange
82
- const intervalSpy = jest.spyOn(global, "setInterval");
83
- const action1 = jest.fn();
84
- const action2 = jest.fn();
85
- const {rerender} = renderHook(
86
- ({action}: any) => useInterval(action, 500),
87
- {
88
- initialProps: {action: action1},
89
- },
90
- );
91
-
92
- // Act
93
- rerender({action: action2});
94
-
95
- // Assert
96
- expect(intervalSpy).toHaveBeenCalledTimes(1);
97
- });
98
-
99
- it("should not reset the interval if the action changes", () => {
100
- // Arrange
101
- const action1 = jest.fn();
102
- const action2 = jest.fn();
103
- const {rerender} = renderHook(
104
- ({action}: any) => useInterval(action, 500),
105
- {
106
- initialProps: {action: action1},
107
- },
108
- );
109
-
110
- // Act
111
- jest.advanceTimersByTime(250);
112
- rerender({action: action2});
113
- jest.advanceTimersByTime(751);
114
-
115
- // Assert
116
- expect(action1).not.toHaveBeenCalled();
117
- expect(action2).toHaveBeenCalledTimes(2);
118
- });
119
-
120
- it("should reset the interval if the action changes and the action policy is Reset", () => {
121
- // Arrange
122
- const action1 = jest.fn();
123
- const action2 = jest.fn();
124
- const {rerender} = renderHook(
125
- ({action}: any) =>
126
- useInterval(action, 500, {actionPolicy: ActionPolicy.Reset}),
127
- {
128
- initialProps: {action: action1},
129
- },
130
- );
131
-
132
- // Act
133
- jest.advanceTimersByTime(250);
134
- rerender({action: action2});
135
- jest.advanceTimersByTime(751);
136
-
137
- // Assert
138
- expect(action1).not.toHaveBeenCalled();
139
- expect(action2).toHaveBeenCalledTimes(1);
140
- });
141
-
142
- it("should use the new interval period after changing it", () => {
143
- // Arrange
144
- const action = jest.fn();
145
- const {rerender} = renderHook(
146
- ({intervalMs}: any) => useInterval(action, intervalMs),
147
- {
148
- initialProps: {intervalMs: 500},
149
- },
150
- );
151
- rerender({intervalMs: 1000});
152
-
153
- // Act
154
- jest.advanceTimersByTime(1501);
155
-
156
- // Assert
157
- expect(action).toHaveBeenCalledTimes(1);
158
- });
159
-
160
- it("should restart the interval if intervalMs changes", () => {
161
- // Arrange
162
- const intervalSpy = jest.spyOn(global, "setInterval");
163
- const {rerender} = renderHook(
164
- ({intervalMs}: any) => useInterval(() => {}, intervalMs),
165
- {
166
- initialProps: {intervalMs: 500},
167
- },
168
- );
169
-
170
- // Act
171
- rerender({intervalMs: 1000});
172
-
173
- // Assert
174
- expect(intervalSpy).toHaveBeenCalledWith(expect.any(Function), 500);
175
- expect(intervalSpy).toHaveBeenCalledWith(expect.any(Function), 1000);
176
- });
177
-
178
- describe("isSet", () => {
179
- it("is false when the interval has not been set [SchedulePolicy.OnDemand]", () => {
180
- // Arrange
181
- const {result} = renderHook(() =>
182
- useInterval(() => {}, 1000, {
183
- schedulePolicy: SchedulePolicy.OnDemand,
184
- }),
185
- );
186
-
187
- // Act
188
- const isSet = result.current.isSet;
189
-
190
- // Assert
191
- expect(isSet).toBeFalsy();
192
- });
193
-
194
- it("is true when the interval is active", () => {
195
- // Arrange
196
- const {result} = renderHook(() => useInterval(() => {}, 1000));
197
- act(() => {
198
- result.current.set();
199
- });
200
-
201
- // Act
202
- const isSet = result.current.isSet;
203
-
204
- // Assert
205
- expect(isSet).toBeTruthy();
206
- });
207
-
208
- it("is false when the interval is cleared", () => {
209
- // Arrange
210
- const {result} = renderHook(() => useInterval(() => {}, 1000));
211
- act(() => {
212
- result.current.set();
213
- result.current.clear();
214
- });
215
-
216
- // Act
217
- const isSet = result.current.isSet;
218
-
219
- // Assert
220
- expect(isSet).toBeFalsy();
221
- });
222
- });
223
-
224
- describe("#set", () => {
225
- it("should call setInterval", () => {
226
- // Arrange
227
- const intervalSpy = jest.spyOn(global, "setInterval");
228
- const {result} = renderHook(() =>
229
- useInterval(() => {}, 500, {
230
- schedulePolicy: SchedulePolicy.OnDemand,
231
- }),
232
- );
233
-
234
- // Act
235
- act(() => {
236
- result.current.set();
237
- });
238
-
239
- // Assert
240
- expect(intervalSpy).toHaveBeenNthCalledWith(
241
- 1,
242
- expect.any(Function),
243
- 500,
244
- );
245
- });
246
-
247
- it("should invoke setInterval to call the given action", () => {
248
- // Arrange
249
- const intervalSpy = jest.spyOn(global, "setInterval");
250
- const action = jest.fn();
251
- const {result} = renderHook(() =>
252
- useInterval(action, 500, {
253
- schedulePolicy: SchedulePolicy.OnDemand,
254
- }),
255
- );
256
-
257
- act(() => {
258
- result.current.set();
259
- });
260
- const scheduledAction = intervalSpy.mock.calls[0][0];
261
-
262
- // Act
263
- scheduledAction();
264
-
265
- // Assert
266
- expect(action).toHaveBeenCalledTimes(1);
267
- });
268
-
269
- it("should clear the active interval", () => {
270
- // Arrange
271
- const action = jest.fn();
272
- const {result} = renderHook(() =>
273
- useInterval(action, 500, {
274
- schedulePolicy: SchedulePolicy.OnDemand,
275
- }),
276
- );
277
- act(() => {
278
- result.current.set();
279
- });
280
-
281
- // Act
282
- act(() => {
283
- result.current.set();
284
- jest.advanceTimersByTime(501);
285
- });
286
-
287
- // Assert
288
- expect(action).toHaveBeenCalledTimes(1);
289
- });
290
-
291
- it("should set an interval that stays active while not cleared", () => {
292
- // Arrange
293
- const action = jest.fn();
294
- const {result} = renderHook(() =>
295
- useInterval(action, 500, {
296
- schedulePolicy: SchedulePolicy.OnDemand,
297
- }),
298
- );
299
- act(() => {
300
- result.current.set();
301
- });
302
-
303
- // Act
304
- act(() => {
305
- jest.advanceTimersByTime(1501);
306
- });
307
-
308
- // Assert
309
- expect(action).toHaveBeenCalledTimes(3);
310
- });
311
-
312
- it("should continue to be set after calling it multiple times", () => {
313
- // Arrange
314
- const action = jest.fn();
315
- const {result} = renderHook(() =>
316
- useInterval(action, 500, {
317
- schedulePolicy: SchedulePolicy.OnDemand,
318
- }),
319
- );
320
- act(() => {
321
- result.current.set();
322
- });
323
-
324
- // Act
325
- act(() => {
326
- result.current.set();
327
- });
328
- act(() => {
329
- jest.advanceTimersByTime(501);
330
- });
331
-
332
- // Assert
333
- expect(action).toHaveBeenCalled();
334
- });
335
-
336
- it("should set the interval after clearing it", () => {
337
- // Arrange
338
- const action = jest.fn();
339
- const {result} = renderHook(() =>
340
- useInterval(action, 500, {
341
- schedulePolicy: SchedulePolicy.OnDemand,
342
- }),
343
- );
344
- act(() => {
345
- result.current.clear();
346
- });
347
-
348
- // Act
349
- act(() => {
350
- result.current.set();
351
- });
352
- act(() => {
353
- jest.advanceTimersByTime(501);
354
- });
355
-
356
- // Assert
357
- expect(action).toHaveBeenCalled();
358
- });
359
-
360
- it("should reset the inteval after calling set() again", () => {
361
- // Arrange
362
- const action = jest.fn();
363
- const {result} = renderHook(() =>
364
- useInterval(action, 750, {
365
- schedulePolicy: SchedulePolicy.OnDemand,
366
- }),
367
- );
368
-
369
- // Act
370
- act(() => {
371
- result.current.set();
372
- jest.advanceTimersByTime(501);
373
- result.current.set();
374
- jest.advanceTimersByTime(501);
375
- });
376
-
377
- // Assert
378
- expect(action).not.toHaveBeenCalled();
379
- });
380
-
381
- it("shouldn't throw an error if called after the component unmounted", () => {
382
- const action = jest.fn();
383
- const {result, unmount} = renderHook(() =>
384
- useInterval(action, 500),
385
- );
386
- act(() => {
387
- unmount();
388
- });
389
-
390
- // Act
391
- const underTest = () => result.current.set();
392
-
393
- // Assert
394
- expect(underTest).not.toThrow();
395
- });
396
- });
397
-
398
- describe("#clear", () => {
399
- it("should clear an active interval", () => {
400
- // Arrange
401
- const action = jest.fn();
402
- const {result} = renderHook(() => useInterval(action, 500));
403
- act(() => {
404
- result.current.set();
405
- });
406
-
407
- // Act
408
- act(() => {
409
- result.current.clear();
410
- });
411
- act(() => {
412
- jest.advanceTimersByTime(501);
413
- });
414
-
415
- // Assert
416
- expect(action).not.toHaveBeenCalled();
417
- });
418
-
419
- it("should invoke the action if clear policy is ClearPolicy.Resolve", () => {
420
- // Arrange
421
- const action = jest.fn();
422
- const {result} = renderHook(() => useInterval(action, 500));
423
- act(() => {
424
- result.current.set();
425
- });
426
-
427
- // Act
428
- act(() => {
429
- result.current.clear(ClearPolicy.Resolve);
430
- });
431
- act(() => {
432
- jest.advanceTimersByTime(501);
433
- });
434
-
435
- // Assert
436
- expect(action).toHaveBeenCalledTimes(1);
437
- });
438
-
439
- it("should not invoke the action if clear policy is ClearPolicy.Cancel", () => {
440
- // Arrange
441
- const action = jest.fn();
442
- const {result} = renderHook(() =>
443
- useInterval(action, 500, {
444
- schedulePolicy: SchedulePolicy.Immediately,
445
- }),
446
- );
447
- act(() => {
448
- result.current.set();
449
- });
450
-
451
- // Act
452
- act(() => {
453
- result.current.clear(ClearPolicy.Cancel);
454
- });
455
- act(() => {
456
- jest.advanceTimersByTime(501);
457
- });
458
-
459
- // Assert
460
- expect(action).not.toHaveBeenCalled();
461
- });
462
-
463
- it("should not invoke the action if interval is inactive and clear policy is ClearPolicy.Resolve", () => {
464
- // Arrange
465
- const action = jest.fn();
466
- const {result} = renderHook(() =>
467
- useInterval(action, 500, {
468
- schedulePolicy: SchedulePolicy.OnDemand,
469
- }),
470
- );
471
-
472
- // Act
473
- act(() => {
474
- result.current.clear(ClearPolicy.Resolve);
475
- jest.advanceTimersByTime(501);
476
- });
477
-
478
- // Assert
479
- expect(action).not.toHaveBeenCalled();
480
- });
481
-
482
- it("should not call the action on unmount if the interval is not running when the clearPolicy is ClearPolicy.Resolve", async () => {
483
- // Arrange
484
- const action = jest.fn();
485
- const {result, unmount} = renderHook(() =>
486
- useInterval(action, 500, {
487
- clearPolicy: ClearPolicy.Resolve,
488
- }),
489
- );
490
-
491
- // Act
492
- act(() => {
493
- result.current.clear();
494
- });
495
- act(() => {
496
- unmount();
497
- });
498
-
499
- // Assert
500
- expect(action).not.toHaveBeenCalled();
501
- });
502
-
503
- it("should not error if calling clear() after unmounting", () => {
504
- // Arrange
505
- const action = jest.fn();
506
- const {result, unmount} = renderHook(() =>
507
- useInterval(action, 500),
508
- );
509
- act(() => {
510
- unmount();
511
- });
512
-
513
- // Act
514
- const underTest = () => result.current.clear();
515
-
516
- // Assert
517
- expect(underTest).not.toThrow();
518
- });
519
- });
520
- });