diff --git a/src/components/SelectionList/BaseSelectionList.tsx b/src/components/SelectionList/BaseSelectionList.tsx index 1c69d00b3910..4e58b53e89fd 100644 --- a/src/components/SelectionList/BaseSelectionList.tsx +++ b/src/components/SelectionList/BaseSelectionList.tsx @@ -415,6 +415,7 @@ function BaseSelectionList( onSubmitEditing={selectFocusedOption} blurOnSubmit={!!flattenedSections.allOptions.length} isLoading={isLoadingNewOptions} + testID="selection-list-text-input" /> )} diff --git a/src/pages/SearchPage/index.js b/src/pages/SearchPage/index.js index 0c17e58837c1..a733bc175ac7 100644 --- a/src/pages/SearchPage/index.js +++ b/src/pages/SearchPage/index.js @@ -33,12 +33,20 @@ const propTypes = { /** Whether or not we are searching for reports on the server */ isSearchingForReports: PropTypes.bool, + + /** + * The navigation prop passed by the navigator. + * + * This is required because transitionEnd event doesn't trigger in the automated testing environment. + */ + navigation: PropTypes.shape({}), }; const defaultProps = { betas: [], reports: {}, isSearchingForReports: false, + navigation: {}, }; const setPerformanceTimersEnd = () => { @@ -48,7 +56,7 @@ const setPerformanceTimersEnd = () => { const SearchPageFooterInstance = ; -function SearchPage({betas, reports, isSearchingForReports}) { +function SearchPage({betas, reports, isSearchingForReports, navigation}) { const [isScreenTransitionEnd, setIsScreenTransitionEnd] = useState(false); const {translate} = useLocalize(); const {isOffline} = useNetwork(); @@ -145,6 +153,7 @@ function SearchPage({betas, reports, isSearchingForReports}) { testID={SearchPage.displayName} onEntryTransitionEnd={handleScreenTransitionEnd} shouldEnableMaxHeight + navigation={navigation} > {({didScreenTransitionEnd, safeAreaPaddingBottomStyle}) => ( <> diff --git a/tests/perf-test/SearchPage.perf-test.js b/tests/perf-test/SearchPage.perf-test.js index 8c6148f9e103..be6b6a5d78f9 100644 --- a/tests/perf-test/SearchPage.perf-test.js +++ b/tests/perf-test/SearchPage.perf-test.js @@ -1,8 +1,9 @@ -import {act, fireEvent, screen} from '@testing-library/react-native'; +import {fireEvent, screen, waitFor} from '@testing-library/react-native'; import React from 'react'; import Onyx from 'react-native-onyx'; import {measurePerformance} from 'reassure'; import _ from 'underscore'; +import {LocaleContextProvider} from '@components/LocaleContextProvider'; import SearchPage from '@pages/SearchPage'; import ComposeProviders from '../../src/components/ComposeProviders'; import OnyxProvider from '../../src/components/OnyxProvider'; @@ -16,6 +17,22 @@ import * as TestHelper from '../utils/TestHelper'; import waitForBatchedUpdates from '../utils/waitForBatchedUpdates'; import wrapOnyxWithWaitForBatchedUpdates from '../utils/wrapOnyxWithWaitForBatchedUpdates'; +jest.mock('lodash/debounce', () => + jest.fn((fn) => { + // eslint-disable-next-line no-param-reassign + fn.cancel = jest.fn(); + return fn; + }), +); + +jest.mock('../../src/libs/Log'); + +jest.mock('../../src/libs/API', () => ({ + write: jest.fn(), + makeRequestWithSideEffects: jest.fn(), + read: jest.fn(), +})); + jest.mock('../../src/libs/Navigation/Navigation'); const mockedNavigate = jest.fn(); @@ -93,7 +110,7 @@ afterEach(() => { function SearchPageWrapper(args) { return ( - + { +test('[Search Page] should interact when text input changes', async () => { const {addListener} = TestHelper.createAddListenerMock(); const scenario = async () => { await screen.findByTestId('SearchPage'); - const input = screen.getByTestId('options-selector-input'); + const input = screen.getByTestId('selection-list-text-input'); fireEvent.changeText(input, 'Email Four'); fireEvent.changeText(input, 'Report'); fireEvent.changeText(input, 'Email Five'); @@ -121,7 +138,6 @@ test.skip('[Search Page] should interact when text input changes', async () => { .then(() => Onyx.multiSet({ ...mockedReports, - [ONYXKEYS.IS_SIDEBAR_LOADED]: true, [ONYXKEYS.PERSONAL_DETAILS_LIST]: mockedPersonalDetails, [ONYXKEYS.BETAS]: mockedBetas, [ONYXKEYS.IS_SEARCHING_FOR_REPORTS]: true, @@ -130,13 +146,14 @@ test.skip('[Search Page] should interact when text input changes', async () => { .then(() => measurePerformance(, {scenario})); }); -test.skip('[Search Page] should render options list', async () => { +test('[Search Page] should render selection list', async () => { const {triggerTransitionEnd, addListener} = TestHelper.createAddListenerMock(); const smallMockedPersonalDetails = getMockedPersonalDetails(5); const scenario = async () => { await screen.findByTestId('SearchPage'); - await act(triggerTransitionEnd); + await waitFor(triggerTransitionEnd); + await screen.findByTestId('selection-list'); await screen.findByText(smallMockedPersonalDetails['1'].login); await screen.findByText(smallMockedPersonalDetails['2'].login); }; @@ -147,7 +164,6 @@ test.skip('[Search Page] should render options list', async () => { .then(() => Onyx.multiSet({ ...mockedReports, - [ONYXKEYS.IS_SIDEBAR_LOADED]: true, [ONYXKEYS.PERSONAL_DETAILS_LIST]: smallMockedPersonalDetails, [ONYXKEYS.BETAS]: mockedBetas, [ONYXKEYS.IS_SEARCHING_FOR_REPORTS]: true, @@ -156,16 +172,18 @@ test.skip('[Search Page] should render options list', async () => { .then(() => measurePerformance(, {scenario})); }); -test.skip('[Search Page] should search in options list', async () => { +test('[Search Page] should search in selection list', async () => { const {triggerTransitionEnd, addListener} = TestHelper.createAddListenerMock(); const scenario = async () => { await screen.findByTestId('SearchPage'); - const input = screen.getByTestId('options-selector-input'); + await waitFor(triggerTransitionEnd); + + const input = screen.getByTestId('selection-list-text-input'); + const searchValue = mockedPersonalDetails['88'].login; - fireEvent.changeText(input, mockedPersonalDetails['88'].login); - await act(triggerTransitionEnd); - await screen.findByText(mockedPersonalDetails['88'].login); + fireEvent.changeText(input, searchValue); + await screen.findByText(searchValue); }; const navigation = {addListener}; @@ -174,7 +192,6 @@ test.skip('[Search Page] should search in options list', async () => { .then(() => Onyx.multiSet({ ...mockedReports, - [ONYXKEYS.IS_SIDEBAR_LOADED]: true, [ONYXKEYS.PERSONAL_DETAILS_LIST]: mockedPersonalDetails, [ONYXKEYS.BETAS]: mockedBetas, [ONYXKEYS.IS_SEARCHING_FOR_REPORTS]: true, @@ -183,17 +200,18 @@ test.skip('[Search Page] should search in options list', async () => { .then(() => measurePerformance(, {scenario})); }); -test.skip('[Search Page] should click on list item', async () => { +test('[Search Page] should click on list item', async () => { const {triggerTransitionEnd, addListener} = TestHelper.createAddListenerMock(); const scenario = async () => { await screen.findByTestId('SearchPage'); - const input = screen.getByTestId('options-selector-input'); + const input = screen.getByTestId('selection-list-text-input'); + await waitFor(triggerTransitionEnd); - fireEvent.changeText(input, mockedPersonalDetails['4'].login); - await act(triggerTransitionEnd); - const optionButton = await screen.findByText(mockedPersonalDetails['4'].login); + const searchValue = mockedPersonalDetails['4'].login; + fireEvent.changeText(input, searchValue); + const optionButton = await screen.findByText(searchValue); fireEvent.press(optionButton); }; @@ -202,7 +220,6 @@ test.skip('[Search Page] should click on list item', async () => { .then(() => Onyx.multiSet({ ...mockedReports, - [ONYXKEYS.IS_SIDEBAR_LOADED]: true, [ONYXKEYS.PERSONAL_DETAILS_LIST]: mockedPersonalDetails, [ONYXKEYS.BETAS]: mockedBetas, [ONYXKEYS.IS_SEARCHING_FOR_REPORTS]: true,