Skip to content

Commit cf8a93a

Browse files
author
Brian Vaughn
committed
Added Jest serializer for Hooks (to sanitize source location)
1 parent 5cb562d commit cf8a93a

File tree

4 files changed

+131
-29
lines changed

4 files changed

+131
-29
lines changed
Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
function hasAbsoluteFileName(hook) {
2+
const fileName = hook.hookSource ? hook.hookSource.fileName : null;
3+
if (fileName == null) {
4+
return false;
5+
} else {
6+
return fileName.indexOf('/react-devtools-shared/') > 0;
7+
}
8+
}
9+
10+
function serializeHook(hook) {
11+
if (!hook.hookSource) return hook;
12+
13+
// Remove user-specific portions of this file path.
14+
let fileName = hook.hookSource.fileName;
15+
const index = fileName.lastIndexOf('/react-devtools-shared/');
16+
fileName = fileName.substring(index + 1);
17+
18+
let subHooks = hook.subHooks;
19+
if (subHooks) {
20+
subHooks = subHooks.map(serializeHook);
21+
}
22+
23+
return {
24+
...hook,
25+
hookSource: {
26+
...hook.hookSource,
27+
fileName,
28+
29+
// Otherwise changes in any test case or formatting might invalidate other tests.
30+
columnNumber: 'removed by Jest serializer',
31+
lineNumber: 'removed by Jest serializer',
32+
},
33+
subHooks,
34+
};
35+
}
36+
37+
// test() is part of Jest's serializer API
38+
export function test(maybeHook) {
39+
if (maybeHook === null || typeof maybeHook !== 'object') {
40+
return false;
41+
}
42+
43+
const hasOwnProperty = Object.prototype.hasOwnProperty.bind(maybeHook);
44+
45+
return (
46+
hasOwnProperty('id') &&
47+
hasOwnProperty('isStateEditable') &&
48+
hasOwnProperty('name') &&
49+
hasOwnProperty('subHooks') &&
50+
hasOwnProperty('value') &&
51+
// Don't re-process an already printed hook.
52+
hasAbsoluteFileName(maybeHook)
53+
);
54+
}
55+
56+
// print() is part of Jest's serializer API
57+
export function print(hook, serialize, indent) {
58+
// Don't stringify this object; that would break nested serializers.
59+
return serialize(serializeHook(hook));
60+
}

packages/react-devtools-shared/src/__tests__/inspectedElement-test.js

Lines changed: 68 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ describe('InspectedElement', () => {
2525
let BridgeContext;
2626
let InspectedElementContext;
2727
let InspectedElementContextController;
28+
let SettingsContextController;
2829
let StoreContext;
2930
let TreeContextController;
3031

@@ -57,6 +58,8 @@ describe('InspectedElement', () => {
5758
.InspectedElementContext;
5859
InspectedElementContextController = require('react-devtools-shared/src/devtools/views/Components/InspectedElementContext')
5960
.InspectedElementContextController;
61+
SettingsContextController = require('react-devtools-shared/src/devtools/views/Settings/SettingsContext')
62+
.SettingsContextController;
6063
StoreContext = require('react-devtools-shared/src/devtools/views/context')
6164
.StoreContext;
6265
TreeContextController = require('react-devtools-shared/src/devtools/views/Components/TreeContext')
@@ -79,15 +82,17 @@ describe('InspectedElement', () => {
7982
}) => (
8083
<BridgeContext.Provider value={bridge}>
8184
<StoreContext.Provider value={store}>
82-
<TreeContextController
83-
defaultSelectedElementID={defaultSelectedElementID}
84-
defaultSelectedElementIndex={defaultSelectedElementIndex}>
85-
<React.Suspense fallback="Loading...">
86-
<InspectedElementContextController>
87-
{children}
88-
</InspectedElementContextController>
89-
</React.Suspense>
90-
</TreeContextController>
85+
<SettingsContextController>
86+
<TreeContextController
87+
defaultSelectedElementID={defaultSelectedElementID}
88+
defaultSelectedElementIndex={defaultSelectedElementIndex}>
89+
<React.Suspense fallback="Loading...">
90+
<InspectedElementContextController>
91+
{children}
92+
</InspectedElementContextController>
93+
</React.Suspense>
94+
</TreeContextController>
95+
</SettingsContextController>
9196
</StoreContext.Provider>
9297
</BridgeContext.Provider>
9398
);
@@ -152,6 +157,12 @@ describe('InspectedElement', () => {
152157
"events": undefined,
153158
"hooks": Array [
154159
Object {
160+
"hookSource": Object {
161+
"columnNumber": "removed by Jest serializer",
162+
"fileName": "react-devtools-shared/src/__tests__/inspectedElement-test.js",
163+
"functionName": "Example",
164+
"lineNumber": "removed by Jest serializer",
165+
},
155166
"id": 0,
156167
"isStateEditable": true,
157168
"name": "State",
@@ -1036,6 +1047,12 @@ describe('InspectedElement', () => {
10361047
expect(inspectedElement.hooks).toMatchInlineSnapshot(`
10371048
Array [
10381049
Object {
1050+
"hookSource": Object {
1051+
"columnNumber": "removed by Jest serializer",
1052+
"fileName": "react-devtools-shared/src/__tests__/inspectedElement-test.js",
1053+
"functionName": "Example",
1054+
"lineNumber": "removed by Jest serializer",
1055+
},
10391056
"id": 0,
10401057
"isStateEditable": true,
10411058
"name": "State",
@@ -1057,6 +1074,12 @@ describe('InspectedElement', () => {
10571074
expect(inspectedElement.hooks).toMatchInlineSnapshot(`
10581075
Array [
10591076
Object {
1077+
"hookSource": Object {
1078+
"columnNumber": "removed by Jest serializer",
1079+
"fileName": "react-devtools-shared/src/__tests__/inspectedElement-test.js",
1080+
"functionName": "Example",
1081+
"lineNumber": "removed by Jest serializer",
1082+
},
10601083
"id": 0,
10611084
"isStateEditable": true,
10621085
"name": "State",
@@ -1542,6 +1565,12 @@ describe('InspectedElement', () => {
15421565
"events": undefined,
15431566
"hooks": Array [
15441567
Object {
1568+
"hookSource": Object {
1569+
"columnNumber": "removed by Jest serializer",
1570+
"fileName": "react-devtools-shared/src/__tests__/inspectedElement-test.js",
1571+
"functionName": "Example",
1572+
"lineNumber": "removed by Jest serializer",
1573+
},
15451574
"id": null,
15461575
"isStateEditable": false,
15471576
"name": "Context",
@@ -1794,11 +1823,23 @@ describe('InspectedElement', () => {
17941823
expect(hooks).toMatchInlineSnapshot(`
17951824
Array [
17961825
Object {
1826+
"hookSource": Object {
1827+
"columnNumber": "removed by Jest serializer",
1828+
"fileName": "react-devtools-shared/src/__tests__/inspectedElement-test.js",
1829+
"functionName": "DisplayedComplexValue",
1830+
"lineNumber": "removed by Jest serializer",
1831+
},
17971832
"id": null,
17981833
"isStateEditable": false,
17991834
"name": "DebuggableHook",
18001835
"subHooks": Array [
18011836
Object {
1837+
"hookSource": Object {
1838+
"columnNumber": "removed by Jest serializer",
1839+
"fileName": "react-devtools-shared/src/__tests__/inspectedElement-test.js",
1840+
"functionName": "useDebuggableHook",
1841+
"lineNumber": "removed by Jest serializer",
1842+
},
18021843
"id": 0,
18031844
"isStateEditable": true,
18041845
"name": "State",
@@ -1872,6 +1913,12 @@ describe('InspectedElement', () => {
18721913
Object {
18731914
"hooks": Array [
18741915
Object {
1916+
"hookSource": Object {
1917+
"columnNumber": "removed by Jest serializer",
1918+
"fileName": "react-devtools-shared/src/__tests__/inspectedElement-test.js",
1919+
"functionName": "Example",
1920+
"lineNumber": "removed by Jest serializer",
1921+
},
18751922
"id": 0,
18761923
"isStateEditable": true,
18771924
"name": "State",
@@ -1905,6 +1952,12 @@ describe('InspectedElement', () => {
19051952
Object {
19061953
"hooks": Array [
19071954
Object {
1955+
"hookSource": Object {
1956+
"columnNumber": "removed by Jest serializer",
1957+
"fileName": "react-devtools-shared/src/__tests__/inspectedElement-test.js",
1958+
"functionName": "Example",
1959+
"lineNumber": "removed by Jest serializer",
1960+
},
19081961
"id": 0,
19091962
"isStateEditable": true,
19101963
"name": "State",
@@ -1938,6 +1991,12 @@ describe('InspectedElement', () => {
19381991
Object {
19391992
"hooks": Array [
19401993
Object {
1994+
"hookSource": Object {
1995+
"columnNumber": "removed by Jest serializer",
1996+
"fileName": "react-devtools-shared/src/__tests__/inspectedElement-test.js",
1997+
"functionName": "Example",
1998+
"lineNumber": "removed by Jest serializer",
1999+
},
19412000
"id": 0,
19422001
"isStateEditable": true,
19432002
"name": "State",

packages/react-devtools-shared/src/__tests__/inspectedElementSerializer.js

Lines changed: 0 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,3 @@
1-
// TODO (named hooks) Don't mutate hooks object
2-
// This method should return a mirror object,
3-
// and its return value should be used in `print()`
4-
function serializeHookSourceFileNames(hooks) {
5-
if (!hooks.length) return;
6-
hooks.forEach(hook => {
7-
if (!hook.hookSource) return;
8-
const filename = hook.hookSource.fileName;
9-
const truncateIdx = filename.lastIndexOf('/react-devtools-shared/');
10-
hook.hookSource.fileName = filename.substring(truncateIdx + 1);
11-
if (hook.subHooks && hook.subHooks.length)
12-
serializeHookSourceFileNames(hook.subHooks);
13-
});
14-
}
15-
161
// test() is part of Jest's serializer API
172
export function test(maybeInspectedElement) {
183
if (
@@ -26,11 +11,6 @@ export function test(maybeInspectedElement) {
2611
maybeInspectedElement,
2712
);
2813

29-
// TODO (named hooks) Remove this call
30-
if (hasOwnProperty('hooks') && maybeInspectedElement.hooks != null) {
31-
serializeHookSourceFileNames(maybeInspectedElement.hooks);
32-
}
33-
3414
return (
3515
hasOwnProperty('canEditFunctionProps') &&
3616
hasOwnProperty('canEditHooks') &&

scripts/jest/config.build-devtools.js

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,9 @@ module.exports = Object.assign({}, baseConfig, {
6666
require.resolve(
6767
'../../packages/react-devtools-shared/src/__tests__/dehydratedValueSerializer.js'
6868
),
69+
require.resolve(
70+
'../../packages/react-devtools-shared/src/__tests__/hookSerializer.js'
71+
),
6972
require.resolve(
7073
'../../packages/react-devtools-shared/src/__tests__/inspectedElementSerializer.js'
7174
),

0 commit comments

Comments
 (0)