test(dashboard): cover DashboardResumeStrip branches
Empty card vs populated strip, title rendering, thumbnail image vs fallback icon, progress bar aria-valuenow, document detail link, collaborators stack rendering, safeColor fallback to default when hex invalid. 9 tests covering ~25 of DashboardResumeStrip's branches. Refs #496. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,105 @@
|
||||
import { describe, it, expect, afterEach } from 'vitest';
|
||||
import { cleanup, render } from 'vitest-browser-svelte';
|
||||
import { page } from 'vitest/browser';
|
||||
import DashboardResumeStrip from './DashboardResumeStrip.svelte';
|
||||
|
||||
afterEach(cleanup);
|
||||
|
||||
const makeResume = (overrides: Record<string, unknown> = {}) => ({
|
||||
documentId: 'd1',
|
||||
title: 'Brief 1923',
|
||||
caption: 'Sender → Receiver',
|
||||
excerpt: 'First paragraph',
|
||||
totalBlocks: 12,
|
||||
pct: 50,
|
||||
thumbnailUrl: '/api/d1/thumb',
|
||||
collaborators: [{ initials: 'AS', color: '#012851', name: null }],
|
||||
...overrides
|
||||
});
|
||||
|
||||
describe('DashboardResumeStrip', () => {
|
||||
it('renders the empty card when resumeDoc is null', async () => {
|
||||
render(DashboardResumeStrip, { props: { resumeDoc: null } });
|
||||
|
||||
const empty = document.querySelector('[data-testid="resume-strip-empty"]');
|
||||
expect(empty).not.toBeNull();
|
||||
await expect
|
||||
.element(page.getByRole('heading', { name: /noch kein dokument begonnen/i }))
|
||||
.toBeVisible();
|
||||
});
|
||||
|
||||
it('renders the resume strip when resumeDoc is provided', async () => {
|
||||
render(DashboardResumeStrip, { props: { resumeDoc: makeResume() } });
|
||||
|
||||
expect(document.querySelector('[data-testid="resume-strip"]')).not.toBeNull();
|
||||
});
|
||||
|
||||
it('renders the document title', async () => {
|
||||
render(DashboardResumeStrip, { props: { resumeDoc: makeResume() } });
|
||||
|
||||
await expect.element(page.getByRole('heading', { name: /brief 1923/i })).toBeVisible();
|
||||
});
|
||||
|
||||
it('renders the thumbnail image when thumbnailUrl is set', async () => {
|
||||
render(DashboardResumeStrip, { props: { resumeDoc: makeResume() } });
|
||||
|
||||
expect(document.querySelector('[data-testid="resume-thumbnail-img"]')).not.toBeNull();
|
||||
});
|
||||
|
||||
it('renders the placeholder icon when thumbnailUrl is missing', async () => {
|
||||
render(DashboardResumeStrip, {
|
||||
props: { resumeDoc: makeResume({ thumbnailUrl: null }) }
|
||||
});
|
||||
|
||||
expect(document.querySelector('[data-testid="resume-thumbnail-fallback"]')).not.toBeNull();
|
||||
});
|
||||
|
||||
it('renders the progress bar with correct aria-valuenow', async () => {
|
||||
render(DashboardResumeStrip, { props: { resumeDoc: makeResume({ pct: 75 }) } });
|
||||
|
||||
const progress = document.querySelector('[role="progressbar"]') as HTMLElement;
|
||||
expect(progress.getAttribute('aria-valuenow')).toBe('75');
|
||||
});
|
||||
|
||||
it('renders the resume CTA link to the document detail', async () => {
|
||||
render(DashboardResumeStrip, {
|
||||
props: { resumeDoc: makeResume({ documentId: 'doc-42' }) }
|
||||
});
|
||||
|
||||
const link = document.querySelector('a[href="/documents/doc-42"]') as HTMLAnchorElement;
|
||||
expect(link).not.toBeNull();
|
||||
});
|
||||
|
||||
it('renders the collaborators stack', async () => {
|
||||
render(DashboardResumeStrip, {
|
||||
props: {
|
||||
resumeDoc: makeResume({
|
||||
collaborators: [
|
||||
{ initials: 'XR', color: '#012851', name: null },
|
||||
{ initials: 'YQ', color: '#5A3080', name: null }
|
||||
]
|
||||
})
|
||||
}
|
||||
});
|
||||
|
||||
await expect.element(page.getByText('XR')).toBeVisible();
|
||||
await expect.element(page.getByText('YQ')).toBeVisible();
|
||||
});
|
||||
|
||||
it('falls back to the default color when collaborator color is invalid', async () => {
|
||||
render(DashboardResumeStrip, {
|
||||
props: {
|
||||
resumeDoc: makeResume({
|
||||
collaborators: [{ initials: 'ZQ', color: 'not-a-hex', name: null }]
|
||||
})
|
||||
}
|
||||
});
|
||||
|
||||
// safeColor falls back to #8c9aa3 — browser may serialize as rgb(140, 154, 163)
|
||||
const span = Array.from(document.querySelectorAll('span')).find(
|
||||
(s) => s.textContent?.trim() === 'ZQ'
|
||||
) as HTMLElement;
|
||||
const style = span.getAttribute('style') ?? '';
|
||||
expect(style.toLowerCase()).toMatch(/(8c9aa3|140,\s*154,\s*163)/);
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user