diff --git a/packages/react-devtools-shared/src/__tests__/inspectedElement-test.js b/packages/react-devtools-shared/src/__tests__/inspectedElement-test.js
index 70a59b135e85e..7cb7ebb77f5ae 100644
--- a/packages/react-devtools-shared/src/__tests__/inspectedElement-test.js
+++ b/packages/react-devtools-shared/src/__tests__/inspectedElement-test.js
@@ -33,6 +33,8 @@ describe('InspectedElement', () => {
let TestUtilsAct;
let TestRendererAct;
+ let testRendererInstance;
+
beforeEach(() => {
utils = require('./utils');
utils.beforeEachProfiling();
@@ -61,6 +63,9 @@ describe('InspectedElement', () => {
.StoreContext;
TreeContextController = require('react-devtools-shared/src/devtools/views/Components/TreeContext')
.TreeContextController;
+
+ // Used by inspectElementAtIndex() helper function
+ testRendererInstance = TestRenderer.create(null);
});
afterEach(() => {
@@ -87,16 +92,48 @@ describe('InspectedElement', () => {
);
- function useInspectedElement(id: number) {
+ function useInspectedElement() {
const {inspectedElement} = React.useContext(InspectedElementContext);
return inspectedElement;
}
- function useInspectElementPath(id: number) {
+ function useInspectElementPath() {
const {inspectPaths} = React.useContext(InspectedElementContext);
return inspectPaths;
}
+ function noop() {}
+
+ async function inspectElementAtIndex(index, useCustomHook = noop) {
+ let didFinish = false;
+ let inspectedElement = null;
+
+ function Suspender() {
+ useCustomHook();
+ inspectedElement = useInspectedElement();
+ didFinish = true;
+ return null;
+ }
+
+ const id = ((store.getElementIDAtIndex(index): any): number);
+
+ await utils.actAsync(() => {
+ testRendererInstance.update(
+
+
+
+
+ ,
+ );
+ }, false);
+
+ expect(didFinish).toBe(true);
+
+ return inspectedElement;
+ }
+
it('should inspect the currently selected element', async done => {
const Example = () => {
const [count] = React.useState(1);
@@ -108,52 +145,29 @@ describe('InspectedElement', () => {
ReactDOM.render(, container),
);
- const id = ((store.getElementIDAtIndex(0): any): number);
-
- let didFinish = false;
-
- function Suspender({target}) {
- const inspectedElement = useInspectedElement(id);
- expect(inspectedElement).toMatchInlineSnapshot(`
- Object {
- "context": null,
- "events": undefined,
- "hooks": Array [
- Object {
- "id": 0,
- "isStateEditable": true,
- "name": "State",
- "subHooks": Array [],
- "value": 1,
- },
- ],
- "id": 2,
- "owners": null,
- "props": Object {
- "a": 1,
- "b": "abc",
+ const inspectedElement = await inspectElementAtIndex(0);
+ expect(inspectedElement).toMatchInlineSnapshot(`
+ Object {
+ "context": null,
+ "events": undefined,
+ "hooks": Array [
+ Object {
+ "id": 0,
+ "isStateEditable": true,
+ "name": "State",
+ "subHooks": Array [],
+ "value": 1,
},
- "state": null,
- }
- `);
- didFinish = true;
- return null;
- }
-
- await utils.actAsync(
- () =>
- TestRenderer.create(
-
-
-
-
- ,
- ),
- false,
- );
- expect(didFinish).toBe(true);
+ ],
+ "id": 2,
+ "owners": null,
+ "props": Object {
+ "a": 1,
+ "b": "abc",
+ },
+ "state": null,
+ }
+ `);
done();
});
@@ -215,57 +229,42 @@ describe('InspectedElement', () => {
),
);
- const ids = [
+ const cases = [
{
//
- id: ((store.getElementIDAtIndex(1): any): number),
+ index: 1,
shouldHaveLegacyContext: true,
},
{
//
- id: ((store.getElementIDAtIndex(2): any): number),
+ index: 2,
shouldHaveLegacyContext: false,
},
{
//
- id: ((store.getElementIDAtIndex(3): any): number),
+ index: 3,
shouldHaveLegacyContext: false,
},
{
//
- id: ((store.getElementIDAtIndex(5): any): number),
+ index: 5,
shouldHaveLegacyContext: false,
},
];
- function Suspender({target, shouldHaveLegacyContext}) {
- const inspectedElement = useInspectedElement(target);
+ for (let i = 0; i < cases.length; i++) {
+ const {index, shouldHaveLegacyContext} = cases[i];
- expect(inspectedElement.context).not.toBe(null);
- expect(inspectedElement.hasLegacyContext).toBe(shouldHaveLegacyContext);
+ // HACK: Recreate TestRenderer instance because we rely on default state values
+ // from props like defaultSelectedElementID and it's easier to reset here than
+ // to read the TreeDispatcherContext and update the selected ID that way.
+ // We're testing the inspected values here, not the context wiring, so that's ok.
+ testRendererInstance = TestRenderer.create(null);
- return null;
- }
+ const inspectedElement = await inspectElementAtIndex(index);
- for (let i = 0; i < ids.length; i++) {
- const {id, shouldHaveLegacyContext} = ids[i];
-
- await utils.actAsync(
- () =>
- TestRenderer.create(
-
-
-
-
- ,
- ),
- false,
- );
+ expect(inspectedElement.context).not.toBe(null);
+ expect(inspectedElement.hasLegacyContext).toBe(shouldHaveLegacyContext);
}
done();
});
@@ -279,26 +278,7 @@ describe('InspectedElement', () => {
false,
);
- const id = ((store.getElementIDAtIndex(0): any): number);
-
- let inspectedElement = null;
-
- function Suspender({target}) {
- inspectedElement = useInspectedElement(id);
- return null;
- }
-
- let renderer;
-
- await utils.actAsync(() => {
- renderer = TestRenderer.create(
-
-
-
-
- ,
- );
- }, false);
+ let inspectedElement = await inspectElementAtIndex(0);
expect(inspectedElement.props).toMatchInlineSnapshot(`
Object {
"a": 1,
@@ -321,19 +301,7 @@ describe('InspectedElement', () => {
jest.runOnlyPendingTimers();
await Promise.resolve();
- await utils.actAsync(
- () =>
- renderer.update(
-
-
-
-
- ,
- ),
- false,
- );
+ inspectedElement = await inspectElementAtIndex(0);
expect(inspectedElement.props).toMatchInlineSnapshot(`
Object {
"a": 2,
@@ -365,31 +333,9 @@ describe('InspectedElement', () => {
),
);
- const id = ((store.getElementIDAtIndex(1): any): number);
-
- let inspectedElement = null;
-
- function Suspender({target}) {
- inspectedElement = useInspectedElement(target);
- return null;
- }
-
targetRenderCount = 0;
- let renderer;
- await utils.actAsync(
- () =>
- (renderer = TestRenderer.create(
-
-
-
-
- ,
- )),
- false,
- );
+ let inspectedElement = await inspectElementAtIndex(1);
expect(targetRenderCount).toBe(1);
expect(inspectedElement.props).toMatchInlineSnapshot(`
Object {
@@ -398,28 +344,14 @@ describe('InspectedElement', () => {
}
`);
- const initialInspectedElement = inspectedElement;
+ const prevInspectedElement = inspectedElement;
targetRenderCount = 0;
- inspectedElement = null;
- await utils.actAsync(
- () =>
- renderer.update(
-
-
-
-
- ,
- ),
- false,
- );
+ inspectedElement = await inspectElementAtIndex(1);
expect(targetRenderCount).toBe(0);
- expect(inspectedElement).toEqual(initialInspectedElement);
+ expect(inspectedElement).toEqual(prevInspectedElement);
targetRenderCount = 0;
- inspectedElement = null;
await utils.actAsync(
() =>
@@ -433,19 +365,7 @@ describe('InspectedElement', () => {
);
// Target should have been rendered once (by ReactDOM) and once by DevTools for inspection.
- await utils.actAsync(
- () =>
- renderer.update(
-
-
-
-
- ,
- ),
- false,
- );
+ inspectedElement = await inspectElementAtIndex(1);
expect(targetRenderCount).toBe(2);
expect(inspectedElement.props).toMatchInlineSnapshot(`
Object {
@@ -490,28 +410,7 @@ describe('InspectedElement', () => {
expect(console.warn).toHaveBeenCalledTimes(1);
expect(console.warn).toHaveBeenCalledWith('warn');
- const id = ((store.getElementIDAtIndex(0): any): number);
-
- let inspectedElement = null;
-
- function Suspender({target}) {
- inspectedElement = useInspectedElement(target);
- return null;
- }
-
- await utils.actAsync(
- () =>
- TestRenderer.create(
-
-
-
-
- ,
- ),
- false,
- );
+ const inspectedElement = await inspectElementAtIndex(0);
expect(inspectedElement).not.toBe(null);
expect(targetRenderCount).toBe(2);
@@ -546,27 +445,7 @@ describe('InspectedElement', () => {
),
);
- const id = ((store.getElementIDAtIndex(0): any): number);
- let inspectedElement = null;
-
- function Suspender({target}) {
- inspectedElement = useInspectedElement(id);
- return null;
- }
-
- await utils.actAsync(
- () =>
- TestRenderer.create(
-
-
-
-
- ,
- ),
- false,
- );
+ const inspectedElement = await inspectElementAtIndex(0);
const {props} = (inspectedElement: any);
expect(props.boolean_false).toBe(false);
@@ -665,28 +544,7 @@ describe('InspectedElement', () => {
),
);
- const id = ((store.getElementIDAtIndex(0): any): number);
-
- let inspectedElement = null;
-
- function Suspender({target}) {
- inspectedElement = useInspectedElement(id);
- return null;
- }
-
- await utils.actAsync(
- () =>
- TestRenderer.create(
-
-
-
-
- ,
- ),
- false,
- );
+ const inspectedElement = await inspectElementAtIndex(0);
const {
anonymous_fn,
@@ -875,28 +733,7 @@ describe('InspectedElement', () => {
ReactDOM.render(, container),
);
- const id = ((store.getElementIDAtIndex(0): any): number);
-
- let inspectedElement = null;
-
- function Suspender({target}) {
- inspectedElement = useInspectedElement(id);
- return null;
- }
-
- await utils.actAsync(
- () =>
- TestRenderer.create(
-
-
-
-
- ,
- ),
- false,
- );
+ const inspectedElement = await inspectElementAtIndex(0);
const {prop} = (inspectedElement: any).props;
expect(prop[meta.inspectable]).toBe(false);
@@ -921,29 +758,7 @@ describe('InspectedElement', () => {
ReactDOM.render(, container),
);
- const id = ((store.getElementIDAtIndex(0): any): number);
-
- let inspectedElement = null;
-
- function Suspender({target}) {
- inspectedElement = useInspectedElement(id);
- return null;
- }
-
- await utils.actAsync(
- () =>
- TestRenderer.create(
-
-
-
-
- ,
- ),
- false,
- );
-
+ const inspectedElement = await inspectElementAtIndex(0);
expect(inspectedElement.props).toMatchInlineSnapshot(`
Object {
"object": Object {
@@ -970,28 +785,7 @@ describe('InspectedElement', () => {
ReactDOM.render(, container),
);
- const id = ((store.getElementIDAtIndex(0): any): number);
-
- let inspectedElement = null;
-
- function Suspender({target}) {
- inspectedElement = useInspectedElement(id);
- return null;
- }
-
- await utils.actAsync(
- () =>
- TestRenderer.create(
-
-
-
-
- ,
- ),
- false,
- );
+ const inspectedElement = await inspectElementAtIndex(0);
// TRICKY: Don't use toMatchInlineSnapshot() for this test!
// Our snapshot serializer relies on hasOwnProperty() for feature detection.
@@ -1026,38 +820,15 @@ describe('InspectedElement', () => {
ReactDOM.render(, container),
);
- const id = ((store.getElementIDAtIndex(0): any): number);
-
- let didFinish = false;
-
- function Suspender({target}) {
- const inspectedElement = useInspectedElement(id);
- expect(inspectedElement.props).toMatchInlineSnapshot(`
- Object {
- "data": Object {
- "_number": 42,
- "number": 42,
- },
- }
- `);
- didFinish = true;
- return null;
- }
-
- await utils.actAsync(
- () =>
- TestRenderer.create(
-
-
-
-
- ,
- ),
- false,
- );
- expect(didFinish).toBe(true);
+ const inspectedElement = await inspectElementAtIndex(0);
+ expect(inspectedElement.props).toMatchInlineSnapshot(`
+ Object {
+ "data": Object {
+ "_number": 42,
+ "number": 42,
+ },
+ }
+ `);
done();
});
@@ -1130,29 +901,7 @@ describe('InspectedElement', () => {
ReactDOM.render(, container),
);
- const id = ((store.getElementIDAtIndex(0): any): number);
-
- let inspectedElement = null;
-
- function Suspender({target}) {
- inspectedElement = useInspectedElement(id);
- return null;
- }
-
- await utils.actAsync(
- () =>
- TestRenderer.create(
-
-
-
-
- ,
- ),
- false,
- );
-
+ const inspectedElement = await inspectElementAtIndex(0);
expect(inspectedElement.props).toMatchInlineSnapshot(`
Object {
"object": Object {
@@ -1193,44 +942,23 @@ describe('InspectedElement', () => {
value: NaN,
writable: true,
enumerable: true,
- configurable: true,
- },
- d: {
- value: 'normal',
- writable: true,
- enumerable: true,
- configurable: true,
- },
- },
- );
- const Example = ({data}) => null;
- const container = document.createElement('div');
- await utils.actAsync(() =>
- ReactDOM.render(, container),
- );
-
- const id = ((store.getElementIDAtIndex(0): any): number);
-
- let inspectedElement = null;
-
- function Suspender({target}) {
- inspectedElement = useInspectedElement(target);
- return null;
- }
-
- await utils.actAsync(
- () =>
- TestRenderer.create(
-
-
-
-
- ,
- ),
- false,
+ configurable: true,
+ },
+ d: {
+ value: 'normal',
+ writable: true,
+ enumerable: true,
+ configurable: true,
+ },
+ },
+ );
+ const Example = ({data}) => null;
+ const container = document.createElement('div');
+ await utils.actAsync(() =>
+ ReactDOM.render(, container),
);
+
+ const inspectedElement = await inspectElementAtIndex(0);
expect(inspectedElement.props).toMatchInlineSnapshot(`
Object {
"data": Object {
@@ -1280,37 +1008,13 @@ describe('InspectedElement', () => {
),
);
- const id = ((store.getElementIDAtIndex(0): any): number);
-
let inspectedElement = null;
let inspectElementPath = null;
- function Suspender({path, target}) {
- inspectedElement = useInspectedElement(id);
- inspectElementPath = useInspectElementPath(id);
- return null;
- }
-
- const renderer = TestRenderer.create(null);
-
- async function getInspectedElement() {
- await utils.actAsync(
- () =>
- renderer.update(
-
-
-
-
- ,
- ),
- false,
- );
- }
-
// Render once to get a handle on inspectElementPath()
- await getInspectedElement();
+ inspectedElement = await inspectElementAtIndex(0, () => {
+ inspectElementPath = useInspectElementPath();
+ });
async function loadPath(path) {
TestUtilsAct(() => {
@@ -1319,7 +1023,8 @@ describe('InspectedElement', () => {
jest.runOnlyPendingTimers();
});
});
- await getInspectedElement();
+
+ inspectedElement = await inspectElementAtIndex(0);
}
expect(inspectedElement.props).toMatchInlineSnapshot(`
@@ -1448,37 +1153,13 @@ describe('InspectedElement', () => {
),
);
- const id = ((store.getElementIDAtIndex(0): any): number);
-
let inspectedElement = null;
let inspectElementPath = null;
- function Suspender({path, target}) {
- inspectedElement = useInspectedElement(id);
- inspectElementPath = useInspectElementPath(id);
- return null;
- }
-
- const renderer = TestRenderer.create(null);
-
- async function getInspectedElement() {
- await utils.actAsync(
- () =>
- renderer.update(
-
-
-
-
- ,
- ),
- false,
- );
- }
-
// Render once to get a handle on inspectElementPath()
- await getInspectedElement();
+ inspectedElement = await inspectElementAtIndex(0, () => {
+ inspectElementPath = useInspectElementPath();
+ });
async function loadPath(path) {
TestUtilsAct(() => {
@@ -1487,7 +1168,8 @@ describe('InspectedElement', () => {
jest.runOnlyPendingTimers();
});
});
- await getInspectedElement();
+
+ inspectedElement = await inspectElementAtIndex(0);
}
expect(inspectedElement.props).toMatchInlineSnapshot(`
@@ -1556,37 +1238,13 @@ describe('InspectedElement', () => {
),
);
- const id = ((store.getElementIDAtIndex(0): any): number);
-
let inspectedElement = null;
let inspectElementPath = null;
- function Suspender({path, target}) {
- inspectedElement = useInspectedElement(id);
- inspectElementPath = useInspectElementPath(id);
- return null;
- }
-
- const renderer = TestRenderer.create(null);
-
- async function getInspectedElement() {
- await utils.actAsync(
- () =>
- renderer.update(
-
-
-
-
- ,
- ),
- false,
- );
- }
-
// Render once to get a handle on inspectElementPath()
- await getInspectedElement();
+ inspectedElement = await inspectElementAtIndex(0, () => {
+ inspectElementPath = useInspectElementPath();
+ });
async function loadPath(path) {
TestUtilsAct(() => {
@@ -1595,7 +1253,8 @@ describe('InspectedElement', () => {
jest.runOnlyPendingTimers();
});
});
- await getInspectedElement();
+
+ inspectedElement = await inspectElementAtIndex(0);
}
expect(inspectedElement.props).toMatchInlineSnapshot(`
@@ -1690,7 +1349,7 @@ describe('InspectedElement', () => {
// Wait for pending poll-for-update and then update inspected element data.
jest.runOnlyPendingTimers();
await Promise.resolve();
- await getInspectedElement();
+ inspectedElement = await inspectElementAtIndex(0);
expect(inspectedElement.props).toMatchInlineSnapshot(`
Object {
@@ -1739,37 +1398,13 @@ describe('InspectedElement', () => {
),
);
- const id = ((store.getElementIDAtIndex(0): any): number);
-
let inspectedElement = null;
let inspectElementPath = null;
- function Suspender({path, target}) {
- inspectedElement = useInspectedElement(id);
- inspectElementPath = useInspectElementPath(id);
- return null;
- }
-
- const renderer = TestRenderer.create(null);
-
- async function getInspectedElement() {
- await utils.actAsync(
- () =>
- renderer.update(
-
-
-
-
- ,
- ),
- false,
- );
- }
-
// Render once to get a handle on inspectElementPath()
- await getInspectedElement();
+ inspectedElement = await inspectElementAtIndex(0, () => {
+ inspectElementPath = useInspectElementPath();
+ });
async function loadPath(path) {
TestUtilsAct(() => {
@@ -1778,7 +1413,8 @@ describe('InspectedElement', () => {
jest.runOnlyPendingTimers();
});
});
- await getInspectedElement();
+
+ inspectedElement = await inspectElementAtIndex(0);
}
expect(inspectedElement.props).toMatchInlineSnapshot(`
@@ -1841,52 +1477,29 @@ describe('InspectedElement', () => {
ReactDOM.render(, container),
);
- const id = ((store.getElementIDAtIndex(0): any): number);
-
- let didFinish = false;
-
- function Suspender({target}) {
- const inspectedElement = useInspectedElement(id);
- expect(inspectedElement).toMatchInlineSnapshot(`
- Object {
- "context": null,
- "events": undefined,
- "hooks": Array [
- Object {
- "id": null,
- "isStateEditable": false,
- "name": "Context",
- "subHooks": Array [],
- "value": true,
- },
- ],
- "id": 2,
- "owners": null,
- "props": Object {
- "a": 1,
- "b": "abc",
+ const inspectedElement = await inspectElementAtIndex(0);
+ expect(inspectedElement).toMatchInlineSnapshot(`
+ Object {
+ "context": null,
+ "events": undefined,
+ "hooks": Array [
+ Object {
+ "id": null,
+ "isStateEditable": false,
+ "name": "Context",
+ "subHooks": Array [],
+ "value": true,
},
- "state": null,
- }
- `);
- didFinish = true;
- return null;
- }
-
- await utils.actAsync(
- () =>
- TestRenderer.create(
-
-
-
-
- ,
- ),
- false,
- );
- expect(didFinish).toBe(true);
+ ],
+ "id": 2,
+ "owners": null,
+ "props": Object {
+ "a": 1,
+ "b": "abc",
+ },
+ "state": null,
+ }
+ `);
done();
});
@@ -1913,46 +1526,30 @@ describe('InspectedElement', () => {
),
);
- const id = ((store.getElementIDAtIndex(0): any): number);
-
let storeAsGlobal: StoreAsGlobal = ((null: any): StoreAsGlobal);
- function Suspender({target}) {
- storeAsGlobal = (elementID: number, path: Array) => {
- const rendererID = store.getRendererIDForElement(elementID);
+ const id = ((store.getElementIDAtIndex(0): any): number);
+ await inspectElementAtIndex(0, () => {
+ storeAsGlobal = (path: Array) => {
+ const rendererID = store.getRendererIDForElement(id);
if (rendererID !== null) {
const {
storeAsGlobal: storeAsGlobalAPI,
} = require('react-devtools-shared/src/backendAPI');
storeAsGlobalAPI({
bridge,
- id: elementID,
+ id,
path,
rendererID,
});
}
};
- return null;
- }
-
- await utils.actAsync(
- () =>
- TestRenderer.create(
-
-
-
-
- ,
- ),
- false,
- );
+ });
jest.spyOn(console, 'log').mockImplementation(() => {});
// Should store the whole value (not just the hydrated parts)
- storeAsGlobal(id, ['props', 'nestedObject']);
+ storeAsGlobal(['props', 'nestedObject']);
jest.runOnlyPendingTimers();
expect(console.log).toHaveBeenCalledWith('$reactTemp0');
expect(global.$reactTemp0).toBe(nestedObject);
@@ -1960,7 +1557,7 @@ describe('InspectedElement', () => {
console.log.mockReset();
// Should store the nested property specified (not just the outer value)
- storeAsGlobal(id, ['props', 'nestedObject', 'a', 'b']);
+ storeAsGlobal(['props', 'nestedObject', 'a', 'b']);
jest.runOnlyPendingTimers();
expect(console.log).toHaveBeenCalledWith('$reactTemp1');
expect(global.$reactTemp1).toBe(nestedObject.a.b);
@@ -1990,45 +1587,28 @@ describe('InspectedElement', () => {
),
);
- const id = ((store.getElementIDAtIndex(0): any): number);
-
let copyPath: CopyInspectedElementPath = ((null: any): CopyInspectedElementPath);
- function Suspender({target}) {
- copyPath = (elementID: number, path: Array) => {
- const rendererID = store.getRendererIDForElement(elementID);
+ const id = ((store.getElementIDAtIndex(0): any): number);
+ await inspectElementAtIndex(0, () => {
+ copyPath = (path: Array) => {
+ const rendererID = store.getRendererIDForElement(id);
if (rendererID !== null) {
const {
copyInspectedElementPath,
} = require('react-devtools-shared/src/backendAPI');
copyInspectedElementPath({
bridge,
- id: elementID,
+ id,
path,
rendererID,
});
}
};
- return null;
- }
-
- await utils.actAsync(
- () =>
- TestRenderer.create(
-
-
-
-
- ,
- ),
- false,
- );
- expect(copyPath).not.toBeNull();
+ });
// Should copy the whole value (not just the hydrated parts)
- copyPath(id, ['props', 'nestedObject']);
+ copyPath(['props', 'nestedObject']);
jest.runOnlyPendingTimers();
expect(global.mockClipboardCopy).toHaveBeenCalledTimes(1);
expect(global.mockClipboardCopy).toHaveBeenCalledWith(
@@ -2038,7 +1618,7 @@ describe('InspectedElement', () => {
global.mockClipboardCopy.mockReset();
// Should copy the nested property specified (not just the outer value)
- copyPath(id, ['props', 'nestedObject', 'a', 'b']);
+ copyPath(['props', 'nestedObject', 'a', 'b']);
jest.runOnlyPendingTimers();
expect(global.mockClipboardCopy).toHaveBeenCalledTimes(1);
expect(global.mockClipboardCopy).toHaveBeenCalledWith(
@@ -2098,48 +1678,32 @@ describe('InspectedElement', () => {
let copyPath: CopyInspectedElementPath = ((null: any): CopyInspectedElementPath);
- function Suspender({target}) {
- copyPath = (elementID: number, path: Array) => {
- const rendererID = store.getRendererIDForElement(elementID);
+ await inspectElementAtIndex(0, () => {
+ copyPath = (path: Array) => {
+ const rendererID = store.getRendererIDForElement(id);
if (rendererID !== null) {
const {
copyInspectedElementPath,
} = require('react-devtools-shared/src/backendAPI');
copyInspectedElementPath({
bridge,
- id: elementID,
+ id,
path,
rendererID,
});
}
};
- return null;
- }
-
- await utils.actAsync(
- () =>
- TestRenderer.create(
-
-
-
-
- ,
- ),
- false,
- );
- expect(copyPath).not.toBeNull();
+ });
// Should copy the whole value (not just the hydrated parts)
- copyPath(id, ['props']);
+ copyPath(['props']);
jest.runOnlyPendingTimers();
// Should not error despite lots of unserialized values.
global.mockClipboardCopy.mockReset();
// Should copy the nested property specified (not just the outer value)
- copyPath(id, ['props', 'bigInt']);
+ copyPath(['props', 'bigInt']);
jest.runOnlyPendingTimers();
expect(global.mockClipboardCopy).toHaveBeenCalledTimes(1);
expect(global.mockClipboardCopy).toHaveBeenCalledWith(
@@ -2149,7 +1713,7 @@ describe('InspectedElement', () => {
global.mockClipboardCopy.mockReset();
// Should copy the nested property specified (not just the outer value)
- copyPath(id, ['props', 'typedArray']);
+ copyPath(['props', 'typedArray']);
jest.runOnlyPendingTimers();
expect(global.mockClipboardCopy).toHaveBeenCalledTimes(1);
expect(global.mockClipboardCopy).toHaveBeenCalledWith(
@@ -2160,12 +1724,6 @@ describe('InspectedElement', () => {
});
it('should display complex values of useDebugValue', async done => {
- let inspectedElement = null;
- function Suspender({target}) {
- inspectedElement = useInspectedElement(target);
- return null;
- }
-
const container = document.createElement('div');
function useDebuggableHook() {
@@ -2182,23 +1740,7 @@ describe('InspectedElement', () => {
ReactDOM.render(, container),
);
- const ignoredComplexValueIndex = 0;
- const ignoredComplexValueId = ((store.getElementIDAtIndex(
- ignoredComplexValueIndex,
- ): any): number);
- await utils.actAsync(
- () =>
- TestRenderer.create(
-
-
-
-
- ,
- ),
- false,
- );
+ const inspectedElement = await inspectElementAtIndex(0);
expect(inspectedElement.hooks).toMatchInlineSnapshot(`
Array [
Object {
@@ -2224,6 +1766,145 @@ describe('InspectedElement', () => {
done();
});
+ describe('$r', () => {
+ it('should support function components', async done => {
+ const Example = () => {
+ const [count] = React.useState(1);
+ return count;
+ };
+
+ const container = document.createElement('div');
+ await utils.actAsync(() =>
+ ReactDOM.render(, container),
+ );
+
+ await inspectElementAtIndex(0);
+
+ expect(global.$r).toMatchInlineSnapshot(`
+ Object {
+ "hooks": Array [
+ Object {
+ "id": 0,
+ "isStateEditable": true,
+ "name": "State",
+ "subHooks": Array [],
+ "value": 1,
+ },
+ ],
+ "props": Object {
+ "a": 1,
+ "b": "abc",
+ },
+ "type": [Function],
+ }
+ `);
+
+ done();
+ });
+
+ it('should support memoized function components', async done => {
+ const Example = React.memo(function Example(props) {
+ const [count] = React.useState(1);
+ return count;
+ });
+
+ const container = document.createElement('div');
+ await utils.actAsync(() =>
+ ReactDOM.render(, container),
+ );
+
+ await inspectElementAtIndex(0);
+
+ expect(global.$r).toMatchInlineSnapshot(`
+ Object {
+ "hooks": Array [
+ Object {
+ "id": 0,
+ "isStateEditable": true,
+ "name": "State",
+ "subHooks": Array [],
+ "value": 1,
+ },
+ ],
+ "props": Object {
+ "a": 1,
+ "b": "abc",
+ },
+ "type": [Function],
+ }
+ `);
+
+ done();
+ });
+
+ it('should support forward refs', async done => {
+ const Example = React.forwardRef(function Example(props, ref) {
+ const [count] = React.useState(1);
+ return count;
+ });
+
+ const container = document.createElement('div');
+ await utils.actAsync(() =>
+ ReactDOM.render(, container),
+ );
+
+ await inspectElementAtIndex(0);
+
+ expect(global.$r).toMatchInlineSnapshot(`
+ Object {
+ "hooks": Array [
+ Object {
+ "id": 0,
+ "isStateEditable": true,
+ "name": "State",
+ "subHooks": Array [],
+ "value": 1,
+ },
+ ],
+ "props": Object {
+ "a": 1,
+ "b": "abc",
+ },
+ "type": [Function],
+ }
+ `);
+
+ done();
+ });
+
+ it('should support class components', async done => {
+ class Example extends React.Component {
+ state = {
+ count: 0,
+ };
+ render() {
+ return null;
+ }
+ }
+
+ const container = document.createElement('div');
+ await utils.actAsync(() =>
+ ReactDOM.render(, container),
+ );
+
+ await inspectElementAtIndex(0);
+
+ expect(global.$r.props).toMatchInlineSnapshot(`
+ Object {
+ "a": 1,
+ "b": "abc",
+ }
+ `);
+ expect(global.$r.state).toMatchInlineSnapshot(`
+ Object {
+ "count": 0,
+ }
+ `);
+
+ done();
+ });
+ });
+
describe('inline errors and warnings', () => {
// Some actions require the Fiber id.
// In those instances you might want to make assertions based on the ID instead of the index.
@@ -2239,7 +1920,7 @@ describe('InspectedElement', () => {
let warnings = null;
function Suspender({target}) {
- const inspectedElement = useInspectedElement(id);
+ const inspectedElement = useInspectedElement();
errors = inspectedElement.errors;
warnings = inspectedElement.warnings;
return null;