import { afterEach, expect, it, vi } from 'vitest'; import { render } from 'svelte/server'; import { writable } from 'svelte/store'; import type { UserRole } from '../../src/lib/auth.js'; import Scripts from '../../src/routes/scripts/+page.svelte'; import Plugins from '../../src/routes/plugins/+page.svelte'; import ConfigLibrary from '../../src/lib/ui/components/ConfigLibrary.svelte'; import ConfigEditor from '../../src/lib/ui/components/ConfigEditor.svelte'; import ConfigTextEditor from '../../src/lib/ui/components/ConfigTextEditor.svelte'; const currentPage = writable({ url: new URL('http://localhost/scripts'), data: { user: { role: 'super_viewer' as UserRole } } }); vi.mock('$app/stores', () => ({ page: { subscribe: (run: Parameters[0]) => currentPage.subscribe(run) } })); vi.mock('$app/navigation', () => ({ goto: vi.fn(), beforeNavigate: vi.fn(), afterNavigate: vi.fn() })); afterEach(() => currentPage.update((value) => ({ ...value, data: { user: { role: 'super_viewer' } } })) ); it.each(['super_viewer', 'viewer'] as const)( 'keeps release libraries browsable without upload or creation controls for %s', (role) => { currentPage.update((value) => ({ ...value, data: { user: { role } } })); const scripts = render(Scripts).body; expect(scripts).toContain('Search scripts'); expect(scripts).not.toContain('Upload scripts'); const plugins = render(Plugins).body; expect(plugins).toContain('Filter plugins by game'); expect(plugins).not.toContain('Add plugin'); const configs = render(ConfigLibrary).body; expect(configs).toContain('Inspect a server'); expect(configs).toContain('Refresh'); expect(configs).not.toContain('New config'); } ); it.each(['operator', 'admin'] as const)('preserves release creation controls for %s', (role) => { currentPage.update((value) => ({ ...value, data: { user: { role } } })); expect(render(Scripts).body).toContain('Upload scripts'); expect(render(Plugins).body).toContain('Add plugin'); expect(render(ConfigLibrary).body).toContain('New config'); }); it('shows a configuration viewer and version selection without importing or restoring edits', () => { const body = render(ConfigEditor, { props: { id: 1, kind: 'config', versions: [{ id: 1, version: 1, notes: null }], currentVersionId: 1, runningBetaId: null, scopeType: 'game', scopeValue: 't5', onsaved: vi.fn() } }).body; expect(body).toContain('Configuration viewer'); expect(body).toContain('Starting version'); expect(body).not.toContain('Import .cfg'); expect(body).not.toContain('Save new version'); }); it('keeps readonly configuration text selectable and its view switch enabled', () => { const body = render(ConfigTextEditor, { props: { text: 'set g_inactivity "0"', readonly: true } }).body; expect(body).toMatch(/]*readonly/); expect(body).not.toMatch(/]*disabled/); expect(body).not.toMatch(/]*disabled/); expect(body).toContain('Raw .cfg'); expect(body).toContain('Settings'); });