@applicaster/zapp-react-native-utils 13.0.0-alpha.4515349201 → 13.0.0-alpha.4700935119

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.
Files changed (95) hide show
  1. package/actionsExecutor/ActionExecutor.ts +16 -9
  2. package/actionsExecutor/ActionExecutorContext.tsx +74 -9
  3. package/alertUtils/alert.ts +148 -0
  4. package/alertUtils/index.ts +1 -148
  5. package/analyticsUtils/AnalyticPlayerListener.ts +18 -1
  6. package/analyticsUtils/__tests__/__snapshots__/analyticsManagerNoModule.test.js.snap +9 -9
  7. package/analyticsUtils/helpers/hooks.ts +1 -1
  8. package/appUtils/HooksManager/{Hook.js → Hook.ts} +35 -23
  9. package/appUtils/HooksManager/__tests__/__snapshots__/hook.test.js.snap +10 -8
  10. package/appUtils/HooksManager/__tests__/__snapshots__/hooksManager.test.js.snap +693 -0
  11. package/appUtils/HooksManager/__tests__/hook.test.js +196 -184
  12. package/appUtils/HooksManager/__tests__/hooksManager.test.js +96 -99
  13. package/appUtils/HooksManager/{constants.js → constants.ts} +1 -1
  14. package/appUtils/HooksManager/{index.js → index.ts} +121 -112
  15. package/appUtils/HooksManager/types.ts +119 -0
  16. package/appUtils/RiverFocusManager/index.js +17 -12
  17. package/appUtils/accessibilityManager/index.ts +42 -1
  18. package/appUtils/contextKeysManager/contextResolver.ts +73 -0
  19. package/appUtils/focusManager/__tests__/__snapshots__/focusManager.test.js.snap +6 -6
  20. package/appUtils/focusManager/index.ts +90 -63
  21. package/appUtils/focusManager/treeDataStructure/Tree/index.js +25 -3
  22. package/appUtils/focusManager/treeDataStructure/Utils/index.js +1 -3
  23. package/appUtils/focusManager/utils/enums.ts +4 -0
  24. package/appUtils/focusManagerAux/utils/index.ts +4 -3
  25. package/appUtils/{index.js → index.ts} +1 -1
  26. package/appUtils/keyCodes/__tests__/__snapshots__/keyCodes.test.js.snap +2 -2
  27. package/appUtils/keyCodes/__tests__/keyCodes.test.js +4 -4
  28. package/appUtils/keyCodes/{index.js → index.ts} +2 -0
  29. package/appUtils/keyCodes/keys/index.ts +3 -0
  30. package/appUtils/keyCodes/{keys.android.js → keys/keyEventMapper.ts} +0 -19
  31. package/appUtils/keyCodes/keys/keys.android.ts +18 -0
  32. package/appUtils/keyCodes/keys/keys.ios.ts +25 -0
  33. package/appUtils/keyCodes/keys/keys.ts +15 -0
  34. package/appUtils/keyCodes/{keysByPlatform.js → keys/keysByPlatform.ts} +3 -3
  35. package/appUtils/keyCodes/keysByPlatform.ts +8 -0
  36. package/appUtils/orientationHelper.ts +1 -1
  37. package/appUtils/platform/const.ts +14 -0
  38. package/appUtils/platform/platformUtils.ts +17 -15
  39. package/appUtils/playerManager/playerNative.ts +1 -1
  40. package/arrayUtils/__tests__/__snapshots__/arrayUtils.test.ts.snap +4 -4
  41. package/domUtils/{cookieManager.js → cookieManager.ts} +1 -2
  42. package/functionUtils/__tests__/__snapshots__/functionUtils.test.js.snap +4 -4
  43. package/functionUtils/index.ts +15 -11
  44. package/logger/const.ts +9 -67
  45. package/manifestUtils/__tests__/createConfig.test.js +18 -16
  46. package/modalState/index.ts +1 -5
  47. package/navigationUtils/__tests__/__snapshots__/navigationUtils.test.js.snap +6 -6
  48. package/navigationUtils/__tests__/itemTypes.test.js +2 -2
  49. package/navigationUtils/__tests__/navigationUtils.test.js +2 -2
  50. package/navigationUtils/index.ts +14 -5
  51. package/package.json +3 -2
  52. package/reactHooks/autoscrolling/__tests__/useTrackCurrentAutoScrollingElement.test.ts +1 -1
  53. package/reactHooks/autoscrolling/__tests__/useTrackedView.test.tsx +1 -1
  54. package/reactHooks/cell-click/__tests__/index.test.js +10 -2
  55. package/reactHooks/cell-click/index.ts +7 -1
  56. package/reactHooks/feed/__tests__/useBuildPipesUrl.test.tsx +4 -4
  57. package/reactHooks/feed/__tests__/useFeedLoader.test.tsx +10 -11
  58. package/reactHooks/feed/useFeedLoader.tsx +1 -1
  59. package/reactHooks/feed/usePipesCacheReset.ts +5 -5
  60. package/reactHooks/flatList/__tests__/index.test.tsx +30 -21
  61. package/reactHooks/layout/__tests__/index.test.tsx +10 -10
  62. package/reactHooks/layout/useDimensions/helpers/__tests__/getInitialDimensions.native.test.js +14 -28
  63. package/reactHooks/navigation/__tests__/index.test.tsx +0 -4
  64. package/reactHooks/navigation/index.ts +29 -218
  65. package/reactHooks/navigation/useGetBottomTabBarHeight.ts +12 -0
  66. package/reactHooks/navigation/useGetNavBarTopBorderWidth.ts +14 -0
  67. package/reactHooks/navigation/useGetTabBarHeight.ts +12 -0
  68. package/reactHooks/navigation/useIsScreenActive.ts +17 -0
  69. package/reactHooks/navigation/useNavigationPluginData.ts +15 -0
  70. package/reactHooks/navigation/useNavigationType.ts +15 -0
  71. package/reactHooks/navigation/usePathname.ts +4 -0
  72. package/reactHooks/navigation/useRoute.ts +100 -0
  73. package/reactHooks/navigation/useUniqueRouteSuffix.ts +41 -0
  74. package/reactHooks/player/TVSeekControlller/ISeekController.ts +19 -2
  75. package/reactHooks/player/TVSeekControlller/LongPressSeekController.ts +20 -41
  76. package/reactHooks/player/TVSeekControlller/TVSeekController.ts +80 -31
  77. package/reactHooks/player/TVSeekControlller/TapSeekController.ts +18 -40
  78. package/reactHooks/player/__tests__/useAutoSeek._test.tsx +115 -0
  79. package/reactHooks/player/__tests__/useTapSeek._test.ts +94 -0
  80. package/reactHooks/player/const.ts +1 -1
  81. package/reactUtils/__tests__/reactUtils.test.js +10 -28
  82. package/reactUtils/createContext/__tests__/__snapshots__/helpers.test.js.snap +19 -19
  83. package/reactUtils/createContext/__tests__/__snapshots__/index.test.js.snap +2 -2
  84. package/reactUtils/createContext/__tests__/__snapshots__/provider.test.js.snap +3 -3
  85. package/reactUtils/createContext/__tests__/helpers.test.js +8 -8
  86. package/reactUtils/index.ts +0 -14
  87. package/theme/__mocks__/index.ts +4 -0
  88. package/time/Timer.ts +1 -1
  89. package/appUtils/keyCodes/keys.ios.js +0 -46
  90. /package/appUtils/HooksManager/{logger.js → logger.ts} +0 -0
  91. /package/appUtils/{directionHelper.js → directionHelper.ts} +0 -0
  92. /package/appUtils/keyCodes/{androidTVKeys.js → androidTVKeys.ts} +0 -0
  93. /package/appUtils/keyCodes/{keys.web.js → keys/keys.web.ts} +0 -0
  94. /package/appUtils/{localizationsHelper.js → localizationsHelper.ts} +0 -0
  95. /package/domUtils/{logger.js → logger.ts} +0 -0
@@ -5,7 +5,11 @@ import { SEEK_TYPE } from "../const";
5
5
  import { createLogger } from "../../../logger";
6
6
  import { Player } from "../../../appUtils/playerManager/player";
7
7
  import { SeekKeyHandlerListener } from "../../../appUtils/keyInputHandler/KeyInputHandler";
8
- import { ISeekController, ISeekControllerDelegate } from "./ISeekController";
8
+ import {
9
+ ISeekController,
10
+ ISeekControllerDelegate,
11
+ SeekIncrementalBaseStrategy,
12
+ } from "./ISeekController";
9
13
 
10
14
  export const { log_warning, log_debug, log_info, log_error, log_verbose } =
11
15
  createLogger({
@@ -23,17 +27,16 @@ const CONFIG_TAP_SEEK = {
23
27
  };
24
28
 
25
29
  const CONFIG_LONG_PRESS = {
26
- TIMER_INTERVAL_MS: 300,
27
- SKIP_INCREMENT_STEP: 5,
28
- MAX_SKIP_PER_TICK: 300,
29
- INITIAL_SKIP_AMOUNT: 10,
30
+ TIMER_INTERVAL_MS: 200,
30
31
  };
31
32
 
32
33
  const LONG_PRESS_THRESHOLD = 500;
34
+ const SEEK_END_TIMEOUT_DURATION = 700;
35
+ // prettier-ignore
33
36
 
34
37
  export class TVSeekController
35
38
  implements SeekKeyHandlerListener, ISeekControllerDelegate {
36
- public delayedSeekOffset: number | null = null;
39
+ public delayedSeekPosition: number | null = null;
37
40
  private readonly playerController: Player;
38
41
  private delayedSeekProgressSubject = new BehaviorSubject<number | null>(null);
39
42
  isPlayerInitiallyPaused: null | boolean = null;
@@ -43,14 +46,20 @@ export class TVSeekController
43
46
  private readonly tapSeekController: TapSeekController;
44
47
  private readonly longPressSeekController: LongPressSeekController;
45
48
  private longPressThresholdTimeout: any | null = null;
49
+ private seekEndTimeout: any | null = null;
46
50
 
47
51
  constructor(playerController: Player) {
48
52
  this.playerController = playerController;
49
53
 
50
- this.tapSeekController = new TapSeekController(this, CONFIG_TAP_SEEK);
54
+ this.tapSeekController = new TapSeekController(
55
+ this,
56
+ new SeekIncrementalBaseStrategy(),
57
+ CONFIG_TAP_SEEK
58
+ );
51
59
 
52
60
  this.longPressSeekController = new LongPressSeekController(
53
61
  this,
62
+ new SeekIncrementalBaseStrategy(),
54
63
  CONFIG_LONG_PRESS
55
64
  );
56
65
 
@@ -64,30 +73,28 @@ export class TVSeekController
64
73
  setStrategy = (seekStrategy: SEEK_STRATEGY) => {
65
74
  switch (seekStrategy) {
66
75
  case SEEK_STRATEGY.TAP_SEEK:
67
- clearTimeout(this.longPressThresholdTimeout);
68
- this.longPressThresholdTimeout = null;
69
76
  this.currentSeekController = this.tapSeekController;
77
+ log_debug("TVSeekController: setStrategy - TAP_SEEK");
70
78
 
71
79
  break;
72
80
  case SEEK_STRATEGY.AUTO_SEEK:
73
- this.currentSeekController.reset();
74
81
  this.currentSeekController = this.longPressSeekController;
82
+ log_debug("TVSeekController: setStrategy - AUTO_SEEK");
83
+
75
84
  break;
76
85
  default:
77
86
  }
78
87
  };
79
88
 
80
89
  handleStartSeek = (seekType: SEEK_TYPE) => {
81
- if (this.currentSeekType !== seekType) {
82
- this.resetAll();
83
- }
84
-
85
90
  this.currentSeekType = seekType;
86
91
 
87
92
  if (this.isPlayerInitiallyPaused === null) {
88
93
  this.isPlayerInitiallyPaused = this.playerController.isPaused();
89
94
  }
90
95
 
96
+ this.clearLongPressThresholdTimeout();
97
+ this.clearSeekCompleteTimeout();
91
98
  this.setStrategy(SEEK_STRATEGY.TAP_SEEK);
92
99
  this.currentSeekController.onStartSeek(seekType);
93
100
 
@@ -110,8 +117,8 @@ export class TVSeekController
110
117
  };
111
118
 
112
119
  onSeekEnd = () => {
120
+ this.clearLongPressThresholdTimeout();
113
121
  this.currentSeekController.onSeekEnd();
114
- this.setStrategy(SEEK_STRATEGY.TAP_SEEK);
115
122
  };
116
123
 
117
124
  onRewindPressOut = () => {
@@ -122,40 +129,39 @@ export class TVSeekController
122
129
  this.onSeekEnd();
123
130
  };
124
131
 
125
- public onVideoProgress = (position: number) => {
126
- if (this.delayedSeekOffset) {
132
+ onVideoProgress = (position: number) => {
133
+ if (this.delayedSeekPosition !== null) {
127
134
  return;
128
135
  }
129
136
 
130
- // TODO: If 1 second after seek, send
131
-
132
137
  this.delayedSeekProgressSubject.next(position);
133
138
  };
134
139
 
135
- handleDelayedSeek = (offset: number) => {
140
+ handleDelayedSeek = (offset: number = 0) => {
136
141
  this.handlePlayerPause();
137
142
 
138
- const newOffset = (this.delayedSeekOffset || 0) + offset;
139
- const currentPos = this.playerController.getPosition();
143
+ const currentPos =
144
+ this.delayedSeekPosition === null
145
+ ? this.playerController.getPosition()
146
+ : this.delayedSeekPosition;
147
+
140
148
  let targetPos = currentPos;
141
149
 
142
150
  if (this.currentSeekType === SEEK_TYPE.FORWARD) {
143
151
  targetPos = Math.min(
144
- currentPos + newOffset,
152
+ currentPos + offset,
145
153
  this.playerController.getSeekableDuration()
146
154
  );
147
155
  } else if (this.currentSeekType === SEEK_TYPE.REWIND) {
148
- targetPos = Math.max(0, currentPos - newOffset);
156
+ targetPos = Math.max(0, currentPos - offset);
149
157
  } else {
150
158
  log_warning(
151
159
  `TVSeekController: handleDelayedSeek - invalid seek type: ${this.currentSeekType}`
152
160
  );
153
161
  }
154
162
 
155
- this.delayedSeekOffset = newOffset;
156
-
157
163
  log_debug(
158
- `TVSeekController: handleDelayedSeek - targetPos: ${targetPos}, offset: ${newOffset}, skipTime: ${offset}`
164
+ `TVSeekController: handleDelayedSeek - targetPos: ${targetPos}, skipTime: ${offset}`
159
165
  );
160
166
 
161
167
  const prevValue = this.delayedSeekProgressSubject.getValue();
@@ -168,9 +174,18 @@ export class TVSeekController
168
174
  }
169
175
  }
170
176
 
177
+ this.delayedSeekPosition = targetPos;
171
178
  this.delayedSeekProgressSubject.next(targetPos);
172
179
  };
173
180
 
181
+ handleSeekTo = (newPosition: number) => {
182
+ this.playerController.seekTo(newPosition);
183
+
184
+ if (!this.isPlayerInitiallyPaused) {
185
+ this.playerController.play();
186
+ }
187
+ };
188
+
174
189
  handleSeek = (offset: number) => {
175
190
  this.playerController[this.currentSeekType](offset);
176
191
 
@@ -180,11 +195,23 @@ export class TVSeekController
180
195
  };
181
196
 
182
197
  handleSeekComplete = () => {
183
- this.resetAll();
198
+ this.clearSeekCompleteTimeout();
199
+
200
+ this.seekEndTimeout = setTimeout(() => {
201
+ if (this.delayedSeekPosition !== null) {
202
+ this.handleSeekTo(this.delayedSeekPosition);
203
+ }
204
+
205
+ log_debug(
206
+ `handleSeekComplete: Seek finished, type: ${this.currentSeekController.title}, seekPosition: ${this.delayedSeekPosition}. Reset all states and seek position.`
207
+ );
208
+
209
+ this.resetAll();
210
+ }, SEEK_END_TIMEOUT_DURATION);
184
211
  };
185
212
 
186
- isAutoSeeking = (): boolean => {
187
- return this.longPressSeekController.isLongPressActive;
213
+ isSeeking = (): boolean => {
214
+ return this.delayedSeekPosition !== null;
188
215
  };
189
216
 
190
217
  handlePlayerPause = () => {
@@ -195,12 +222,34 @@ export class TVSeekController
195
222
  this.playerController.pause();
196
223
  };
197
224
 
225
+ clearSeekCompleteTimeout = () => {
226
+ if (this.seekEndTimeout === null) {
227
+ return;
228
+ }
229
+
230
+ clearTimeout(this.seekEndTimeout);
231
+ this.seekEndTimeout = null;
232
+ };
233
+
234
+ clearLongPressThresholdTimeout = () => {
235
+ if (this.longPressThresholdTimeout === null) {
236
+ return;
237
+ }
238
+
239
+ clearTimeout(this.longPressThresholdTimeout);
240
+ this.longPressThresholdTimeout = null;
241
+ };
242
+
198
243
  resetAll() {
199
244
  log_debug("TVSeekController: Reset all states");
200
245
  this.currentSeekType = null;
201
- this.delayedSeekOffset = null;
246
+
247
+ this.delayedSeekPosition = null;
202
248
  this.isPlayerInitiallyPaused = null;
203
249
 
250
+ this.clearSeekCompleteTimeout();
251
+ this.clearLongPressThresholdTimeout();
252
+
204
253
  this.tapSeekController.reset();
205
254
  this.longPressSeekController.reset();
206
255
 
@@ -1,75 +1,53 @@
1
- import { ISeekController, ISeekControllerDelegate } from "./ISeekController";
2
- import { SEEK_TYPE, MAX_SEEK_TIME, SKIP_TIME_BASE } from "../const";
1
+ import {
2
+ ISeekController,
3
+ ISeekControllerDelegate,
4
+ SeekIncrementalBaseStrategy,
5
+ } from "./ISeekController";
6
+ import { SEEK_TYPE } from "../const";
3
7
  import { log_debug } from "./TVSeekController";
4
8
 
5
9
  interface TapPressConfig {
6
10
  CLICKS_BEFORE_PAUSE: number;
7
11
  }
8
12
 
9
- const getSkipTime = (multiplier: number) =>
10
- Math.min(MAX_SEEK_TIME, SKIP_TIME_BASE * multiplier);
11
-
12
13
  export class TapSeekController implements ISeekController {
13
- private tapSequenceTimeout: any | null = null;
14
- private seekMultiplier = 1;
15
- private readonly ON_PRESS_RESET_DURATION = 500; // ms
16
-
14
+ readonly title = "TapSeek";
17
15
  constructor(
18
16
  private seekControllerDelegate: ISeekControllerDelegate,
17
+ private seekIncrementalStrategy: SeekIncrementalBaseStrategy,
19
18
  private config: TapPressConfig
20
19
  ) {}
21
20
 
22
21
  onStartSeek = (seekType: SEEK_TYPE) => {
23
- log_debug(`TapSeekController: start tap seek type: ${seekType}.`);
22
+ log_debug(`${this.title}: start tap seek type: ${seekType}.`);
24
23
 
25
- if (this.tapSequenceTimeout) {
26
- clearTimeout(this.tapSequenceTimeout);
27
- this.tapSequenceTimeout = null;
28
- }
24
+ const skipTime = this.seekIncrementalStrategy.getSkipTime();
25
+ const seekMultiplier = this.seekIncrementalStrategy.getSkipMultiplier();
29
26
 
30
- const skipTime = getSkipTime(this.seekMultiplier);
31
-
32
- if (this.seekMultiplier > this.config.CLICKS_BEFORE_PAUSE) {
27
+ if (seekMultiplier > this.config.CLICKS_BEFORE_PAUSE) {
33
28
  log_debug(
34
- `TapSeekController: handle delayed seek type:${seekType} - skipTime: ${skipTime}.`
29
+ `${this.title}: handle delayed seek type:${seekType} - skipTime: ${skipTime}, seekMultiplier: ${seekMultiplier}.`
35
30
  );
36
31
 
37
32
  this.seekControllerDelegate.handleDelayedSeek(skipTime);
38
33
  } else {
39
34
  log_debug(
40
- `TapSeekController: handle seek type:${seekType} - skipTime: ${skipTime}.`
35
+ `${this.title}: handle seek type:${seekType} - skipTime: ${skipTime}.`
41
36
  );
42
37
 
43
38
  this.seekControllerDelegate.handleSeek(skipTime);
44
39
  }
45
40
 
46
- this.seekMultiplier++;
41
+ this.seekIncrementalStrategy.increment();
47
42
  };
48
43
 
49
44
  onSeekEnd = () => {
50
- this.tapSequenceTimeout = setTimeout(() => {
51
- if (this.seekControllerDelegate.delayedSeekOffset !== null) {
52
- this.seekControllerDelegate.handleSeek(
53
- this.seekControllerDelegate.delayedSeekOffset
54
- );
55
- }
56
-
57
- log_debug(
58
- `TapSeekController: Tap sequence timeout fired, delayedSeekOffset: ${this.seekControllerDelegate.delayedSeekOffset}.`
59
- );
60
-
61
- this.seekControllerDelegate.handleSeekComplete();
62
- }, this.ON_PRESS_RESET_DURATION);
45
+ this.seekControllerDelegate.handleSeekComplete();
63
46
  };
64
47
 
65
48
  reset = () => {
66
- log_debug("TapSeekController: Reset states");
49
+ log_debug("{this.title}: Reset states");
67
50
 
68
- this.seekMultiplier = 1;
69
-
70
- if (this.tapSequenceTimeout) {
71
- clearTimeout(this.tapSequenceTimeout);
72
- this.tapSequenceTimeout = null;
73
- }
51
+ this.seekIncrementalStrategy.reset();
74
52
  };
75
53
  }
@@ -0,0 +1,115 @@
1
+ import { act, renderHook } from "@testing-library/react-hooks";
2
+ import { playerManager } from "@applicaster/zapp-react-native-utils/appUtils/playerManager";
3
+
4
+ import { ON_HOLD_INTERVAL, SEEK_TYPE, SKIP_TIME_BASE } from "../const";
5
+
6
+ import { useAutoSeek } from "../useAutoSeek";
7
+
8
+ jest.useFakeTimers({ legacyFakeTimers: true });
9
+
10
+ const rewind = jest.fn();
11
+ const forward = jest.fn();
12
+
13
+ jest
14
+ .spyOn(playerManager, "getInstanceController")
15
+ .mockReturnValue({ rewind, forward });
16
+
17
+ describe("useAutoSeek", () => {
18
+ beforeEach(() => {
19
+ rewind.mockReset();
20
+ forward.mockReset();
21
+ });
22
+
23
+ describe("autoSeekStart", () => {
24
+ it("should call forward method on playerInstance", () => {
25
+ const { result } = renderHook(() => useAutoSeek());
26
+
27
+ act(() => {
28
+ result.current.autoSeekStart(SEEK_TYPE.FORWARD);
29
+ });
30
+
31
+ expect(forward).toBeCalled();
32
+ result.current.autoSeekStop();
33
+ });
34
+
35
+ it("should call rewind method on playerManager", () => {
36
+ const { result } = renderHook(() => useAutoSeek());
37
+
38
+ act(() => {
39
+ result.current.autoSeekStart(SEEK_TYPE.REWIND);
40
+ });
41
+
42
+ expect(rewind).toBeCalled();
43
+ result.current.autoSeekStop();
44
+ });
45
+
46
+ it("should call rewind with default skip time", () => {
47
+ const { result } = renderHook(() => useAutoSeek());
48
+
49
+ act(() => {
50
+ result.current.autoSeekStart(SEEK_TYPE.REWIND);
51
+ });
52
+
53
+ expect(rewind).toBeCalledWith(SKIP_TIME_BASE);
54
+ result.current.autoSeekStop();
55
+ });
56
+
57
+ it("should call forward with default skip time", () => {
58
+ const { result } = renderHook(() => useAutoSeek());
59
+
60
+ act(() => {
61
+ result.current.autoSeekStart(SEEK_TYPE.FORWARD);
62
+ });
63
+
64
+ expect(forward).toBeCalledWith(SKIP_TIME_BASE);
65
+ result.current.autoSeekStop();
66
+ });
67
+
68
+ it("should call rewind in intervals set in configuration", () => {
69
+ const { result } = renderHook(() => useAutoSeek());
70
+
71
+ act(() => {
72
+ result.current.autoSeekStart(SEEK_TYPE.REWIND);
73
+ });
74
+
75
+ expect(rewind).toBeCalled();
76
+ jest.advanceTimersByTime(ON_HOLD_INTERVAL * 3);
77
+ expect(rewind).toBeCalledTimes(4);
78
+ result.current.autoSeekStop();
79
+ });
80
+
81
+ it("should call forward in intervals set in configuration", () => {
82
+ const { result } = renderHook(() => useAutoSeek());
83
+
84
+ act(() => {
85
+ result.current.autoSeekStart(SEEK_TYPE.FORWARD);
86
+ });
87
+
88
+ expect(forward).toBeCalled();
89
+ jest.advanceTimersByTime(ON_HOLD_INTERVAL * 3);
90
+ expect(forward).toBeCalledTimes(4);
91
+ result.current.autoSeekStop();
92
+ });
93
+ });
94
+
95
+ describe("autoSeekStop", () => {
96
+ it("should stop calling playerManager method after autoSeekStop is called", () => {
97
+ const { result } = renderHook(() => useAutoSeek());
98
+
99
+ act(() => {
100
+ result.current.autoSeekStart(SEEK_TYPE.FORWARD);
101
+ });
102
+
103
+ expect(forward).toBeCalled();
104
+ jest.advanceTimersByTime(ON_HOLD_INTERVAL * 3);
105
+ expect(forward).toBeCalledTimes(4);
106
+
107
+ act(() => {
108
+ result.current.autoSeekStop();
109
+ });
110
+
111
+ jest.advanceTimersByTime(ON_HOLD_INTERVAL * 3);
112
+ expect(forward).toBeCalledTimes(4);
113
+ });
114
+ });
115
+ });
@@ -0,0 +1,94 @@
1
+ import { renderHook } from "@testing-library/react-hooks";
2
+ import { playerManager } from "@applicaster/zapp-react-native-utils/appUtils/playerManager";
3
+ import { useTapSeek } from "../useTapSeek";
4
+
5
+ import { ON_PRESS_RESET_DURATION, SEEK_TYPE, SKIP_TIME_BASE } from "../const";
6
+
7
+ const rewind = jest.fn();
8
+ const forward = jest.fn();
9
+
10
+ jest
11
+ .spyOn(playerManager, "getInstanceController")
12
+ // @ts-ignore
13
+ .mockImplementation(() => ({ rewind, forward }));
14
+
15
+ describe("useTapSeek", () => {
16
+ beforeEach(() => {
17
+ rewind.mockReset();
18
+ forward.mockReset();
19
+ });
20
+
21
+ describe("forward", () => {
22
+ it("should call forward method on playerManager", () => {
23
+ const { result } = renderHook(() => useTapSeek());
24
+
25
+ result.current(SEEK_TYPE.FORWARD);
26
+ expect(forward).toBeCalled();
27
+ });
28
+
29
+ it("should call forward with default skip time", () => {
30
+ const { result } = renderHook(() => useTapSeek());
31
+
32
+ result.current(SEEK_TYPE.FORWARD);
33
+ expect(forward).toBeCalledWith(SKIP_TIME_BASE);
34
+ });
35
+
36
+ it("should multiply skip time for every call", async () => {
37
+ const { result } = renderHook(() => useTapSeek());
38
+
39
+ result.current(SEEK_TYPE.FORWARD);
40
+ expect(forward).toBeCalledWith(SKIP_TIME_BASE);
41
+ result.current(SEEK_TYPE.FORWARD);
42
+ expect(forward).toBeCalledWith(SKIP_TIME_BASE * 2);
43
+ });
44
+
45
+ it("should reset multiplier if waiting more then resetDuration between press actions", () => {
46
+ const { result, waitFor } = renderHook(() => useTapSeek());
47
+
48
+ result.current(SEEK_TYPE.FORWARD);
49
+ expect(forward).toBeCalledWith(SKIP_TIME_BASE);
50
+ waitFor(jest.fn(), { timeout: ON_PRESS_RESET_DURATION });
51
+ result.current(SEEK_TYPE.FORWARD);
52
+ expect(forward).toBeCalledWith(SKIP_TIME_BASE);
53
+ });
54
+ });
55
+
56
+ describe("rewind", () => {
57
+ it("should call rewind method on playerManager", () => {
58
+ const { result } = renderHook(() => useTapSeek());
59
+
60
+ result.current(SEEK_TYPE.REWIND);
61
+ expect(rewind).toBeCalled();
62
+ });
63
+
64
+ it("should call rewind with default skip time", () => {
65
+ const { result } = renderHook(() => useTapSeek());
66
+
67
+ result.current(SEEK_TYPE.REWIND);
68
+ expect(rewind).toBeCalledWith(SKIP_TIME_BASE);
69
+ });
70
+
71
+ it("should multiply skip time for every call", async () => {
72
+ const { result } = renderHook(() => useTapSeek());
73
+
74
+ result.current(SEEK_TYPE.REWIND);
75
+ expect(rewind).toBeCalledWith(SKIP_TIME_BASE);
76
+ result.current(SEEK_TYPE.REWIND);
77
+ expect(rewind).toBeCalledWith(SKIP_TIME_BASE * 2);
78
+ });
79
+ });
80
+
81
+ describe("mixed usage", () => {
82
+ it("should reset timer if different type of event is emitted", () => {
83
+ const { result } = renderHook(() => useTapSeek());
84
+ result.current(SEEK_TYPE.REWIND);
85
+ expect(rewind).toBeCalledWith(SKIP_TIME_BASE);
86
+
87
+ result.current(SEEK_TYPE.REWIND);
88
+ expect(rewind).toBeCalledWith(SKIP_TIME_BASE * 2);
89
+
90
+ result.current(SEEK_TYPE.FORWARD);
91
+ expect(forward).toBeCalledWith(SKIP_TIME_BASE);
92
+ });
93
+ });
94
+ });
@@ -1,6 +1,6 @@
1
1
  export const SKIP_TIME_BASE = 10;
2
2
 
3
- export const MAX_SEEK_TIME = 60;
3
+ export const MAX_SEEK_TIME = 600;
4
4
 
5
5
  export enum SEEK_TYPE {
6
6
  FORWARD = "forward",
@@ -1,4 +1,3 @@
1
- jest.mock("create-react-ref/lib/createRef", () => jest.fn());
2
1
  import * as React from "react";
3
2
  import * as helpers from "../helpers";
4
3
 
@@ -8,13 +7,7 @@ import {
8
7
  componentDidMount,
9
8
  } from "./fixtures";
10
9
 
11
- const {
12
- attachLifeCycleMethods,
13
- createReactRef,
14
- mergeChildrenProps,
15
- } = require("../index");
16
-
17
- const createRef = require("create-react-ref/lib/createRef");
10
+ import { attachLifeCycleMethods, createReactRef, mergeChildrenProps } from "..";
18
11
 
19
12
  describe("attachLifeCycleMethods", () => {
20
13
  let addLifeCycleMethodsSpy;
@@ -50,30 +43,19 @@ describe("attachLifeCycleMethods", () => {
50
43
 
51
44
  describe("createReactRef", () => {
52
45
  it("calls the React.createRef function if it exists", () => {
53
- jest.resetModules();
54
-
55
- jest.doMock("react", () => ({
56
- ...jest.requireActual("react"),
57
- createRef: jest.fn(),
58
- }));
59
-
60
- const React = require("react");
46
+ jest.clearAllMocks();
61
47
 
62
- createReactRef();
63
- expect(React.createRef).toHaveBeenCalled();
64
- expect(createRef).not.toHaveBeenCalled();
48
+ const ref = createReactRef();
49
+ expect(ref).toHaveProperty("current");
65
50
  });
66
51
 
67
52
  it("calls the polyfill if React.createRef doesn't exist", () => {
68
- jest.resetModules();
69
-
70
- jest.doMock("react", () => ({
71
- ...jest.requireActual("react"),
72
- createRef: undefined,
73
- }));
74
-
75
- createReactRef();
76
- expect(createRef).toHaveBeenCalled();
53
+ jest.clearAllMocks();
54
+ const originalCreateRef = React.createRef;
55
+ React.createRef = undefined;
56
+ const ref = createReactRef();
57
+ expect(ref).toHaveProperty("current");
58
+ React.createRef = originalCreateRef;
77
59
  });
78
60
  });
79
61