Files
agent-workbench/assets/dashboard/tests/draft-storage.test.mjs

14 lines
3.2 KiB
JavaScript

import test from 'node:test'
import assert from 'node:assert/strict'
import { draftKey,readDraft,writeDraft,clearDraft,clearIfUnchanged } from '../src/lib/draft-storage.ts'
class Memory { data=new Map();get length(){return this.data.size}key(i){return [...this.data.keys()][i]??null}getItem(k){return this.data.get(k)??null}setItem(k,v){this.data.set(k,v)}removeItem(k){this.data.delete(k)} }
const valid=v=>!!v&&typeof v.text==='string';const empty={text:''}
test('remount/reload recovers text and same unknown-delivery attempt key',()=>{const s=new Memory(),scope=['instance','communication','human'];writeDraft(s,scope,{text:'hello',attempt:{key:'stable',text:'hello'}});assert.deepEqual(readDraft(s,scope,empty,valid),{text:'hello',attempt:{key:'stable',text:'hello'}})})
test('instance session decision channel and version isolate records',()=>{const s=new Memory(),a=['i','decision','d1','1'];writeDraft(s,a,{text:'private'});for(const b of [['other','decision','d1','1'],['i','decision','d2','1'],['i','consultation','d1','1'],['i','decision','d1','2']])assert.deepEqual(readDraft(s,b,empty,valid),empty)})
test('new revision recovers old content without changing its revision or attempt',()=>{const s=new Memory();writeDraft(s,['i','decision','d','1'],{text:'old',revision:1,attempt:{key:'same'}});assert.equal(readDraft(s,['i','decision','d','2'],empty,valid,true).revision,1);assert.equal(s.length,1)})
test('successful clearing does not clear consultation or restore old selection',()=>{const s=new Memory(),scope=['i','decision','d','2'];writeDraft(s,['i','decision','d','1'],{text:'old'});writeDraft(s,scope,{text:'sent'});writeDraft(s,['i','consultation','d','2'],{text:'chat'});clearIfUnchanged(s,scope,s.getItem(draftKey(scope)));assert.deepEqual(readDraft(s,scope,empty,valid,true),empty);assert.equal(readDraft(s,['i','consultation','d','2'],empty,valid).text,'chat')})
test('late success cannot remove a newer draft',()=>{const s=new Memory(),scope=['i','c','s'];writeDraft(s,scope,{text:'sent'});const expected=s.getItem(draftKey(scope));writeDraft(s,scope,{text:'new'});assert.equal(clearIfUnchanged(s,scope,expected),false);assert.equal(readDraft(s,scope,empty,valid).text,'new')})
test('explicit clear removes only selected decision versions',()=>{const s=new Memory();for(const id of ['a','b'])for(const version of ['1','2'])writeDraft(s,['i','decision',id,version],{text:id});clearDraft(s,['i','decision','a','2'],true);assert.equal(readDraft(s,['i','decision','b','1'],empty,valid).text,'b');assert.deepEqual(readDraft(s,['i','decision','a','2'],empty,valid,true),empty);assert.equal(s.getItem(draftKey(['i','decision','a','1'])),null)})
test('unavailable storage and corrupt data throw instead of claiming saved',()=>{const s=new Memory();s.setItem=()=>{throw Error('quota')};assert.throws(()=>writeDraft(s,['i'],{text:'x'}));s.getItem=()=>'{broken';assert.throws(()=>readDraft(s,['i'],empty,valid))})
test('transient sending/errors are not revived as a stuck pending UI',()=>{const s=new Memory();writeDraft(s,['i'],{text:'retry',sending:true,error:'offline',attempt:{key:'stable'}});const value=readDraft(s,['i'],empty,valid);assert.equal(value.sending,undefined);assert.equal(value.error,undefined);assert.equal(value.attempt.key,'stable')})