UNPKG

2.12 kBPlain TextView Raw
1interface FrameCallback {
2 (time: number): any;
3}
4
5export default class AnimationFrame {
6 private isUsingMockAnimationFrame = false;
7 private queued: {[key: number]: FrameCallback} = {};
8 private originalRequestAnimationFrame: any;
9 private originalCancelAnimationFrame: any;
10 private currentAnimationFrame = 0;
11
12 mock() {
13 if (this.isUsingMockAnimationFrame) {
14 throw new Error(
15 'The animation frame is already mocked, but you tried to mock it again.',
16 );
17 }
18
19 this.isUsingMockAnimationFrame = true;
20
21 this.originalRequestAnimationFrame = window.requestAnimationFrame;
22 window.requestAnimationFrame = this.requestAnimationFrame;
23
24 this.originalCancelAnimationFrame = window.cancelAnimationFrame;
25 window.cancelAnimationFrame = this.cancelAnimationFrame;
26 }
27
28 restore() {
29 if (!this.isUsingMockAnimationFrame) {
30 throw new Error(
31 'The animation frame is already real, but you tried to restore it again.',
32 );
33 }
34
35 this.isUsingMockAnimationFrame = false;
36
37 window.requestAnimationFrame = this.originalRequestAnimationFrame;
38 window.cancelAnimationFrame = this.originalCancelAnimationFrame;
39 }
40
41 isMocked() {
42 return this.isUsingMockAnimationFrame;
43 }
44
45 runFrame() {
46 this.ensureAnimationFrameIsMock();
47 // We need to do it this way so that frames that queue other frames
48 // don't get removed
49 Object.keys(this.queued).forEach((frame: any) => {
50 const callback = this.queued[frame];
51 delete this.queued[frame];
52 callback(Date.now());
53 });
54 }
55
56 private requestAnimationFrame = (callback: FrameCallback): number => {
57 this.currentAnimationFrame += 1;
58 this.queued[this.currentAnimationFrame] = callback;
59 return this.currentAnimationFrame;
60 };
61
62 private cancelAnimationFrame = (frame: number) => {
63 delete this.queued[frame];
64 };
65
66 private ensureAnimationFrameIsMock() {
67 if (!this.isUsingMockAnimationFrame) {
68 throw new Error(
69 'You must call animationFrame.mock() before interacting with the mock request- or cancel- AnimationFrame methods.',
70 );
71 }
72 }
73}