import { expect, test } from '@playwright/test' const email = process.env.DEVRUNBOOK_E2E_EMAIL const password = process.env.DEVRUNBOOK_E2E_PASSWORD test.describe('authenticated Milestone 2 library', () => { test.skip(!email || !password, 'live local-account credentials are required') test.use({ storageState: 'test-results/.auth/m2.json' }) test.beforeEach(async ({ page }) => { await page.goto('/library') await expect(page).toHaveURL(/\/library(?:\?.*)?$/u) }) test('search, filter, view and refresh state remain URL-backed', async ({ page, }) => { const errors: string[] = [] page.on('console', (message) => { if (message.type() === 'error') errors.push(message.text()) }) page.on('pageerror', (error) => errors.push(error.message)) await expect( page.getByRole('heading', { level: 1, name: 'Library' }), ).toBeVisible() await expect(page.locator('[data-playbook-slug]')).toHaveCount(28) await page.getByLabel('Search playbooks').fill('root cause') await page.getByRole('button', { name: 'Search', exact: true }).click() await expect(page).toHaveURL(/q=root(?:\+|%20)cause/u) await expect( page.locator('[data-playbook-slug="root-cause-bugfix"]'), ).toBeVisible() await page.getByRole('link', { name: 'Dense' }).click() await expect(page).toHaveURL(/view=dense/u) await page.reload() await expect(page.locator('[data-view="dense"]')).toBeVisible() await expect(page.getByLabel('Search playbooks')).toHaveValue('root cause') expect(errors).toEqual([]) }) test('favorites persist and can be recovered through the saved filter', async ({ page, }, testInfo) => { test.skip(testInfo.project.name !== 'chromium', 'mutation is covered once') const card = page.locator('[data-playbook-slug="root-cause-bugfix"]') const favorite = card.getByRole('button', { name: /favorites/i }) const initiallySaved = (await favorite.getAttribute('aria-pressed')) === 'true' if (!initiallySaved) await favorite.click() await expect(favorite).toHaveAttribute('aria-pressed', 'true') await page.getByLabel('Saved playbooks only').check() await page.getByRole('button', { name: 'Apply filters' }).click() await expect(page).toHaveURL(/favorites=true/u) await expect(card).toBeVisible() await card.getByRole('button', { name: /favorites/i }).click() await expect( card.getByRole('button', { name: /favorites/i }), ).toHaveAttribute('aria-pressed', 'false') }) test('detail exposes governance panels and version-bound composer handoff', async ({ page, }) => { await page.goto('/library/root-cause-bugfix') await expect( page.getByRole('heading', { level: 1, name: /root.?cause/i }), ).toBeVisible() for (const panel of [ 'Intent and outcome', 'Inputs and defaults', 'Repository compatibility', 'Guardrails', 'Workflow', 'Validation requirements', 'Completion criteria', 'Quality and limitations', 'Package files', 'Version history', ]) { await expect( page.getByRole('heading', { level: 2, name: panel }), ).toBeVisible() } await page.getByRole('link', { name: /Compose with this version/i }).click() await expect(page).toHaveURL( /\/composer\/new\?playbook=root-cause-bugfix&version=1\.0\.0/u, ) await expect(page.getByText('root-cause-bugfix@1.0.0')).toBeVisible() }) test('command palette, theme and narrow keyboard layout are operable', async ({ page, }) => { await page.setViewportSize({ width: 390, height: 844 }) await page.goto('/library') await page.keyboard.press('Control+K') await expect( page.getByRole('dialog', { name: 'Command palette' }), ).toBeVisible() await page .getByRole('dialog', { name: 'Command palette' }) .getByRole('combobox') .fill('root cause') await page.keyboard.press('Enter') await expect(page).toHaveURL(/\/library\/root-cause-bugfix$/u) expect( await page.evaluate( () => document.documentElement.scrollWidth <= document.documentElement.clientWidth, ), ).toBe(true) await page.getByRole('button', { name: 'Use light theme' }).click() await expect(page.locator('html')).toHaveAttribute('data-theme', 'light') await page.reload() await expect(page.locator('html')).toHaveAttribute('data-theme', 'light') }) })