feat(#145): transform home page into user dashboard #151

Merged
marcel merged 14 commits from feat/145-dashboard into main 2026-03-29 12:39:39 +02:00
2 changed files with 60 additions and 44 deletions
Showing only changes of commit dc487e2f97 - Show all commits

View File

@@ -1,45 +1,3 @@
/**
* Captures dashboard screenshots at multiple viewport sizes and in both
* light and dark theme. Output goes to proofshot-artifacts/dashboard/.
* Run via: npx playwright test e2e/dashboard-screenshots.spec.ts
*/
import { test } from '@playwright/test';
import path from 'path';
import fs from 'fs';
import { fileURLToPath } from 'url';
import { captureProofshots } from './proofshots';
const __dirname = path.dirname(fileURLToPath(import.meta.url));
const outDir = path.join(__dirname, '../../proofshot-artifacts/dashboard');
fs.mkdirSync(outDir, { recursive: true });
const viewports = [
{ name: 'mobile', width: 390, height: 844 },
{ name: 'tablet', width: 768, height: 1024 },
{ name: 'desktop', width: 1440, height: 900 }
];
for (const vp of viewports) {
for (const theme of ['light', 'dark'] as const) {
test(`dashboard ${vp.name} ${theme}`, async ({ page }) => {
await page.setViewportSize({ width: vp.width, height: vp.height });
await page.goto('/');
// Apply theme
await page.evaluate((t) => {
document.documentElement.setAttribute('data-theme', t);
localStorage.setItem('theme', t);
}, theme);
// Wait for the main content to be rendered.
// 'networkidle' is unreliable in SvelteKit dev mode due to the HMR WebSocket.
await page.waitForLoadState('domcontentloaded');
// Wait for at least one dashboard widget or the search bar to be visible
await page.waitForSelector('main', { state: 'visible' });
await page.screenshot({
path: path.join(outDir, `dashboard-${vp.name}-${theme}.png`),
fullPage: true
});
});
}
}
captureProofshots('/', 'dashboard');

View File

@@ -0,0 +1,58 @@
/**
* Shared proofshot helper for Playwright.
*
* Usage in any spec file:
* import { captureProofshots } from './proofshots';
* captureProofshots('/persons', 'persons');
*
* This registers one test per viewport × theme combination.
* Screenshots are saved to proofshot-artifacts/{featureName}/.
*/
import { test } from '@playwright/test';
import path from 'path';
import fs from 'fs';
import { fileURLToPath } from 'url';
const __dirname = path.dirname(fileURLToPath(import.meta.url));
const viewports = [
{ name: 'mobile', width: 390, height: 844 },
{ name: 'tablet', width: 768, height: 1024 },
{ name: 'desktop', width: 1440, height: 900 }
];
/**
* Registers Playwright tests that navigate to `url`, apply each theme,
* and capture full-page screenshots at all standard viewports.
*
* @param url The path to screenshot (e.g. '/', '/persons', '/admin')
* @param featureName Used as the output directory name and screenshot file prefix
*/
export function captureProofshots(url: string, featureName: string): void {
const outDir = path.join(__dirname, '../../proofshot-artifacts', featureName);
fs.mkdirSync(outDir, { recursive: true });
for (const vp of viewports) {
for (const theme of ['light', 'dark'] as const) {
test(`${featureName} ${vp.name} ${theme}`, async ({ page }) => {
await page.setViewportSize({ width: vp.width, height: vp.height });
await page.goto(url);
// Apply theme via data-theme attribute and localStorage
await page.evaluate((t) => {
document.documentElement.setAttribute('data-theme', t);
localStorage.setItem('theme', t);
}, theme);
// 'networkidle' is unreliable in SvelteKit dev mode due to the HMR WebSocket.
await page.waitForLoadState('domcontentloaded');
await page.waitForSelector('main', { state: 'visible' });
await page.screenshot({
path: path.join(outDir, `${featureName}-${vp.name}-${theme}.png`),
fullPage: true
});
});
}
}
}