Files
familienarchiv/frontend/src/routes/page.svelte.spec.ts
Marcel 5a98edac86 feat(dashboard): complete frontend redesign for Issue #271
- +layout.svelte: Upload button in header (authenticated users only)
- +page.server.ts: call /api/dashboard/resume, /pulse, /activity;
  remove deprecated /api/documents/incomplete and /recent-activity
- +page.svelte: 2-col grid layout (main + 320px sidebar), greeting,
  DashboardFamilyPulse + DashboardActivityFeed in sidebar
- DashboardResumeStrip: refactored to use server data (resumeDoc prop),
  SVG thumbnail, progress bar with aria-*, empty state, CTA
- DashboardFamilyPulse: new component — weekly stats from audit_log
- DashboardActivityFeed: new component — activity feed with "für dich" badge
- Update specs for new data shapes

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-20 07:45:16 +02:00

81 lines
2.5 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import { afterEach, describe, expect, it, vi } from 'vitest';
import { cleanup, render } from 'vitest-browser-svelte';
import { page } from 'vitest/browser';
import type { components } from '$lib/generated/api';
import Page from './+page.svelte';
type User = components['schemas']['AppUser'];
afterEach(cleanup);
vi.mock('$app/navigation', () => ({ goto: vi.fn(), invalidateAll: vi.fn() }));
const baseData = {
user: {
id: 'u1',
email: 'max@example.com',
firstName: 'Max',
lastName: '',
groups: [],
enabled: true,
createdAt: '2024-01-01T00:00:00Z'
} as User,
canWrite: true,
canAnnotate: false,
resumeDoc: null,
pulse: null,
activityFeed: [],
stats: null,
segmentationDocs: [],
transcriptionDocs: [],
readyDocs: [],
weeklyStats: null,
error: null
};
// ─── Dashboard layout ─────────────────────────────────────────────────────────
describe('Home page dashboard layout', () => {
it('does not render a search input', async () => {
render(Page, { data: baseData });
const input = page.getByPlaceholder('Titel, Personen, Tags durchsuchen…');
await expect.element(input).not.toBeInTheDocument();
});
it('renders a greeting for the logged-in user', async () => {
render(Page, { data: baseData });
await expect.element(page.getByRole('heading', { level: 1 })).toBeInTheDocument();
});
it('renders resume strip empty state when resumeDoc is null', async () => {
render(Page, { data: baseData });
const empty = page.getByTestId('resume-strip-empty');
await expect.element(empty).toBeInTheDocument();
});
it('renders resume card when resumeDoc is provided', async () => {
const resume = {
documentId: 'doc-1',
title: 'Geburtsurkunde',
caption: 'Max · 1920',
excerpt: 'Hiermit…',
totalBlocks: 3,
pct: 33,
collaborators: []
};
render(Page, { data: { ...baseData, resumeDoc: resume } });
const strip = page.getByTestId('resume-strip');
await expect.element(strip).toBeInTheDocument();
});
it('shows drop zone when canWrite is true', async () => {
render(Page, { data: { ...baseData, canWrite: true } });
await expect.element(page.getByText(/Dateien auf einmal hochladen/i)).toBeInTheDocument();
});
it('hides drop zone when canWrite is false', async () => {
render(Page, { data: { ...baseData, canWrite: false } });
await expect.element(page.getByText(/Dateien auf einmal hochladen/i)).not.toBeInTheDocument();
});
});