mirror of
https://github.com/fluxerapp/fluxer
synced 2026-10-07 19:22:14 +09:00
fix(channel): sync a cleared group DM name without a reload (#2882)
This commit is contained in:
@@ -150,7 +150,7 @@ function serializeGroupDMChannel(channel: Channel): ChannelResponse {
|
||||
return {
|
||||
...serializeBaseChannelFields(channel),
|
||||
...serializeMessageableFields(channel),
|
||||
name: channel.name ?? undefined,
|
||||
name: channel.name ?? null,
|
||||
icon: channel.iconHash ?? null,
|
||||
owner_id: channel.ownerId ? channel.ownerId.toString() : null,
|
||||
nicks: nicknameMap.size > 0 ? nicks : undefined,
|
||||
|
||||
@@ -0,0 +1,62 @@
|
||||
// SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
|
||||
import {createTestAccount} from '@app/api/auth/tests/AuthTestUtils';
|
||||
import {createFriendship, createGroupDmChannel, getChannel} from '@app/api/channel/tests/ChannelTestUtils';
|
||||
import {ensureSessionStarted} from '@app/api/message/tests/MessageTestUtils';
|
||||
import {type ApiTestHarness, createApiTestHarness} from '@app/api/test/ApiTestHarness';
|
||||
import {NoopGatewayService} from '@app/api/test/NoopGatewayService';
|
||||
import {HTTP_STATUS} from '@app/api/test/TestConstants';
|
||||
import {createBuilder} from '@app/api/test/TestRequestBuilder';
|
||||
import type {ChannelResponse} from '@fluxer/schema/src/domains/channel/ChannelSchemas';
|
||||
import {afterAll, beforeAll, beforeEach, describe, expect, it, vi} from 'vitest';
|
||||
|
||||
describe('Group DM name clear', () => {
|
||||
let harness: ApiTestHarness;
|
||||
beforeAll(async () => {
|
||||
harness = await createApiTestHarness();
|
||||
});
|
||||
beforeEach(async () => {
|
||||
await harness.reset();
|
||||
});
|
||||
afterAll(async () => {
|
||||
await harness?.shutdown();
|
||||
});
|
||||
it.each([
|
||||
['an empty string', ''],
|
||||
['null', null],
|
||||
])('sends a null name to every recipient when cleared with %s', async (_label, clearedName) => {
|
||||
const user1 = await createTestAccount(harness);
|
||||
const user2 = await createTestAccount(harness);
|
||||
const user3 = await createTestAccount(harness);
|
||||
await ensureSessionStarted(harness, user1.token);
|
||||
await ensureSessionStarted(harness, user2.token);
|
||||
await ensureSessionStarted(harness, user3.token);
|
||||
await createFriendship(harness, user1, user2);
|
||||
await createFriendship(harness, user1, user3);
|
||||
const groupDm = await createGroupDmChannel(harness, user1.token, [user2.userId, user3.userId]);
|
||||
await createBuilder<ChannelResponse>(harness, user1.token)
|
||||
.patch(`/channels/${groupDm.id}`)
|
||||
.body({name: 'Weekend plans'})
|
||||
.expect(HTTP_STATUS.OK)
|
||||
.execute();
|
||||
const dispatchSpy = vi.spyOn(NoopGatewayService.prototype, 'dispatchPresence');
|
||||
try {
|
||||
const cleared = await createBuilder<ChannelResponse>(harness, user1.token)
|
||||
.patch(`/channels/${groupDm.id}`)
|
||||
.body({name: clearedName})
|
||||
.expect(HTTP_STATUS.OK)
|
||||
.execute();
|
||||
expect(cleared).toHaveProperty('name', null);
|
||||
const channelUpdates = dispatchSpy.mock.calls.filter(([params]) => params.event === 'CHANNEL_UPDATE');
|
||||
expect(channelUpdates.map(([params]) => params.userId.toString()).sort()).toEqual(
|
||||
[user1.userId, user2.userId, user3.userId].sort(),
|
||||
);
|
||||
for (const [params] of channelUpdates) {
|
||||
expect(params.data).toHaveProperty('name', null);
|
||||
}
|
||||
} finally {
|
||||
dispatchSpy.mockRestore();
|
||||
}
|
||||
expect(await getChannel(harness, user2.token, groupDm.id)).toHaveProperty('name', null);
|
||||
});
|
||||
});
|
||||
@@ -24224,7 +24224,7 @@
|
||||
"description": "The ID of the guild this channel belongs to",
|
||||
"$ref": "#/components/schemas/SnowflakeStringType"
|
||||
},
|
||||
"name": {"description": "The name of the channel", "type": "string"},
|
||||
"name": {"description": "The name of the channel", "type": ["string", "null"]},
|
||||
"topic": {"description": "The topic of the channel", "type": ["string", "null"]},
|
||||
"url": {
|
||||
"description": "The URL associated with the channel",
|
||||
|
||||
@@ -87,7 +87,7 @@ export class Channel {
|
||||
this.instanceId = options?.instanceId ?? RuntimeConfig.localInstanceDomain;
|
||||
this.id = channel.id;
|
||||
this.guildId = channel.guild_id;
|
||||
this.name = channel.name;
|
||||
this.name = channel.name ?? undefined;
|
||||
noteText(this.name);
|
||||
this.topic = channel.topic ?? null;
|
||||
this.url = channel.url ?? null;
|
||||
@@ -223,7 +223,7 @@ export class Channel {
|
||||
{
|
||||
id: this.id,
|
||||
guild_id: updates.guild_id ?? this.guildId,
|
||||
name: updates.name ?? this.name,
|
||||
name: updates.name !== undefined ? updates.name : this.name,
|
||||
topic: updates.topic !== undefined ? updates.topic : this.topic,
|
||||
url: updates.url !== undefined ? updates.url : this.url,
|
||||
icon: updates.icon !== undefined ? updates.icon : this.icon,
|
||||
|
||||
@@ -50,7 +50,7 @@ export type CallEligibilityResponse = z.infer<typeof CallEligibilityResponse>;
|
||||
export const ChannelResponse = z.object({
|
||||
id: SnowflakeStringType.describe('The unique identifier (snowflake) for this channel'),
|
||||
guild_id: SnowflakeStringType.optional().describe('The ID of the guild this channel belongs to'),
|
||||
name: z.string().optional().describe('The name of the channel'),
|
||||
name: z.string().nullish().describe('The name of the channel'),
|
||||
topic: z.string().nullish().describe('The topic of the channel'),
|
||||
url: z.url().nullish().describe('The URL associated with the channel'),
|
||||
icon: z.string().nullish().describe('The icon hash of the channel (for group DMs)'),
|
||||
@@ -141,7 +141,7 @@ export interface ChannelOverwrite {
|
||||
export interface Channel {
|
||||
readonly id: string;
|
||||
readonly guild_id?: string;
|
||||
readonly name?: string;
|
||||
readonly name?: string | null;
|
||||
readonly topic?: string | null;
|
||||
readonly url?: string | null;
|
||||
readonly icon?: string | null;
|
||||
|
||||
Reference in New Issue
Block a user