+
+
+
+
+
{#each documents as doc (doc.id)}
- -
-
-
-
+ {:else}
+ —
+ {/if}
+
+
+
+
+
{relativeTimeDe(new Date(doc.updatedAt))}
-
+
{/each}
diff --git a/frontend/src/lib/shared/dashboard/ReaderRecentDocs.svelte.spec.ts b/frontend/src/lib/shared/dashboard/ReaderRecentDocs.svelte.spec.ts
index 8960a5fa..f12f09f1 100644
--- a/frontend/src/lib/shared/dashboard/ReaderRecentDocs.svelte.spec.ts
+++ b/frontend/src/lib/shared/dashboard/ReaderRecentDocs.svelte.spec.ts
@@ -37,30 +37,73 @@ describe('ReaderRecentDocs', () => {
await expect.element(link).toHaveAttribute('href', '/documents/doc1');
});
- it('shows "Neu" badge when createdAt equals updatedAt', async () => {
+ it('card has overflow-hidden and flex-col classes (no p-6, no shadow-sm)', async () => {
+ render(ReaderRecentDocs, { documents: [baseDoc] });
+ const heading = page.getByRole('heading', { level: 3 });
+ const card = (await heading.element())?.closest('div');
+ const rootCard = card?.parentElement;
+ const cls = rootCard?.className ?? '';
+ expect(cls).toMatch(/overflow-hidden/);
+ expect(cls).toMatch(/flex-col/);
+ expect(cls).not.toMatch(/\bp-6\b/);
+ expect(cls).not.toMatch(/shadow-sm/);
+ });
+
+ it('card-head contains an h3 (not h2)', async () => {
+ render(ReaderRecentDocs, { documents: [baseDoc] });
+ const h3 = page.getByRole('heading', { level: 3 });
+ await expect.element(h3).toBeInTheDocument();
+ const h2 = page.getByRole('heading', { level: 2 });
+ await expect.element(h2).not.toBeInTheDocument();
+ });
+
+ it('"Alle Dokumente" link in card-head points to /documents', async () => {
+ render(ReaderRecentDocs, { documents: [baseDoc] });
+ const link = page.getByRole('link', { name: /Alle Dokumente/i });
+ await expect.element(link).toHaveAttribute('href', '/documents');
+ });
+
+ it('"Alle Dokumente" link has min-h-[44px]', async () => {
+ render(ReaderRecentDocs, { documents: [baseDoc] });
+ const link = page.getByRole('link', { name: /Alle Dokumente/i });
+ const cls = ((await link.element()) as HTMLElement).className;
+ expect(cls).toMatch(/min-h-\[44px\]/);
+ });
+
+ it('doc-row link has min-h-[44px] touch target', async () => {
+ render(ReaderRecentDocs, { documents: [baseDoc] });
+ const link = page.getByRole('link', { name: /Brief an Hans/ });
+ const cls = ((await link.element()) as HTMLElement).className;
+ expect(cls).toMatch(/min-h-\[44px\]/);
+ });
+
+ it('thumb element has correct classes', async () => {
+ render(ReaderRecentDocs, { documents: [baseDoc] });
+ const link = page.getByRole('link', { name: /Brief an Hans/ });
+ const el = (await link.element()) as HTMLElement;
+ const thumb = el.querySelector('[class*="w-5"][class*="h-6"]');
+ expect(thumb).not.toBeNull();
+ expect(thumb!.className).toMatch(/bg-canvas/);
+ expect(thumb!.className).toMatch(/border-line/);
+ expect(thumb!.className).toMatch(/rounded-/);
+ });
+
+ it('shows "Neu" mint-pill badge when createdAt equals updatedAt', async () => {
render(ReaderRecentDocs, { documents: [baseDoc] });
const badge = page.getByText(/^Neu$/i);
await expect.element(badge).toBeInTheDocument();
- });
-
- it('shows "Aktualisiert" badge when updatedAt differs from createdAt', async () => {
- render(ReaderRecentDocs, { documents: [updatedDoc] });
- const badge = page.getByText(/^Aktualisiert$/i);
- await expect.element(badge).toBeInTheDocument();
- });
-
- it('renders the "Aktualisiert" badge with high-contrast text-ink-1', async () => {
- render(ReaderRecentDocs, { documents: [updatedDoc] });
- const badge = page.getByText(/^Aktualisiert$/i);
const cls = ((await badge.element()) as HTMLElement).className;
- expect(cls).toMatch(/text-ink-1/);
- expect(cls).not.toMatch(/text-ink-3(?!\/)/);
+ expect(cls).toMatch(/bg-mint-soft/);
+ expect(cls).toMatch(/rounded-full/);
+ expect(cls).toMatch(/text-brand-navy/);
});
- it('does not show "Neu" badge when updatedAt differs from createdAt', async () => {
+ it('shows no badge when updatedAt differs from createdAt', async () => {
render(ReaderRecentDocs, { documents: [updatedDoc] });
const badge = page.getByText(/^Neu$/i);
await expect.element(badge).not.toBeInTheDocument();
+ const updatedBadge = page.getByText(/^Aktualisiert$/i);
+ await expect.element(updatedBadge).not.toBeInTheDocument();
});
it('shows "Neu" badge when createdAt and updatedAt represent the same instant in different ISO formats', async () => {
@@ -75,7 +118,7 @@ describe('ReaderRecentDocs', () => {
await expect.element(badge).toBeInTheDocument();
});
- it('renders sender link when sender is present', async () => {
+ it('renders sender name text when sender is present', async () => {
const docWithSender: Document = {
...baseDoc,
sender: {
@@ -88,7 +131,15 @@ describe('ReaderRecentDocs', () => {
}
};
render(ReaderRecentDocs, { documents: [docWithSender] });
- const senderLink = page.getByRole('link', { name: /Anna Müller/ });
- await expect.element(senderLink).toHaveAttribute('href', '/persons/p1');
+ const link = page.getByRole('link', { name: /Brief an Hans/ });
+ const el = (await link.element()) as HTMLElement;
+ expect(el.textContent).toContain('Anna Müller');
+ });
+
+ it('shows em-dash when sender is absent', async () => {
+ render(ReaderRecentDocs, { documents: [baseDoc] });
+ const link = page.getByRole('link', { name: /Brief an Hans/ });
+ const el = (await link.element()) as HTMLElement;
+ expect(el.textContent).toContain('—');
});
});