Files
Nexumi/packages/shared/src/dashboard.test.ts
smueller 2ef6b23136 Implement Phase 7 features and enhance dashboard schemas
- Updated PHASE-TRACKING.md to reflect the completion of Batch A features, including the implementation of dashboard pages and API routes for various modules.
- Added new Prisma models and migration for owner features, including CommandOverride and GlobalUserBlacklist.
- Expanded dashboard schemas in dashboard.ts to include Ticket, Giveaway, Self Role, Tag, and Starboard configurations, along with their respective validation tests in dashboard.test.ts.
- Enhanced localization files with new i18n keys for the added modules and features.
- Verified successful builds and tests across multiple packages, ensuring stability and functionality of new features.
2026-07-22 15:10:30 +02:00

181 lines
5.6 KiB
TypeScript

import { describe, expect, it } from 'vitest';
import {
AutomodConfigDashboardPatchSchema,
CaseListQuerySchema,
EconomyConfigDashboardPatchSchema,
FunConfigDashboardSchema,
GiveawayCreateDashboardSchema,
LoggingConfigDashboardPatchSchema,
ModerationDashboardPatchSchema,
OptionalSnowflakeSchema,
ScheduledMessageDashboardCreateSchema,
SelfRolePanelDashboardCreateSchema,
SocialFeedDashboardCreateSchema,
StarboardConfigDashboardPatchSchema,
SuggestionActionSchema,
TagDashboardCreateSchema,
TicketCategoryDashboardCreateSchema,
TicketConfigDashboardPatchSchema,
WelcomeConfigDashboardPatchSchema
} from './dashboard.js';
describe('dashboard schemas', () => {
it('accepts moderation patches with escalations', () => {
const parsed = ModerationDashboardPatchSchema.parse({
moderationEnabled: true,
escalations: [{ warnCount: 3, action: 'TIMEOUT', durationMs: 60_000, enabled: true }]
});
expect(parsed.escalations?.[0]?.action).toBe('TIMEOUT');
});
it('rejects empty moderation patches', () => {
expect(() => ModerationDashboardPatchSchema.parse({})).toThrow();
});
it('validates automod patches', () => {
const parsed = AutomodConfigDashboardPatchSchema.parse({
antiRaidEnabled: true,
antiRaidJoinThreshold: 15
});
expect(parsed.antiRaidJoinThreshold).toBe(15);
});
it('validates logging patches with channel mappings', () => {
const parsed = LoggingConfigDashboardPatchSchema.parse({
logChannels: [{ eventType: 'MEMBER_JOIN', channelId: '123456789012345678' }]
});
expect(parsed.logChannels?.[0]?.eventType).toBe('MEMBER_JOIN');
});
it('rejects invalid log channel ids', () => {
expect(() =>
LoggingConfigDashboardPatchSchema.parse({
logChannels: [{ eventType: 'MEMBER_JOIN', channelId: 'not-a-snowflake' }]
})
).toThrow();
});
it('accepts empty string or a valid snowflake as optional id', () => {
expect(OptionalSnowflakeSchema.parse('')).toBe('');
expect(OptionalSnowflakeSchema.parse('123456789012345678')).toBe('123456789012345678');
expect(() => OptionalSnowflakeSchema.parse('abc')).toThrow();
});
it('validates welcome patches', () => {
const parsed = WelcomeConfigDashboardPatchSchema.parse({
welcomeEnabled: true,
welcomeChannelId: '123456789012345678'
});
expect(parsed.welcomeEnabled).toBe(true);
});
it('validates economy patches', () => {
const parsed = EconomyConfigDashboardPatchSchema.parse({ currencyName: 'Gems', dailyAmount: 100 });
expect(parsed.currencyName).toBe('Gems');
});
it('validates fun config', () => {
const parsed = FunConfigDashboardSchema.parse({ enabled: true, mediaEnabled: false });
expect(parsed.mediaEnabled).toBe(false);
});
it('applies default limit for case list queries', () => {
const parsed = CaseListQuerySchema.parse({});
expect(parsed.limit).toBe(25);
});
it('validates ticket config patches', () => {
const parsed = TicketConfigDashboardPatchSchema.parse({ mode: 'THREAD', inactivityHours: 24 });
expect(parsed.mode).toBe('THREAD');
});
it('validates ticket category creation', () => {
const parsed = TicketCategoryDashboardCreateSchema.parse({
name: 'Support',
description: null,
emoji: '🎫',
supportRoleIds: ['123456789012345678']
});
expect(parsed.supportRoleIds).toHaveLength(1);
});
it('validates giveaway creation input', () => {
const parsed = GiveawayCreateDashboardSchema.parse({
channelId: '123456789012345678',
prize: 'Nitro',
winnerCount: 1,
endsAt: new Date(Date.now() + 60_000).toISOString()
});
expect(parsed.prize).toBe('Nitro');
});
it('rejects giveaway creation with invalid date', () => {
expect(() =>
GiveawayCreateDashboardSchema.parse({
channelId: '123456789012345678',
prize: 'Nitro',
winnerCount: 1,
endsAt: 'not-a-date'
})
).toThrow();
});
it('validates self role panel creation', () => {
const parsed = SelfRolePanelDashboardCreateSchema.parse({
channelId: '123456789012345678',
title: 'Colors',
mode: 'BUTTONS',
behavior: 'NORMAL',
roles: [{ roleId: '123456789012345678', label: 'Red' }]
});
expect(parsed.roles).toHaveLength(1);
});
it('validates tag creation', () => {
const parsed = TagDashboardCreateSchema.parse({
name: 'rules',
content: 'Please read the rules',
responseType: 'TEXT',
allowedRoleIds: [],
allowedChannelIds: []
});
expect(parsed.name).toBe('rules');
});
it('validates starboard patches', () => {
const parsed = StarboardConfigDashboardPatchSchema.parse({ threshold: 5 });
expect(parsed.threshold).toBe(5);
});
it('validates suggestion staff actions', () => {
const parsed = SuggestionActionSchema.parse({ status: 'APPROVED', staffReason: 'Great idea' });
expect(parsed.status).toBe('APPROVED');
});
it('validates social feed creation', () => {
const parsed = SocialFeedDashboardCreateSchema.parse({
type: 'TWITCH',
sourceId: 'somechannel',
channelId: '123456789012345678',
enabled: true
});
expect(parsed.type).toBe('TWITCH');
});
it('validates scheduled message creation requires cron or runAt', () => {
expect(() =>
ScheduledMessageDashboardCreateSchema.parse({
channelId: '123456789012345678',
content: 'Hello'
})
).toThrow();
const parsed = ScheduledMessageDashboardCreateSchema.parse({
channelId: '123456789012345678',
content: 'Hello',
runAt: new Date(Date.now() + 60_000).toISOString()
});
expect(parsed.content).toBe('Hello');
});
});