diff --git a/code/websites/pokedex.online/tests/unit/composables/useFeatureFlags.test.js b/code/websites/pokedex.online/tests/unit/composables/useFeatureFlags.test.js deleted file mode 100644 index 5c844e5..0000000 --- a/code/websites/pokedex.online/tests/unit/composables/useFeatureFlags.test.js +++ /dev/null @@ -1,219 +0,0 @@ -/** - * useFeatureFlags Composable Tests - * Verifies feature flag state management, permissions, and overrides - */ - -import { describe, it, expect, beforeEach, afterEach, vi } from 'vitest'; -import * as useAuthModule from '../../../src/composables/useAuth.js'; -import { useFeatureFlags } from '../../../src/composables/useFeatureFlags.js'; - -// Mock useAuth module with default no-permissions user -vi.spyOn(useAuthModule, 'useAuth').mockReturnValue({ - user: { isAdmin: false, permissions: [] }, - token: null, - hasPermission: vi.fn(() => false) -}); - -describe('useFeatureFlags', () => { - beforeEach(() => { - // Clear localStorage before each test - localStorage.clear(); - }); - - afterEach(() => { - localStorage.clear(); - }); - - describe('isEnabled', () => { - it('returns flag default value when no override exists', () => { - const { isEnabled } = useFeatureFlags(); - - // ENABLE_CACHING defaults to true - expect(isEnabled.value('enable-caching')).toBe(true); - // DARK_MODE defaults to false - expect(isEnabled.value('dark-mode')).toBe(false); - }); - - it('returns false for unknown flag name', () => { - const { isEnabled } = useFeatureFlags(); - expect(isEnabled.value('nonexistent-flag')).toBe(false); - }); - - it('respects local override when set in same instance', () => { - const { isEnabled, toggle } = useFeatureFlags(); - - expect(isEnabled.value('dark-mode')).toBe(false); - - toggle('dark-mode'); - // Should be toggled in same instance - expect(isEnabled.value('dark-mode')).toBe(true); - }); - - it('returns false for flag requiring permission without it', () => { - const { isEnabled } = useFeatureFlags(); - - // GAMEMASTER_DIFF_VIEWER requires 'gamemaster-advanced' permission - expect(isEnabled.value('gamemaster-diff-viewer')).toBe(false); - }); - }); - - describe('toggle', () => { - it('toggles flag override in development mode', () => { - const { toggle, isEnabled } = useFeatureFlags(); - - expect(isEnabled.value('dark-mode')).toBe(false); - - const result = toggle('dark-mode'); - expect(result).toBe(true); - expect(isEnabled.value('dark-mode')).toBe(true); - }); - - it('persists override to localStorage', () => { - const { toggle } = useFeatureFlags(); - - toggle('dark-mode'); - - const stored = localStorage.getItem('feature_flag_overrides'); - expect(stored).not.toBeNull(); - - const overrides = JSON.parse(stored); - expect(overrides['dark-mode']).toBe(true); - }); - - it('loads overrides from localStorage on init', () => { - // Set override in storage first - localStorage.setItem( - 'feature_flag_overrides', - JSON.stringify({ - 'dark-mode': true, - 'experimental-search': true - }) - ); - - const { isEnabled } = useFeatureFlags(); - - expect(isEnabled.value('dark-mode')).toBe(true); - expect(isEnabled.value('experimental-search')).toBe(true); - }); - }); - - describe('reset', () => { - it('removes override for specific flag', () => { - const { isEnabled, toggle, reset } = useFeatureFlags(); - - toggle('dark-mode'); - expect(isEnabled.value('dark-mode')).toBe(true); - - reset('dark-mode'); - expect(isEnabled.value('dark-mode')).toBe(false); - }); - - it('returns to default after reset', () => { - const { isEnabled, toggle, reset } = useFeatureFlags(); - - // ENABLE_CACHING defaults to true - const beforeToggle = isEnabled.value('enable-caching'); - toggle('enable-caching'); - expect(isEnabled.value('enable-caching')).not.toBe(beforeToggle); - - reset('enable-caching'); - expect(isEnabled.value('enable-caching')).toBe(beforeToggle); - }); - }); - - describe('resetAll', () => { - it('clears all overrides', () => { - const { isEnabled, toggle, resetAll } = useFeatureFlags(); - - toggle('dark-mode'); - toggle('experimental-search'); - - resetAll(); - - // Should return to defaults - expect(isEnabled.value('dark-mode')).toBe(false); - expect(isEnabled.value('experimental-search')).toBe(false); - }); - - it('clears localStorage after reset', () => { - const { toggle, resetAll } = useFeatureFlags(); - - toggle('dark-mode'); - resetAll(); - - const stored = localStorage.getItem('feature_flag_overrides'); - expect(stored).toBe('{}'); - }); - }); - - describe('getFlags', () => { - it('returns array of all flags with status', () => { - const { getFlags } = useFeatureFlags(); - - const flags = getFlags(); - - expect(Array.isArray(flags)).toBe(true); - expect(flags.length).toBeGreaterThan(0); - - const darkMode = flags.find(f => f.name === 'dark-mode'); - expect(darkMode).toBeDefined(); - expect(darkMode).toHaveProperty('isEnabled'); - expect(darkMode).toHaveProperty('hasOverride'); - expect(darkMode).toHaveProperty('requiresPermission'); - }); - - it('marks flags with overrides', () => { - const { getFlags, toggle } = useFeatureFlags(); - - toggle('dark-mode'); - - const flags = getFlags(); - const darkMode = flags.find(f => f.name === 'dark-mode'); - - expect(darkMode.hasOverride).toBe(true); - expect(darkMode.override).toBe(true); - }); - - it('indicates permission requirements for flags', () => { - const { getFlags } = useFeatureFlags(); - - const flags = getFlags(); - - // Should have flags with and without permissions - const withPerm = flags.find(f => f.requiresPermission); - const withoutPerm = flags.find(f => !f.requiresPermission); - - expect(withPerm).toBeDefined(); - expect(withoutPerm).toBeDefined(); - }); - }); - - describe('setBackendFlags', () => { - it('sets flags from backend response', () => { - const { isEnabled, setBackendFlags } = useFeatureFlags(); - - expect(isEnabled.value('dark-mode')).toBe(false); - - setBackendFlags({ - 'dark-mode': true, - 'experimental-search': true - }); - - expect(isEnabled.value('dark-mode')).toBe(true); - expect(isEnabled.value('experimental-search')).toBe(true); - }); - - it('local overrides take precedence over backend flags', () => { - const { isEnabled, toggle, setBackendFlags } = useFeatureFlags(); - - toggle('dark-mode'); // Local override to true - - setBackendFlags({ - 'dark-mode': false // Backend says false - }); - - // Local override should win - expect(isEnabled.value('dark-mode')).toBe(true); - }); - }); -});