/** * @feature Dashboard * @see e2e/features/pages/dashboard.feature */ import { describe, test, expect } from 'vitest'; import { setupBrowser } from '../../support/browser'; import { waitForAppReady, seedItems, clearItems } from '../../support/seed'; import { buildItem, buildCheckedOutItem, buildConsumableItem, resetCounter } from '../../support/item-factory'; import { assertMinTouchTarget, assertWithinViewport } from '../../support/layout'; import { expectVisible, expectText } from '../../support/expect'; const { getPage } = setupBrowser(); describe('Dashboard', () => { test('empty state shows call-to-action', async () => { const page = getPage(); await page.goto('/'); await waitForAppReady(page); await clearItems(page); await page.reload(); await waitForAppReady(page); await expectVisible(page.getByText('No items yet')); await expectVisible(page.getByText('Add First Item')); await expectText(page.getByRole('heading', { level: 1 }), 'SolidHaus'); }); test('stats grid shows inventory summary', async () => { const page = getPage(); resetCounter(); await page.goto('/'); await waitForAppReady(page); const items = Array.from({ length: 5 }, (_, i) => buildItem({ name: `Item ${i + 1}`, category: i % 2 === 0 ? 'Electronics' : 'Kitchen' }) ); await seedItems(page, items); await page.reload(); await waitForAppReady(page); await expectVisible(page.getByText('Total Items')); await expectVisible(page.getByText('Checked Out')); await expectVisible(page.getByText('Overdue')); await expectVisible(page.getByText('Low Stock')); }); test('checked-out section appears when items are out', async () => { const page = getPage(); await page.goto('/'); await waitForAppReady(page); const item = buildCheckedOutItem({ name: 'Drill' }); await seedItems(page, [item]); await page.reload(); await waitForAppReady(page); await expectVisible(page.getByText('Drill').first()); }); test('low-stock section appears for depleted consumables', async () => { const page = getPage(); await page.goto('/'); await waitForAppReady(page); const item = buildConsumableItem({ name: 'Batteries', currentQuantity: 2, originalQuantity: 10, lowThreshold: 5, }); await seedItems(page, [item]); await page.reload(); await waitForAppReady(page); await expectVisible(page.getByText('Batteries').first()); }); test('recently updated items are shown', async () => { const page = getPage(); resetCounter(); await page.goto('/'); await waitForAppReady(page); const items = Array.from({ length: 3 }, (_, i) => buildItem({ name: `Item ${i + 1}` })); await seedItems(page, items); await page.reload(); await waitForAppReady(page); await expectVisible(page.getByText('Recently Updated')); }); test('navigation bar is visible and accessible', async () => { const page = getPage(); await page.goto('/'); await waitForAppReady(page); const navLinks = page.locator('nav a'); const count = await navLinks.count(); expect(count).toBe(5); for (let i = 0; i < count; i++) { await assertMinTouchTarget(navLinks.nth(i)); } await assertWithinViewport(page.locator('nav'), page); }); test('dashboard screenshot', async () => { const page = getPage(); resetCounter(); await page.goto('/'); await waitForAppReady(page); const items = Array.from({ length: 3 }, (_, i) => buildItem({ name: `Item ${i + 1}` })); await seedItems(page, items); await page.reload(); await waitForAppReady(page); const screenshot = await page.screenshot(); expect(screenshot).toBeInstanceOf(Buffer); }); });