feat(#447): permission-gated reader dashboard #477

Merged
marcel merged 25 commits from worktree-feat+issue-447-reader-dashboard into main 2026-05-08 15:56:54 +02:00
Showing only changes of commit 3379392465 - Show all commits

View File

@@ -10,16 +10,18 @@ afterEach(cleanup);
vi.mock('$app/navigation', () => ({ goto: vi.fn(), invalidateAll: vi.fn() }));
const baseUser: User = {
id: 'u1',
email: 'max@example.com',
firstName: 'Max',
lastName: '',
groups: [],
enabled: true,
createdAt: '2024-01-01T00:00:00Z'
};
const baseData = {
user: {
id: 'u1',
email: 'max@example.com',
firstName: 'Max',
lastName: '',
groups: [],
enabled: true,
createdAt: '2024-01-01T00:00:00Z'
} as User,
user: baseUser,
isReader: false as const,
canWrite: true,
canAnnotate: false,
@@ -37,6 +39,20 @@ const baseData = {
error: null
};
const readerData = {
user: baseUser,
isReader: true as const,
canWrite: false,
canAnnotate: false,
canBlogWrite: false,
readerStats: { totalPersons: 12, totalDocuments: 34, totalStories: 5 },
topPersons: [],
recentDocs: [],
recentStories: [],
drafts: [],
error: null
};
// ─── Dashboard layout ─────────────────────────────────────────────────────────
describe('Home page dashboard layout', () => {
@@ -82,3 +98,34 @@ describe('Home page dashboard layout', () => {
await expect.element(page.getByText(/Dateien auf einmal hochladen/i)).not.toBeInTheDocument();
});
});
// ─── Reader dashboard layout ──────────────────────────────────────────────────
describe('Home page reader dashboard layout', () => {
it('renders ReaderStatsStrip totals when isReader is true', async () => {
render(Page, { data: readerData });
await expect.element(page.getByText('34')).toBeInTheDocument();
await expect.element(page.getByText('12')).toBeInTheDocument();
await expect.element(page.getByText('5')).toBeInTheDocument();
});
it('renders the recent-docs heading when isReader is true', async () => {
render(Page, { data: readerData });
await expect.element(page.getByText('Zuletzt aktualisiert')).toBeInTheDocument();
});
it('hides the contributor mission control caption when isReader is true', async () => {
render(Page, { data: readerData });
await expect.element(page.getByText('Offene Aufgaben')).not.toBeInTheDocument();
});
it('renders the drafts module when canBlogWrite is true', async () => {
render(Page, { data: { ...readerData, canBlogWrite: true } });
await expect.element(page.getByText('Meine Entwürfe')).toBeInTheDocument();
});
it('hides the drafts module when canBlogWrite is false', async () => {
render(Page, { data: readerData });
await expect.element(page.getByText('Meine Entwürfe')).not.toBeInTheDocument();
});
});