react-jitter 0.4.0 → 0.5.0
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/README.md
CHANGED
|
@@ -256,6 +256,33 @@ Here is an example of the `change` object when `includeArguments` is enabled:
|
|
|
256
256
|
|
|
257
257
|
In this example, the `arguments` field shows that the `UserContext` was used, and the `changedKeys` field shows that the `user` property has changed.
|
|
258
258
|
|
|
259
|
+
### Detecting Unstable Hooks in Unit Tests
|
|
260
|
+
|
|
261
|
+
React Jitter can also be a powerful tool for improving code quality within your unit tests.
|
|
262
|
+
|
|
263
|
+
You can leverage this to write tests that fail if a hook becomes unstable, catching performance regressions early in the a testing setup where you might initialize React Jitter in a global setup file, you can easily override the `onHookChange` handler on a per-test basis.
|
|
264
|
+
|
|
265
|
+
```javascript
|
|
266
|
+
// Example of a Vitest/Jest test
|
|
267
|
+
it('should not have unstable hooks', () => {
|
|
268
|
+
const unstableChanges = [];
|
|
269
|
+
// Initialize React Jitter in a global setup file (e.g., setupTests.js)
|
|
270
|
+
// Then, override the onHookChange handler for specific tests.
|
|
271
|
+
window.reactJitter.onHookChange = (change) => {
|
|
272
|
+
// You can ignore mocked hooks or handle them specifically
|
|
273
|
+
if (change.unstable && !change.isMocked) {
|
|
274
|
+
unstableChanges.push(change);
|
|
275
|
+
}
|
|
276
|
+
};
|
|
277
|
+
|
|
278
|
+
render(<MyComponent />);
|
|
279
|
+
|
|
280
|
+
// Assert that no unstable values were detected during the render
|
|
281
|
+
expect(unstableChanges).toHaveLength(0);
|
|
282
|
+
});
|
|
283
|
+
```
|
|
284
|
+
|
|
285
|
+
The `onHookChange` callback's `change` object includes an `isMocked` boolean property. This is automatically set to `true` if React Jitter detects that the hook has been mocked (e.g., using `jest.fn()` or `vi.fn()`). This allows you to reliably identify and assert against unstable values in your test environment.
|
|
259
286
|
|
|
260
287
|
## How It Works
|
|
261
288
|
|
package/package.json
CHANGED
|
Binary file
|
package/runtime/dist/index.d.mts
CHANGED
|
@@ -40,6 +40,7 @@ type HookEndEvent = {
|
|
|
40
40
|
line: number;
|
|
41
41
|
offset: number;
|
|
42
42
|
arguments?: string[];
|
|
43
|
+
isMocked?: boolean;
|
|
43
44
|
};
|
|
44
45
|
type HookAddress = Pick<HookEndEvent, 'hook' | 'file' | 'line' | 'offset' | 'arguments'>;
|
|
45
46
|
type ReactJitterOptions = {
|
|
@@ -82,6 +83,7 @@ declare function useJitterScope(scope: Scope): {
|
|
|
82
83
|
s: (id: string) => void;
|
|
83
84
|
e: (hookResult: unknown, hookEndEvent: HookEndEvent) => unknown;
|
|
84
85
|
re: <T>(renderResult: T) => T;
|
|
86
|
+
m: (value: unknown) => boolean;
|
|
85
87
|
};
|
|
86
88
|
declare function reactJitter(options: ReactJitterOptions): void;
|
|
87
89
|
|
package/runtime/dist/index.d.ts
CHANGED
|
@@ -40,6 +40,7 @@ type HookEndEvent = {
|
|
|
40
40
|
line: number;
|
|
41
41
|
offset: number;
|
|
42
42
|
arguments?: string[];
|
|
43
|
+
isMocked?: boolean;
|
|
43
44
|
};
|
|
44
45
|
type HookAddress = Pick<HookEndEvent, 'hook' | 'file' | 'line' | 'offset' | 'arguments'>;
|
|
45
46
|
type ReactJitterOptions = {
|
|
@@ -82,6 +83,7 @@ declare function useJitterScope(scope: Scope): {
|
|
|
82
83
|
s: (id: string) => void;
|
|
83
84
|
e: (hookResult: unknown, hookEndEvent: HookEndEvent) => unknown;
|
|
84
85
|
re: <T>(renderResult: T) => T;
|
|
86
|
+
m: (value: unknown) => boolean;
|
|
85
87
|
};
|
|
86
88
|
declare function reactJitter(options: ReactJitterOptions): void;
|
|
87
89
|
|
package/runtime/dist/index.js
CHANGED
|
@@ -592,6 +592,9 @@ function useJitterScope(scope) {
|
|
|
592
592
|
if (hookEndEvent.arguments) {
|
|
593
593
|
hookCall.arguments = hookEndEvent.arguments;
|
|
594
594
|
}
|
|
595
|
+
if (hookEndEvent.isMocked) {
|
|
596
|
+
hookCall.isMocked = hookEndEvent.isMocked;
|
|
597
|
+
}
|
|
595
598
|
scopes[scopeId].hookChanges.push(hookCall);
|
|
596
599
|
callOnHookChange(hookCall);
|
|
597
600
|
}
|
|
@@ -603,6 +606,12 @@ function useJitterScope(scope) {
|
|
|
603
606
|
re: (renderResult) => {
|
|
604
607
|
callOnRender(scopes[scopeId]);
|
|
605
608
|
return renderResult;
|
|
609
|
+
},
|
|
610
|
+
m: (value) => {
|
|
611
|
+
if (typeof value !== "function") {
|
|
612
|
+
return false;
|
|
613
|
+
}
|
|
614
|
+
return "mockImplementation" in value || "mockReturnValue" in value;
|
|
606
615
|
}
|
|
607
616
|
};
|
|
608
617
|
}
|
package/runtime/dist/index.mjs
CHANGED
|
@@ -557,6 +557,9 @@ function useJitterScope(scope) {
|
|
|
557
557
|
if (hookEndEvent.arguments) {
|
|
558
558
|
hookCall.arguments = hookEndEvent.arguments;
|
|
559
559
|
}
|
|
560
|
+
if (hookEndEvent.isMocked) {
|
|
561
|
+
hookCall.isMocked = hookEndEvent.isMocked;
|
|
562
|
+
}
|
|
560
563
|
scopes[scopeId].hookChanges.push(hookCall);
|
|
561
564
|
callOnHookChange(hookCall);
|
|
562
565
|
}
|
|
@@ -568,6 +571,12 @@ function useJitterScope(scope) {
|
|
|
568
571
|
re: (renderResult) => {
|
|
569
572
|
callOnRender(scopes[scopeId]);
|
|
570
573
|
return renderResult;
|
|
574
|
+
},
|
|
575
|
+
m: (value) => {
|
|
576
|
+
if (typeof value !== "function") {
|
|
577
|
+
return false;
|
|
578
|
+
}
|
|
579
|
+
return "mockImplementation" in value || "mockReturnValue" in value;
|
|
571
580
|
}
|
|
572
581
|
};
|
|
573
582
|
}
|