5180 fichiers 38.5 Mo 0 téléchargements 377 vues mis à jour il y a 7 heures ui
nitro-v36-with-renderer-v36 / src / components / housekeeping / views / shell / HousekeepingGlobalSearch.test.tsx
HousekeepingGlobalSearch.test.tsx 5.5 Ko Télécharger le fichier
/* @vitest-environment jsdom */

import { cleanup, fireEvent, render, screen } from '@testing-library/react';
import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest';
import { HousekeepingGlobalSearch } from './HousekeepingGlobalSearch';

const mocks = vi.hoisted(() => ({
    store: {
        userSuggestions: [] as { id: number; username: string; online: boolean }[],
        roomSuggestions: [] as { id: number; name: string; ownerName: string }[],
        recentLookups: [] as { kind: 'user' | 'room'; id: number; label: string }[],
        requestUserSuggestions: vi.fn(),
        requestRoomSuggestions: vi.fn(),
        lookupUserById: vi.fn(),
        lookupRoomById: vi.fn(),
        setActiveTab: vi.fn()
    }
}));

vi.mock('../../../../api', async () => {
    const search = await vi.importActual<typeof import('../../../../api/housekeeping/HousekeepingSearch')>('../../../../api/housekeeping/HousekeepingSearch');
    const texts: Record<string, string> = {
        'housekeeping.search.placeholder': 'Search users and rooms',
        'housekeeping.search.no_results': 'Nothing found',
        'housekeeping.search.open_user': 'Open user #%id%',
        'housekeeping.search.open_room': 'Open room #%id%',
        'housekeeping.user.recent': 'Recent'
    };

    return {
        HousekeepingTabId: { USERS: 'users', ROOMS: 'rooms' },
        parseHousekeepingSearch: search.parseHousekeepingSearch,
        LocalizeText: (key: string, params: string[] = [], values: string[] = []) =>
            params.reduce((text, name, index) => text.replace(`%${name}%`, values[index]), texts[key] ?? key)
    };
});

vi.mock('../../../../hooks', () => ({ useHousekeepingStore: () => mocks.store }));

const renderSearch = () => render(<HousekeepingGlobalSearch />);

const input = () => screen.getByRole('combobox', { name: 'Search users and rooms' }) as HTMLInputElement;

const type = (value: string) => {
    fireEvent.focus(input());
    fireEvent.change(input(), { target: { value } });
};

describe('HousekeepingGlobalSearch', () => {
    beforeEach(() => {
        Object.values(mocks.store).forEach((value) => typeof value === 'function' && (value as ReturnType<typeof vi.fn>).mockClear());
        mocks.store.userSuggestions = [{ id: 7, username: 'Alice', online: true }];
        mocks.store.roomSuggestions = [{ id: 411, name: 'Alice lounge', ownerName: 'Bob' }];
        mocks.store.recentLookups = [{ kind: 'room', id: 12, label: 'Pool' }];
    });
    afterEach(() => cleanup());

    it('lists the recent lookups under a header when the box is focused empty', () => {
        renderSearch();
        fireEvent.focus(input());

        expect(screen.getByText('Recent')).toBeInTheDocument();
        expect(screen.getByRole('option', { name: /Pool/ })).toBeInTheDocument();
    });

    it('searches users and rooms for a name and lists both', () => {
        renderSearch();
        type('Ali');

        expect(mocks.store.requestUserSuggestions).toHaveBeenLastCalledWith('Ali');
        expect(mocks.store.requestRoomSuggestions).toHaveBeenLastCalledWith('Ali');
        expect(screen.getAllByRole('option').map((option) => option.textContent)).toEqual(['Alice#7', 'Alice loungeBob']);
    });

    it('opens the highlighted row with Enter and clears the box', () => {
        renderSearch();
        type('Ali');
        fireEvent.keyDown(input(), { key: 'Enter' });

        expect(mocks.store.setActiveTab).toHaveBeenCalledWith('users');
        expect(mocks.store.lookupUserById).toHaveBeenCalledWith(7);
        expect(input().value).toBe('');
        expect(screen.queryByRole('option')).toBeNull();
    });

    it('moves the highlight with the arrow keys before Enter', () => {
        renderSearch();
        type('Ali');
        fireEvent.keyDown(input(), { key: 'ArrowDown' });
        fireEvent.keyDown(input(), { key: 'Enter' });

        expect(mocks.store.setActiveTab).toHaveBeenCalledWith('rooms');
        expect(mocks.store.lookupRoomById).toHaveBeenCalledWith(411);
    });

    it('opens a row on click without writing its label into the box', () => {
        renderSearch();
        type('Ali');
        fireEvent.click(screen.getByRole('option', { name: /Alice lounge/ }));

        expect(mocks.store.lookupRoomById).toHaveBeenCalledWith(411);
        expect(input().value).toBe('');
    });

    it('opens a user or a room by typed id', () => {
        renderSearch();
        type('#12');
        expect(screen.getByRole('option', { name: 'Open user #12' })).toBeInTheDocument();
        fireEvent.keyDown(input(), { key: 'Enter' });
        expect(mocks.store.lookupUserById).toHaveBeenCalledWith(12);

        type('s:411');
        fireEvent.keyDown(input(), { key: 'Enter' });
        expect(mocks.store.lookupRoomById).toHaveBeenCalledWith(411);
    });

    it('says so when a name finds nothing', () => {
        renderSearch();
        mocks.store.userSuggestions = [];
        mocks.store.roomSuggestions = [];
        type('zzz');

        expect(screen.getByText('Nothing found')).toBeInTheDocument();
    });

    it('closes the list on Escape and on an outside press', () => {
        renderSearch();
        type('Ali');
        expect(screen.getAllByRole('option')).toHaveLength(2);

        fireEvent.keyDown(input(), { key: 'Escape' });
        expect(screen.queryByRole('option')).toBeNull();

        type('Alic');
        expect(screen.getAllByRole('option')).toHaveLength(2);

        fireEvent.pointerDown(document.body);
        fireEvent.mouseDown(document.body);
        fireEvent.click(document.body);
        expect(screen.queryByRole('option')).toBeNull();
    });
});
15Sujets
1Dépôts
20Membres
3En ligne
Profile
Inscrit
Dernière visite
Messages
0
Votes positifs
0
Votes négatifs
0

Nous utilisons des cookies pour assurer le bon fonctionnement du site et améliorer votre expérience. en savoir plus

Autoriser