Files
deepseek-harness/apps/desktop/tests/operation-report.spec.ts
T

74 lines
4.5 KiB
TypeScript

import { mkdtemp, readFile, rm, writeFile } from 'node:fs/promises'
import { tmpdir } from 'node:os'
import { join } from 'node:path'
import { expect, it, onTestFinished } from 'vitest'
import { appendOperationReport } from '../src/operation-report.ts'
import { writeCrashReport, type CrashReportInput } from '../src/crash-report.ts'
const input: CrashReportInput = {
operationHistoryPlanned: true, source: 'host', phase: 'startup', error: new Error('startup failed'),
rendererConsole: [], time: new Date('2026-10-19T00:00:00Z'),
app: { name: 'test', version: '1', platform: 'win32', arch: 'x64', electron: '44', node: '24', locale: 'zh-CN' },
}
const limits = { bytes: 65536, recordBytes: 4096, records: 100, outputBytes: 65536 }
async function fixture() {
const directory = await mkdtemp(join(tmpdir(), 'desktop-operation-report-'))
onTestFinished(async () => { await rm(directory, { recursive: true, force: true }) })
const report = await writeCrashReport(directory, input)
if (report === undefined) throw new Error('Basic report fixture was not saved')
return { directory, report, basic: await readFile(report, 'utf8') }
}
it('preserves the independently saved basic report and appends whitelisted recent history', async () => {
const { directory, report, basic } = await fixture()
const record = { runId: 'c254ab28-97c9-4382-95e6-2db9c66f98c8', transportDropped: 0,
operation: { id: 'c254ab28-97c9-4382-95e6-2db9c66f98c9', time: '2026-10-19T00:00:00.000Z',
reason: 'bundle', phase: 'started', target: 'test-bundle', stage: 'enable', diagnostic: 'secret' } }
await writeFile(join(directory, 'operations.jsonl'), JSON.stringify(record) + '\n')
expect(await appendOperationReport(report, directory, limits, new AbortController().signal, null)).toBe(true)
const combined = await readFile(report, 'utf8')
expect(combined.startsWith(basic)).toBe(true)
expect(combined).toContain('test-bundle')
expect(combined).not.toContain('secret')
expect(combined).toContain('operation history collection complete')
await expect(combined.slice(basic.length)).toMatchFileSnapshot('./expected/operation-history.txt')
})
it('leaves basic bytes unchanged when collection is cancelled or fails before append', async () => {
const { directory, report, basic } = await fixture()
expect(await appendOperationReport(report, directory, limits, AbortSignal.abort(), null)).toBe(false)
expect(await appendOperationReport(report, directory, { ...limits, bytes: 0 }, new AbortController().signal, null)).toBe(false)
expect(await readFile(report, 'utf8')).toBe(basic)
expect(basic).toContain('unavailable or incomplete')
})
it('bounds the entire appended section and refuses a budget smaller than its metadata', async () => {
const { directory, report, basic } = await fixture()
expect(await appendOperationReport(report, directory, { ...limits, outputBytes: 1 }, new AbortController().signal, null)).toBe(false)
expect(await readFile(report, 'utf8')).toBe(basic)
expect(await appendOperationReport(report, directory, { ...limits, outputBytes: 512 }, new AbortController().signal, null)).toBe(true)
const summary = (await readFile(report, 'utf8')).slice(basic.length)
expect(Buffer.byteLength(summary)).toBeLessThanOrEqual(512)
expect(summary).toContain('"outputRecordsOmitted":0')
})
it('omits oldest records to fit the output budget, counting UTF-8 bytes and all metadata', async () => {
const { directory, report, basic } = await fixture()
const records = Array.from({ length: 20 }, (_, index) => ({
runId: 'c254ab28-97c9-4382-95e6-2db9c66f98c8', transportDropped: 0,
operation: { id: 'c254ab28-97c9-4382-95e6-2db9c66f98c9', time: '2026-10-19T00:00:00.000Z',
reason: 'bundle', phase: 'started', target: `测试插件-${index}`, stage: 'enable' },
}))
await writeFile(join(directory, 'operations.jsonl'), records.map(record => JSON.stringify(record)).join('\n') + '\n')
expect(await appendOperationReport(report, directory, { ...limits, outputBytes: 1024 }, new AbortController().signal, null)).toBe(true)
const section = (await readFile(report, 'utf8')).slice(basic.length)
expect(Buffer.byteLength(section)).toBeLessThanOrEqual(1024)
const summary = JSON.parse(section.split('\n').find(line => line.startsWith('{'))!) as {
outputRecordsOmitted: number
records: { operation: { target: string } }[]
}
expect(summary.outputRecordsOmitted).toBeGreaterThan(0)
expect(summary.records.length + summary.outputRecordsOmitted).toBe(20)
expect(summary.records[0]?.operation.target).toBe('测试插件-19')
})