mattermost-mobile/app/screens/home/search/search.test.tsx
Daniel Espino García 6c53533080
Standardize tabs across different components (#8691)
* Standardize tabs across different components

* Add tests and minor fixes

* Remove unneeded tests

* Add missing change

* Fix test

* Refactor to remove the component from the hook

* Rename hasDot for requiresUserAttention.

* Apply the changes to scheduled posts

* Fix texts

* Fix tests and fix minor style issue on iOS

* Fix filter positioning

* Fix some e2e tests

* Fix tests

---------

Co-authored-by: Mattermost Build <build@mattermost.com>
2025-05-28 16:23:37 +02:00

207 lines
6.3 KiB
TypeScript

// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See LICENSE.txt for license information.
import {act, fireEvent, waitFor} from '@testing-library/react-native';
import React from 'react';
import {addSearchToTeamSearchHistory} from '@actions/local/team';
import {searchPosts, searchFiles} from '@actions/remote/search';
import useTabs from '@hooks/use_tabs';
import {bottomSheet} from '@screens/navigation';
import {renderWithEverything} from '@test/intl-test-helper';
import TestHelper from '@test/test_helper';
import SearchScreen from './search';
import type {TeamModel} from '@database/models/server';
import type {Database} from '@nozbe/watermelondb';
// Some subcomponents require react-native-camera-roll, which is not available in the test environment
jest.mock('@react-native-camera-roll/camera-roll', () => ({}));
jest.mock('@react-navigation/native', () => ({
useNavigation: () => ({
getState: () => ({
index: 0,
routes: [{params: {searchTerm: ''}}],
}),
}),
useIsFocused: () => true,
}));
jest.mock('@actions/local/post', () => ({
getPosts: jest.fn().mockResolvedValue([]),
}));
jest.mock('@actions/local/team', () => ({
addSearchToTeamSearchHistory: jest.fn(),
}));
jest.mock('@actions/remote/search', () => ({
searchPosts: jest.fn().mockResolvedValue({order: [], matches: {}}),
searchFiles: jest.fn().mockResolvedValue({files: [], channels: []}),
}));
jest.mock('@mattermost/hardware-keyboard', () => ({
useHardwareKeyboardEvents: jest.fn(),
}));
jest.mock('@screens/navigation', () => ({
bottomSheet: jest.fn(),
}));
jest.mock('@hooks/use_tabs', () => ({
__esModule: true,
default: jest.fn(jest.requireActual('@hooks/use_tabs').default),
}));
describe('SearchScreen', () => {
const baseProps = {
teamId: 'team1',
teams: [
{id: 'team1', displayName: 'Team 1'},
{id: 'team2', displayName: 'Team 2'},
] as TeamModel[],
crossTeamSearchEnabled: true,
};
let database: Database;
beforeAll(async () => {
const server = await TestHelper.setupServerDatabase();
database = server.database;
});
beforeEach(() => {
jest.clearAllMocks();
});
it('renders search screen correctly', () => {
const {getByTestId, getByText, getByPlaceholderText} = renderWithEverything(
<SearchScreen {...baseProps}/>,
{database},
);
expect(getByTestId('search_messages.screen')).toBeTruthy();
// The page title
expect(getByText('Search')).toBeTruthy();
// The search input with the expected placeholder
expect(getByPlaceholderText('Search messages & files')).toBeTruthy();
});
it('handles search input changes', () => {
const {getByTestId} = renderWithEverything(
<SearchScreen {...baseProps}/>,
{database},
);
const searchInput = getByTestId('navigation.header.search_bar.search.input');
act(() => {
fireEvent.changeText(searchInput, 'test search');
});
expect(searchInput.props.value).toBe('test search');
});
it('performs search when submitting', async () => {
const {getByTestId} = renderWithEverything(
<SearchScreen {...baseProps}/>,
{database},
);
const searchInput = getByTestId('navigation.header.search_bar.search.input');
await act(async () => {
fireEvent.changeText(searchInput, 'test search');
});
await act(async () => {
fireEvent(searchInput, 'submitEditing');
});
await waitFor(() => {
expect(searchPosts).toHaveBeenCalledWith(
expect.any(String),
'team1',
expect.objectContaining({terms: 'test search'}),
);
expect(searchFiles).toHaveBeenCalledWith(
expect.any(String),
'team1',
expect.objectContaining({terms: 'test search'}),
);
});
});
it('handles team changes', async () => {
const {getByTestId} = renderWithEverything(
<SearchScreen {...baseProps}/>,
{database},
);
const teamPicker = getByTestId('team_picker.button');
act(() => {
fireEvent.press(teamPicker);
});
expect(teamPicker).toBeTruthy();
expect(bottomSheet).toHaveBeenCalled();
});
it('clears search when clear button is pressed', async () => {
const {getByTestId} = renderWithEverything(
<SearchScreen {...baseProps}/>,
{database},
);
const searchInput = getByTestId('navigation.header.search_bar.search.input');
act(() => {
fireEvent.changeText(searchInput, 'test search');
});
const clearButton = getByTestId('navigation.header.search_bar.search.clear.button');
act(() => {
fireEvent.press(clearButton);
});
expect(searchInput.props.value).toBe('');
});
it('adds search to team history when searching in a specific team', async () => {
const {getByTestId} = renderWithEverything(
<SearchScreen {...baseProps}/>,
{database},
);
const searchInput = getByTestId('navigation.header.search_bar.search.input');
await act(async () => {
fireEvent.changeText(searchInput, 'test search');
});
await act(async () => {
fireEvent(searchInput, 'submitEditing');
});
await waitFor(() => {
expect(addSearchToTeamSearchHistory).toHaveBeenCalledWith(
expect.any(String),
'team1',
'test search',
);
});
});
it('initializes with correct tabs configuration', () => {
renderWithEverything(
<SearchScreen {...baseProps}/>,
{database},
);
expect(useTabs).toHaveBeenCalledWith(
'MESSAGES',
[
expect.objectContaining({id: 'MESSAGES', name: expect.objectContaining({defaultMessage: 'Messages'})}),
expect.objectContaining({id: 'FILES', name: expect.objectContaining({defaultMessage: 'Files'})}),
],
undefined,
expect.any(String),
);
});
});