Extract dashboard RoomCardV2 component (#59)
* review: harden readonly git checks and lint verification * test: satisfy readonly reviewer sandbox typing * test: fix readonly reviewer sandbox assertions * test: remove impossible readonly sandbox guards * test: relax readonly sandbox assertions * test: cast readonly sandbox expectation shape * test: cast readonly sandbox expectation through unknown * Phase 0 — STEP_DONE/TASK_DONE split + owner-follow-up integration smoke * Add STEP_DONE guards, verdict storage, and stale delivery suppression * style: format paired stepdone telemetry files * Route STEP_DONE through reviewer * Add structured Discord attachments * style: format structured attachment test * Fix room thread bot output parity * Remove duplicate work item attachment migration from owner branch * Remove legacy dashboard rooms renderer * Extract dashboard parsed body renderer * Extract dashboard redaction helpers * Extract dashboard RoomCardV2 component * Include RoomCardV2 test in vitest suite
This commit is contained in:
112
apps/dashboard/src/RoomCardV2.test.ts
Normal file
112
apps/dashboard/src/RoomCardV2.test.ts
Normal file
@@ -0,0 +1,112 @@
|
||||
import { createElement } from 'react';
|
||||
import { renderToStaticMarkup } from 'react-dom/server';
|
||||
import { describe, expect, it } from 'vitest';
|
||||
|
||||
import type { DashboardRoomActivity } from './api';
|
||||
import { messages } from './i18n';
|
||||
import { RoomCardV2, type RoomEntryWithService } from './RoomCardV2';
|
||||
|
||||
const t = messages.ko;
|
||||
|
||||
const entry: RoomEntryWithService = {
|
||||
jid: 'room-1',
|
||||
name: 'eyejokerdb-main',
|
||||
folder: 'eyejokerdb',
|
||||
agentType: 'codex',
|
||||
status: 'inactive',
|
||||
elapsedMs: null,
|
||||
pendingMessages: false,
|
||||
pendingTasks: 0,
|
||||
serviceId: 'svc-1',
|
||||
};
|
||||
|
||||
const formatters = {
|
||||
formatDate: (value: string | null | undefined) => value ?? '-',
|
||||
formatDuration: (value: number | null) => (value === null ? '-' : `${value}`),
|
||||
formatLiveElapsed: (value: number) => `${value}`,
|
||||
senderRoleClass: (value: string | null | undefined) =>
|
||||
(value ?? '').toLowerCase().includes('owner') ? 'role-owner' : 'role-human',
|
||||
statusLabel: (status: string) => status,
|
||||
};
|
||||
|
||||
function activity(
|
||||
overrides: Partial<DashboardRoomActivity> = {},
|
||||
): DashboardRoomActivity {
|
||||
return {
|
||||
serviceId: 'svc-1',
|
||||
jid: 'room-1',
|
||||
name: 'eyejokerdb-main',
|
||||
folder: 'eyejokerdb',
|
||||
agentType: 'codex',
|
||||
status: 'inactive',
|
||||
elapsedMs: null,
|
||||
pendingMessages: false,
|
||||
pendingTasks: 0,
|
||||
messages: [],
|
||||
pairedTask: null,
|
||||
...overrides,
|
||||
};
|
||||
}
|
||||
|
||||
describe('RoomCardV2', () => {
|
||||
it('renders an inactive room without activity', () => {
|
||||
const html = renderToStaticMarkup(
|
||||
createElement(RoomCardV2, {
|
||||
activity: undefined,
|
||||
activityLoading: false,
|
||||
busy: false,
|
||||
draft: '',
|
||||
entry,
|
||||
expanded: false,
|
||||
inboxItems: [],
|
||||
locale: 'ko',
|
||||
onDraftChange: () => {},
|
||||
onSendMessage: () => {},
|
||||
onToggle: () => {},
|
||||
pinned: false,
|
||||
t,
|
||||
...formatters,
|
||||
}),
|
||||
);
|
||||
|
||||
expect(html).toContain('eyejokerdb-main');
|
||||
expect(html).toContain(t.rooms.noActivity);
|
||||
});
|
||||
|
||||
it('renders regular bot messages in the expanded thread', () => {
|
||||
const html = renderToStaticMarkup(
|
||||
createElement(RoomCardV2, {
|
||||
activity: activity({
|
||||
messages: [
|
||||
{
|
||||
id: 'bot-1',
|
||||
sender: 'bot-1',
|
||||
senderName: 'owner',
|
||||
content: 'TASK_DONE\n\nprod 배포 완료',
|
||||
timestamp: '2026-04-28T02:00:00.000Z',
|
||||
isFromMe: false,
|
||||
isBotMessage: true,
|
||||
sourceKind: 'bot',
|
||||
},
|
||||
],
|
||||
}),
|
||||
activityLoading: false,
|
||||
busy: false,
|
||||
draft: '',
|
||||
entry,
|
||||
expanded: true,
|
||||
inboxItems: [],
|
||||
locale: 'ko',
|
||||
onDraftChange: () => {},
|
||||
onSendMessage: () => {},
|
||||
onToggle: () => {},
|
||||
pinned: true,
|
||||
t,
|
||||
...formatters,
|
||||
}),
|
||||
);
|
||||
|
||||
expect(html).toContain('TASK_DONE');
|
||||
expect(html).toContain('prod 배포 완료');
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user