refactor(briefwechsel): extract bilateral DistributionBar component
Lifts the inline distribution bar out of ConversationTimeline so the same two-tone ratio widget can be reused on other bilateral surfaces (e.g. the person detail page). Markup/styling is byte-identical to the inline version; only the prop interface is new. Refs #305 Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
58
frontend/src/lib/components/DistributionBar.svelte.spec.ts
Normal file
58
frontend/src/lib/components/DistributionBar.svelte.spec.ts
Normal file
@@ -0,0 +1,58 @@
|
||||
import { describe, it, expect, afterEach } from 'vitest';
|
||||
import { cleanup, render } from 'vitest-browser-svelte';
|
||||
|
||||
import DistributionBar from './DistributionBar.svelte';
|
||||
|
||||
afterEach(() => {
|
||||
cleanup();
|
||||
});
|
||||
|
||||
describe('DistributionBar', () => {
|
||||
it('renders both counts and short names, and the two-tone fill bar', async () => {
|
||||
render(DistributionBar, {
|
||||
outCount: 3,
|
||||
inCount: 7,
|
||||
senderName: 'Hans Müller',
|
||||
receiverName: 'Anna Schmidt'
|
||||
});
|
||||
|
||||
const container = document.querySelector('[role="img"]') as HTMLElement;
|
||||
expect(container).toBeTruthy();
|
||||
expect(container.getAttribute('aria-label')).toContain('3 von Hans Müller');
|
||||
expect(container.getAttribute('aria-label')).toContain('7 von Anna Schmidt');
|
||||
|
||||
expect(container.textContent).toContain('3 von Hans');
|
||||
expect(container.textContent).toContain('7 von Anna');
|
||||
|
||||
// 3/10 → 30% / 70% split on the two segments
|
||||
const segments = container.querySelectorAll('[data-testid="dist-bar-segment"]');
|
||||
expect(segments).toHaveLength(2);
|
||||
expect((segments[0] as HTMLElement).style.width).toBe('30%');
|
||||
expect((segments[1] as HTMLElement).style.width).toBe('70%');
|
||||
});
|
||||
|
||||
it('falls back to the full name when it has no space to split', async () => {
|
||||
render(DistributionBar, {
|
||||
outCount: 1,
|
||||
inCount: 0,
|
||||
senderName: 'SingleWord',
|
||||
receiverName: 'Another'
|
||||
});
|
||||
|
||||
const container = document.querySelector('[role="img"]') as HTMLElement;
|
||||
expect(container.textContent).toContain('1 von SingleWord');
|
||||
});
|
||||
|
||||
it('renders a zero-percent left segment when outCount is zero', async () => {
|
||||
render(DistributionBar, {
|
||||
outCount: 0,
|
||||
inCount: 4,
|
||||
senderName: 'Hans',
|
||||
receiverName: 'Anna'
|
||||
});
|
||||
|
||||
const segments = document.querySelectorAll('[data-testid="dist-bar-segment"]');
|
||||
expect((segments[0] as HTMLElement).style.width).toBe('0%');
|
||||
expect((segments[1] as HTMLElement).style.width).toBe('100%');
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user