Harden audit findings: correctness, type-safety, Windows conventions & polish
Audit-pass over CODE-AUDIT.md (~48 items closed this pass; all verified — typecheck + 234 tests + eslint + prettier green). Correctness / bugs: - B3: match the release checksum to the asset's filename line (no wrong-hash verify) - B4: newline-safe metadata probe (one --print with a unit-separator delimiter) - B5 / L88: guard the meta event against canceled items; progress no longer promotes a queued item outside pump() - B7: cookie-login promise always resolves (handles destroy-without-close) - L146: trim parser rejects >2 colon-group times; M36: Library selection counts only actionable rows - L11 / L50 / L156 / L57 / L159 / L15 / L3: live queue count, empty-cookie message, schedule picker min, dead-code/comment cleanup Type safety: - Enable noUncheckedIndexedAccess + noFallthroughCasesInSwitch (15 real edge cases fixed) Resilience / Windows / metadata: - R5: settings write failure handled (no unhandled IPC rejection; reconciles to truth) - W1 / W5 / W6: min window size, seeded folder picker, parented sign-in window; L147 dead macOS branches removed - CL1: shared stdout markers; package/builder metadata (license, homepage, repository, copyright, tsbuildinfo glob) Copy / docs / tests: - M37 / SR9 dev-jargon cleanup in hints; M8 / M25 / M26 / L66 / L80 / L81 reconciled - New unit tests for L35 (isValidMediaItem) and L36 (compareVersions) This commit also checkpoints the previously-uncommitted feat/tray-background-clipboard work it builds on: background running + auto-download, library clipboard detection, tray, binary management & library scale, credential encryption at rest, the shared jsonStore and ui/ primitives, and the eslint/prettier tooling. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,60 @@
|
||||
import { describe, it, expect, afterEach } from 'vitest'
|
||||
import { mkdtempSync, rmSync, writeFileSync, readdirSync } from 'fs'
|
||||
import { tmpdir } from 'os'
|
||||
import { join } from 'path'
|
||||
import { readJsonArraySafe, writeJsonAtomic } from '../src/main/jsonStore'
|
||||
|
||||
interface Row {
|
||||
id: string
|
||||
}
|
||||
const isRow = (o: unknown): o is Row =>
|
||||
typeof o === 'object' && o !== null && typeof (o as Row).id === 'string'
|
||||
|
||||
describe('jsonStore atomic write + safe read', () => {
|
||||
const dirs: string[] = []
|
||||
function tmp(): string {
|
||||
const d = mkdtempSync(join(tmpdir(), 'aerofetch-jsonstore-'))
|
||||
dirs.push(d)
|
||||
return d
|
||||
}
|
||||
afterEach(() => {
|
||||
for (const d of dirs.splice(0)) {
|
||||
try {
|
||||
rmSync(d, { recursive: true, force: true })
|
||||
} catch {
|
||||
/* ignore */
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
it('round-trips a valid array (R1 write → read)', () => {
|
||||
const file = join(tmp(), 'data.json')
|
||||
writeJsonAtomic(file, [{ id: 'a' }, { id: 'b' }])
|
||||
expect(readJsonArraySafe(file, isRow)).toEqual([{ id: 'a' }, { id: 'b' }])
|
||||
})
|
||||
|
||||
it('leaves no .tmp file behind (atomic temp+rename)', () => {
|
||||
const d = tmp()
|
||||
writeJsonAtomic(join(d, 'data.json'), [{ id: 'a' }])
|
||||
expect(readdirSync(d)).toEqual(['data.json'])
|
||||
})
|
||||
|
||||
it('returns [] for a missing file (first run)', () => {
|
||||
expect(readJsonArraySafe(join(tmp(), 'nope.json'), isRow)).toEqual([])
|
||||
})
|
||||
|
||||
it('drops rows that fail validation', () => {
|
||||
const file = join(tmp(), 'data.json')
|
||||
writeFileSync(file, JSON.stringify([{ id: 'a' }, { nope: 1 }, { id: 'c' }]))
|
||||
expect(readJsonArraySafe(file, isRow)).toEqual([{ id: 'a' }, { id: 'c' }])
|
||||
})
|
||||
|
||||
it('backs up a corrupt file instead of silently wiping it (R2)', () => {
|
||||
const d = tmp()
|
||||
const file = join(d, 'data.json')
|
||||
writeFileSync(file, '{ truncated, not valid json')
|
||||
expect(readJsonArraySafe(file, isRow)).toEqual([])
|
||||
const backups = readdirSync(d).filter((f) => f.startsWith('data.json.corrupt-'))
|
||||
expect(backups.length).toBe(1)
|
||||
})
|
||||
})
|
||||
Reference in New Issue
Block a user