fix(MM-64763): search page doesn't clear hashtag on search input (#9194)

This commit is contained in:
Rahim Rahman 2025-10-10 10:51:56 -06:00 committed by GitHub
parent 6ed8a56be4
commit f6e8ebc2e9
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 66 additions and 1 deletions

View file

@ -204,4 +204,65 @@ describe('SearchScreen', () => {
expect.any(String),
);
});
it('does not restore searchTerm after clearing when navigated with hashtag', async () => {
const mockNavigation = {
getState: () => ({
index: 0,
routes: [{params: {searchTerm: '#hashtag'}}],
}),
};
jest.spyOn(require('@react-navigation/native'), 'useNavigation').mockReturnValue(mockNavigation);
const {getByTestId} = renderWithEverything(
<SearchScreen {...baseProps}/>,
{database},
);
await waitFor(() => {
const searchInput = getByTestId('navigation.header.search_bar.search.input');
expect(searchInput.props.value).toBe('#hashtag');
});
const searchInput = getByTestId('navigation.header.search_bar.search.input');
const clearButton = getByTestId('navigation.header.search_bar.search.clear.button');
act(() => {
fireEvent.press(clearButton);
});
await waitFor(() => {
expect(searchInput.props.value).toBe('');
});
});
it('populates searchTerm when navigating to screen with hashtag', async () => {
const mockNavigation = {
getState: () => ({
index: 0,
routes: [{params: {searchTerm: '#newtag'}}],
}),
};
jest.spyOn(require('@react-navigation/native'), 'useNavigation').mockReturnValue(mockNavigation);
const {getByTestId} = renderWithEverything(
<SearchScreen {...baseProps}/>,
{database},
);
await waitFor(() => {
const searchInput = getByTestId('navigation.header.search_bar.search.input');
expect(searchInput.props.value).toBe('#newtag');
});
await waitFor(() => {
expect(searchPosts).toHaveBeenCalledWith(
expect.any(String),
'team1',
expect.objectContaining({terms: '#newtag'}),
);
});
});
});

View file

@ -112,6 +112,7 @@ const SearchScreen = ({teamId, teams, crossTeamSearchEnabled}: Props) => {
const clearRef = useRef<boolean>(false);
const cancelRef = useRef<boolean>(false);
const searchRef = useRef<SearchRef>(null);
const processedSearchTermRef = useRef<string>('');
const [cursorPosition, setCursorPosition] = useState(searchTerm?.length || 0);
const [searchValue, setSearchValue] = useState<string>(searchTerm || '');
@ -137,6 +138,7 @@ const SearchScreen = ({teamId, teams, crossTeamSearchEnabled}: Props) => {
const onSnap = useCallback((offset: number, animated = true) => {
scrollRef.current?.scrollToOffset({offset, animated});
// eslint-disable-next-line react-hooks/exhaustive-deps -- scrollRef is a ref object, so its reference should not change between renders
}, []);
const onSnapWithTimeout = useCallback((offset: number, animated = true) => {
@ -365,7 +367,8 @@ const SearchScreen = ({teamId, teams, crossTeamSearchEnabled}: Props) => {
}, [unlock, onSnapWithTimeout]);
useEffect(() => {
if (searchTerm) {
if (searchTerm && searchTerm !== processedSearchTermRef.current) {
processedSearchTermRef.current = searchTerm;
clearInputs();
setSearchValue(searchTerm);
handleSearch(searchTeamId, searchTerm);
@ -379,6 +382,7 @@ const SearchScreen = ({teamId, teams, crossTeamSearchEnabled}: Props) => {
}, 300);
} else {
setAutoScroll(false);
processedSearchTermRef.current = '';
}
}, [isFocused]);