| 1 | /** |
| 2 | * Copyright (c) Meta Platforms, Inc. and affiliates. |
| 3 | * |
| 4 | * This source code is licensed under the MIT license found in the |
| 5 | * LICENSE file in the root directory of this source tree. |
| 6 | * |
| 7 | * @flow |
| 8 | */ |
| 9 | import {getVersionedRenderImplementation} from './utils'; |
| 10 | |
| 11 | describe('Store React.optimisticKey', () => { |
| 12 | let act; |
| 13 | let actAsync; |
| 14 | let React; |
| 15 | let TestRenderer; |
| 16 | let bridge; |
| 17 | let store; |
| 18 | |
| 19 | let BridgeContext; |
| 20 | let StoreContext; |
| 21 | let TreeContext; |
| 22 | |
| 23 | let dispatch; |
| 24 | let state; |
| 25 | |
| 26 | beforeAll(() => { |
| 27 | // JSDDOM doesn't implement getClientRects so we're just faking one for testing purposes |
| 28 | Element.prototype.getClientRects = function (this: Element) { |
| 29 | const textContent = this.textContent; |
| 30 | return [ |
| 31 | new DOMRect(1, 2, textContent.length, textContent.split('\n').length), |
| 32 | ]; |
| 33 | }; |
| 34 | }); |
| 35 | |
| 36 | beforeEach(() => { |
| 37 | global.IS_REACT_ACT_ENVIRONMENT = true; |
| 38 | |
| 39 | store = global.store; |
| 40 | bridge = global.bridge; |
| 41 | |
| 42 | React = require('react'); |
| 43 | |
| 44 | const utils = require('./utils'); |
| 45 | act = utils.act; |
| 46 | actAsync = utils.actAsync; |
| 47 | TestRenderer = utils.requireTestRenderer(); |
| 48 | |
| 49 | BridgeContext = |
| 50 | require('react-devtools-shared/src/devtools/views/context').BridgeContext; |
| 51 | StoreContext = |
| 52 | require('react-devtools-shared/src/devtools/views/context').StoreContext; |
| 53 | TreeContext = require('react-devtools-shared/src/devtools/views/Components/TreeContext'); |
| 54 | }); |
| 55 | |
| 56 | const {render} = getVersionedRenderImplementation(); |
| 57 | |
| 58 | const Capture = () => { |
| 59 | dispatch = React.useContext(TreeContext.TreeDispatcherContext); |
| 60 | state = React.useContext(TreeContext.TreeStateContext); |
| 61 | return null; |
| 62 | }; |
| 63 | |
| 64 | const Contexts = () => { |
| 65 | return ( |
| 66 | <BridgeContext.Provider value={bridge}> |
| 67 | <StoreContext.Provider value={store}> |
| 68 | <TreeContext.TreeContextController> |
| 69 | <Capture /> |
| 70 | </TreeContext.TreeContextController> |
| 71 | </StoreContext.Provider> |
| 72 | </BridgeContext.Provider> |
| 73 | ); |
| 74 | }; |
| 75 | |
| 76 | // @reactVersion >= 19.3 |
| 77 | it('is included in the tree', async () => { |
| 78 | if (React.optimisticKey === undefined) { |
| 79 | return; |
| 80 | } |
| 81 | |
| 82 | function Component() { |
| 83 | return null; |
| 84 | } |
| 85 | |
| 86 | await actAsync(() => { |
| 87 | render(<Component key={React.optimisticKey} />); |
| 88 | }); |
| 89 | |
| 90 | expect(store).toMatchInlineSnapshot(` |
| 91 | [root] |
| 92 | <Component key="React.optimisticKey"> |
| 93 | `); |
| 94 | expect(store.getElementAtIndex(0)).toEqual( |
| 95 | expect.objectContaining({key: 'React.optimisticKey'}), |
| 96 | ); |
| 97 | }); |
| 98 | |
| 99 | // @reactVersion >= 19.3 |
| 100 | it('is searchable', async () => { |
| 101 | if (React.optimisticKey === undefined) { |
| 102 | return; |
| 103 | } |
| 104 | await actAsync(() => { |
| 105 | render(<React.Fragment key={React.optimisticKey} />); |
| 106 | }); |
| 107 | let renderer; |
| 108 | act(() => (renderer = TestRenderer.create(<Contexts />))); |
| 109 | |
| 110 | expect(state).toMatchInlineSnapshot(` |
| 111 | [root] |
| 112 | <Fragment key="React.optimisticKey"> |
| 113 | `); |
| 114 | |
| 115 | act(() => dispatch({type: 'SET_SEARCH_TEXT', payload: 'optimistic'})); |
| 116 | act(() => renderer.update(<Contexts />)); |
| 117 | |
| 118 | expect(state).toMatchInlineSnapshot(` |
| 119 | [root] |
| 120 | <Fragment key="React.optimisticKey"> |
| 121 | `); |
| 122 | |
| 123 | act(() => dispatch({type: 'SET_SEARCH_TEXT', payload: 'react'})); |
| 124 | act(() => renderer.update(<Contexts />)); |
| 125 | |
| 126 | expect(state).toMatchInlineSnapshot(` |
| 127 | [root] |
| 128 | → <Fragment key="React.optimisticKey"> |
| 129 | `); |
| 130 | }); |
| 131 | }); |