- RadioGroup: mutual exclusion with div-wrapped items, shared name attr - settingsSchema: playback field validation (Bug #5) - useAccountSettings: password error clears on input (Bug #17), DELETE text validation (Bug #9), correct API endpoint (Bug #1) - useTwoFactorSetup: toast.success() not bare toast() (Bug #3) - Checkbox: no hardcoded "Checkbox" aria-label (Bug #11) - PreferenceSettings: timezone label is "Time Zone" (Bug #18) 49 tests pass across 6 test files. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
123 lines
3.3 KiB
TypeScript
123 lines
3.3 KiB
TypeScript
/**
|
|
* settingsSchema regression tests
|
|
* Covers Bug #5: Schema validation must accept playback field
|
|
*/
|
|
import { describe, it, expect } from 'vitest';
|
|
import { settingsSchema } from './settingsSchema';
|
|
|
|
describe('settingsSchema', () => {
|
|
const validSettings = {
|
|
notifications: {
|
|
email_notifications: true,
|
|
push_notifications: true,
|
|
browser_notifications: true,
|
|
email_on_follow: true,
|
|
email_on_like: true,
|
|
email_on_comment: true,
|
|
email_on_message: true,
|
|
email_on_mention: true,
|
|
email_marketing: false,
|
|
},
|
|
privacy: {
|
|
allow_search_indexing: true,
|
|
show_activity: true,
|
|
},
|
|
content: {
|
|
explicit_content: false,
|
|
autoplay: true,
|
|
},
|
|
preferences: {
|
|
language: 'en' as const,
|
|
timezone: 'UTC',
|
|
theme: 'auto' as const,
|
|
},
|
|
};
|
|
|
|
it('should validate a complete settings object', () => {
|
|
const result = settingsSchema.safeParse(validSettings);
|
|
expect(result.success).toBe(true);
|
|
});
|
|
|
|
// Bug #5 regression: playback field must be accepted
|
|
it('[Bug #5] should accept settings with playback field', () => {
|
|
const withPlayback = {
|
|
...validSettings,
|
|
playback: {
|
|
quality: 'high' as const,
|
|
volume: 0.8,
|
|
crossfade: 3,
|
|
autoplay: true,
|
|
},
|
|
};
|
|
const result = settingsSchema.safeParse(withPlayback);
|
|
expect(result.success).toBe(true);
|
|
});
|
|
|
|
it('[Bug #5] should accept settings without playback (optional)', () => {
|
|
const result = settingsSchema.safeParse(validSettings);
|
|
expect(result.success).toBe(true);
|
|
});
|
|
|
|
it('[Bug #5] should validate playback quality enum', () => {
|
|
const withBadQuality = {
|
|
...validSettings,
|
|
playback: {
|
|
quality: 'ultra-hd',
|
|
volume: 0.8,
|
|
crossfade: 3,
|
|
autoplay: true,
|
|
},
|
|
};
|
|
const result = settingsSchema.safeParse(withBadQuality);
|
|
expect(result.success).toBe(false);
|
|
});
|
|
|
|
it('[Bug #5] should validate playback volume range (0-1)', () => {
|
|
const withBadVolume = {
|
|
...validSettings,
|
|
playback: {
|
|
quality: 'high' as const,
|
|
volume: 1.5,
|
|
crossfade: 3,
|
|
autoplay: true,
|
|
},
|
|
};
|
|
const result = settingsSchema.safeParse(withBadVolume);
|
|
expect(result.success).toBe(false);
|
|
});
|
|
|
|
it('[Bug #5] should validate playback crossfade range (0-12)', () => {
|
|
const withBadCrossfade = {
|
|
...validSettings,
|
|
playback: {
|
|
quality: 'high' as const,
|
|
volume: 0.8,
|
|
crossfade: 20,
|
|
autoplay: true,
|
|
},
|
|
};
|
|
const result = settingsSchema.safeParse(withBadCrossfade);
|
|
expect(result.success).toBe(false);
|
|
});
|
|
|
|
it('should reject invalid theme values', () => {
|
|
const withBadTheme = {
|
|
...validSettings,
|
|
preferences: { ...validSettings.preferences, theme: 'neon' },
|
|
};
|
|
const result = settingsSchema.safeParse(withBadTheme);
|
|
expect(result.success).toBe(false);
|
|
if (!result.success) {
|
|
expect(result.error.errors[0].message).toContain('Thème invalide');
|
|
}
|
|
});
|
|
|
|
it('should reject invalid language values', () => {
|
|
const withBadLang = {
|
|
...validSettings,
|
|
preferences: { ...validSettings.preferences, language: 'xx' },
|
|
};
|
|
const result = settingsSchema.safeParse(withBadLang);
|
|
expect(result.success).toBe(false);
|
|
});
|
|
});
|