feat(desktop): workflow.event live consumption + inspector Feedback tab + upstream ledger L-5
This commit is contained in:
115
examples/desktop/test/feedback-annotations.test.js
Normal file
115
examples/desktop/test/feedback-annotations.test.js
Normal file
@@ -0,0 +1,115 @@
|
||||
// feedback-annotations.test.js — lane-wf-feedback item 2 (main-process store).
|
||||
//
|
||||
// Points DSH_DESKTOP_HOME at a per-test tmp dir so real ~/.dsh-desktop never
|
||||
// gets touched. Exercises the per-event annotation store's upsert / clear /
|
||||
// remove semantics + the persisted record shape (the RL seed).
|
||||
|
||||
'use strict'
|
||||
|
||||
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')
|
||||
|
||||
function withTmpHome(fn) {
|
||||
const home = fs.mkdtempSync(path.join(os.tmpdir(), 'dsh-feedback-'))
|
||||
const prev = process.env.DSH_DESKTOP_HOME
|
||||
process.env.DSH_DESKTOP_HOME = home
|
||||
try { fn(home) }
|
||||
finally {
|
||||
if (prev == null) delete process.env.DSH_DESKTOP_HOME
|
||||
else process.env.DSH_DESKTOP_HOME = prev
|
||||
fs.rmSync(home, { recursive: true, force: true })
|
||||
}
|
||||
}
|
||||
|
||||
function freshRequire() {
|
||||
delete require.cache[require.resolve('../src/main/feedback-annotations.js')]
|
||||
return require('../src/main/feedback-annotations.js')
|
||||
}
|
||||
|
||||
test('list: empty before any write', () => {
|
||||
withTmpHome(() => {
|
||||
const F = freshRequire()
|
||||
assert.deepEqual(F.list(), { ok: true, entries: [] })
|
||||
})
|
||||
})
|
||||
|
||||
test('upsert: writes a record and list reads it back with the RL-seed shape', () => {
|
||||
withTmpHome(() => {
|
||||
const F = freshRequire()
|
||||
const r = F.upsert({ sessionId: 's1', seq: 7, verdict: 'up', note: 'good turn', rubricDim: 'convergence' })
|
||||
assert.equal(r.ok, true)
|
||||
assert.equal(r.entry.sessionId, 's1')
|
||||
assert.equal(r.entry.seq, 7)
|
||||
assert.equal(r.entry.verdict, 'up')
|
||||
assert.equal(r.entry.note, 'good turn')
|
||||
assert.equal(r.entry.rubricDim, 'convergence')
|
||||
assert.equal(typeof r.entry.at, 'number')
|
||||
const { entries } = F.list()
|
||||
assert.equal(entries.length, 1)
|
||||
assert.equal(entries[0].sessionId, 's1')
|
||||
})
|
||||
})
|
||||
|
||||
test('upsert: re-annotating the same (sessionId, seq) overwrites in place', () => {
|
||||
withTmpHome(() => {
|
||||
const F = freshRequire()
|
||||
F.upsert({ sessionId: 's1', seq: 7, verdict: 'up', note: 'first' })
|
||||
F.upsert({ sessionId: 's1', seq: 7, verdict: 'down', note: 'revised' })
|
||||
const { entries } = F.list()
|
||||
assert.equal(entries.length, 1, 'still one record for the same key')
|
||||
assert.equal(entries[0].verdict, 'down')
|
||||
assert.equal(entries[0].note, 'revised')
|
||||
})
|
||||
})
|
||||
|
||||
test('upsert: distinct (sessionId, seq) pairs accumulate', () => {
|
||||
withTmpHome(() => {
|
||||
const F = freshRequire()
|
||||
F.upsert({ sessionId: 's1', seq: 1, verdict: 'up', note: 'a' })
|
||||
F.upsert({ sessionId: 's1', seq: 2, verdict: 'down', note: 'b' })
|
||||
F.upsert({ sessionId: 's2', seq: 1, verdict: 'up', note: 'c' })
|
||||
assert.equal(F.list().entries.length, 3)
|
||||
})
|
||||
})
|
||||
|
||||
test('upsert: an empty annotation clears an existing record', () => {
|
||||
withTmpHome(() => {
|
||||
const F = freshRequire()
|
||||
F.upsert({ sessionId: 's1', seq: 7, verdict: 'up', note: 'x' })
|
||||
const r = F.upsert({ sessionId: 's1', seq: 7, verdict: null, note: ' ' })
|
||||
assert.equal(r.ok, true)
|
||||
assert.equal(r.cleared, true)
|
||||
assert.equal(F.list().entries.length, 0)
|
||||
})
|
||||
})
|
||||
|
||||
test('upsert: missing sessionId/seq is rejected, no file written', () => {
|
||||
withTmpHome(() => {
|
||||
const F = freshRequire()
|
||||
assert.equal(F.upsert({ seq: 7, verdict: 'up' }).ok, false)
|
||||
assert.equal(F.upsert({ sessionId: 's1', verdict: 'up' }).ok, false)
|
||||
assert.equal(F.list().entries.length, 0)
|
||||
})
|
||||
})
|
||||
|
||||
test('remove: drops a record; removing a missing one is a no-op ok', () => {
|
||||
withTmpHome(() => {
|
||||
const F = freshRequire()
|
||||
F.upsert({ sessionId: 's1', seq: 7, verdict: 'up', note: 'x' })
|
||||
assert.deepEqual(F.remove({ sessionId: 's1', seq: 7 }), { ok: true, removed: true })
|
||||
assert.deepEqual(F.remove({ sessionId: 's1', seq: 7 }), { ok: true, removed: false })
|
||||
assert.equal(F.list().entries.length, 0)
|
||||
})
|
||||
})
|
||||
|
||||
test('annotationsPath lands under DSH_DESKTOP_HOME', () => {
|
||||
withTmpHome((home) => {
|
||||
const F = freshRequire()
|
||||
assert.equal(F.annotationsPath(), path.join(home, 'feedback-annotations.json'))
|
||||
F.upsert({ sessionId: 's1', seq: 7, verdict: 'up', note: 'x' })
|
||||
assert.equal(fs.existsSync(path.join(home, 'feedback-annotations.json')), true)
|
||||
})
|
||||
})
|
||||
Reference in New Issue
Block a user