agenthub/tests/ui-shared.test.ts
chahinebrini 986639a5f3 TSK-0028: AgentHub UI foundation + /team page
- Add src/server/ui-shared.ts: design tokens, agentAvatar(), statusPill(),
  escapeHtml(), liveTimerJs(), pageHeader(). No emojis, no deps.
- Add src/server/team.ts: role hierarchy renderer (architect -> implementer/
  reviewer/tester) with per-agent free/busy state derived from in-progress tasks.
- Wire GET /team route in src/server/routes.ts.
- Add tests/team.test.ts and tests/ui-shared.test.ts.

Build: npm run build clean. Tests: 132 passed (was 122).
2026-06-29 00:24:39 +02:00

51 lines
1.7 KiB
TypeScript

import { describe, it, expect } from 'vitest';
import { agentAvatar, designTokensCss, escapeHtml, liveTimerJs, statusPill } from '../src/server/ui-shared.js';
describe('ui-shared helpers', () => {
it('designTokensCss returns the dark palette variables', () => {
const css = designTokensCss();
expect(css).toContain('--bg: #0F172A');
expect(css).toContain('--status-in_progress: #58A6FF');
expect(css).toContain('prefers-reduced-motion');
});
it('agentAvatar renders initials without emojis', () => {
const html = agentAvatar('kimi');
expect(html).toContain('K');
expect(html).toContain('#7C3AED');
expect(html).not.toContain('emoji');
});
it('agentAvatar renders deterministic fallback for unknown agents', () => {
const html = agentAvatar('robo-agent-42');
expect(html).toContain('R');
expect(html).toContain('agent-avatar');
});
it('agentAvatar adds architect ring when requested', () => {
const html = agentAvatar('claude', { architectRing: true });
expect(html).toContain('box-shadow');
});
it('statusPill renders each known status', () => {
for (const status of ['open', 'in_progress', 'review', 'done', 'cancelled'] as const) {
const html = statusPill(status);
expect(html).toContain(`data-status="${status}"`);
expect(html).toContain('status-pill');
}
});
it('escapeHtml escapes dangerous characters', () => {
expect(escapeHtml('<script>alert("x")</script>')).toBe(
'&lt;script&gt;alert(&quot;x&quot;)&lt;/script&gt;',
);
});
it('liveTimerJs contains the setInterval updater', () => {
const js = liveTimerJs();
expect(js).toContain('setInterval');
expect(js).toContain('data-live-timer');
expect(js).toContain('claimed');
});
});