feat(guilds): встроенные шаблоны серверов
- каталог шаблонов «Пустой», «Сообщество», «Игровой» (AGENT.md 7.3): роли, категории, текстовые и голосовые комнаты без сообщений - POST /guilds принимает template_id, неизвестный шаблон отклоняется; аудит фиксирует выбранный шаблон - GET /guild-templates отдаёт каталог с предпросмотром структуры - клиент: выбор шаблона в окне создания сервера - тесты: Go (структура каждого шаблона) и Vitest (выбор шаблона)
This commit is contained in:
@@ -322,3 +322,64 @@ describe('оформление «для друзей»', () => {
|
||||
expect(within(row).getByTestId('nick-name')).toHaveStyle({ color: '#2ecc71' });
|
||||
});
|
||||
});
|
||||
|
||||
describe('шаблоны серверов', () => {
|
||||
it('создаёт сервер по выбранному шаблону', async () => {
|
||||
const templates = [
|
||||
{
|
||||
id: 'empty',
|
||||
name: 'Пустой',
|
||||
description: 'Одна общая текстовая комната.',
|
||||
roles: ['Администратор', 'Пользователь'],
|
||||
text_channels: 1,
|
||||
voice_channels: 0,
|
||||
categories: [],
|
||||
},
|
||||
{
|
||||
id: 'gaming',
|
||||
name: 'Игровой',
|
||||
description: 'Текстовые комнаты и две голосовые.',
|
||||
roles: ['Администратор', 'Пользователь', 'Игрок'],
|
||||
text_channels: 2,
|
||||
voice_channels: 2,
|
||||
categories: ['Текстовые', 'Голосовые'],
|
||||
},
|
||||
];
|
||||
const fetchMock = installFetch([
|
||||
{ match: '/api/v1/guild-templates', response: () => json({ templates }) },
|
||||
{
|
||||
match: '/api/v1/guilds',
|
||||
method: 'POST',
|
||||
response: () =>
|
||||
json({
|
||||
guild: {
|
||||
id: 'g-new',
|
||||
name: 'Новый',
|
||||
owner_id: 'user-1',
|
||||
is_main: false,
|
||||
member_count: 1,
|
||||
my_role_ids: [],
|
||||
my_permissions: ['ADMINISTRATOR'],
|
||||
},
|
||||
}),
|
||||
},
|
||||
{ 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' } }) },
|
||||
]);
|
||||
renderApp('/app');
|
||||
await userEvent.click(await screen.findByLabelText('Создать сервер'));
|
||||
|
||||
const picker = await screen.findByTestId('guild-templates');
|
||||
await userEvent.click(within(picker).getByTestId('guild-template-gaming'));
|
||||
await userEvent.type(screen.getByLabelText('Название сервера'), 'Новый');
|
||||
await userEvent.click(screen.getByRole('button', { name: 'Создать' }));
|
||||
|
||||
await waitFor(() => {
|
||||
expect(bodyOf(findRequest(fetchMock, { url: '/guilds', method: 'POST' }))).toMatchObject({
|
||||
name: 'Новый',
|
||||
template_id: 'gaming',
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -337,6 +337,7 @@ describe('основной экран', () => {
|
||||
const createCall = recordedRequests(fetchMock).find(
|
||||
(request) => request.url.endsWith('/api/v1/guilds') && request.method === 'POST',
|
||||
);
|
||||
expect(createCall?.body).toEqual({ name: 'Новый' });
|
||||
// Шаблон по умолчанию — «Пустой»: структура комнат и ролей (AGENT.md 7.3).
|
||||
expect(createCall?.body).toEqual({ name: 'Новый', template_id: 'empty' });
|
||||
});
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user