mirror of
https://github.com/Ark0N/Codeman.git
synced 2026-10-02 05:29:42 +02:00
83 lines
3.1 KiB
TypeScript
83 lines
3.1 KiB
TypeScript
/** @fileoverview Header plan-usage chip provider rows (Claude above Codex). */
|
|
|
|
import { readFileSync } from 'node:fs';
|
|
import { performance } from 'node:perf_hooks';
|
|
import { resolve } from 'node:path';
|
|
import vm from 'node:vm';
|
|
import { describe, expect, it, vi } from 'vitest';
|
|
|
|
function loadCodemanAppClass() {
|
|
const constants = readFileSync(resolve(import.meta.dirname, '../src/web/public/constants.js'), 'utf8');
|
|
const source = readFileSync(resolve(import.meta.dirname, '../src/web/public/app.js'), 'utf8');
|
|
const chip = { innerHTML: '', title: '' };
|
|
const context = vm.createContext({
|
|
console,
|
|
performance,
|
|
setInterval: vi.fn(),
|
|
clearInterval: vi.fn(),
|
|
setTimeout,
|
|
clearTimeout,
|
|
requestAnimationFrame: vi.fn(),
|
|
HTMLCanvasElement: class HTMLCanvasElement {},
|
|
fetch: (...args: Parameters<typeof fetch>) => global.fetch(...args),
|
|
document: {
|
|
addEventListener: vi.fn(),
|
|
getElementById: (id: string) => (id === 'planUsageChip' ? chip : null),
|
|
},
|
|
localStorage: {
|
|
length: 0,
|
|
key: vi.fn(),
|
|
getItem: vi.fn(),
|
|
setItem: vi.fn(),
|
|
removeItem: vi.fn(),
|
|
},
|
|
window: { addEventListener: vi.fn(), removeEventListener: vi.fn() },
|
|
MobileDetection: {},
|
|
});
|
|
vm.runInContext(`${constants}\n${source}\nglobalThis.__CodemanApp = CodemanApp;`, context);
|
|
return {
|
|
CodemanApp: (context as { __CodemanApp: new () => unknown }).__CodemanApp,
|
|
chip,
|
|
};
|
|
}
|
|
|
|
type UsageApp = { updatePlanUsageChip: (data: unknown) => void };
|
|
|
|
describe('header plan usage chip', () => {
|
|
it('renders Claude first and the main Codex limits underneath', () => {
|
|
const { CodemanApp, chip } = loadCodemanAppClass();
|
|
const app = Object.create((CodemanApp as { prototype: object }).prototype) as UsageApp;
|
|
|
|
app.updatePlanUsageChip({
|
|
fiveHour: { usedPercentage: 97, resetAt: 1000 },
|
|
sevenDay: { usedPercentage: 44, resetAt: 2000 },
|
|
codex: { sevenDay: { usedPercentage: 40, resetAt: 3000 } },
|
|
});
|
|
|
|
expect(chip.innerHTML).toContain('class="pu-row"');
|
|
expect(chip.innerHTML).toContain('class="pu-provider">Claude</span>');
|
|
expect(chip.innerHTML).toContain('class="pu-provider">Codex</span>');
|
|
expect(chip.innerHTML.indexOf('Claude')).toBeLessThan(chip.innerHTML.indexOf('Codex'));
|
|
expect(chip.innerHTML).toContain('97%');
|
|
expect(chip.innerHTML).toContain('44%');
|
|
expect(chip.innerHTML).toContain('40%');
|
|
expect(chip.title).toContain('Claude plan usage');
|
|
expect(chip.title).toContain('Codex plan usage');
|
|
});
|
|
|
|
it('omits unavailable Codex windows instead of inventing zero usage', () => {
|
|
const { CodemanApp, chip } = loadCodemanAppClass();
|
|
const app = Object.create((CodemanApp as { prototype: object }).prototype) as UsageApp;
|
|
|
|
app.updatePlanUsageChip({
|
|
fiveHour: { usedPercentage: 10, resetAt: 1000 },
|
|
sevenDay: { usedPercentage: 20, resetAt: 2000 },
|
|
codex: { sevenDay: { usedPercentage: 40, resetAt: 3000 } },
|
|
});
|
|
|
|
const codexRow = chip.innerHTML.slice(chip.innerHTML.indexOf('Codex'));
|
|
expect(codexRow).not.toContain('5h');
|
|
expect(codexRow).toContain('7d');
|
|
});
|
|
});
|