chore(repo): remove dead code and useless tests (#3375)

This commit is contained in:
Hampus authored and GitHub committed 2026-10-10 21:43:29 +02:00
1 parent 7e177a1c90
commit 1cd62eb661
1391 files changed
+783 -120415

No files matched your search

@@ -1,29 +0,0 @@
// SPDX-License-Identifier: AGPL-3.0-or-later
import {
CaptchaConfigSchema,
CaptchaConfigUpdateRequest,
DEFAULT_CAPTCHA_CONFIG,
} from '@fluxer/schema/src/domains/admin/CaptchaSchemas';
import {describe, expect, test} from 'vitest';
describe('captcha configuration', () => {
test('defaults to enabled at the mobile-friendly difficulty', () => {
expect(CaptchaConfigSchema.parse({})).toEqual({enabled: true, cost: 5000, max_counter: 1000});
expect(DEFAULT_CAPTCHA_CONFIG).toEqual({enabled: true, cost: 5000, max_counter: 1000});
});
test('rejects difficulty outside the supported range', () => {
expect(CaptchaConfigUpdateRequest.safeParse({cost: 999}).success).toBe(false);
expect(CaptchaConfigUpdateRequest.safeParse({cost: 20001}).success).toBe(false);
expect(CaptchaConfigUpdateRequest.safeParse({max_counter: 99}).success).toBe(false);
expect(CaptchaConfigUpdateRequest.safeParse({max_counter: 20001}).success).toBe(false);
expect(CaptchaConfigSchema.safeParse({cost: 20001}).success).toBe(false);
});
test('keeps a partial update partial without filling defaults', () => {
expect(CaptchaConfigUpdateRequest.parse({})).toEqual({});
expect(CaptchaConfigUpdateRequest.parse({enabled: false})).toEqual({enabled: false});
expect(CaptchaConfigUpdateRequest.parse({cost: 1000, max_counter: 100})).toEqual({cost: 1000, max_counter: 100});
});
});
@@ -1,54 +0,0 @@
// SPDX-License-Identifier: AGPL-3.0-or-later
import {AuditLogActionType} from '@fluxer/constants/src/AuditLogActionType';
import {GuildAuditLogEntryResponse} from '@fluxer/schema/src/domains/guild/GuildAuditLogSchemas';
import {describe, expect, it} from 'vitest';
function entryWith(fields: Record<string, unknown>): Record<string, unknown> {
return {
id: '1420000000000000100',
action_type: AuditLogActionType.MEMBER_BAN_ADD,
user_id: '1420000000000000001',
target_id: '1420000000000000002',
...fields,
};
}
describe('GuildAuditLogEntryResponse', () => {
it('parses delete_message_seconds as a number', () => {
const parsed = GuildAuditLogEntryResponse.parse(entryWith({options: {delete_message_seconds: 3600}}));
expect(parsed.options).toEqual({delete_message_seconds: 3600});
});
it('rejects delete_message_seconds sent as a string', () => {
const result = GuildAuditLogEntryResponse.safeParse(entryWith({options: {delete_message_seconds: '3600'}}));
expect(result.success).toBe(false);
});
it('parses the legacy delete_member_days string', () => {
const parsed = GuildAuditLogEntryResponse.parse(entryWith({options: {delete_member_days: '7'}}));
expect(parsed.options).toEqual({delete_member_days: '7'});
});
it('parses a permissions_diff change value', () => {
const changes = [
{key: 'permissions', old_value: '1024', new_value: '3072'},
{key: 'permissions_diff', new_value: {added: ['SEND_MESSAGES'], removed: []}},
];
const parsed = GuildAuditLogEntryResponse.parse(
entryWith({action_type: AuditLogActionType.ROLE_UPDATE, options: {role_name: 'Moderators'}, changes}),
);
expect(parsed.changes).toEqual(changes);
expect(parsed.options).toEqual({role_name: 'Moderators'});
});
it('strips unknown option keys', () => {
const parsed = GuildAuditLogEntryResponse.parse(
entryWith({
action_type: AuditLogActionType.MEMBER_UPDATE,
options: {channel_id: '1420000000000000003', timeout_reason: 'raw', future_option: 1},
}),
);
expect(parsed.options).toEqual({channel_id: '1420000000000000003'});
});
});
@@ -1,235 +0,0 @@
// SPDX-License-Identifier: AGPL-3.0-or-later
import {
ReportFlowMessageSubmissionRequest,
ReportFlowQuery,
ReportFlowResponse,
ReportFlowUserSubmissionRequest,
} from '@fluxer/schema/src/domains/report/ReportFlowSchemas';
import {describe, expect, it} from 'vitest';
const userFlowResponse = {
target_type: 'user',
surface: 'in_app',
revision_hash: '9c41d2a07e5b18f3',
locale: 'en-US',
start_screen_id: 'profile_intro',
guidelines_url: 'https://fluxer.app/guidelines',
screens: [
{
id: 'profile_intro',
title: 'Report profile',
subtitle: "Tell us what's wrong with this profile. They won't be told who reported them.",
urgent: false,
options: [
{
id: 'learn_more',
label: 'Read the Fluxer Community Guidelines',
outcome: {
type: 'link',
screen_id: null,
reason: null,
notice_id: null,
url: 'https://fluxer.app/guidelines',
},
},
],
options_heading: 'Learn more',
checklist: null,
next_screen_id: 'profile_parts',
},
{
id: 'profile_parts',
title: 'Which parts of their profile are a problem?',
subtitle: 'Pick as many as you need.',
urgent: false,
options: [],
options_heading: null,
checklist: {
items: [
{id: 'photo', label: 'Pictures', description: 'What they use as avatar and banner'},
{id: 'name', label: 'Names', description: 'Username, display name or community nickname'},
{id: 'descriptors', label: 'Profile text', description: 'Bio, custom status or pronouns'},
],
min_checked: 1,
outcome: {type: 'screen', screen_id: 'root_user', reason: null, notice_id: null, url: null},
},
next_screen_id: null,
},
],
notices: [
{
id: 'need_more_info',
title: "We can't act on this yet",
body: "To review this, we need a message where they say how old they are or make it clear they're under Fluxer's minimum age. Report that message instead.",
},
],
};
const messageSubmission = {
channel_id: '1427410010101010101',
message_id: '1427410099999999999',
revision_hash: '6b1f0c9e2a7d4413',
locale: 'de',
steps: [
{screen_id: 'root_message', option_id: 'abuse'},
{screen_id: 'abuse', option_id: 'sexual'},
{screen_id: 'sexual', option_id: 'minor_sexual'},
{screen_id: 'minor_sexual', option_id: 'csam'},
],
};
const userSubmission = {
user_id: '1427410010101010102',
guild_id: '1427410010101010103',
revision_hash: '9c41d2a07e5b18f3',
locale: 'en-US',
steps: [
{screen_id: 'profile_intro'},
{screen_id: 'profile_parts', item_ids: ['photo']},
{screen_id: 'root_user', option_id: 'abuse'},
{screen_id: 'profile_abuse', option_id: 'harassment'},
],
};
describe('ReportFlowResponse', () => {
it('parses the user flow example', () => {
expect(ReportFlowResponse.parse(userFlowResponse)).toEqual(userFlowResponse);
});
it('accepts reasons and locales it does not know', () => {
const response = {
...userFlowResponse,
locale: 'tlh-Latn',
screens: [
{
...userFlowResponse.screens[0],
options: [
{
id: 'future_option',
label: 'A future option',
outcome: {type: 'submit', screen_id: null, reason: 'reason_added_later', notice_id: null, url: null},
},
],
},
],
};
expect(ReportFlowResponse.safeParse(response).success).toBe(true);
});
it('rejects an unknown outcome type', () => {
const response = {
...userFlowResponse,
screens: [
{
...userFlowResponse.screens[0],
options: [
{
id: 'x',
label: 'X',
outcome: {type: 'redirect', screen_id: null, reason: null, notice_id: null, url: null},
},
],
},
],
};
expect(ReportFlowResponse.safeParse(response).success).toBe(false);
});
});
describe('ReportFlowQuery', () => {
it('defaults the surface to in_app', () => {
expect(ReportFlowQuery.parse({})).toEqual({surface: 'in_app'});
});
it('accepts any locale tag up to 35 characters', () => {
expect(ReportFlowQuery.parse({surface: 'dsa', locale: 'xx-YY'})).toEqual({surface: 'dsa', locale: 'xx-YY'});
expect(ReportFlowQuery.safeParse({locale: 'a'.repeat(36)}).success).toBe(false);
});
it('rejects an unknown surface', () => {
expect(ReportFlowQuery.safeParse({surface: 'nope'}).success).toBe(false);
});
});
describe('ReportFlowMessageSubmissionRequest', () => {
it('parses the message submission example', () => {
const parsed = ReportFlowMessageSubmissionRequest.parse(messageSubmission);
expect(parsed.steps).toEqual(messageSubmission.steps);
expect(parsed.revision_hash).toBe('6b1f0c9e2a7d4413');
expect(parsed.locale).toBe('de');
});
it('accepts a checklist step and an unknown locale string', () => {
const body = {
...messageSubmission,
locale: 'zz-Unknown',
steps: [
{screen_id: 'root_message', option_id: 'private_info'},
{screen_id: 'private_info', item_ids: ['email', 'phone']},
],
};
expect(ReportFlowMessageSubmissionRequest.safeParse(body).success).toBe(true);
});
it('accepts 16 steps and rejects 17', () => {
const step = {screen_id: 'root_message', option_id: 'abuse'};
const sixteen = {...messageSubmission, steps: Array.from({length: 16}, () => step)};
const seventeen = {...messageSubmission, steps: Array.from({length: 17}, () => step)};
expect(ReportFlowMessageSubmissionRequest.safeParse(sixteen).success).toBe(true);
expect(ReportFlowMessageSubmissionRequest.safeParse(seventeen).success).toBe(false);
});
it('rejects an empty walk', () => {
expect(ReportFlowMessageSubmissionRequest.safeParse({...messageSubmission, steps: []}).success).toBe(false);
});
it('accepts 32 item ids and rejects 33 or none', () => {
const items = (count: number) => Array.from({length: count}, (_, index) => `item_${index}`);
const body = (itemIds: Array<string>) => ({
...messageSubmission,
steps: [{screen_id: 'private_info', item_ids: itemIds}],
});
expect(ReportFlowMessageSubmissionRequest.safeParse(body(items(32))).success).toBe(true);
expect(ReportFlowMessageSubmissionRequest.safeParse(body(items(33))).success).toBe(false);
expect(ReportFlowMessageSubmissionRequest.safeParse(body([])).success).toBe(false);
});
it('accepts a 48-character id and rejects a 49-character id', () => {
const body = (id: string) => ({...messageSubmission, steps: [{screen_id: id, option_id: 'abuse'}]});
expect(ReportFlowMessageSubmissionRequest.safeParse(body('a'.repeat(48))).success).toBe(true);
expect(ReportFlowMessageSubmissionRequest.safeParse(body('a'.repeat(49))).success).toBe(false);
expect(
ReportFlowMessageSubmissionRequest.safeParse({
...messageSubmission,
steps: [{screen_id: 'root_message', option_id: 'b'.repeat(49)}],
}).success,
).toBe(false);
expect(
ReportFlowMessageSubmissionRequest.safeParse({
...messageSubmission,
steps: [{screen_id: 'private_info', item_ids: ['c'.repeat(49)]}],
}).success,
).toBe(false);
});
it('requires the revision hash and the message ids', () => {
const {revision_hash: _revisionHash, ...withoutHash} = messageSubmission;
const {message_id: _messageId, ...withoutMessage} = messageSubmission;
expect(ReportFlowMessageSubmissionRequest.safeParse(withoutHash).success).toBe(false);
expect(ReportFlowMessageSubmissionRequest.safeParse(withoutMessage).success).toBe(false);
});
});
describe('ReportFlowUserSubmissionRequest', () => {
it('parses the user submission example with info steps', () => {
const parsed = ReportFlowUserSubmissionRequest.parse(userSubmission);
expect(parsed.steps).toEqual(userSubmission.steps);
expect(parsed.locale).toBe('en-US');
});
it('makes the guild and locale optional', () => {
const {guild_id: _guildId, locale: _locale, ...body} = userSubmission;
expect(ReportFlowUserSubmissionRequest.safeParse(body).success).toBe(true);
});
});
@@ -128,17 +128,6 @@ export const RpcRequest = z.discriminatedUnion('type', [
)
.describe('List of subscriptions to delete'),
}),
z.object({
type: z
.literal('send_apns_push')
.describe('Request type for sending an APNs notification through the API HTTP/2 client'),
user_id: SnowflakeType.describe('ID of the user receiving the notification'),
subscription_id: createStringType().describe('ID of the APNs subscription to report back to the gateway'),
device_token: createStringType(1, 4096).describe('APNs device token'),
app_id: createStringType(1, 128).describe('Client app channel or bundle mapping identifier'),
provider_environment: z.enum(['production', 'development']).describe('APNs provider environment'),
payload: z.record(z.string(), z.unknown()).describe('Notification payload built by the gateway'),
}),
z.object({
type: z.literal('get_user_blocked_ids').describe('Request type for fetching blocked user IDs'),
user_ids: z.array(SnowflakeType).max(RPC_USER_BATCH_MAX).describe('IDs of users to fetch blocked lists for'),
@@ -485,17 +474,6 @@ export const RpcResponse = z.discriminatedUnion('type', [
type: z.literal('delete_push_subscriptions').describe('Response type for push subscription deletion'),
data: z.object({success: z.boolean().describe('Whether the deletion was successful')}).describe('Deletion result'),
}),
z.object({
type: z.literal('send_apns_push').describe('Response type for APNs push delivery'),
data: z
.object({
success: z.boolean().describe('Whether APNs accepted the notification'),
should_delete: z.boolean().describe('Whether the gateway should delete this subscription'),
reason: z.string().optional().describe('APNs or local failure reason'),
status_code: z.number().optional().describe('APNs HTTP status code'),
})
.describe('APNs delivery result'),
}),
z.object({
type: z.literal('get_user_blocked_ids').describe('Response type for blocked user IDs'),
data: z.record(SnowflakeStringType, z.array(SnowflakeStringType)).describe('Blocked user IDs keyed by user ID'),
@@ -1,122 +0,0 @@
// SPDX-License-Identifier: AGPL-3.0-or-later
import {ListGuildEmojisResponse, LookupGuildResponse} from '@fluxer/schema/src/domains/admin/AdminSchemas';
import {ListUserRelationshipsResponse} from '@fluxer/schema/src/domains/admin/AdminUserSchemas';
import {describe, expect, it} from 'vitest';
function snowflakeAt(index: number): string {
return String(100000000000000000n + BigInt(index));
}
describe('LookupGuildResponse', () => {
const validGuild = {
id: '123456789012345678',
owner_id: '111111111111111111',
owner_username: 'owner',
owner_global_name: null,
owner_discriminator: '0001',
name: 'Test Guild',
vanity_url_code: null,
icon: null,
banner: null,
splash: null,
embed_splash: null,
features: [],
verification_level: 0,
mfa_level: 0,
nsfw_level: 0,
explicit_content_filter: 0,
default_message_notifications: 0,
afk_channel_id: null,
afk_timeout: 300,
system_channel_id: null,
system_channel_flags: 0,
rules_channel_id: null,
disabled_operations: 0,
member_count: 1,
channels: [],
roles: [],
};
it('accepts more roles than the old response ceiling', () => {
const result = LookupGuildResponse.safeParse({
guild: {
...validGuild,
roles: Array.from({length: 251}, (_, index) => ({
id: snowflakeAt(index),
name: `role-${index}`,
color: 0,
position: index,
permissions: '0',
hoist: false,
mentionable: false,
})),
},
});
expect(result.success).toBe(true);
if (result.success) {
expect(result.data.guild?.roles).toHaveLength(251);
}
});
it('accepts more channels than the old response ceiling', () => {
const result = LookupGuildResponse.safeParse({
guild: {
...validGuild,
channels: Array.from({length: 501}, (_, index) => ({
id: snowflakeAt(index),
name: `channel-${index}`,
type: 0,
position: index,
parent_id: null,
nsfw: false,
url: null,
})),
},
});
expect(result.success).toBe(true);
if (result.success) {
expect(result.data.guild?.channels).toHaveLength(501);
}
});
});
describe('ListGuildEmojisResponse', () => {
it('accepts more emojis than the old response ceiling', () => {
const result = ListGuildEmojisResponse.safeParse({
guild_id: '123456789012345678',
emojis: Array.from({length: 501}, (_, index) => ({
id: snowflakeAt(index),
name: `emoji_${index}`,
animated: false,
creator_id: '111111111111111111',
media_url: 'https://example.com/emoji.png',
})),
});
expect(result.success).toBe(true);
if (result.success) {
expect(result.data.emojis).toHaveLength(501);
}
});
});
describe('ListUserRelationshipsResponse', () => {
it('accepts more friends than the old response ceiling', () => {
const result = ListUserRelationshipsResponse.safeParse({
friends: Array.from({length: 10001}, (_, index) => ({
target_user_id: snowflakeAt(index),
category: 'friend',
nickname: null,
since: null,
target: null,
})),
incoming_requests: [],
outgoing_requests: [],
blocked: [],
});
expect(result.success).toBe(true);
if (result.success) {
expect(result.data.friends).toHaveLength(10001);
}
});
});
@@ -1,132 +0,0 @@
// SPDX-License-Identifier: AGPL-3.0-or-later
import {ChannelTypes, MessageFlags, MessageTypes, WebhookTypes} from '@fluxer/constants/src/ChannelConstants';
import {
ChannelFollowerStatsResponse,
ChannelFollowRequest,
FollowedChannelResponse,
} from '@fluxer/schema/src/domains/channel/ChannelFollowSchemas';
import {ChannelCreateRequest, ChannelUpdateRequest} from '@fluxer/schema/src/domains/channel/ChannelRequestSchemas';
import {MessageResponseSchema} from '@fluxer/schema/src/domains/message/MessageResponseSchemas';
import {
WebhookCreateResponse,
WebhookResponse,
WebhookTokenResponse,
} from '@fluxer/schema/src/domains/webhook/WebhookSchemas';
import {ChannelTypeSchema} from '@fluxer/schema/src/primitives/ChannelValidators';
import {MessageTypeSchema} from '@fluxer/schema/src/primitives/MessageValidators';
import {describe, expect, it} from 'vitest';
const creator = {
id: '100',
username: 'owner',
discriminator: '0001',
global_name: null,
avatar: null,
avatar_color: null,
flags: 0,
mention_flags: 0,
};
const incomingWebhook = {
id: '1',
guild_id: '2',
channel_id: '3',
name: 'Hook',
avatar: null,
type: WebhookTypes.INCOMING,
token: 'secret',
};
describe('announcement channel type', () => {
it('accepts type 5 as a channel type', () => {
expect(ChannelTypeSchema.parse(ChannelTypes.GUILD_ANNOUNCEMENT)).toBe(5);
});
it('creates an announcement channel with the text channel fields', () => {
const parsed = ChannelCreateRequest.parse({
type: ChannelTypes.GUILD_ANNOUNCEMENT,
name: 'news',
topic: 'Updates',
rate_limit_per_user: 10,
});
expect(parsed).toMatchObject({type: 5, name: 'news', topic: 'Updates', rate_limit_per_user: 10, nsfw: false});
});
it('updates an announcement channel through its own variant', () => {
expect(ChannelUpdateRequest.parse({type: ChannelTypes.GUILD_ANNOUNCEMENT, topic: 'New'})).toMatchObject({
type: 5,
topic: 'New',
});
});
});
describe('channel follow add message type', () => {
it('accepts type 12 as a message type', () => {
expect(MessageTypeSchema.parse(MessageTypes.CHANNEL_FOLLOW_ADD)).toBe(12);
});
});
describe('channel follow schemas', () => {
it('parses the target channel of a follow request', () => {
expect(ChannelFollowRequest.parse({webhook_channel_id: '123'})).toEqual({webhook_channel_id: 123n});
expect(ChannelFollowRequest.safeParse({webhook_channel_id: 'abc'}).success).toBe(false);
expect(ChannelFollowRequest.safeParse({}).success).toBe(false);
});
it('describes the followed channel and its webhook', () => {
expect(FollowedChannelResponse.parse({channel_id: '1', webhook_id: '2'})).toEqual({
channel_id: '1',
webhook_id: '2',
});
});
it('reports follower counts as integers', () => {
expect(ChannelFollowerStatsResponse.parse({channel_count: 3, guild_count: 2})).toEqual({
channel_count: 3,
guild_count: 2,
});
expect(ChannelFollowerStatsResponse.safeParse({channel_count: 1.5, guild_count: 1}).success).toBe(false);
});
});
describe('webhook responses', () => {
it('keeps the token required on token responses', () => {
expect(WebhookTokenResponse.parse(incomingWebhook)).toEqual(incomingWebhook);
const {token: _token, ...withoutToken} = incomingWebhook;
expect(WebhookTokenResponse.safeParse(withoutToken).success).toBe(false);
expect(WebhookCreateResponse.safeParse({...withoutToken, user: creator}).success).toBe(false);
});
it('omits the token and includes the source on follower webhooks', () => {
const {token: _token, ...withoutToken} = incomingWebhook;
const follower = {
...withoutToken,
type: WebhookTypes.CHANNEL_FOLLOWER,
user: creator,
source_guild: {id: '7', name: 'Source', icon: null},
source_channel: {id: '8', name: 'news'},
};
const parsed = WebhookResponse.parse(follower);
expect(parsed).not.toHaveProperty('token');
expect(parsed.source_guild).toEqual({id: '7', name: 'Source', icon: null});
expect(parsed.source_channel).toEqual({id: '8', name: 'news'});
});
it('rejects unknown webhook types', () => {
expect(WebhookResponse.safeParse({...incomingWebhook, type: 3, user: creator}).success).toBe(false);
});
});
describe('message responses', () => {
it('allows a message reference without a message id', () => {
const shape = MessageResponseSchema.shape.message_reference;
const reference = {type: 0, guild_id: '1', channel_id: '2'};
expect(shape.parse(reference)).toEqual(reference);
});
it('accepts the crosspost flags', () => {
const flags = MessageFlags.CROSSPOSTED | MessageFlags.IS_CROSSPOST | MessageFlags.SOURCE_MESSAGE_DELETED;
expect(MessageResponseSchema.shape.flags.parse(flags)).toBe(flags);
});
});
@@ -1,23 +0,0 @@
// SPDX-License-Identifier: AGPL-3.0-or-later
import {MAX_GUILD_STICKER_TAGS} from '@fluxer/constants/src/LimitConstants';
import {GuildStickerResponse} from '@fluxer/schema/src/domains/guild/GuildEmojiSchemas';
import {describe, expect, it} from 'vitest';
const buildSticker = (tagCount: number) => ({
id: '1234567890123456789',
name: 'sticker',
description: 'A sticker',
tags: Array.from({length: tagCount}, (_, index) => `tag${index}`),
animated: false,
nsfw: false,
});
describe('GuildStickerResponse', () => {
it('accepts the maximum tag count', () => {
expect(GuildStickerResponse.safeParse(buildSticker(MAX_GUILD_STICKER_TAGS)).success).toBe(true);
});
it('rejects one tag beyond the maximum', () => {
expect(GuildStickerResponse.safeParse(buildSticker(MAX_GUILD_STICKER_TAGS + 1)).success).toBe(false);
});
});
@@ -1,84 +1,8 @@
// SPDX-License-Identifier: AGPL-3.0-or-later
import {
MAX_GUILD_ROLES,
MAX_GUILD_STICKER_TAGS,
MAX_TEMP_BAN_DURATION_SECONDS,
MIN_TEMP_BAN_DURATION_SECONDS,
} from '@fluxer/constants/src/LimitConstants';
import {
DiscoveryApplicationPatchRequest,
DiscoveryApplicationRequest,
DiscoverySearchQuery,
} from '@fluxer/schema/src/domains/guild/GuildDiscoverySchemas';
import {
GuildBanCreateRequest,
GuildMemberUpdateRequest,
GuildStickerCreateRequest,
} from '@fluxer/schema/src/domains/guild/GuildRequestSchemas';
import {TemplateChannel} from '@fluxer/schema/src/domains/guild/GuildTemplateSchemas';
import {describe, expect, it} from 'vitest';
describe.each([
{name: 'application', schema: DiscoveryApplicationRequest.shape.primary_language},
{name: 'application patch', schema: DiscoveryApplicationPatchRequest.shape.primary_language},
{name: 'search', schema: DiscoverySearchQuery.shape.language},
])('discovery $name language', ({schema}) => {
it.each(['en-US', 'sv-SE', undefined])('preserves supported or omitted language %j', (language) => {
expect(schema.parse(language)).toBe(language);
});
it.each(['unsupported', 'EN-US', ' en-US '])('rejects unsupported language %j without normalization', (language) => {
expect(schema.safeParse(language).error?.issues).toEqual([
{code: 'custom', message: 'Unsupported language code', path: []},
]);
});
});
describe('GuildBanCreateRequest', () => {
it('accepts permanent bans and arbitrary temporary durations within range', () => {
expect(GuildBanCreateRequest.safeParse({ban_duration_seconds: 0}).success).toBe(true);
expect(GuildBanCreateRequest.safeParse({ban_duration_seconds: MIN_TEMP_BAN_DURATION_SECONDS}).success).toBe(true);
expect(GuildBanCreateRequest.safeParse({ban_duration_seconds: 3601}).success).toBe(true);
expect(GuildBanCreateRequest.safeParse({ban_duration_seconds: MAX_TEMP_BAN_DURATION_SECONDS}).success).toBe(true);
});
it('rejects temporary ban durations outside the allowed range', () => {
expect(GuildBanCreateRequest.safeParse({ban_duration_seconds: MIN_TEMP_BAN_DURATION_SECONDS - 1}).success).toBe(
false,
);
expect(GuildBanCreateRequest.safeParse({ban_duration_seconds: MAX_TEMP_BAN_DURATION_SECONDS + 1}).success).toBe(
false,
);
});
});
const buildRoleIds = (count: number) =>
Array.from({length: count}, (_, index) => `${1234567890123456789n + BigInt(index)}`);
describe('GuildMemberUpdateRequest', () => {
it('accepts every role a member can hold', () => {
expect(GuildMemberUpdateRequest.safeParse({roles: buildRoleIds(MAX_GUILD_ROLES)}).success).toBe(true);
});
it('rejects one role beyond the guild role limit', () => {
expect(GuildMemberUpdateRequest.safeParse({roles: buildRoleIds(MAX_GUILD_ROLES + 1)}).success).toBe(false);
});
});
describe('GuildStickerCreateRequest', () => {
const buildTags = (count: number) => Array.from({length: count}, (_, index) => `tag${index}`);
const image = `data:image/png;base64,${Buffer.from('sticker').toString('base64')}`;
it('accepts the maximum tag count', () => {
expect(
GuildStickerCreateRequest.safeParse({name: 'sticker', tags: buildTags(MAX_GUILD_STICKER_TAGS), image}).success,
).toBe(true);
});
it('rejects one tag beyond the maximum', () => {
expect(
GuildStickerCreateRequest.safeParse({name: 'sticker', tags: buildTags(MAX_GUILD_STICKER_TAGS + 1), image})
.success,
).toBe(false);
});
});
describe('TemplateChannel permission overwrites', () => {
it.each([
['role', 0],
@@ -1,52 +0,0 @@
// SPDX-License-Identifier: AGPL-3.0-or-later
import {JobLedgerEntrySchema, ListJobsQuery, ListJobsRequest} from '@fluxer/schema/src/domains/admin/JobsSchemas';
import {describe, expect, test} from 'vitest';
describe('jobs schemas', () => {
test('the job status enum rejects failed, which the ledger never writes', () => {
expect(ListJobsQuery.safeParse({status: 'failed'}).success).toBe(false);
expect(ListJobsRequest.safeParse({status: 'failed'}).success).toBe(false);
expect(JobLedgerEntrySchema.shape.status.safeParse('failed').success).toBe(false);
});
test.each(['queued', 'running', 'succeeded', 'cancelled', 'deadletter'])(
'accepts ledger status %s across query, request, and response',
(status) => {
expect(ListJobsQuery.parse({status}).status).toBe(status);
expect(ListJobsRequest.parse({status}).status).toBe(status);
expect(JobLedgerEntrySchema.shape.status.parse(status)).toBe(status);
},
);
});
describe('job pagination cursor', () => {
const cursor = {
cursor_bucket_day: '2024-02-29',
cursor_created_at: '2024-02-29T12:00:00Z',
cursor_job_id: '123',
};
test('accepts a complete cursor and applies query defaults', () => {
expect(ListJobsQuery.parse(cursor)).toEqual({...cursor, limit: 50, max_lookback_days: 14});
});
test.each(['cursor_bucket_day', 'cursor_created_at', 'cursor_job_id'] as const)(
'rejects a cursor missing %s',
(field) => {
expect(ListJobsQuery.safeParse({...cursor, [field]: undefined})).toMatchObject({
success: false,
error: {issues: [{path: [field]}]},
});
},
);
test.each([
{cursor_bucket_day: '2023-02-29'},
{cursor_bucket_day: '2024-04-31'},
{cursor_created_at: '2024-02-30T12:00:00Z'},
{cursor_job_id: '01'},
])('rejects malformed cursor component %j', (invalid) => {
expect(ListJobsQuery.safeParse({...cursor, ...invalid}).success).toBe(false);
});
});
@@ -1,13 +1,3 @@
import {ChannelTypes} from '@fluxer/constants/src/ChannelConstants';
import {
CreateVoiceServerRequest,
CreateVoiceServerRequestBody,
UpdateVoiceRegionRequest,
UpdateVoiceRegionRequestBody,
UpdateVoiceServerRequest,
UpdateVoiceServerRequestBody,
} from '@fluxer/schema/src/domains/admin/AdminVoiceSchemas';
import {ChannelUpdateRequest, ChannelUpdateRequestBody} from '@fluxer/schema/src/domains/channel/ChannelRequestSchemas';
import {
BulkDeleteSelfMessagesFilter,
BulkDeleteSelfMessagesRequest,
@@ -15,127 +5,6 @@ import {
} from '@fluxer/schema/src/domains/user/UserRequestSchemas';
import {describe, expect, it} from 'vitest';
const server = {
server_id: 'primary',
endpoint: 'wss://voice.example.com',
api_key: 'key',
api_secret: 'secret',
};
describe('voice request bodies', () => {
it('requires server creation fields but not the URL-supplied region', () => {
const body = CreateVoiceServerRequestBody.parse(server);
expect(body).toEqual({
...server,
is_active: true,
soft_connection_limit: null,
vip_only: false,
required_guild_features: [],
allowed_guild_ids: [],
allowed_user_ids: [],
});
expect(CreateVoiceServerRequestBody.safeParse({}).success).toBe(false);
expect(CreateVoiceServerRequest.safeParse(server).success).toBe(false);
expect(CreateVoiceServerRequest.parse({...server, region_id: 'eu'})).toEqual({...body, region_id: 'eu'});
});
it.each(['server_id', 'endpoint', 'api_key', 'api_secret'] as const)('requires creation field %s', (field) => {
expect(CreateVoiceServerRequestBody.safeParse({...server, [field]: undefined}).success).toBe(false);
});
it('keeps patch bodies empty without injecting defaults', () => {
expect(UpdateVoiceRegionRequestBody.parse({})).toEqual({});
expect(UpdateVoiceServerRequestBody.parse({})).toEqual({});
expect(UpdateVoiceRegionRequest.parse({id: 'eu'})).toEqual({id: 'eu'});
expect(UpdateVoiceServerRequest.parse({region_id: 'eu', server_id: 'primary'})).toEqual({
region_id: 'eu',
server_id: 'primary',
});
});
it('does not treat client-supplied path fields as body properties', () => {
expect(UpdateVoiceRegionRequestBody.parse({id: 'ignored', name: 'Europe'})).toEqual({name: 'Europe'});
expect(UpdateVoiceServerRequestBody.parse({region_id: 'ignored', server_id: 'ignored'})).toEqual({});
});
it('retains explicit false, null, and snowflake transformations', () => {
expect(
UpdateVoiceServerRequestBody.parse({is_active: false, soft_connection_limit: null, allowed_user_ids: ['123']}),
).toEqual({is_active: false, soft_connection_limit: null, allowed_user_ids: [123n]});
});
});
describe.each([
{name: 'create body', schema: CreateVoiceServerRequestBody, required: server},
{name: 'create service request', schema: CreateVoiceServerRequest, required: {...server, region_id: 'eu'}},
{name: 'update body', schema: UpdateVoiceServerRequestBody, required: {}},
{name: 'update service request', schema: UpdateVoiceServerRequest, required: {region_id: 'eu', server_id: 'primary'}},
])('$name coordinates', ({schema, required}) => {
it.each([{}, {latitude: 0, longitude: 0}, {latitude: null, longitude: null}])(
'accepts the paired state %j',
(coordinates) => {
expect(schema.parse({...required, ...coordinates})).toMatchObject(coordinates);
},
);
it.each([
{latitude: 0},
{longitude: 0},
{latitude: null},
{longitude: null},
{latitude: 0, longitude: null},
{latitude: null, longitude: 0},
])('rejects the unpaired state %j', (coordinates) => {
expect(schema.safeParse({...required, ...coordinates})).toMatchObject({
success: false,
error: {
issues: [{path: ['latitude'], message: 'Latitude and longitude must both be provided or both be omitted'}],
},
});
});
});
describe('channel update request body', () => {
it('permits an empty body while the service validator still requires the stored channel type', () => {
expect(ChannelUpdateRequestBody.parse({})).toEqual({});
expect(ChannelUpdateRequest.safeParse({}).success).toBe(false);
});
it.each([
ChannelTypes.GUILD_TEXT,
ChannelTypes.GUILD_ANNOUNCEMENT,
ChannelTypes.GUILD_VOICE,
ChannelTypes.GUILD_CATEGORY,
ChannelTypes.GUILD_LINK,
ChannelTypes.GROUP_DM,
])('preserves field transformations for stored channel type %i', (type) => {
const input = {name: ' General ', owner_id: '123'};
const expected = {name: 'General', owner_id: 123n};
expect(ChannelUpdateRequestBody.parse(input)).toEqual(expected);
expect(ChannelUpdateRequest.parse({...input, type})).toEqual({...expected, type});
});
it('preserves guild-only fields in the documented body', () => {
const input = {
topic: ' Topic ',
parent_id: '123',
nsfw_override: false,
bitrate: 64000,
rtc_region: null,
rtc_p2p: true,
};
expect(ChannelUpdateRequestBody.parse(input)).toEqual({...input, topic: 'Topic', parent_id: 123n});
});
it('keeps only text and announcement conversions as a body type', () => {
expect(ChannelUpdateRequestBody.parse({type: ChannelTypes.GUILD_TEXT})).toEqual({type: ChannelTypes.GUILD_TEXT});
expect(ChannelUpdateRequestBody.parse({type: ChannelTypes.GUILD_ANNOUNCEMENT})).toEqual({
type: ChannelTypes.GUILD_ANNOUNCEMENT,
});
expect(ChannelUpdateRequestBody.parse({type: ChannelTypes.GUILD_VOICE})).toEqual({});
});
});
const bulkDeleteDefaults = {
scope: 'selected',
include_dms: true,
@@ -1,189 +0,0 @@
// SPDX-License-Identifier: AGPL-3.0-or-later
import {
type ReportAdminResponseSchema,
type ResolveReportResponse,
SearchReportsRequest,
} from '@fluxer/schema/src/domains/admin/AdminSchemas';
import {
ReportFlowQuery,
ReportFlowSurface,
ReportFlowTargetType,
} from '@fluxer/schema/src/domains/report/ReportFlowSchemas';
import {
createInt32EnumType,
createNamedLiteralUnion,
createNamedStringLiteralUnion,
withFieldDescription,
withOpenApiType,
} from '@fluxer/schema/src/primitives/SchemaPrimitives';
import {schemaMetadata} from '@fluxer/schema/src/SchemaMetadata';
import {describe, expect, expectTypeOf, it} from 'vitest';
import {z} from 'zod';
describe('named literal union inference', () => {
it('infers string literals from a bare union', () => {
const schema = createNamedStringLiteralUnion([
['asc', 'asc', 'Ascending'],
['desc', 'desc', 'Descending'],
]);
expectTypeOf<z.infer<typeof schema>>().toEqualTypeOf<'asc' | 'desc'>();
expect(schema.options.map((option) => option.value)).toEqual(['asc', 'desc']);
});
it('infers string literals through withOpenApiType', () => {
const schema = withOpenApiType(
createNamedStringLiteralUnion([
['asc', 'asc', 'Ascending'],
['desc', 'desc', 'Descending'],
]),
'TypeTestSortOrder',
);
expectTypeOf<z.infer<typeof schema>>().toEqualTypeOf<'asc' | 'desc'>();
expect(schemaMetadata.get(schema)?.name).toBe('TypeTestSortOrder');
});
it('infers string literals through withFieldDescription', () => {
const schema = withFieldDescription(
createNamedStringLiteralUnion([
['asc', 'asc', 'Ascending'],
['desc', 'desc', 'Descending'],
]),
'Sort order',
);
expectTypeOf<z.infer<typeof schema>>().toEqualTypeOf<'asc' | 'desc'>();
expect(schema.description).toBe('Sort order');
});
it('infers string literals through both wrappers and object modifiers', () => {
const schema = z.object({
order: withFieldDescription(
withOpenApiType(
createNamedStringLiteralUnion([
['asc', 'asc', 'Ascending'],
['desc', 'desc', 'Descending'],
]),
'TypeTestNestedSortOrder',
),
'Sort order',
).optional(),
fallback: withOpenApiType(
createNamedStringLiteralUnion([
['asc', 'asc'],
['desc', 'desc'],
]),
'TypeTestFallbackSortOrder',
).default('asc'),
});
expectTypeOf<z.infer<typeof schema>>().toEqualTypeOf<{order?: 'asc' | 'desc'; fallback: 'asc' | 'desc'}>();
expect(schema.parse({})).toEqual({fallback: 'asc'});
});
it('infers number literals from a bare union', () => {
const schema = createNamedLiteralUnion([
[0, 'ROLE', 'A role'],
[1, 'MEMBER', 'A member'],
]);
expectTypeOf<z.infer<typeof schema>>().toEqualTypeOf<0 | 1>();
expect(schema.options.map((option) => option.value)).toEqual([0, 1]);
});
it('infers number literals through withOpenApiType and withFieldDescription', () => {
const named = withOpenApiType(
createNamedLiteralUnion([
[0, 'ROLE', 'A role'],
[1, 'MEMBER', 'A member'],
]),
'TypeTestOverwriteType',
);
const described = withFieldDescription(
createNamedLiteralUnion([
[0, 'ROLE', 'A role'],
[1, 'MEMBER', 'A member'],
]),
'Overwrite type',
);
expectTypeOf<z.infer<typeof named>>().toEqualTypeOf<0 | 1>();
expectTypeOf<z.infer<typeof described>>().toEqualTypeOf<0 | 1>();
expect(named.safeParse(2).success).toBe(false);
expect(described.safeParse(1).success).toBe(true);
});
it('infers the widened value type from pairs that are not literals', () => {
const pairs: ReadonlyArray<readonly [string, string]> = [
['asc', 'asc'],
['desc', 'desc'],
];
const schema = createNamedStringLiteralUnion(pairs);
expectTypeOf<z.infer<typeof schema>>().toEqualTypeOf<string>();
expect(schema.safeParse('asc').success).toBe(true);
});
it('infers the report flow target and surface unions', () => {
expectTypeOf<ReportFlowTargetType>().toEqualTypeOf<'message' | 'user' | 'guild'>();
expectTypeOf<ReportFlowSurface>().toEqualTypeOf<'in_app' | 'dsa'>();
expectTypeOf<ReportFlowQuery['surface']>().toEqualTypeOf<'in_app' | 'dsa'>();
expect(ReportFlowTargetType.options.map((option) => option.value)).toEqual(['message', 'user', 'guild']);
expect(ReportFlowSurface.options.map((option) => option.value)).toEqual(['in_app', 'dsa']);
expect(ReportFlowQuery.parse({}).surface).toBe('in_app');
});
});
describe('int32 enum inference', () => {
it('infers number literals from a bare enum', () => {
const schema = createInt32EnumType(
[
[0, 'PENDING', 'Pending'],
[1, 'RESOLVED', 'Resolved'],
],
'Status',
'TypeTestBareStatus',
);
expectTypeOf<z.infer<typeof schema>>().toEqualTypeOf<0 | 1>();
expect(schema.parse(1)).toBe(1);
});
it('infers number literals through withOpenApiType and withFieldDescription', () => {
const named = withOpenApiType(
createInt32EnumType(
[
[0, 'PENDING', 'Pending'],
[1, 'RESOLVED', 'Resolved'],
],
'Status',
'TypeTestWrappedStatus',
),
'TypeTestWrappedStatus',
);
const described = withFieldDescription(
createInt32EnumType([
[0, 'MESSAGE'],
[1, 'USER'],
[2, 'GUILD'],
]),
'Report type',
);
expectTypeOf<z.infer<typeof named>>().toEqualTypeOf<0 | 1>();
expectTypeOf<z.infer<typeof described>>().toEqualTypeOf<0 | 1 | 2>();
expect(named.safeParse(2).success).toBe(false);
expect(described.safeParse(2).success).toBe(true);
expect(schemaMetadata.get(named)).toEqual({
name: 'TypeTestWrappedStatus',
format: 'int32',
enumEntries: [
{value: 0, name: 'PENDING', description: 'Pending'},
{value: 1, name: 'RESOLVED', description: 'Resolved'},
],
});
});
it('infers the widened value type from pairs that are not literals', () => {
const pairs: ReadonlyArray<readonly [number, string]> = [
[0, 'PENDING'],
[1, 'RESOLVED'],
];
const schema = createInt32EnumType(pairs);
expectTypeOf<z.infer<typeof schema>>().toEqualTypeOf<number>();
expect(schema.safeParse(1).success).toBe(true);
});
it('infers the report status and type literals on the admin schemas', () => {
expectTypeOf<z.infer<typeof ReportAdminResponseSchema>['status']>().toEqualTypeOf<0 | 1>();
expectTypeOf<z.infer<typeof ReportAdminResponseSchema>['report_type']>().toEqualTypeOf<0 | 1 | 2>();
expectTypeOf<z.infer<typeof ResolveReportResponse>['status']>().toEqualTypeOf<0 | 1>();
expectTypeOf<SearchReportsRequest['status']>().toEqualTypeOf<0 | 1 | undefined>();
expectTypeOf<SearchReportsRequest['report_type']>().toEqualTypeOf<0 | 1 | 2 | undefined>();
expect(SearchReportsRequest.safeParse({status: 2}).success).toBe(false);
expect(SearchReportsRequest.safeParse({report_type: 2}).success).toBe(true);
});
});
@@ -4,88 +4,6 @@ import {isValidSingleUnicodeEmoji} from '@fluxer/schema/src/primitives/EmojiVali
import {describe, expect, it} from 'vitest';
describe('isValidSingleUnicodeEmoji', () => {
describe('valid single emojis', () => {
it('accepts simple emoji', () => {
expect(isValidSingleUnicodeEmoji('👍')).toBe(true);
});
it('accepts common face emojis', () => {
expect(isValidSingleUnicodeEmoji('😀')).toBe(true);
expect(isValidSingleUnicodeEmoji('😂')).toBe(true);
expect(isValidSingleUnicodeEmoji('🥺')).toBe(true);
expect(isValidSingleUnicodeEmoji('😡')).toBe(true);
expect(isValidSingleUnicodeEmoji('🤔')).toBe(true);
});
it('accepts emoji with skin tone modifier', () => {
expect(isValidSingleUnicodeEmoji('👍🏿')).toBe(true);
expect(isValidSingleUnicodeEmoji('👍🏻')).toBe(true);
expect(isValidSingleUnicodeEmoji('👍🏽')).toBe(true);
});
it('accepts ZWJ sequence emojis', () => {
expect(isValidSingleUnicodeEmoji('👨‍👩‍👧‍👦')).toBe(true);
expect(isValidSingleUnicodeEmoji('👩‍💻')).toBe(true);
expect(isValidSingleUnicodeEmoji('🧑‍🎄')).toBe(true);
});
it('accepts ZWJ sequence with skin tone at correct position', () => {
expect(isValidSingleUnicodeEmoji('🧑🏿‍🎄')).toBe(true);
expect(isValidSingleUnicodeEmoji('👩🏻‍💻')).toBe(true);
});
it('accepts flag emojis', () => {
expect(isValidSingleUnicodeEmoji('🇺🇸')).toBe(true);
expect(isValidSingleUnicodeEmoji('🇬🇧')).toBe(true);
expect(isValidSingleUnicodeEmoji('🏳️‍🌈')).toBe(true);
});
it('accepts single regional indicator symbols', () => {
expect(isValidSingleUnicodeEmoji('🇦')).toBe(true);
expect(isValidSingleUnicodeEmoji('🇧')).toBe(true);
expect(isValidSingleUnicodeEmoji('🇵')).toBe(true);
expect(isValidSingleUnicodeEmoji('🇿')).toBe(true);
});
it('accepts all 26 regional indicator symbols', () => {
for (let cp = 0x1f1e6; cp <= 0x1f1ff; cp++) {
expect(isValidSingleUnicodeEmoji(String.fromCodePoint(cp))).toBe(true);
}
});
it('accepts keycap emojis', () => {
expect(isValidSingleUnicodeEmoji('1️⃣')).toBe(true);
expect(isValidSingleUnicodeEmoji('#️⃣')).toBe(true);
expect(isValidSingleUnicodeEmoji('*️⃣')).toBe(true);
expect(isValidSingleUnicodeEmoji('0️⃣')).toBe(true);
expect(isValidSingleUnicodeEmoji('9️⃣')).toBe(true);
});
it('accepts variation selector emojis', () => {
expect(isValidSingleUnicodeEmoji('❤️')).toBe(true);
expect(isValidSingleUnicodeEmoji('☀️')).toBe(true);
});
it('accepts text-style emojis without variation selector', () => {
expect(isValidSingleUnicodeEmoji('❤')).toBe(true);
expect(isValidSingleUnicodeEmoji('☀')).toBe(true);
expect(isValidSingleUnicodeEmoji('☺')).toBe(true);
});
it('accepts copyright, registered, and trademark symbols', () => {
expect(isValidSingleUnicodeEmoji('©')).toBe(true);
expect(isValidSingleUnicodeEmoji('©️')).toBe(true);
expect(isValidSingleUnicodeEmoji('®')).toBe(true);
expect(isValidSingleUnicodeEmoji('®️')).toBe(true);
expect(isValidSingleUnicodeEmoji('™')).toBe(true);
expect(isValidSingleUnicodeEmoji('™️')).toBe(true);
});
it('accepts animal and nature emojis', () => {
expect(isValidSingleUnicodeEmoji('🐱')).toBe(true);
expect(isValidSingleUnicodeEmoji('🌸')).toBe(true);
expect(isValidSingleUnicodeEmoji('🌍')).toBe(true);
});
it('accepts food and object emojis', () => {
expect(isValidSingleUnicodeEmoji('🍕')).toBe(true);
expect(isValidSingleUnicodeEmoji('🎸')).toBe(true);
expect(isValidSingleUnicodeEmoji('💎')).toBe(true);
});
it('accepts symbol emojis', () => {
expect(isValidSingleUnicodeEmoji('✅')).toBe(true);
expect(isValidSingleUnicodeEmoji('❌')).toBe(true);
expect(isValidSingleUnicodeEmoji('⚠️')).toBe(true);
expect(isValidSingleUnicodeEmoji('💯')).toBe(true);
});
});
describe('invalid inputs', () => {
it('rejects empty string', () => {
expect(isValidSingleUnicodeEmoji('')).toBe(false);
@@ -132,10 +50,6 @@ describe('isValidSingleUnicodeEmoji', () => {
it('rejects skin tone at wrong position in ZWJ sequence', () => {
expect(isValidSingleUnicodeEmoji('🧑‍🎄🏿')).toBe(false);
});
it('accepts standalone skin tone modifier as valid emoji', () => {
expect(isValidSingleUnicodeEmoji('🏿')).toBe(true);
expect(isValidSingleUnicodeEmoji('🏻')).toBe(true);
});
it('rejects standalone ZWJ character', () => {
expect(isValidSingleUnicodeEmoji('\u200D')).toBe(false);
});
@@ -1,14 +0,0 @@
// SPDX-License-Identifier: AGPL-3.0-or-later
import {WebhookTypeSchema} from '@fluxer/schema/src/primitives/WebhookValidators';
import {describe, expect, it} from 'vitest';
describe('WebhookTypeSchema', () => {
it.each([1, 2])('accepts webhook type %i', (value) => {
expect(WebhookTypeSchema.parse(value)).toBe(value);
});
it.each([0, 3, -1, 1.5, '1', null])('rejects unknown or nonnumeric webhook type %j', (value) => {
expect(WebhookTypeSchema.safeParse(value).success).toBe(false);
});
});