import assert from 'node:assert/strict' import { readFileSync } from 'node:fs' import { resolve } from 'node:path' import { renderToStaticMarkup } from 'react-dom/server' import { freezeAssistantModelMetadata } from '../src/shared/assistant-model' import { AssistantMessageDetails, formatMessageTime } from '../src/renderer/src/components/AssistantMessageDetails' import { getModelIconByName } from '../src/renderer/src/workbuddy/composer/model-selector/source.mjs' import type { ChatMessage } from '../src/shared/types' const renderTime = new Date() renderTime.setHours(12, 0, 0, 0) const profile = { id: 'profile-1', name: 'Frozen Model' } const metadata = freezeAssistantModelMetadata(profile) profile.name = 'Renamed Model' assert.deepEqual(metadata, { modelId: 'profile-1', modelName: 'Frozen Model' }) const newAssistantMessage: ChatMessage = { id: 'assistant-1', role: 'assistant', content: 'answer', createdAt: renderTime.getTime(), status: 'done', ...metadata } const newFooter = renderToStaticMarkup() assert.match(newFooter, /cb-credit-usage-text cb-credit-usage-text--feedback/) assert.match(newFooter, /title="profile-1"/) assert.match(newFooter, /class="cb-model-tag-icon"[^>]*aria-hidden="true"/) assert.match(newFooter, /Frozen Model/) assert.doesNotMatch(newFooter, /Renamed Model/) assert.match(newFooter, /_message_time_tip_1p6pj_1 cb-message-time-tip/) assert.match(newFooter, />12:00<\/span>/) const historicalMessage: ChatMessage = { id: 'assistant-old', role: 'assistant', content: 'legacy answer', createdAt: renderTime.getTime(), status: 'done' } const historicalFooter = renderToStaticMarkup() assert.doesNotMatch(historicalFooter, /cb-credit-usage-text/) assert.doesNotMatch(historicalFooter, /Frozen Model|Renamed Model/) const footerCss = readFileSync(resolve('src/renderer/src/components/assistant-message-details.css'), 'utf8') assert.doesNotMatch(footerCss, /\.cb-credit-usage-text--feedback\s*\{[^}]*opacity:\s*0/s) assert.doesNotMatch(footerCss, /top:4px/, 'metadata shares a flex centerline instead of a timestamp offset') assert.match(footerCss, /cb-assistant-message-details\{[^}]*font-family:[^}]*sans-serif[^}]*font-size:15px[^}]*line-height:24px/s) const brandMarkup = (name: string): string => renderToStaticMarkup() const gptGlyph = renderToStaticMarkup(<>{getModelIconByName('gpt-6-luna')}) const deepseekGlyph = renderToStaticMarkup(<>{getModelIconByName('deepseek-flash')}) assert.notEqual(gptGlyph, deepseekGlyph, 'GPT and DeepSeek must use different brand logos') assert.ok(brandMarkup('gpt-6-luna').includes(gptGlyph)) assert.ok(brandMarkup('deepseek-flash').includes(deepseekGlyph)) assert.match(footerCss, /\.cb-assistant-message:hover \.cb-credit-usage-text--feedback,\.cb-assistant-message:hover \.cb-message-time-tip\{opacity:1\}/) const now = new Date(2025, 3, 10, 12, 0) const today = new Date(2025, 3, 10, 8, 4).getTime() const yesterday = new Date(2025, 3, 9, 9, 5).getTime() const earlierThisYear = new Date(2025, 3, 7, 9, 5).getTime() const earlierYear = new Date(2024, 11, 31, 9, 5).getTime() assert.equal(formatMessageTime(today, now), '08:04') assert.equal(formatMessageTime(yesterday, now), '4月9日 09:05') assert.equal(formatMessageTime(earlierThisYear, now), '4月7日 09:05') assert.equal(formatMessageTime(earlierYear, now), '2024年12月31日 09:05') assert.equal(formatMessageTime(Number.NaN, now), undefined) console.log('assistant-message-footer-regression: frozen model metadata, legacy history, and date formatting passed')