hermes-test 1.0.1 → 1.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.
@@ -2,15 +2,19 @@
2
2
  // Provides stub implementations of commonly used RN APIs.
3
3
  // Users can override via hermes-test.config.json "shims" or mockModule().
4
4
 
5
- var noop = function() {};
6
- var noopReturn = function(x) { return x; };
5
+ var noop = function () {};
6
+ var noopReturn = function (x) {
7
+ return x;
8
+ };
7
9
 
8
10
  module.exports = {
9
11
  // Platform
10
12
  Platform: {
11
13
  OS: 'ios',
12
14
  Version: 19,
13
- select: function(obj) { return obj.ios !== undefined ? obj.ios : obj.default; },
15
+ select: function (obj) {
16
+ return obj.ios !== undefined ? obj.ios : obj.default;
17
+ },
14
18
  isPad: false,
15
19
  isTVOS: false,
16
20
  isTV: false,
@@ -18,8 +22,10 @@ module.exports = {
18
22
 
19
23
  // StyleSheet
20
24
  StyleSheet: {
21
- create: function(styles) { return styles; },
22
- flatten: function(style) {
25
+ create: function (styles) {
26
+ return styles;
27
+ },
28
+ flatten: function (style) {
23
29
  if (!style) return {};
24
30
  if (Array.isArray(style)) {
25
31
  var result = {};
@@ -37,23 +43,35 @@ module.exports = {
37
43
 
38
44
  // Dimensions
39
45
  Dimensions: {
40
- get: function() { return { width: 375, height: 812, scale: 3, fontScale: 1 }; },
41
- addEventListener: function() { return { remove: noop }; },
46
+ get: function () {
47
+ return { width: 375, height: 812, scale: 3, fontScale: 1 };
48
+ },
49
+ addEventListener: function () {
50
+ return { remove: noop };
51
+ },
42
52
  removeEventListener: noop,
43
53
  },
44
54
 
45
55
  // PixelRatio
46
56
  PixelRatio: {
47
- get: function() { return 3; },
48
- getFontScale: function() { return 1; },
49
- getPixelSizeForLayoutSize: function(size) { return size * 3; },
50
- roundToNearestPixel: function(size) { return Math.round(size * 3) / 3; },
57
+ get: function () {
58
+ return 3;
59
+ },
60
+ getFontScale: function () {
61
+ return 1;
62
+ },
63
+ getPixelSizeForLayoutSize: function (size) {
64
+ return size * 3;
65
+ },
66
+ roundToNearestPixel: function (size) {
67
+ return Math.round(size * 3) / 3;
68
+ },
51
69
  },
52
70
 
53
71
  // AppState
54
72
  AppState: {
55
73
  currentState: 'active',
56
- addEventListener: function(event, cb) {
74
+ addEventListener: function (event, cb) {
57
75
  return { remove: noop };
58
76
  },
59
77
  removeEventListener: noop,
@@ -67,46 +85,106 @@ module.exports = {
67
85
 
68
86
  // Linking
69
87
  Linking: {
70
- openURL: function() { return Promise.resolve(); },
71
- canOpenURL: function() { return Promise.resolve(true); },
72
- getInitialURL: function() { return Promise.resolve(null); },
73
- addEventListener: function() { return { remove: noop }; },
88
+ openURL: function () {
89
+ return Promise.resolve();
90
+ },
91
+ canOpenURL: function () {
92
+ return Promise.resolve(true);
93
+ },
94
+ getInitialURL: function () {
95
+ return Promise.resolve(null);
96
+ },
97
+ addEventListener: function () {
98
+ return { remove: noop };
99
+ },
74
100
  removeEventListener: noop,
75
101
  },
76
102
 
77
103
  // Keyboard
78
104
  Keyboard: {
79
105
  dismiss: noop,
80
- addListener: function() { return { remove: noop }; },
106
+ addListener: function () {
107
+ return { remove: noop };
108
+ },
81
109
  removeListener: noop,
82
110
  removeAllListeners: noop,
83
111
  },
84
112
 
85
113
  // Animated
86
114
  Animated: {
87
- Value: function(val) {
115
+ Value: function (val) {
88
116
  this._value = val;
89
- this.setValue = function(v) { this._value = v; };
90
- this.interpolate = function() { return new module.exports.Animated.Value(0); };
91
- this.addListener = function() { return { remove: noop }; };
117
+ this.setValue = function (v) {
118
+ this._value = v;
119
+ };
120
+ this.interpolate = function () {
121
+ return new module.exports.Animated.Value(0);
122
+ };
123
+ this.addListener = function () {
124
+ return { remove: noop };
125
+ };
92
126
  this.removeListener = noop;
93
127
  this.removeAllListeners = noop;
94
- this.stopAnimation = function(cb) { if (cb) cb(this._value); };
128
+ this.stopAnimation = function (cb) {
129
+ if (cb) cb(this._value);
130
+ };
95
131
  },
96
- ValueXY: function() {
132
+ ValueXY: function () {
97
133
  this.x = new module.exports.Animated.Value(0);
98
134
  this.y = new module.exports.Animated.Value(0);
99
135
  this.setValue = noop;
100
- this.getLayout = function() { return { left: this.x, top: this.y }; };
101
- },
102
- timing: function() { return { start: function(cb) { if (cb) cb({ finished: true }); } }; },
103
- spring: function() { return { start: function(cb) { if (cb) cb({ finished: true }); } }; },
104
- decay: function() { return { start: function(cb) { if (cb) cb({ finished: true }); } }; },
105
- parallel: function() { return { start: function(cb) { if (cb) cb({ finished: true }); } }; },
106
- sequence: function() { return { start: function(cb) { if (cb) cb({ finished: true }); } }; },
107
- stagger: function() { return { start: function(cb) { if (cb) cb({ finished: true }); } }; },
108
- loop: function() { return { start: noop, stop: noop }; },
109
- event: function() { return noop; },
136
+ this.getLayout = function () {
137
+ return { left: this.x, top: this.y };
138
+ };
139
+ },
140
+ timing: function () {
141
+ return {
142
+ start: function (cb) {
143
+ if (cb) cb({ finished: true });
144
+ },
145
+ };
146
+ },
147
+ spring: function () {
148
+ return {
149
+ start: function (cb) {
150
+ if (cb) cb({ finished: true });
151
+ },
152
+ };
153
+ },
154
+ decay: function () {
155
+ return {
156
+ start: function (cb) {
157
+ if (cb) cb({ finished: true });
158
+ },
159
+ };
160
+ },
161
+ parallel: function () {
162
+ return {
163
+ start: function (cb) {
164
+ if (cb) cb({ finished: true });
165
+ },
166
+ };
167
+ },
168
+ sequence: function () {
169
+ return {
170
+ start: function (cb) {
171
+ if (cb) cb({ finished: true });
172
+ },
173
+ };
174
+ },
175
+ stagger: function () {
176
+ return {
177
+ start: function (cb) {
178
+ if (cb) cb({ finished: true });
179
+ },
180
+ };
181
+ },
182
+ loop: function () {
183
+ return { start: noop, stop: noop };
184
+ },
185
+ event: function () {
186
+ return noop;
187
+ },
110
188
  createAnimatedComponent: noopReturn,
111
189
  View: 'Animated.View',
112
190
  Text: 'Animated.Text',
@@ -116,8 +194,12 @@ module.exports = {
116
194
  },
117
195
 
118
196
  // Hooks
119
- useWindowDimensions: function() { return { width: 375, height: 812, scale: 3, fontScale: 1 }; },
120
- useColorScheme: function() { return 'light'; },
197
+ useWindowDimensions: function () {
198
+ return { width: 375, height: 812, scale: 3, fontScale: 1 };
199
+ },
200
+ useColorScheme: function () {
201
+ return 'light';
202
+ },
121
203
 
122
204
  // Components (string stubs — not rendered in test)
123
205
  View: 'View',
@@ -147,22 +229,32 @@ module.exports = {
147
229
 
148
230
  // Appearance
149
231
  Appearance: {
150
- getColorScheme: function() { return 'light'; },
151
- addChangeListener: function() { return { remove: noop }; },
232
+ getColorScheme: function () {
233
+ return 'light';
234
+ },
235
+ addChangeListener: function () {
236
+ return { remove: noop };
237
+ },
152
238
  },
153
239
 
154
240
  // NativeModules fallback
155
241
  NativeModules: {},
156
- NativeEventEmitter: function() {
157
- this.addListener = function() { return { remove: noop }; };
242
+ NativeEventEmitter: function () {
243
+ this.addListener = function () {
244
+ return { remove: noop };
245
+ };
158
246
  this.removeListener = noop;
159
247
  this.removeAllListeners = noop;
160
248
  },
161
249
 
162
250
  // AccessibilityInfo
163
251
  AccessibilityInfo: {
164
- isScreenReaderEnabled: function() { return Promise.resolve(false); },
165
- addEventListener: function() { return { remove: noop }; },
252
+ isScreenReaderEnabled: function () {
253
+ return Promise.resolve(false);
254
+ },
255
+ addEventListener: function () {
256
+ return { remove: noop };
257
+ },
166
258
  announceForAccessibility: noop,
167
259
  },
168
260
  };
@@ -2,15 +2,15 @@
2
2
  // react-reconciler imports 'react' — this shim delegates to globalThis.__HT_React.
3
3
  // The Proxy ensures late-binding: properties are read at access time, not import time.
4
4
  var handler = {
5
- get: function(_, prop) {
5
+ get: function (_, prop) {
6
6
  if (prop === Symbol.toPrimitive || prop === 'then') return undefined;
7
7
  var R = globalThis.__HT_React;
8
8
  return R ? R[prop] : undefined;
9
9
  },
10
- set: function(_, prop, value) {
10
+ set: function (_, prop, value) {
11
11
  var R = globalThis.__HT_React;
12
12
  if (R) R[prop] = value;
13
13
  return true;
14
- }
14
+ },
15
15
  };
16
16
  module.exports = new Proxy({}, handler);
@@ -12,10 +12,10 @@ var real = require('@__ht_real_pkg/@reduxjs/toolkit/query');
12
12
  var _apiCache = {};
13
13
 
14
14
  var handler = {
15
- get: function(target, prop) {
15
+ get: function (target, prop) {
16
16
  if (prop === 'createApi') {
17
17
  return function createApi(opts) {
18
- var key = opts && opts.reducerPath || 'api';
18
+ var key = (opts && opts.reducerPath) || 'api';
19
19
  if (_apiCache[key]) return _apiCache[key];
20
20
  var api = real.createApi(opts);
21
21
  _apiCache[key] = api;
@@ -24,16 +24,26 @@ var handler = {
24
24
  }
25
25
  return real[prop];
26
26
  },
27
- ownKeys: function() {
28
- try { return Object.getOwnPropertyNames(real); } catch(e) { return []; }
27
+ ownKeys: function () {
28
+ try {
29
+ return Object.getOwnPropertyNames(real);
30
+ } catch (e) {
31
+ return [];
32
+ }
29
33
  },
30
- getOwnPropertyDescriptor: function(target, prop) {
34
+ getOwnPropertyDescriptor: function (target, prop) {
31
35
  try {
32
36
  var d = Object.getOwnPropertyDescriptor(real, prop);
33
- if (d) return { configurable: true, enumerable: d.enumerable, writable: true, value: d.get ? d.get() : d.value };
34
- } catch(e) {}
37
+ if (d)
38
+ return {
39
+ configurable: true,
40
+ enumerable: d.enumerable,
41
+ writable: true,
42
+ value: d.get ? d.get() : d.value,
43
+ };
44
+ } catch (e) {}
35
45
  return { configurable: true, enumerable: false, writable: true, value: undefined };
36
- }
46
+ },
37
47
  };
38
48
 
39
49
  module.exports = new Proxy({}, handler);
@@ -17,10 +17,10 @@ var _apiCache = {};
17
17
  // Proxy delegates everything to the real module with late binding.
18
18
  // This avoids eagerly copying ESM live bindings that may not be initialized yet.
19
19
  var handler = {
20
- get: function(target, prop) {
20
+ get: function (target, prop) {
21
21
  if (prop === 'createApi') {
22
22
  return function createApi(opts) {
23
- var key = opts && opts.reducerPath || 'api';
23
+ var key = (opts && opts.reducerPath) || 'api';
24
24
  if (_apiCache[key]) return _apiCache[key];
25
25
  var api = real.createApi(opts);
26
26
  _apiCache[key] = api;
@@ -29,16 +29,26 @@ var handler = {
29
29
  }
30
30
  return real[prop];
31
31
  },
32
- ownKeys: function() {
33
- try { return Object.getOwnPropertyNames(real); } catch(e) { return []; }
32
+ ownKeys: function () {
33
+ try {
34
+ return Object.getOwnPropertyNames(real);
35
+ } catch (e) {
36
+ return [];
37
+ }
34
38
  },
35
- getOwnPropertyDescriptor: function(target, prop) {
39
+ getOwnPropertyDescriptor: function (target, prop) {
36
40
  try {
37
41
  var d = Object.getOwnPropertyDescriptor(real, prop);
38
- if (d) return { configurable: true, enumerable: d.enumerable, writable: true, value: d.get ? d.get() : d.value };
39
- } catch(e) {}
42
+ if (d)
43
+ return {
44
+ configurable: true,
45
+ enumerable: d.enumerable,
46
+ writable: true,
47
+ value: d.get ? d.get() : d.value,
48
+ };
49
+ } catch (e) {}
40
50
  return { configurable: true, enumerable: false, writable: true, value: undefined };
41
- }
51
+ },
42
52
  };
43
53
 
44
54
  module.exports = new Proxy({}, handler);
@@ -50,7 +50,7 @@ mod.withQueryClient = function withQueryClient(opts) {
50
50
  var React = require('react');
51
51
  var QCP = mod.QueryClientProvider;
52
52
 
53
- var wrapper = function(props) {
53
+ var wrapper = function (props) {
54
54
  return React.createElement(QCP, { client: client }, props.children);
55
55
  };
56
56
 
@@ -59,7 +59,7 @@ mod.withQueryClient = function withQueryClient(opts) {
59
59
  return {
60
60
  queryClient: client,
61
61
  wrapper: wrapper,
62
- renderHookWithQuery: function(hookFn, hookOpts) {
62
+ renderHookWithQuery: function (hookFn, hookOpts) {
63
63
  return renderHook(hookFn, Object.assign({}, hookOpts, { wrapper: wrapper }));
64
64
  },
65
65
  };
package/src/spy.ts CHANGED
@@ -1,31 +1,30 @@
1
- export type Spy<F extends (...args: any[]) => any = (...args: any[]) => any> =
2
- F & {
3
- readonly calls: ReadonlyArray<Parameters<F>>;
4
- readonly callCount: number;
5
- readonly returnValues: ReadonlyArray<ReturnType<F>>;
6
- reset(): void;
7
-
8
- // Core
9
- setImpl(impl: F): void;
10
- returns(value: ReturnType<F>): Spy<F>;
11
-
12
- // Jest-compatible API
13
- mockImplementation(fn: F): Spy<F>;
14
- mockImplementationOnce(fn: F): Spy<F>;
15
- mockReturnValue(value: ReturnType<F>): Spy<F>;
16
- mockReturnValueOnce(value: ReturnType<F>): Spy<F>;
17
- mockResolvedValue(value: any): Spy<F>;
18
- mockResolvedValueOnce(value: any): Spy<F>;
19
- mockRejectedValue(value: any): Spy<F>;
20
- mockRejectedValueOnce(value: any): Spy<F>;
21
- mockClear(): void;
22
- mockReset(): void;
23
- mockRestore(): void;
24
-
25
- // spyOn support
26
- _restore?: () => void;
27
- _isSpy: true;
28
- };
1
+ export type Spy<F extends (...args: any[]) => any = (...args: any[]) => any> = F & {
2
+ readonly calls: ReadonlyArray<Parameters<F>>;
3
+ readonly callCount: number;
4
+ readonly returnValues: ReadonlyArray<ReturnType<F>>;
5
+ reset(): void;
6
+
7
+ // Core
8
+ setImpl(impl: F): void;
9
+ returns(value: ReturnType<F>): Spy<F>;
10
+
11
+ // Jest-compatible API
12
+ mockImplementation(fn: F): Spy<F>;
13
+ mockImplementationOnce(fn: F): Spy<F>;
14
+ mockReturnValue(value: ReturnType<F>): Spy<F>;
15
+ mockReturnValueOnce(value: ReturnType<F>): Spy<F>;
16
+ mockResolvedValue(value: any): Spy<F>;
17
+ mockResolvedValueOnce(value: any): Spy<F>;
18
+ mockRejectedValue(value: any): Spy<F>;
19
+ mockRejectedValueOnce(value: any): Spy<F>;
20
+ mockClear(): void;
21
+ mockReset(): void;
22
+ mockRestore(): void;
23
+
24
+ // spyOn support
25
+ _restore?: () => void;
26
+ _isSpy: true;
27
+ };
29
28
 
30
29
  // Registry of all spies created — clearAllMocks() clears them all at once.
31
30
  const _allSpies: Spy[] = [];
@@ -34,9 +33,7 @@ export function clearAllMocks(): void {
34
33
  for (const s of _allSpies) s.mockClear();
35
34
  }
36
35
 
37
- export function spy<F extends (...args: any[]) => any = () => void>(
38
- impl?: F
39
- ): Spy<F> {
36
+ export function spy<F extends (...args: any[]) => any = () => void>(impl?: F): Spy<F> {
40
37
  let baseImpl: F | undefined = impl;
41
38
  const onceImpls: F[] = []; // FIFO queue for mockImplementationOnce/mockReturnValueOnce
42
39
  const calls: any[][] = [];
@@ -154,13 +151,12 @@ export function spy<F extends (...args: any[]) => any = () => void>(
154
151
  }
155
152
 
156
153
  // --- spyOn: replace a method on an object with a spy, preserving original ---
157
- export function spyOn<T extends Record<string, any>>(
158
- obj: T,
159
- method: keyof T & string,
160
- ): Spy {
154
+ export function spyOn<T extends Record<string, any>>(obj: T, method: keyof T & string): Spy {
161
155
  const original = obj[method];
162
156
  const s = spy(typeof original === 'function' ? original.bind(obj) : undefined);
163
- (s as any)._restore = () => { obj[method] = original; };
157
+ (s as any)._restore = () => {
158
+ obj[method] = original;
159
+ };
164
160
  obj[method] = s as any;
165
161
  return s;
166
162
  }
package/src/store.ts CHANGED
@@ -9,7 +9,6 @@ import React from 'react';
9
9
  import { Provider } from 'react-redux';
10
10
  import { configureStore } from '@reduxjs/toolkit';
11
11
 
12
-
13
12
  type StoreContext = {
14
13
  store: any;
15
14
  wrapper: any;
@@ -17,7 +16,10 @@ type StoreContext = {
17
16
  getState: () => any;
18
17
  setState: (state: Record<string, any>) => void;
19
18
  patchState: (partial: Record<string, any>) => void;
20
- renderHookWithReduxStore: <T>(hookFn: (props?: any) => T, options?: { initialProps?: any }) => any;
19
+ renderHookWithReduxStore: <T>(
20
+ hookFn: (props?: any) => T,
21
+ options?: { initialProps?: any },
22
+ ) => any;
21
23
  };
22
24
 
23
25
  function withTestActions(reducer: (state: any, action: any) => any) {
@@ -39,8 +41,12 @@ function makeCtx(store: any): StoreContext {
39
41
  wrapper,
40
42
  dispatch: store.dispatch.bind(store),
41
43
  getState: store.getState.bind(store),
42
- setState(state: Record<string, any>) { store.dispatch({ type: '__SET_STATE__', payload: state }); },
43
- patchState(partial: Record<string, any>) { store.dispatch({ type: '__PATCH__', payload: partial }); },
44
+ setState(state: Record<string, any>) {
45
+ store.dispatch({ type: '__SET_STATE__', payload: state });
46
+ },
47
+ patchState(partial: Record<string, any>) {
48
+ store.dispatch({ type: '__PATCH__', payload: partial });
49
+ },
44
50
  renderHookWithReduxStore<T>(hookFn: (props?: any) => T, options?: { initialProps?: any }) {
45
51
  return renderHook(hookFn, { ...options, wrapper });
46
52
  },
@@ -49,11 +55,13 @@ function makeCtx(store: any): StoreContext {
49
55
 
50
56
  /** Quick store from plain state object — identity reducer, any shape */
51
57
  export function withStore(initialState: Record<string, any> = {}): StoreContext {
52
- return makeCtx(configureStore({
53
- reducer: withTestActions((s: any = initialState) => s),
54
- preloadedState: initialState,
55
- middleware: (gdm) => gdm({ serializableCheck: false, immutableCheck: false }),
56
- }));
58
+ return makeCtx(
59
+ configureStore({
60
+ reducer: withTestActions((s: any = initialState) => s),
61
+ preloadedState: initialState,
62
+ middleware: gdm => gdm({ serializableCheck: false, immutableCheck: false }),
63
+ }),
64
+ );
57
65
  }
58
66
 
59
67
  /** Real app reducer — patchState + real actions both work */
@@ -61,11 +69,13 @@ export function withAppReducer(
61
69
  reducer: (state: any, action: any) => any,
62
70
  preloadedState?: Record<string, any>,
63
71
  ): StoreContext {
64
- return makeCtx(configureStore({
65
- reducer: withTestActions(reducer),
66
- preloadedState,
67
- middleware: (gdm) => gdm({ serializableCheck: false, immutableCheck: false }),
68
- }));
72
+ return makeCtx(
73
+ configureStore({
74
+ reducer: withTestActions(reducer),
75
+ preloadedState,
76
+ middleware: gdm => gdm({ serializableCheck: false, immutableCheck: false }),
77
+ }),
78
+ );
69
79
  }
70
80
 
71
81
  interface RtkQueryApi {
@@ -103,11 +113,11 @@ export function setupApiStore(
103
113
  const store = configureStore({
104
114
  reducer: reducerMap,
105
115
  preloadedState: options?.preloadedState,
106
- middleware: (gdm) => {
116
+ middleware: gdm => {
107
117
  let chain = gdm({ serializableCheck: false, immutableCheck: false });
108
118
  for (const a of apis) chain = chain.concat(a.middleware);
109
- for (const mw of (options?.middleware?.concat ?? [])) chain = chain.concat(mw);
110
- for (const mw of (options?.middleware?.prepend ?? [])) chain = chain.prepend(mw);
119
+ for (const mw of options?.middleware?.concat ?? []) chain = chain.concat(mw);
120
+ for (const mw of options?.middleware?.prepend ?? []) chain = chain.prepend(mw);
111
121
  return chain;
112
122
  },
113
123
  });
package/src/timers.ts CHANGED
@@ -10,7 +10,9 @@
10
10
  // useFakeTimers does `globalThis.Date.now = () => fakeNow` which mutates the original
11
11
  // Date object's .now property. So we must save the function itself, not the constructor.
12
12
  const _savedDateNow: () => number = Date.now;
13
- export function realDateNow(): number { return _savedDateNow(); }
13
+ export function realDateNow(): number {
14
+ return _savedDateNow();
15
+ }
14
16
 
15
17
  interface PendingTimer {
16
18
  id: number;
@@ -118,7 +120,7 @@ export function runAllTimers() {
118
120
  if (!isFake) throw new Error('runAllTimers called without useFakeTimers()');
119
121
  let safety = 1000;
120
122
  while (pending.length > 0 && safety-- > 0) {
121
- const next = pending.reduce((min, t) => t.fireAt < min.fireAt ? t : min);
123
+ const next = pending.reduce((min, t) => (t.fireAt < min.fireAt ? t : min));
122
124
  fakeNow = next.fireAt;
123
125
  if (next.type === 'timeout') {
124
126
  pending = pending.filter(t => t.id !== next.id);
@@ -136,6 +138,6 @@ export function getTimerCount(): number {
136
138
 
137
139
  export function advanceTimersToNextTimer() {
138
140
  if (!isFake || pending.length === 0) return;
139
- const next = pending.reduce((min, t) => t.fireAt < min.fireAt ? t : min);
141
+ const next = pending.reduce((min, t) => (t.fireAt < min.fireAt ? t : min));
140
142
  advanceTimersByTime(next.fireAt - fakeNow);
141
143
  }