/** * 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. * * @emails react-core */ 'use strict'; describe('ReactDOMTestSelectors', () => { let React; let createRoot; let act; let createComponentSelector; let createHasPseudoClassSelector; let createRoleSelector; let createTextSelector; let createTestNameSelector; let findAllNodes; let findBoundingRects; let focusWithin; let getFindAllNodesFailureDescription; let observeVisibleRects; let container; beforeEach(() => { jest.resetModules(); React = require('react'); act = require('internal-test-utils').act; if (__EXPERIMENTAL__ || global.__WWW__) { const ReactDOM = require('react-dom/unstable_testing'); createComponentSelector = ReactDOM.createComponentSelector; createHasPseudoClassSelector = ReactDOM.createHasPseudoClassSelector; createRoleSelector = ReactDOM.createRoleSelector; createTextSelector = ReactDOM.createTextSelector; createTestNameSelector = ReactDOM.createTestNameSelector; findAllNodes = ReactDOM.findAllNodes; findBoundingRects = ReactDOM.findBoundingRects; focusWithin = ReactDOM.focusWithin; getFindAllNodesFailureDescription = ReactDOM.getFindAllNodesFailureDescription; observeVisibleRects = ReactDOM.observeVisibleRects; createRoot = ReactDOM.createRoot; } container = document.createElement('div'); document.body.appendChild(container); }); afterEach(() => { document.body.removeChild(container); }); describe('findAllNodes', () => { // @gate www || experimental it('should support searching from the document root', async () => { function Example() { return (
); } const root = createRoot(container); await act(() => { root.render(); }); const matches = findAllNodes(document.body, [ createComponentSelector(Example), createTestNameSelector('match'), ]); expect(matches).toHaveLength(1); expect(matches[0].id).toBe('match'); }); // @gate www || experimental it('should support searching from the container', async () => { function Example() { return (
); } const root = createRoot(container); await act(() => { root.render(); }); const matches = findAllNodes(container, [ createComponentSelector(Example), createTestNameSelector('match'), ]); expect(matches).toHaveLength(1); expect(matches[0].id).toBe('match'); }); // @gate www || experimental it('should support searching from a previous match if the match had a data-testname', async () => { function Outer() { return (
); } function Inner() { return
; } const root = createRoot(container); await act(() => { root.render(); }); let matches = findAllNodes(container, [ createComponentSelector(Outer), createTestNameSelector('outer'), ]); expect(matches).toHaveLength(1); expect(matches[0].id).toBe('outer'); matches = findAllNodes(matches[0], [ createComponentSelector(Inner), createTestNameSelector('inner'), ]); expect(matches).toHaveLength(1); expect(matches[0].id).toBe('inner'); }); // @gate www || experimental it('should not support searching from a previous match if the match did not have a data-testname', async () => { function Outer() { return (
); } function Inner() { return
; } const root = createRoot(container); await act(() => { root.render(); }); const matches = findAllNodes(container, [createComponentSelector(Outer)]); expect(matches).toHaveLength(1); expect(matches[0].id).toBe('outer'); expect(() => { findAllNodes(matches[0], [ createComponentSelector(Inner), createTestNameSelector('inner'), ]); }).toThrow( 'Invalid host root specified. Should be either a React container or a node with a testname attribute.', ); }); // @gate www || experimental it('should support an multiple component types in the selector array', async () => { function Outer() { return ( <>
); } function Middle() { return ( <>
); } function Inner() { return ( <>
); } const root = createRoot(container); await act(() => { root.render(); }); let matches = findAllNodes(document.body, [ createComponentSelector(Outer), createComponentSelector(Middle), createTestNameSelector('match'), ]); expect(matches).toHaveLength(2); expect(matches.map(m => m.id).sort()).toEqual(['match2', 'match3']); matches = findAllNodes(document.body, [ createComponentSelector(Outer), createComponentSelector(Middle), createComponentSelector(Inner), createTestNameSelector('match'), ]); expect(matches).toHaveLength(1); expect(matches[0].id).toBe('match3'); matches = findAllNodes(document.body, [ createComponentSelector(Outer), createComponentSelector(Inner), createTestNameSelector('match'), ]); expect(matches).toHaveLength(1); expect(matches[0].id).toBe('match3'); }); // @gate www || experimental it('should find multiple matches', async () => { function Example1() { return (
); } function Example2() { return (
); } const root = createRoot(container); await act(() => { root.render( <> , ); }); const matches = findAllNodes(document.body, [ createTestNameSelector('match'), ]); expect(matches).toHaveLength(3); expect(matches.map(m => m.id).sort()).toEqual([ 'match1', 'match2', 'match3', ]); }); // @gate www || experimental it('should ignore nested matches', async () => { function Example() { return (
); } const root = createRoot(container); await act(() => { root.render(); }); const matches = findAllNodes(document.body, [ createComponentSelector(Example), createTestNameSelector('match'), ]); expect(matches).toHaveLength(1); expect(matches[0].id).toEqual('match1'); }); // @gate www || experimental it('should enforce the specific order of selectors', async () => { function Outer() { return ( <>
); } function Inner() { return
; } const root = createRoot(container); await act(() => { root.render(); }); expect( findAllNodes(document.body, [ createComponentSelector(Inner), createComponentSelector(Outer), createTestNameSelector('match'), ]), ).toHaveLength(0); }); // @gate www || experimental it('should not search within hidden subtrees', async () => { const ref1 = React.createRef(null); const ref2 = React.createRef(null); function Outer() { return ( <>