Release v0.1.29: media previews, clean composer, regional profiles and cloud retention
This commit is contained in:
+28
-1
@@ -16,7 +16,34 @@ test('journals default to private and encode content before rendering',()=>{
|
||||
assert.doesNotMatch(js,/localStorage|indexedDB|caches\.open|access_token|secretKey.*localStorage/);
|
||||
});
|
||||
test('leave clears media URLs, live microphone tracks, and pending requests',()=>{
|
||||
const js=fs.readFileSync('web/journal.js','utf8');assert.match(js,/journalRequest\?\.abort\(\)/);assert.match(js,/URL.revokeObjectURL/);assert.match(js,/getTracks\(\).forEach\(t=>t.stop\(\)\)/);
|
||||
const js=fs.readFileSync('web/journal.js','utf8');assert.match(js,/journalRequest\?\.abort\(\)/);assert.match(js,/releaseJournalMedia/);assert.match(js,/removeAttribute\('src'\)/);assert.match(js,/getTracks\(\).forEach\(t=>t.stop\(\)\)/);
|
||||
});
|
||||
test('photos load by default and audio/video preload metadata with controls, never autoplay',()=>{
|
||||
const vm=require('node:vm'),js=fs.readFileSync('web/journal.js','utf8');
|
||||
const code=js.slice(js.indexOf('function journalMediaView('),js.indexOf('function bindJournalMedia('));
|
||||
const c=vm.createContext({esc:s=>String(s).replaceAll('<','<'),journalMediaUrl:id=>'/media/journal?id='+id});vm.runInContext(code,c);
|
||||
for(const mime of ['image/png','audio/webm','video/mp4']){
|
||||
const html=c.journalMediaView({id:'a',name:'<test>',mime});assert.match(html,/src="\/media\/journal\?id=a"/);assert.doesNotMatch(html,/autoplay|<test>/);
|
||||
if(mime.startsWith('image'))assert.match(html,/loading="lazy"/);else assert.match(html,/controls preload="metadata"/);
|
||||
}
|
||||
});
|
||||
test('successful save clears draft attachment ids, stops recorder, and reloads feed',()=>{
|
||||
const js=fs.readFileSync('web/journal.js','utf8');
|
||||
const fn=js.slice(js.indexOf('function newJournal'),js.indexOf('async function loadJournal'));
|
||||
assert.match(fn,/journalDraftMedia.clear\(\)/);assert.match(fn,/journalSelectedMedia.clear\(\)/);assert.match(fn,/stopJournalVoice\(\)/);assert.match(fn,/journal-library'\).open=false/);
|
||||
assert.match(js,/newJournal\(\);\$\('#journal-mode'\).value='mine';journalPage=0;await loadJournal\(\)/);
|
||||
assert.match(js,/available.filter\(m=>journalDraftMedia.has\(m.id\)\)/);
|
||||
});
|
||||
test('attachment preview uses a closable dialog and deletion has a restore path',()=>{
|
||||
const js=fs.readFileSync('web/journal.js','utf8'),html=fs.readFileSync('web/index.html','utf8');
|
||||
assert.match(html,/<dialog id="journal-preview"/);assert.match(js,/addEventListener\('close'/);assert.match(js,/\/api\/journal\/restore-upload/);
|
||||
assert.match(js,/journal-library-list/);assert.match(js,/if\(other!==media\)other.pause\(\)/);
|
||||
});
|
||||
test('structured place formatting and search preserve separate ancestral/birth/legacy locations',()=>{
|
||||
const vm=require('node:vm'),js=fs.readFileSync('web/family.js','utf8');
|
||||
const c=vm.createContext({});vm.runInContext(js.slice(js.indexOf('function personLocation'),js.indexOf('function personName')),c);
|
||||
const person={nativeProvince:'山东省',nativeCity:'烟台市',nativeDistrict:'莱阳市',birthCity:'济南市',birthplace:'旧村名'};
|
||||
assert.equal(c.personLocation(person,'native'),'山东省 · 烟台市 · 莱阳市');assert.equal(c.personLocation(person,'birth'),'济南市');assert.ok(c.personSearch(person).includes('旧村名'));
|
||||
});
|
||||
test('new entry clears hidden edit identifiers even when form.reset preserves them',()=>{
|
||||
const vm=require('node:vm'),js=fs.readFileSync('web/journal.js','utf8');
|
||||
|
||||
Reference in New Issue
Block a user