/** * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. * * @flow */ import typeof ReactTestRenderer from 'react-test-renderer'; import type {Element} from 'react-devtools-shared/src/devtools/views/Components/types'; import type {FrontendBridge} from 'react-devtools-shared/src/bridge'; import type Store from 'react-devtools-shared/src/devtools/store'; describe('OwnersListContext', () => { let React; let TestRenderer: ReactTestRenderer; let bridge: FrontendBridge; let legacyRender; let store: Store; let utils; let BridgeContext; let OwnersListContext; let OwnersListContextController; let StoreContext; let TreeContextController; beforeEach(() => { utils = require('./utils'); utils.beforeEachProfiling(); legacyRender = utils.legacyRender; bridge = global.bridge; store = global.store; store.collapseNodesByDefault = false; React = require('react'); TestRenderer = utils.requireTestRenderer(); BridgeContext = require('react-devtools-shared/src/devtools/views/context').BridgeContext; OwnersListContext = require('react-devtools-shared/src/devtools/views/Components/OwnersListContext').OwnersListContext; OwnersListContextController = require('react-devtools-shared/src/devtools/views/Components/OwnersListContext').OwnersListContextController; StoreContext = require('react-devtools-shared/src/devtools/views/context').StoreContext; TreeContextController = require('react-devtools-shared/src/devtools/views/Components/TreeContext').TreeContextController; }); const Contexts = ({children, defaultOwnerID = null}) => ( {children} ); async function getOwnersListForOwner(owner) { let ownerDisplayNames = null; function Suspender() { const read = React.useContext(OwnersListContext); const owners = read(owner.id); ownerDisplayNames = owners.map(({displayName}) => displayName); return null; } await utils.actAsync(() => TestRenderer.create( , ), ); expect(ownerDisplayNames).not.toBeNull(); return ownerDisplayNames; } it('should fetch the owners list for the selected element', async () => { const Grandparent = () => ; const Parent = () => { return ( ); }; const Child = () => null; utils.act(() => legacyRender(, document.createElement('div')), ); expect(store).toMatchInlineSnapshot(` [root] ▾ `); const parent = ((store.getElementAtIndex(1): any): Element); const firstChild = ((store.getElementAtIndex(2): any): Element); expect(await getOwnersListForOwner(parent)).toMatchInlineSnapshot(` [ "Grandparent", "Parent", ] `); expect(await getOwnersListForOwner(firstChild)).toMatchInlineSnapshot(` [ "Grandparent", "Parent", "Child", ] `); }); it('should fetch the owners list for the selected element that includes filtered components', async () => { store.componentFilters = [utils.createDisplayNameFilter('^Parent$')]; const Grandparent = () => ; const Parent = () => { return ( ); }; const Child = () => null; utils.act(() => legacyRender(, document.createElement('div')), ); expect(store).toMatchInlineSnapshot(` [root] ▾ `); const firstChild = ((store.getElementAtIndex(1): any): Element); expect(await getOwnersListForOwner(firstChild)).toMatchInlineSnapshot(` [ "Grandparent", "Parent", "Child", ] `); }); it('should include the current element even if there are no other owners', async () => { store.componentFilters = [utils.createDisplayNameFilter('^Parent$')]; const Grandparent = () => ; const Parent = () => null; utils.act(() => legacyRender(, document.createElement('div')), ); expect(store).toMatchInlineSnapshot(` [root] `); const grandparent = ((store.getElementAtIndex(0): any): Element); expect(await getOwnersListForOwner(grandparent)).toMatchInlineSnapshot(` [ "Grandparent", ] `); }); it('should include all owners for a component wrapped in react memo', async () => { const InnerComponent = (props, ref) =>
; const ForwardRef = React.forwardRef(InnerComponent); const Memo = React.memo(ForwardRef); const Grandparent = () => { const ref = React.createRef(); return ; }; utils.act(() => legacyRender(, document.createElement('div')), ); expect(store).toMatchInlineSnapshot(` [root] ▾ [Memo] [ForwardRef] `); const wrapped = ((store.getElementAtIndex(2): any): Element); expect(await getOwnersListForOwner(wrapped)).toMatchInlineSnapshot(` [ "Grandparent", "InnerComponent", "InnerComponent", ] `); }); });