Files
lms-fe/scripts/test-daily-log.cjs

79 lines
3.6 KiB
JavaScript

const { test } = require('node:test')
const assert = require('node:assert/strict')
const fs = require('node:fs')
const os = require('node:os')
const path = require('node:path')
const vm = require('node:vm')
const ts = require('typescript')
const exportsObject = {}
const source = fs.readFileSync(path.resolve(__dirname, '../src/main/dailyLog.ts'), 'utf8')
vm.runInNewContext(ts.transpileModule(source, {
compilerOptions: { module: ts.ModuleKind.CommonJS, target: ts.ScriptTarget.ES2022 }
}).outputText, { exports: exportsObject, require })
const { createDailyLog, redactLog } = exportsObject
test('appends and rotates by local date, retaining unrelated files', (t) => {
const root = fs.mkdtempSync(path.join(os.tmpdir(), 'lms-log-test-'))
t.after(() => fs.rmSync(root, { recursive: true, force: true }))
fs.writeFileSync(path.join(root, 'renderer.log'), 'existing log')
let date = new Date(2026, 8, 29, 23, 59)
const log = createDailyLog([root], () => date)
log.write('test', 'first')
log.write('test', 'second')
const oldPath = log.path()
assert.match(oldPath, /lms-2026-09-29\.log$/)
assert.match(fs.readFileSync(oldPath, 'utf8'), /first[\s\S]*second/)
assert.equal(fs.statSync(oldPath).mode & 0o777, 0o600)
date = new Date(2026, 8, 30, 0, 1)
log.write('test', 'next day')
assert.match(log.path(), /lms-2026-09-30\.log$/)
assert.equal(fs.existsSync(oldPath), false)
assert.equal(fs.readFileSync(path.join(root, 'renderer.log'), 'utf8'), 'existing log')
})
test('falls back when the primary directory is unusable', (t) => {
const root = fs.mkdtempSync(path.join(os.tmpdir(), 'lms-log-test-'))
t.after(() => fs.rmSync(root, { recursive: true, force: true }))
const blocked = path.join(root, 'file')
fs.writeFileSync(blocked, '')
const log = createDailyLog([blocked, path.join(root, 'fallback')])
log.write('test', 'fallback')
assert.equal(path.dirname(log.path()), path.join(root, 'fallback'))
const unavailable = createDailyLog([blocked])
assert.doesNotThrow(() => unavailable.write('test', 'ignored'))
assert.equal(unavailable.path(), '')
})
test('redacts common authentication fields and credential URLs', () => {
const result = redactLog('https://oauth2:secret123@example.com/repo.git Bearer secret456 --handoff-token=secret789 ?password=secret000 {"accessToken":"secret111"} password=secret222')
for (const secret of ['secret123', 'secret456', 'secret789', 'secret000', 'secret111', 'secret222']) {
assert.equal(result.includes(secret), false)
}
assert.match(result, /example.com\/repo.git/)
})
test('bootstrap logs dependency loading failures before exiting', async () => {
const events = []
const bootstrap = fs.readFileSync(path.resolve(__dirname, '../src/main/bootstrap.ts'), 'utf8')
const code = ts.transpileModule(bootstrap, {
compilerOptions: { module: ts.ModuleKind.CommonJS, target: ts.ScriptTarget.ES2022 }
}).outputText
vm.runInNewContext(code, {
exports: {}, Error,
require: (name) => {
if (name === 'electron') return { app: { exit: (code) => events.push(['exit', code]) } }
if (name === './appLogging') {
events.push(['logger-ready'])
return { appLog: { write: (...args) => events.push(args) } }
}
if (name === './index') throw new Error('test native module failure')
throw new Error(`Unexpected dependency: ${name}`)
}
})
await new Promise((resolve) => setImmediate(resolve))
assert.equal(events[0][0], 'logger-ready')
assert.equal(events[1][0], 'startup-error')
assert.match(events[1][1], /test native module failure/)
assert.deepEqual(events[2], ['exit', 1])
})