fix(web): права в шапке сервера обновляются после выдачи роли

По MEMBER_UPDATE/ROLE_* клиент перечитывал участников, роли и комнаты, но
не сводку сервера: `my_permissions` в сторе сессии оставались прежними, и
кнопки управления (🔗 приглашение, ⚙ настройки, + комната) появлялись
только после перезагрузки. Матрица 11.6 требует, чтобы права сразу меняли
доступные действия (AGENT.md 11.6).

- в ветках `MEMBER_UPDATE`/`MEMBER_REMOVE` и `ROLE_*` вызывается
  `addGuildFromRest` — сводка сервера перечитывается и мержится;
- vitest: кнопки появляются по событию (тест падает без правки).
This commit is contained in:
2026-09-26 11:06:32 +03:00
parent 70eae99873
commit cf36488e6f
2 changed files with 42 additions and 1 deletions
+5
View File
@@ -295,6 +295,9 @@ export function dispatchGatewayEvent(event: GatewayDispatch): void {
if (guildId !== null) {
void invalidateMembershipQueries(guildId);
session.scheduleGuildChannelsReload(guildId);
// Свои права после выдачи роли обновляет только сводка сервера: без
// неё кнопки управления в шапке появлялись лишь после перезагрузки.
void addGuildFromRest(guildId);
}
return;
}
@@ -305,6 +308,8 @@ export function dispatchGatewayEvent(event: GatewayDispatch): void {
if (role !== null) {
void invalidateMembershipQueries(role.guild_id);
session.scheduleGuildChannelsReload(role.guild_id);
// Права роли могли измениться и у меня: обновляем сводку сервера.
void addGuildFromRest(role.guild_id);
}
return;
}
+37 -1
View File
@@ -33,6 +33,12 @@ const user = makeUser();
const channels = [{ id: 'c-general', name: 'общий', type: 'text' as const, position: 0 }];
/**
* Права, которые отдаёт REST-сводка сервера: тест выдачи роли меняет их и
* проверяет, что клиент перечитал сводку по событию MEMBER_UPDATE.
*/
let restPermissions: string[] | null = null;
function guildSummary(overrides: Record<string, unknown> = {}) {
return {
id: 'g-1',
@@ -79,7 +85,17 @@ function routes(guild: Record<string, unknown> = guildDetail()): FetchRoute[] {
method: 'POST',
response: () => json({ guild: guildDetail({ icon_file_id: '777', banner_file_id: '555' }) }),
},
{ match: '/api/v1/users/@me/guilds', response: () => json({ guilds: [guildSummary(guild)] }) },
{
match: '/api/v1/users/@me/guilds',
response: () =>
json({
guilds: [
guildSummary(
restPermissions === null ? guild : { ...guild, my_permissions: restPermissions },
),
],
}),
},
{ 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: [] }) },
@@ -122,6 +138,7 @@ async function bootApp(guild: Record<string, unknown> = guildDetail()) {
beforeEach(() => {
resetStores();
restPermissions = null;
});
describe('оформление сервера в шапке и рейке', () => {
@@ -217,6 +234,25 @@ describe('приглашение из шапки сервера', () => {
await screen.findByTestId('guild-header');
expect(screen.queryByTestId('guild-invite')).toBeNull();
});
it('появляет кнопки после выдачи роли, без перезагрузки', async () => {
// Роль выдали уже в открытом клиенте: сводка сервера перечитывается по
// MEMBER_UPDATE, иначе кнопки управления ждали бы перезагрузки (AGENT.md 11.6).
const { gateway } = await bootApp(guildDetail({ my_permissions: [], owner_id: 'user-9' }));
await screen.findByTestId('guild-header');
expect(screen.queryByTestId('guild-invite')).toBeNull();
restPermissions = ['MANAGE_GUILD', 'CREATE_INVITES'];
act(() => {
gateway.dispatch('MEMBER_UPDATE', { guild_id: 'g-1', user_id: 'user-1' });
});
await waitFor(() => {
expect(screen.getByTestId('guild-invite')).toBeInTheDocument();
});
expect(screen.getByLabelText('Настройки сервера')).toBeInTheDocument();
expect(screen.getByLabelText('Создать комнату')).toBeInTheDocument();
});
});
describe('встроенные звуки интерфейса', () => {