mirror of
https://github.com/claude-code-best/claude-code.git
synced 2026-06-18 22:35:51 +00:00
style: 完成所有文件的lint
This commit is contained in:
@@ -1,4 +1,4 @@
|
||||
import { describe, expect, test } from "bun:test";
|
||||
import { describe, expect, test } from 'bun:test'
|
||||
import {
|
||||
formatFileSize,
|
||||
formatSecondsShort,
|
||||
@@ -8,291 +8,291 @@ import {
|
||||
formatRelativeTime,
|
||||
formatRelativeTimeAgo,
|
||||
formatLogMetadata,
|
||||
} from "../format";
|
||||
} from '../format'
|
||||
|
||||
describe("formatFileSize", () => {
|
||||
test("formats bytes", () => {
|
||||
expect(formatFileSize(500)).toBe("500 bytes");
|
||||
});
|
||||
describe('formatFileSize', () => {
|
||||
test('formats bytes', () => {
|
||||
expect(formatFileSize(500)).toBe('500 bytes')
|
||||
})
|
||||
|
||||
test("formats kilobytes", () => {
|
||||
expect(formatFileSize(1536)).toBe("1.5KB");
|
||||
});
|
||||
test('formats kilobytes', () => {
|
||||
expect(formatFileSize(1536)).toBe('1.5KB')
|
||||
})
|
||||
|
||||
test("formats megabytes", () => {
|
||||
expect(formatFileSize(1.5 * 1024 * 1024)).toBe("1.5MB");
|
||||
});
|
||||
test('formats megabytes', () => {
|
||||
expect(formatFileSize(1.5 * 1024 * 1024)).toBe('1.5MB')
|
||||
})
|
||||
|
||||
test("formats gigabytes", () => {
|
||||
expect(formatFileSize(2 * 1024 * 1024 * 1024)).toBe("2GB");
|
||||
});
|
||||
test('formats gigabytes', () => {
|
||||
expect(formatFileSize(2 * 1024 * 1024 * 1024)).toBe('2GB')
|
||||
})
|
||||
|
||||
test("removes trailing .0", () => {
|
||||
expect(formatFileSize(1024)).toBe("1KB");
|
||||
});
|
||||
});
|
||||
test('removes trailing .0', () => {
|
||||
expect(formatFileSize(1024)).toBe('1KB')
|
||||
})
|
||||
})
|
||||
|
||||
describe("formatSecondsShort", () => {
|
||||
test("formats milliseconds to seconds", () => {
|
||||
expect(formatSecondsShort(1234)).toBe("1.2s");
|
||||
});
|
||||
describe('formatSecondsShort', () => {
|
||||
test('formats milliseconds to seconds', () => {
|
||||
expect(formatSecondsShort(1234)).toBe('1.2s')
|
||||
})
|
||||
|
||||
test("formats zero", () => {
|
||||
expect(formatSecondsShort(0)).toBe("0.0s");
|
||||
});
|
||||
test('formats zero', () => {
|
||||
expect(formatSecondsShort(0)).toBe('0.0s')
|
||||
})
|
||||
|
||||
test("formats sub-second", () => {
|
||||
expect(formatSecondsShort(500)).toBe("0.5s");
|
||||
});
|
||||
});
|
||||
test('formats sub-second', () => {
|
||||
expect(formatSecondsShort(500)).toBe('0.5s')
|
||||
})
|
||||
})
|
||||
|
||||
describe("formatDuration", () => {
|
||||
test("formats 0 as 0s", () => {
|
||||
expect(formatDuration(0)).toBe("0s");
|
||||
});
|
||||
describe('formatDuration', () => {
|
||||
test('formats 0 as 0s', () => {
|
||||
expect(formatDuration(0)).toBe('0s')
|
||||
})
|
||||
|
||||
test("formats seconds", () => {
|
||||
expect(formatDuration(5000)).toBe("5s");
|
||||
});
|
||||
test('formats seconds', () => {
|
||||
expect(formatDuration(5000)).toBe('5s')
|
||||
})
|
||||
|
||||
test("formats minutes and seconds", () => {
|
||||
expect(formatDuration(125000)).toBe("2m 5s");
|
||||
});
|
||||
test('formats minutes and seconds', () => {
|
||||
expect(formatDuration(125000)).toBe('2m 5s')
|
||||
})
|
||||
|
||||
test("formats hours", () => {
|
||||
expect(formatDuration(3661000)).toBe("1h 1m 1s");
|
||||
});
|
||||
test('formats hours', () => {
|
||||
expect(formatDuration(3661000)).toBe('1h 1m 1s')
|
||||
})
|
||||
|
||||
test("formats days", () => {
|
||||
expect(formatDuration(90000000)).toBe("1d 1h 0m");
|
||||
});
|
||||
test('formats days', () => {
|
||||
expect(formatDuration(90000000)).toBe('1d 1h 0m')
|
||||
})
|
||||
|
||||
test("hideTrailingZeros removes zero components", () => {
|
||||
expect(formatDuration(3600000, { hideTrailingZeros: true })).toBe("1h");
|
||||
expect(formatDuration(60000, { hideTrailingZeros: true })).toBe("1m");
|
||||
});
|
||||
test('hideTrailingZeros removes zero components', () => {
|
||||
expect(formatDuration(3600000, { hideTrailingZeros: true })).toBe('1h')
|
||||
expect(formatDuration(60000, { hideTrailingZeros: true })).toBe('1m')
|
||||
})
|
||||
|
||||
test("mostSignificantOnly returns largest unit", () => {
|
||||
expect(formatDuration(90000000, { mostSignificantOnly: true })).toBe("1d");
|
||||
expect(formatDuration(3661000, { mostSignificantOnly: true })).toBe("1h");
|
||||
});
|
||||
});
|
||||
test('mostSignificantOnly returns largest unit', () => {
|
||||
expect(formatDuration(90000000, { mostSignificantOnly: true })).toBe('1d')
|
||||
expect(formatDuration(3661000, { mostSignificantOnly: true })).toBe('1h')
|
||||
})
|
||||
})
|
||||
|
||||
describe("formatNumber", () => {
|
||||
test("formats small numbers as-is", () => {
|
||||
expect(formatNumber(900)).toBe("900");
|
||||
});
|
||||
describe('formatNumber', () => {
|
||||
test('formats small numbers as-is', () => {
|
||||
expect(formatNumber(900)).toBe('900')
|
||||
})
|
||||
|
||||
test("formats thousands with k suffix", () => {
|
||||
expect(formatNumber(1321)).toBe("1.3k");
|
||||
});
|
||||
test('formats thousands with k suffix', () => {
|
||||
expect(formatNumber(1321)).toBe('1.3k')
|
||||
})
|
||||
|
||||
test("formats millions", () => {
|
||||
expect(formatNumber(1500000)).toBe("1.5m");
|
||||
});
|
||||
test('formats millions', () => {
|
||||
expect(formatNumber(1500000)).toBe('1.5m')
|
||||
})
|
||||
|
||||
test("formats 0 as-is", () => {
|
||||
expect(formatNumber(0)).toBe("0");
|
||||
});
|
||||
test('formats 0 as-is', () => {
|
||||
expect(formatNumber(0)).toBe('0')
|
||||
})
|
||||
|
||||
test("formats billions", () => {
|
||||
expect(formatNumber(1500000000)).toBe("1.5b");
|
||||
});
|
||||
});
|
||||
test('formats billions', () => {
|
||||
expect(formatNumber(1500000000)).toBe('1.5b')
|
||||
})
|
||||
})
|
||||
|
||||
describe("formatTokens", () => {
|
||||
test("removes .0 from formatted number", () => {
|
||||
expect(formatTokens(1000)).toBe("1k");
|
||||
});
|
||||
describe('formatTokens', () => {
|
||||
test('removes .0 from formatted number', () => {
|
||||
expect(formatTokens(1000)).toBe('1k')
|
||||
})
|
||||
|
||||
test("formats small numbers", () => {
|
||||
expect(formatTokens(500)).toBe("500");
|
||||
});
|
||||
test('formats small numbers', () => {
|
||||
expect(formatTokens(500)).toBe('500')
|
||||
})
|
||||
|
||||
test("formats 1000 without .0", () => {
|
||||
expect(formatTokens(1000)).toBe("1k");
|
||||
});
|
||||
test('formats 1000 without .0', () => {
|
||||
expect(formatTokens(1000)).toBe('1k')
|
||||
})
|
||||
|
||||
test("formats 1500 as 1.5k", () => {
|
||||
expect(formatTokens(1500)).toBe("1.5k");
|
||||
});
|
||||
});
|
||||
test('formats 1500 as 1.5k', () => {
|
||||
expect(formatTokens(1500)).toBe('1.5k')
|
||||
})
|
||||
})
|
||||
|
||||
describe("formatRelativeTime", () => {
|
||||
const now = new Date("2026-01-15T12:00:00Z");
|
||||
describe('formatRelativeTime', () => {
|
||||
const now = new Date('2026-01-15T12:00:00Z')
|
||||
|
||||
test("formats seconds ago", () => {
|
||||
const date = new Date("2026-01-15T11:59:30Z");
|
||||
expect(formatRelativeTime(date, { now })).toBe("30s ago");
|
||||
});
|
||||
test('formats seconds ago', () => {
|
||||
const date = new Date('2026-01-15T11:59:30Z')
|
||||
expect(formatRelativeTime(date, { now })).toBe('30s ago')
|
||||
})
|
||||
|
||||
test("formats minutes ago", () => {
|
||||
const date = new Date("2026-01-15T11:55:00Z");
|
||||
expect(formatRelativeTime(date, { now })).toBe("5m ago");
|
||||
});
|
||||
test('formats minutes ago', () => {
|
||||
const date = new Date('2026-01-15T11:55:00Z')
|
||||
expect(formatRelativeTime(date, { now })).toBe('5m ago')
|
||||
})
|
||||
|
||||
test("formats future time", () => {
|
||||
const date = new Date("2026-01-15T13:00:00Z");
|
||||
expect(formatRelativeTime(date, { now })).toBe("in 1h");
|
||||
});
|
||||
test('formats future time', () => {
|
||||
const date = new Date('2026-01-15T13:00:00Z')
|
||||
expect(formatRelativeTime(date, { now })).toBe('in 1h')
|
||||
})
|
||||
|
||||
test("handles zero difference", () => {
|
||||
expect(formatRelativeTime(now, { now })).toBe("0s ago");
|
||||
});
|
||||
test('handles zero difference', () => {
|
||||
expect(formatRelativeTime(now, { now })).toBe('0s ago')
|
||||
})
|
||||
|
||||
test("formats hours ago", () => {
|
||||
const date = new Date("2026-01-15T09:00:00Z");
|
||||
expect(formatRelativeTime(date, { now })).toBe("3h ago");
|
||||
});
|
||||
test('formats hours ago', () => {
|
||||
const date = new Date('2026-01-15T09:00:00Z')
|
||||
expect(formatRelativeTime(date, { now })).toBe('3h ago')
|
||||
})
|
||||
|
||||
test("formats days ago", () => {
|
||||
const date = new Date("2026-01-13T12:00:00Z");
|
||||
expect(formatRelativeTime(date, { now })).toBe("2d ago");
|
||||
});
|
||||
test('formats days ago', () => {
|
||||
const date = new Date('2026-01-13T12:00:00Z')
|
||||
expect(formatRelativeTime(date, { now })).toBe('2d ago')
|
||||
})
|
||||
|
||||
test("formats weeks ago", () => {
|
||||
const date = new Date("2026-01-01T12:00:00Z");
|
||||
expect(formatRelativeTime(date, { now })).toBe("2w ago");
|
||||
});
|
||||
});
|
||||
test('formats weeks ago', () => {
|
||||
const date = new Date('2026-01-01T12:00:00Z')
|
||||
expect(formatRelativeTime(date, { now })).toBe('2w ago')
|
||||
})
|
||||
})
|
||||
|
||||
describe("formatRelativeTimeAgo", () => {
|
||||
const now = new Date("2026-01-15T12:00:00Z");
|
||||
describe('formatRelativeTimeAgo', () => {
|
||||
const now = new Date('2026-01-15T12:00:00Z')
|
||||
|
||||
test("formats past date with 'ago' suffix", () => {
|
||||
const date = new Date("2026-01-15T11:59:30Z");
|
||||
const result = formatRelativeTimeAgo(date, { now });
|
||||
expect(result).toBe("30s ago");
|
||||
});
|
||||
const date = new Date('2026-01-15T11:59:30Z')
|
||||
const result = formatRelativeTimeAgo(date, { now })
|
||||
expect(result).toBe('30s ago')
|
||||
})
|
||||
|
||||
test("formats future date without 'ago' suffix", () => {
|
||||
const date = new Date("2026-01-15T13:00:00Z");
|
||||
const result = formatRelativeTimeAgo(date, { now });
|
||||
expect(result).toBe("in 1h");
|
||||
});
|
||||
const date = new Date('2026-01-15T13:00:00Z')
|
||||
const result = formatRelativeTimeAgo(date, { now })
|
||||
expect(result).toBe('in 1h')
|
||||
})
|
||||
|
||||
test("formats minutes ago", () => {
|
||||
const date = new Date("2026-01-15T11:55:00Z");
|
||||
const result = formatRelativeTimeAgo(date, { now });
|
||||
expect(result).toBe("5m ago");
|
||||
});
|
||||
test('formats minutes ago', () => {
|
||||
const date = new Date('2026-01-15T11:55:00Z')
|
||||
const result = formatRelativeTimeAgo(date, { now })
|
||||
expect(result).toBe('5m ago')
|
||||
})
|
||||
|
||||
test("formats hours ago", () => {
|
||||
const date = new Date("2026-01-15T09:00:00Z");
|
||||
const result = formatRelativeTimeAgo(date, { now });
|
||||
expect(result).toBe("3h ago");
|
||||
});
|
||||
test('formats hours ago', () => {
|
||||
const date = new Date('2026-01-15T09:00:00Z')
|
||||
const result = formatRelativeTimeAgo(date, { now })
|
||||
expect(result).toBe('3h ago')
|
||||
})
|
||||
|
||||
test("formats days ago", () => {
|
||||
const date = new Date("2026-01-13T12:00:00Z");
|
||||
const result = formatRelativeTimeAgo(date, { now });
|
||||
expect(result).toBe("2d ago");
|
||||
});
|
||||
test('formats days ago', () => {
|
||||
const date = new Date('2026-01-13T12:00:00Z')
|
||||
const result = formatRelativeTimeAgo(date, { now })
|
||||
expect(result).toBe('2d ago')
|
||||
})
|
||||
|
||||
test("handles date equal to now as past", () => {
|
||||
test('handles date equal to now as past', () => {
|
||||
// date === now, treated as past (not future)
|
||||
const result = formatRelativeTimeAgo(now, { now });
|
||||
expect(result).toBe("0s ago");
|
||||
});
|
||||
const result = formatRelativeTimeAgo(now, { now })
|
||||
expect(result).toBe('0s ago')
|
||||
})
|
||||
|
||||
test("uses numeric always for past dates", () => {
|
||||
test('uses numeric always for past dates', () => {
|
||||
// Should always use numeric format for past dates
|
||||
const date = new Date("2026-01-15T11:59:00Z");
|
||||
const result = formatRelativeTimeAgo(date, { now });
|
||||
expect(result).toContain("ago");
|
||||
});
|
||||
const date = new Date('2026-01-15T11:59:00Z')
|
||||
const result = formatRelativeTimeAgo(date, { now })
|
||||
expect(result).toContain('ago')
|
||||
})
|
||||
|
||||
test("future date does not contain 'ago'", () => {
|
||||
const date = new Date("2026-01-15T14:00:00Z");
|
||||
const result = formatRelativeTimeAgo(date, { now });
|
||||
expect(result).not.toContain("ago");
|
||||
});
|
||||
});
|
||||
const date = new Date('2026-01-15T14:00:00Z')
|
||||
const result = formatRelativeTimeAgo(date, { now })
|
||||
expect(result).not.toContain('ago')
|
||||
})
|
||||
})
|
||||
|
||||
describe("formatLogMetadata", () => {
|
||||
describe('formatLogMetadata', () => {
|
||||
// Use a date very recently in the past so it always shows "Xs ago" or similar
|
||||
const modified = new Date(Date.now() - 5 * 60 * 1000); // 5 minutes ago
|
||||
const modified = new Date(Date.now() - 5 * 60 * 1000) // 5 minutes ago
|
||||
|
||||
test("includes relative time and message count", () => {
|
||||
test('includes relative time and message count', () => {
|
||||
const result = formatLogMetadata({
|
||||
modified,
|
||||
messageCount: 10,
|
||||
});
|
||||
expect(result).toContain("ago");
|
||||
expect(result).toContain("10 messages");
|
||||
});
|
||||
})
|
||||
expect(result).toContain('ago')
|
||||
expect(result).toContain('10 messages')
|
||||
})
|
||||
|
||||
test("uses fileSize instead of messageCount when provided", () => {
|
||||
test('uses fileSize instead of messageCount when provided', () => {
|
||||
const result = formatLogMetadata({
|
||||
modified,
|
||||
messageCount: 5,
|
||||
fileSize: 1536,
|
||||
});
|
||||
expect(result).toContain("1.5KB");
|
||||
expect(result).not.toContain("messages");
|
||||
});
|
||||
})
|
||||
expect(result).toContain('1.5KB')
|
||||
expect(result).not.toContain('messages')
|
||||
})
|
||||
|
||||
test("includes gitBranch when provided", () => {
|
||||
test('includes gitBranch when provided', () => {
|
||||
const result = formatLogMetadata({
|
||||
modified,
|
||||
messageCount: 3,
|
||||
gitBranch: "main",
|
||||
});
|
||||
expect(result).toContain("main");
|
||||
});
|
||||
gitBranch: 'main',
|
||||
})
|
||||
expect(result).toContain('main')
|
||||
})
|
||||
|
||||
test("omits gitBranch when not provided", () => {
|
||||
test('omits gitBranch when not provided', () => {
|
||||
const result = formatLogMetadata({
|
||||
modified,
|
||||
messageCount: 3,
|
||||
});
|
||||
})
|
||||
// Should not have a dangling separator from missing branch
|
||||
expect(result).not.toMatch(/^ · | · $/);
|
||||
});
|
||||
expect(result).not.toMatch(/^ · | · $/)
|
||||
})
|
||||
|
||||
test("includes tag when provided", () => {
|
||||
test('includes tag when provided', () => {
|
||||
const result = formatLogMetadata({
|
||||
modified,
|
||||
messageCount: 3,
|
||||
tag: "my-tag",
|
||||
});
|
||||
expect(result).toContain("#my-tag");
|
||||
});
|
||||
tag: 'my-tag',
|
||||
})
|
||||
expect(result).toContain('#my-tag')
|
||||
})
|
||||
|
||||
test("includes agentSetting when provided", () => {
|
||||
test('includes agentSetting when provided', () => {
|
||||
const result = formatLogMetadata({
|
||||
modified,
|
||||
messageCount: 3,
|
||||
agentSetting: "custom-agent",
|
||||
});
|
||||
expect(result).toContain("@custom-agent");
|
||||
});
|
||||
agentSetting: 'custom-agent',
|
||||
})
|
||||
expect(result).toContain('@custom-agent')
|
||||
})
|
||||
|
||||
test("includes prNumber when provided", () => {
|
||||
test('includes prNumber when provided', () => {
|
||||
const result = formatLogMetadata({
|
||||
modified,
|
||||
messageCount: 3,
|
||||
prNumber: 42,
|
||||
});
|
||||
expect(result).toContain("#42");
|
||||
});
|
||||
})
|
||||
expect(result).toContain('#42')
|
||||
})
|
||||
|
||||
test("includes prRepository with prNumber when both provided", () => {
|
||||
test('includes prRepository with prNumber when both provided', () => {
|
||||
const result = formatLogMetadata({
|
||||
modified,
|
||||
messageCount: 3,
|
||||
prNumber: 99,
|
||||
prRepository: "owner/repo",
|
||||
});
|
||||
expect(result).toContain("owner/repo#99");
|
||||
});
|
||||
prRepository: 'owner/repo',
|
||||
})
|
||||
expect(result).toContain('owner/repo#99')
|
||||
})
|
||||
|
||||
test("parts are joined with ' · ' separator", () => {
|
||||
const result = formatLogMetadata({
|
||||
modified,
|
||||
messageCount: 5,
|
||||
gitBranch: "feat/x",
|
||||
});
|
||||
expect(result).toContain(" · ");
|
||||
});
|
||||
});
|
||||
gitBranch: 'feat/x',
|
||||
})
|
||||
expect(result).toContain(' · ')
|
||||
})
|
||||
})
|
||||
|
||||
Reference in New Issue
Block a user