import { act, render, screen, within } from '@testing-library/react' import userEvent from '@testing-library/user-event' import { expect, test, vi } from 'vitest' import { PRESETS } from '../../themes/presets.generated' import { argbToCss } from '../../themes/types' import { ActiveThemeProvider } from '../../themes/useActiveTheme' import { ClickGuiWindow } from '../ClickGuiWindow' import { DEMO, guiReducer, initialGuiState, LOOP_MS } from '../demo' const renderGui = () => render() const row = (name: string) => screen.getByRole('button', { name: new RegExp(`^${name}$`) }) test('the Modules screen shows the four in-game category panels', () => { renderGui() const panels = within(screen.getByRole('list', { name: 'Категории модулей' })).getAllByRole('listitem', { name: /./ }) expect(panels).toHaveLength(4) for (const title of ['Combat', 'Player', 'Visuals', 'Other']) expect(screen.getByRole('heading', { name: title })).toBeInTheDocument() expect(screen.getByRole('tab', { name: 'Modules' })).toHaveAttribute('aria-selected', 'true') }) test('enabled modules carry a check mark; clicking a row toggles it', async () => { const user = userEvent.setup() renderGui() const predictions = row('Predictions') expect(predictions).toHaveAttribute('aria-pressed', 'true') expect(predictions.querySelector('.lv-gui-row-check')).not.toBeNull() const autoLeave = row('Auto Leave') expect(autoLeave.querySelector('.lv-gui-row-check')).toBeNull() await user.click(autoLeave) expect(autoLeave).toHaveAttribute('aria-pressed', 'true') expect(autoLeave.querySelector('.lv-gui-row-check')).not.toBeNull() }) test('reduced motion shows the finished demo frame', () => { renderGui() expect(row('AmbientParticles')).toHaveAttribute('aria-pressed', 'true') expect(row('DamageTint')).toHaveAttribute('aria-pressed', 'true') }) test('Settings lists every preset as a theme card, and picking one re-themes the GUI', async () => { const user = userEvent.setup() renderGui() await user.click(screen.getByRole('tab', { name: 'Settings' })) expect(screen.getByRole('heading', { name: 'Темы' })).toBeInTheDocument() expect(screen.getAllByRole('option')).toHaveLength(PRESETS.length) const nitro = PRESETS.find((p) => p.id === 'nitro')! await user.click(screen.getByRole('option', { name: 'Тема Nitro' })) expect(screen.getByRole('option', { name: 'Тема Nitro' })).toHaveAttribute('aria-selected', 'true') expect(screen.getByTestId('clickgui-root').style.getPropertyValue('--gui-accent')).toBe(argbToCss(nitro.theme.accent)) await user.click(screen.getByRole('tab', { name: 'Modules' })) expect(screen.getByRole('heading', { name: 'Combat' })).toBeInTheDocument() }) test('the scripted demo toggles modules, visits Settings and loops back', () => { vi.useFakeTimers() vi.stubGlobal('matchMedia', (q: string) => ({ matches: !q.includes('reduce'), addEventListener() {}, removeEventListener() {} })) renderGui() expect(row('AmbientParticles')).toHaveAttribute('aria-pressed', 'false') act(() => vi.advanceTimersByTime(2000)) expect(row('AmbientParticles')).toHaveAttribute('aria-pressed', 'true') act(() => vi.advanceTimersByTime(3000)) expect(screen.getByRole('tab', { name: 'Settings' })).toHaveAttribute('aria-selected', 'true') act(() => vi.advanceTimersByTime(LOOP_MS + 600 - 5000 + 500)) // into the next cycle, before its first click expect(screen.getByRole('tab', { name: 'Modules' })).toHaveAttribute('aria-selected', 'true') expect(row('AmbientParticles')).toHaveAttribute('aria-pressed', 'false') vi.unstubAllGlobals() vi.useRealTimers() }) test('demo timeline fits in the loop and the reducer resets', () => { expect(Math.max(...DEMO.map((s) => s.at))).toBeLessThan(LOOP_MS) const toggled = guiReducer(initialGuiState(), { type: 'toggle', module: 'Chams' }) expect(toggled.enabled.Chams).toBe(false) const settings = guiReducer(toggled, { type: 'tab', id: 'settings' }) expect(guiReducer(settings, { type: 'reset' })).toEqual(initialGuiState()) }) test('controlled mode: onPickTheme receives the card and the site theme stays put; backdrop is swappable', async () => { const user = userEvent.setup() const onPickTheme = vi.fn() render( , ) const root = screen.getByTestId('clickgui-root') expect(root.style.getPropertyValue('--gui-backdrop-image')).toBe('url("/shots/f1.png")') await user.click(screen.getByRole('tab', { name: 'Settings' })) const before = screen.getByRole('option', { selected: true }) const accent = root.style.getPropertyValue('--gui-accent') await user.click(screen.getByRole('option', { name: 'Тема Legacy' })) expect(onPickTheme).toHaveBeenCalledWith('legacy') expect(screen.getByRole('option', { selected: true })).toBe(before) expect(root.style.getPropertyValue('--gui-accent')).toBe(accent) })