项目文件夹

文件
2026-04-21 10:05:27 +10:00

134 行
4.3 KiB
JavaScript

import { test } from 'node:test';
import assert from 'node:assert/strict';
import { mkdtemp, rm, writeFile } from 'node:fs/promises';
import * as path from 'node:path';
import { tmpdir } from 'node:os';
import { DEFAULT_CONFIG } from '../dist/config.js';
import { getUsageFromExternalSnapshot } from '../dist/external-usage.js';
async function withTempFile(content) {
const dir = await mkdtemp(path.join(tmpdir(), 'claude-hud-external-usage-'));
const filePath = path.join(dir, 'usage.json');
await writeFile(filePath, content, 'utf8');
return {
filePath,
cleanup: async () => rm(dir, { recursive: true, force: true }),
};
}
function makeConfig(filePath, freshnessMs = 300000) {
return {
...DEFAULT_CONFIG,
display: {
...DEFAULT_CONFIG.display,
externalUsagePath: filePath,
externalUsageFreshnessMs: freshnessMs,
},
};
}
test('getUsageFromExternalSnapshot returns null without a configured path', () => {
const usage = getUsageFromExternalSnapshot(DEFAULT_CONFIG, Date.now());
assert.equal(usage, null);
});
test('getUsageFromExternalSnapshot parses a fresh snapshot', async () => {
const updatedAt = Date.UTC(2026, 3, 20, 12, 0, 0);
const resetAt = '2026-04-20T15:00:00.000Z';
const { filePath, cleanup } = await withTempFile(JSON.stringify({
updated_at: new Date(updatedAt).toISOString(),
five_hour: { used_percentage: 42.4, resets_at: resetAt },
seven_day: { used_percentage: 84.6, resets_at: '2026-04-27T12:00:00.000Z' },
}));
try {
const usage = getUsageFromExternalSnapshot(makeConfig(filePath), updatedAt + 60_000);
assert.deepEqual(usage, {
fiveHour: 42,
sevenDay: 85,
fiveHourResetAt: new Date(resetAt),
sevenDayResetAt: new Date('2026-04-27T12:00:00.000Z'),
});
} finally {
await cleanup();
}
});
test('getUsageFromExternalSnapshot ignores stale snapshots', async () => {
const updatedAt = Date.UTC(2026, 3, 20, 12, 0, 0);
const { filePath, cleanup } = await withTempFile(JSON.stringify({
updated_at: new Date(updatedAt).toISOString(),
five_hour: { used_percentage: 42, resets_at: '2026-04-20T15:00:00.000Z' },
}));
try {
const usage = getUsageFromExternalSnapshot(makeConfig(filePath, 1000), updatedAt + 1001);
assert.equal(usage, null);
} finally {
await cleanup();
}
});
test('getUsageFromExternalSnapshot rejects invalid schema data', async () => {
const updatedAt = Date.UTC(2026, 3, 20, 12, 0, 0);
const { filePath, cleanup } = await withTempFile(JSON.stringify({
updated_at: new Date(updatedAt).toISOString(),
five_hour: { used_percentage: 42, resets_at: 'not-a-date' },
}));
try {
const usage = getUsageFromExternalSnapshot(makeConfig(filePath), updatedAt + 1);
assert.equal(usage, null);
} finally {
await cleanup();
}
});
test('getUsageFromExternalSnapshot rejects future-dated snapshots beyond clock skew tolerance', async () => {
const now = Date.UTC(2026, 3, 20, 12, 0, 0);
const { filePath, cleanup } = await withTempFile(JSON.stringify({
updated_at: new Date(now + 61_000).toISOString(),
five_hour: { used_percentage: 42, resets_at: '2026-04-20T15:00:00.000Z' },
}));
try {
const usage = getUsageFromExternalSnapshot(makeConfig(filePath), now);
assert.equal(usage, null);
} finally {
await cleanup();
}
});
test('getUsageFromExternalSnapshot rejects non-regular paths', async () => {
const dirPath = await mkdtemp(path.join(tmpdir(), 'claude-hud-external-usage-dir-'));
try {
const usage = getUsageFromExternalSnapshot(makeConfig(dirPath), Date.now());
assert.equal(usage, null);
} finally {
await rm(dirPath, { recursive: true, force: true });
}
});
test('getUsageFromExternalSnapshot rejects oversized snapshot files', async () => {
const { filePath, cleanup } = await withTempFile('x'.repeat(70_000));
try {
const usage = getUsageFromExternalSnapshot(makeConfig(filePath), Date.now());
assert.equal(usage, null);
} finally {
await cleanup();
}
});
test('getUsageFromExternalSnapshot returns null for invalid JSON', async () => {
const { filePath, cleanup } = await withTempFile('{');
try {
const usage = getUsageFromExternalSnapshot(makeConfig(filePath), Date.now());
assert.equal(usage, null);
} finally {
await cleanup();
}
});