From c831387e9c53d55d152cc2c00c3388854d7ee97e Mon Sep 17 00:00:00 2001 From: Sebastian Silbermann Date: Wed, 19 Feb 2020 09:38:22 +0100 Subject: [PATCH 1/5] test: Failing test for complex debug values in custom hooks --- package.json | 1 + .../src/__tests__/HooksTree-test.js | 92 +++++++++++++++++++ .../inspectedElementContext-test.js.snap | 29 ++++++ .../__tests__/inspectedElementContext-test.js | 50 ++++++++++ scripts/jest/config.build-devtools.js | 3 + yarn.lock | 12 +++ 6 files changed, 187 insertions(+) create mode 100644 packages/react-devtools-shared/src/__tests__/HooksTree-test.js diff --git a/package.json b/package.json index 42fa148eb0714..d49453c1a10a4 100644 --- a/package.json +++ b/package.json @@ -63,6 +63,7 @@ "glob-stream": "^6.1.0", "google-closure-compiler": "^20200112.0.0", "gzip-size": "^5.1.1", + "identity-obj-proxy": "^3.0.0", "jasmine-check": "^1.0.0-rc.0", "jest": "^25.1.0", "jest-diff": "^25.1.0", diff --git a/packages/react-devtools-shared/src/__tests__/HooksTree-test.js b/packages/react-devtools-shared/src/__tests__/HooksTree-test.js new file mode 100644 index 0000000000000..10f436d051c81 --- /dev/null +++ b/packages/react-devtools-shared/src/__tests__/HooksTree-test.js @@ -0,0 +1,92 @@ +describe('HooksTree', () => { + let React; + let ReactDOM; + let bridge: FrontendBridge; + let store: Store; + let utils; + let HooksTree; + + let BridgeContext; + let InspectedElementContextController; + let StoreContext; + let TreeContextController; + + beforeEach(() => { + utils = require('./utils'); + utils.beforeEachProfiling(); + + bridge = global.bridge; + store = global.store; + store.collapseNodesByDefault = false; + + React = require('react'); + ReactDOM = require('react-dom'); + + BridgeContext = require('react-devtools-shared/src/devtools/views/context') + .BridgeContext; + InspectedElementContextController = require('react-devtools-shared/src/devtools/views/Components/InspectedElementContext') + .InspectedElementContextController; + StoreContext = require('react-devtools-shared/src/devtools/views/context') + .StoreContext; + TreeContextController = require('react-devtools-shared/src/devtools/views/Components/TreeContext') + .TreeContextController; + + HooksTree = require('react-devtools-shared/src/devtools/views/Components/HooksTree') + .HooksTreeView; + }); + + const Contexts = ({ + children, + defaultSelectedElementID = null, + defaultSelectedElementIndex = null, + }) => ( + + + + + {children} + + + + + ); + + it('shows the complex value of custom hooks with sub-hooks', () => { + // props from `InspectedElementContext display complex values of useDebugValue: DisplayedComplexValue 1` snapshot + + const container = document.createElement('div'); + ReactDOM.render( + + + , + container, + ); + + const hook = container.querySelector('.NameValueRow'); + // it's actually DebuggableHook: {foo:2} but the first colon is added by css + // which isn't available in the test + expect(hook.textContent).toEqual('DebuggableHook{foo: 2}'); + }); +}); diff --git a/packages/react-devtools-shared/src/__tests__/__snapshots__/inspectedElementContext-test.js.snap b/packages/react-devtools-shared/src/__tests__/__snapshots__/inspectedElementContext-test.js.snap index 0c7b024dffb81..2ef217a451e61 100644 --- a/packages/react-devtools-shared/src/__tests__/__snapshots__/inspectedElementContext-test.js.snap +++ b/packages/react-devtools-shared/src/__tests__/__snapshots__/inspectedElementContext-test.js.snap @@ -1,5 +1,34 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP +exports[`InspectedElementContext display complex values of useDebugValue: DisplayedComplexValue 1`] = ` +{ + "id": 2, + "owners": null, + "context": null, + "hooks": [ + { + "id": null, + "isStateEditable": false, + "name": "DebuggableHook", + "value": { + "foo": 2 + }, + "subHooks": [ + { + "id": 0, + "isStateEditable": true, + "name": "State", + "value": 1, + "subHooks": [] + } + ] + } + ], + "props": {}, + "state": null +} +`; + exports[`InspectedElementContext should dehydrate complex nested values when requested: 1: Initially inspect element 1`] = ` { "id": 2, diff --git a/packages/react-devtools-shared/src/__tests__/inspectedElementContext-test.js b/packages/react-devtools-shared/src/__tests__/inspectedElementContext-test.js index 07ee71fc69de3..4e292ecdbe5a7 100644 --- a/packages/react-devtools-shared/src/__tests__/inspectedElementContext-test.js +++ b/packages/react-devtools-shared/src/__tests__/inspectedElementContext-test.js @@ -1571,4 +1571,54 @@ describe('InspectedElementContext', () => { done(); }); + + it('display complex values of useDebugValue', async done => { + let getInspectedElementPath: GetInspectedElementPath = ((null: any): GetInspectedElementPath); + let inspectedElement = null; + function Suspender({target}) { + const context = React.useContext(InspectedElementContext); + getInspectedElementPath = context.getInspectedElementPath; + inspectedElement = context.getInspectedElement(target); + return null; + } + + const container = document.createElement('div'); + + function useDebuggableHook() { + React.useDebugValue({foo: 2}); + React.useState(1); + return 1; + } + function DisplayedComplexValue() { + useDebuggableHook(); + return null; + } + + await utils.actAsync(() => + ReactDOM.render(, container), + ); + + const ignoredComplexValueIndex = 0; + const ignoredComplexValueId = ((store.getElementIDAtIndex( + ignoredComplexValueIndex, + ): any): number); + await utils.actAsync( + () => + TestRenderer.create( + + + + + , + ), + false, + ); + expect(getInspectedElementPath).not.toBeNull(); + expect(inspectedElement).not.toBeNull(); + expect(inspectedElement).toMatchSnapshot('DisplayedComplexValue'); + + done(); + }); }); diff --git a/scripts/jest/config.build-devtools.js b/scripts/jest/config.build-devtools.js index 9c8501486ab49..42dee14104295 100644 --- a/scripts/jest/config.build-devtools.js +++ b/scripts/jest/config.build-devtools.js @@ -43,6 +43,9 @@ packages.forEach(name => { ] = `/build/node_modules/${name}/$1`; }); +// https://jestjs.io/docs/en/webpack#mocking-css-modules +moduleNameMapper['\\.(css|less)$'] = 'identity-obj-proxy'; + module.exports = Object.assign({}, baseConfig, { // Redirect imports to the compiled bundles moduleNameMapper, diff --git a/yarn.lock b/yarn.lock index 50f7b5818f924..3a5b4e5a1543d 100644 --- a/yarn.lock +++ b/yarn.lock @@ -6591,6 +6591,11 @@ har-validator@~5.1.0: ajv "^6.5.5" har-schema "^2.0.0" +harmony-reflect@^1.4.6: + version "1.6.1" + resolved "https://registry.yarnpkg.com/harmony-reflect/-/harmony-reflect-1.6.1.tgz#c108d4f2bb451efef7a37861fdbdae72c9bdefa9" + integrity sha512-WJTeyp0JzGtHcuMsi7rw2VwtkvLa+JyfEKJCFyfcS0+CDkjQ5lHPu7zEhFZP+PDSRrEgXa5Ah0l1MbgbE41XjA== + has-ansi@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/has-ansi/-/has-ansi-2.0.0.tgz#34f5049ce1ecdf2b0649af3ef24e45ed35416d91" @@ -6938,6 +6943,13 @@ icss-utils@^2.1.0: dependencies: postcss "^6.0.1" +identity-obj-proxy@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/identity-obj-proxy/-/identity-obj-proxy-3.0.0.tgz#94d2bda96084453ef36fbc5aaec37e0f79f1fc14" + integrity sha1-lNK9qWCERT7zb7xarsN+D3nx/BQ= + dependencies: + harmony-reflect "^1.4.6" + ieee754@^1.1.12, ieee754@^1.1.4: version "1.1.13" resolved "https://registry.yarnpkg.com/ieee754/-/ieee754-1.1.13.tgz#ec168558e95aa181fd87d37f55c32bbcb6708b84" From 13a999281662f9031caf479892c4b7fca82ca116 Mon Sep 17 00:00:00 2001 From: Sebastian Silbermann Date: Wed, 19 Feb 2020 09:38:39 +0100 Subject: [PATCH 2/5] fix: complex debug values not showing in collapsed state --- .../src/devtools/views/Components/HooksTree.js | 14 ++++---------- 1 file changed, 4 insertions(+), 10 deletions(-) diff --git a/packages/react-devtools-shared/src/devtools/views/Components/HooksTree.js b/packages/react-devtools-shared/src/devtools/views/Components/HooksTree.js index f055d207e9066..a6e3237c7c72e 100644 --- a/packages/react-devtools-shared/src/devtools/views/Components/HooksTree.js +++ b/packages/react-devtools-shared/src/devtools/views/Components/HooksTree.js @@ -17,7 +17,7 @@ import EditableValue from './EditableValue'; import ExpandCollapseToggle from './ExpandCollapseToggle'; import {InspectedElementContext} from './InspectedElementContext'; import KeyValue from './KeyValue'; -import {serializeHooksForCopy} from '../utils'; +import {getMetaValueLabel, serializeHooksForCopy} from '../utils'; import styles from './HooksTree.css'; import useContextMenu from '../../ContextMenu/useContextMenu'; import {meta} from '../../../hydration'; @@ -202,17 +202,11 @@ function HookView({canEditHooks, hook, id, inspectPath, path}: HookViewProps) { className={name !== '' ? styles.Name : styles.NameAnonymous}> {name || 'Anonymous'} + + {getMetaValueLabel(value)} + From c1048ef20e5036d9fa27615e8ba3f3480c1f35ab Mon Sep 17 00:00:00 2001 From: Sebastian Silbermann Date: Mon, 9 Mar 2020 22:58:45 +0100 Subject: [PATCH 3/5] test: Remove view test --- package.json | 1 - .../src/__tests__/HooksTree-test.js | 92 ------------------- scripts/jest/config.build-devtools.js | 3 - yarn.lock | 12 --- 4 files changed, 108 deletions(-) delete mode 100644 packages/react-devtools-shared/src/__tests__/HooksTree-test.js diff --git a/package.json b/package.json index d49453c1a10a4..42fa148eb0714 100644 --- a/package.json +++ b/package.json @@ -63,7 +63,6 @@ "glob-stream": "^6.1.0", "google-closure-compiler": "^20200112.0.0", "gzip-size": "^5.1.1", - "identity-obj-proxy": "^3.0.0", "jasmine-check": "^1.0.0-rc.0", "jest": "^25.1.0", "jest-diff": "^25.1.0", diff --git a/packages/react-devtools-shared/src/__tests__/HooksTree-test.js b/packages/react-devtools-shared/src/__tests__/HooksTree-test.js deleted file mode 100644 index 10f436d051c81..0000000000000 --- a/packages/react-devtools-shared/src/__tests__/HooksTree-test.js +++ /dev/null @@ -1,92 +0,0 @@ -describe('HooksTree', () => { - let React; - let ReactDOM; - let bridge: FrontendBridge; - let store: Store; - let utils; - let HooksTree; - - let BridgeContext; - let InspectedElementContextController; - let StoreContext; - let TreeContextController; - - beforeEach(() => { - utils = require('./utils'); - utils.beforeEachProfiling(); - - bridge = global.bridge; - store = global.store; - store.collapseNodesByDefault = false; - - React = require('react'); - ReactDOM = require('react-dom'); - - BridgeContext = require('react-devtools-shared/src/devtools/views/context') - .BridgeContext; - InspectedElementContextController = require('react-devtools-shared/src/devtools/views/Components/InspectedElementContext') - .InspectedElementContextController; - StoreContext = require('react-devtools-shared/src/devtools/views/context') - .StoreContext; - TreeContextController = require('react-devtools-shared/src/devtools/views/Components/TreeContext') - .TreeContextController; - - HooksTree = require('react-devtools-shared/src/devtools/views/Components/HooksTree') - .HooksTreeView; - }); - - const Contexts = ({ - children, - defaultSelectedElementID = null, - defaultSelectedElementIndex = null, - }) => ( - - - - - {children} - - - - - ); - - it('shows the complex value of custom hooks with sub-hooks', () => { - // props from `InspectedElementContext display complex values of useDebugValue: DisplayedComplexValue 1` snapshot - - const container = document.createElement('div'); - ReactDOM.render( - - - , - container, - ); - - const hook = container.querySelector('.NameValueRow'); - // it's actually DebuggableHook: {foo:2} but the first colon is added by css - // which isn't available in the test - expect(hook.textContent).toEqual('DebuggableHook{foo: 2}'); - }); -}); diff --git a/scripts/jest/config.build-devtools.js b/scripts/jest/config.build-devtools.js index 42dee14104295..9c8501486ab49 100644 --- a/scripts/jest/config.build-devtools.js +++ b/scripts/jest/config.build-devtools.js @@ -43,9 +43,6 @@ packages.forEach(name => { ] = `/build/node_modules/${name}/$1`; }); -// https://jestjs.io/docs/en/webpack#mocking-css-modules -moduleNameMapper['\\.(css|less)$'] = 'identity-obj-proxy'; - module.exports = Object.assign({}, baseConfig, { // Redirect imports to the compiled bundles moduleNameMapper, diff --git a/yarn.lock b/yarn.lock index 3a5b4e5a1543d..50f7b5818f924 100644 --- a/yarn.lock +++ b/yarn.lock @@ -6591,11 +6591,6 @@ har-validator@~5.1.0: ajv "^6.5.5" har-schema "^2.0.0" -harmony-reflect@^1.4.6: - version "1.6.1" - resolved "https://registry.yarnpkg.com/harmony-reflect/-/harmony-reflect-1.6.1.tgz#c108d4f2bb451efef7a37861fdbdae72c9bdefa9" - integrity sha512-WJTeyp0JzGtHcuMsi7rw2VwtkvLa+JyfEKJCFyfcS0+CDkjQ5lHPu7zEhFZP+PDSRrEgXa5Ah0l1MbgbE41XjA== - has-ansi@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/has-ansi/-/has-ansi-2.0.0.tgz#34f5049ce1ecdf2b0649af3ef24e45ed35416d91" @@ -6943,13 +6938,6 @@ icss-utils@^2.1.0: dependencies: postcss "^6.0.1" -identity-obj-proxy@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/identity-obj-proxy/-/identity-obj-proxy-3.0.0.tgz#94d2bda96084453ef36fbc5aaec37e0f79f1fc14" - integrity sha1-lNK9qWCERT7zb7xarsN+D3nx/BQ= - dependencies: - harmony-reflect "^1.4.6" - ieee754@^1.1.12, ieee754@^1.1.4: version "1.1.13" resolved "https://registry.yarnpkg.com/ieee754/-/ieee754-1.1.13.tgz#ec168558e95aa181fd87d37f55c32bbcb6708b84" From ee3a74fc39db02b26d2f5f02d7b9dcde9120743b Mon Sep 17 00:00:00 2001 From: Brian Vaughn Date: Tue, 17 Mar 2020 13:21:47 -0700 Subject: [PATCH 4/5] Adding nowrap style to `HooksTree` labels. --- .../src/devtools/views/Components/HooksTree.css | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/react-devtools-shared/src/devtools/views/Components/HooksTree.css b/packages/react-devtools-shared/src/devtools/views/Components/HooksTree.css index 37e0d9dbd5e00..7b381faa9fa02 100644 --- a/packages/react-devtools-shared/src/devtools/views/Components/HooksTree.css +++ b/packages/react-devtools-shared/src/devtools/views/Components/HooksTree.css @@ -53,6 +53,7 @@ overflow: hidden; text-overflow: ellipsis; cursor: default; + white-space: nowrap; } .None { From 32bac9ef5aaef03eb4805c0230c7bb93c0e2d3da Mon Sep 17 00:00:00 2001 From: Brian Vaughn Date: Tue, 17 Mar 2020 13:22:47 -0700 Subject: [PATCH 5/5] Added tree back to complex hooks. Only show meta label when collapsed. --- .../src/devtools/views/Components/HooksTree.js | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/packages/react-devtools-shared/src/devtools/views/Components/HooksTree.js b/packages/react-devtools-shared/src/devtools/views/Components/HooksTree.js index a6e3237c7c72e..c4ff5a8765ffc 100644 --- a/packages/react-devtools-shared/src/devtools/views/Components/HooksTree.js +++ b/packages/react-devtools-shared/src/devtools/views/Components/HooksTree.js @@ -203,10 +203,19 @@ function HookView({canEditHooks, hook, id, inspectPath, path}: HookViewProps) { {name || 'Anonymous'} - {getMetaValueLabel(value)} + {isOpen || getMetaValueLabel(value)}