// @ts-check const { test, expect } = require('@playwright/test'); const { openTerminal, typeCommand } = require('./helpers'); const STORAGE_KEY = 'reese-terminal-achievements'; test.describe('Achievements system', () => { test('starts hidden until the first unlock', async ({ page }) => { await page.goto('/'); await expect(page.locator('#achievements')).toBeHidden(); await expect(page.locator('#nav-achievements')).toHaveCount(0); }); test('uptime unlock shows a toast, persists to localStorage, reveals the section', async ({ page }) => { await page.goto('/'); await openTerminal(page); await typeCommand(page, 'uptime'); // toast with the achievement name const toast = page.locator('.toast').filter({ hasText: 'Time Flies' }); await expect(toast).toBeVisible(); await expect(toast).toContainText('Achievement Unlocked'); await expect(page.locator('#toast-container .toast')).toHaveCount(1); // persisted const stored = await page.evaluate(k => JSON.parse(localStorage.getItem(k) || '[]'), STORAGE_KEY); expect(stored).toContain('time_flies'); // section revealed + counter + nav link await expect(page.locator('#achievements')).toBeVisible(); await expect(page.locator('#achievements-count')).toHaveText(/1 \/ \d+ achievements unlocked/); await expect(page.locator('#nav-achievements a')).toHaveAttribute('href', '#achievements'); // the unlocked card shows its name; locked ones stay mysterious const cards = page.locator('#achievements-grid .achievement-card'); const unlocked = page.locator('#achievements-grid .achievement-card.unlocked'); await expect(unlocked).toHaveCount(1); await expect(unlocked).toContainText('Time Flies'); expect(await cards.count()).toBeGreaterThan(1); await expect(page.locator('#achievements-grid .achievement-card.locked')).not.toHaveCount(0); }); test('unlocks survive a page reload (localStorage restore)', async ({ page }) => { await page.goto('/'); await openTerminal(page); await typeCommand(page, 'uptime'); await expect(page.locator('#achievements')).toBeVisible(); await page.reload(); await expect(page.locator('#achievements')).toBeVisible(); await expect(page.locator('#achievements-count')).toHaveText(/1 \/ \d+ achievements unlocked/); await expect(page.locator('#nav-achievements a')).toHaveAttribute('href', '#achievements'); }); test('special achievements: sudo, nice-try rm, vim splash', async ({ page }) => { await page.goto('/'); await openTerminal(page); await typeCommand(page, 'sudo su -'); await expect(page.locator('.toast').filter({ hasText: 'Power User' })).toBeVisible(); await typeCommand(page, 'rm -rf /'); // root variant: the destruction easter egg wipes the page (and its // toasts) ~500ms later — verify the unlock via localStorage instead await page.reload(); await openTerminal(page); await typeCommand(page, 'rm -rf /'); await expect(page.locator('.toast').filter({ hasText: 'Nice Try' })).toBeVisible(); await typeCommand(page, 'vim'); await expect(page.locator('.toast').filter({ hasText: 'Vi sIgnificantly worse M' })).toBeVisible(); await page.keyboard.press('q'); const stored = await page.evaluate(k => JSON.parse(localStorage.getItem(k) || '[]'), STORAGE_KEY); expect(stored).toEqual( expect.arrayContaining(['power_user', 'restore_backup', 'nice_try', 'vim_splash'])); }); test('multiple unlocks stack toasts and increment the counter', async ({ page }) => { await page.goto('/'); await openTerminal(page); await typeCommand(page, 'uptime'); await typeCommand(page, 'whoami'); await typeCommand(page, 'clear'); const stored = await page.evaluate(k => JSON.parse(localStorage.getItem(k) || '[]'), STORAGE_KEY); expect(stored).toEqual( expect.arrayContaining(['time_flies', 'self_aware', 'clean_slate'])); await expect(page.locator('#achievements-count')).toHaveText(/3 \/ \d+ achievements unlocked/); }); });