import { beforeEach, describe, expect, it } from 'vitest'; import { act, screen, waitFor } from '@testing-library/react'; import { installFetch, installGatewaySocket, json, makeReadySnapshot, makeUser, renderApp, resetStores, type FetchRoute, } from './helpers'; /** * Шапка комнаты показывает статус комнаты — описание рядом с названием * (AGENT.md 7.5, 11.6): раньше описание жило только в настройках, и проверить * «статус комнаты в шапке» было нечем. */ const user = makeUser(); /** Текущий список комнат: его перечитывает клиент по CHANNEL_UPDATE. */ let channels: Record[] = []; function routes(): FetchRoute[] { return [ { match: '/api/v1/users/@me/guilds', response: () => json({ guilds: [] }) }, { match: '/api/v1/users/@me', response: () => json({ user }) }, { match: '/api/v1/instance', response: () => json({ instance: { name: 'glchat-test' } }) }, { match: '/api/v1/guilds/g-1/members', response: () => json({ members: [] }), }, { match: '/api/v1/guilds/g-1/roles', response: () => json({ roles: [] }) }, { match: '/api/v1/guilds/g-1/channels', response: () => json({ channels }) }, { match: '/api/v1/guilds/g-1', response: () => json({ guild: { id: 'g-1', name: 'Сервер', owner_id: 'user-1' } }), }, { match: '/api/v1/channels/c-1/messages', response: () => json({ messages: [] }) }, ]; } /** Поднимает приложение на комнате `c-1` с заданными полями комнаты. */ async function boot(channel: Record) { channels = [{ id: 'c-1', name: 'общий', type: 'text', position: 0, ...channel }]; const snapshot = makeReadySnapshot([ { id: 'g-1', name: 'Сервер', is_main: true, owner_id: 'user-1', my_permissions: ['MANAGE_CHANNELS', 'SEND_MESSAGES'], channels: [channel as { id: string; name: string }], }, ]); installFetch(routes()); const gateway = installGatewaySocket(snapshot); renderApp('/app/g-1/c-1'); await gateway.greet(); await screen.findByTestId('guild-rail'); return { gateway }; } beforeEach(() => { resetStores(); }); describe('статус комнаты в шапке', () => { it('показывает описание комнаты из снапшота', async () => { await boot({ id: 'c-1', name: 'общий', description: 'Статус комнаты' }); const header = await screen.findByTestId('channel-header'); const description = await screen.findByTestId('channel-description'); expect(description).toHaveTextContent('Статус комнаты'); expect(description.getAttribute('title')).toBe('Статус комнаты'); expect(header).toHaveTextContent('общий'); }); it('не показывает статус у комнаты без описания', async () => { await boot({ id: 'c-1', name: 'общий' }); await screen.findByTestId('channel-header'); expect(screen.queryByTestId('channel-description')).toBeNull(); }); it('обновляет статус по CHANNEL_UPDATE без перезагрузки', async () => { const { gateway } = await boot({ id: 'c-1', name: 'общий', description: 'Старый статус' }); await screen.findByTestId('channel-description'); // Сервер перечитал комнаты: клиент по событию запрашивает список заново. channels = [ { id: 'c-1', name: 'общий', type: 'text', position: 0, description: 'Новый статус' }, ]; act(() => { gateway.dispatch('CHANNEL_UPDATE', { id: 'c-1', guild_id: 'g-1', name: 'общий', type: 'text', description: 'Новый статус', }); }); await waitFor(() => { expect(screen.getByTestId('channel-description')).toHaveTextContent('Новый статус'); }); }); });