mirror of
https://github.com/tiennm99/ccs.git
synced 2026-07-16 08:17:11 +00:00
fix(ui): guard invalid log detail timestamps
This commit is contained in:
@@ -9,6 +9,7 @@ import { LogLevelBadge } from './log-level-badge';
|
||||
import { LogsEmpty } from './logs-empty';
|
||||
import {
|
||||
formatJson,
|
||||
formatLogTimestampIso,
|
||||
getDisplayLatency,
|
||||
getDisplayModule,
|
||||
getDisplayRequestId,
|
||||
@@ -34,7 +35,7 @@ interface OverviewRow {
|
||||
function buildOverviewRows(entry: LogsEntry, sourceLabel?: string): OverviewRow[] {
|
||||
// Use shared accessors so this panel and the list row never diverge.
|
||||
return [
|
||||
{ label: 'Time', value: new Date(entry.timestamp).toISOString(), mono: true },
|
||||
{ label: 'Time', value: formatLogTimestampIso(entry.timestamp), mono: true },
|
||||
{ label: 'Level', value: entry.level },
|
||||
{ label: 'Module', value: getDisplayModule(entry, sourceLabel) },
|
||||
{ label: 'Stage', value: getDisplayStage(entry) },
|
||||
|
||||
@@ -21,6 +21,19 @@ export function formatLogTimestamp(timestamp: string | null | undefined) {
|
||||
}).format(date);
|
||||
}
|
||||
|
||||
export function formatLogTimestampIso(timestamp: string | null | undefined) {
|
||||
if (!timestamp) {
|
||||
return 'No activity yet';
|
||||
}
|
||||
|
||||
const date = new Date(timestamp);
|
||||
if (Number.isNaN(date.getTime())) {
|
||||
return timestamp;
|
||||
}
|
||||
|
||||
return date.toISOString();
|
||||
}
|
||||
|
||||
export function formatRelativeLogTime(timestamp: string | null | undefined) {
|
||||
if (!timestamp) {
|
||||
return 'No activity yet';
|
||||
|
||||
@@ -0,0 +1,27 @@
|
||||
import { render, screen } from '@tests/setup/test-utils';
|
||||
import { describe, expect, it } from 'vitest';
|
||||
import { LogsDetailPanel } from '@/components/logs/logs-detail-panel';
|
||||
import type { LogsEntry } from '@/lib/api-client';
|
||||
|
||||
function buildEntry(overrides: Partial<LogsEntry> = {}): LogsEntry {
|
||||
return {
|
||||
id: 'entry-1',
|
||||
timestamp: '2026-04-07T11:00:00.000Z',
|
||||
level: 'info',
|
||||
source: 'dashboard',
|
||||
event: 'logs.bootstrap',
|
||||
message: 'Dashboard log entry',
|
||||
processId: 25582,
|
||||
runId: 'run-1',
|
||||
...overrides,
|
||||
};
|
||||
}
|
||||
|
||||
describe('LogsDetailPanel', () => {
|
||||
it('falls back to the raw timestamp when the selected log entry has an invalid timestamp', () => {
|
||||
render(<LogsDetailPanel entry={buildEntry({ timestamp: 'not-a-date' })} />);
|
||||
|
||||
expect(screen.getByText('not-a-date')).toBeInTheDocument();
|
||||
expect(screen.getByTitle('not-a-date')).toHaveTextContent('not-a-date');
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user