const test = require('node:test'); const assert = require('node:assert/strict'); const fs = require('node:fs'); const path = require('node:path'); const vm = require('node:vm'); const root = path.resolve(__dirname,'..'); const walk = directory => fs.readdirSync(directory,{withFileTypes:true}).flatMap(entry=> entry.isDirectory()?walk(path.join(directory,entry.name)):[path.join(directory,entry.name)]); test('the release contains source files and assets, with no server credentials or nested bundles',()=>{ for(const file of walk(root)){ assert.doesNotMatch(path.relative(root,file),/\.(?:key|pem|sqlite3|zip|xpi|pyc)$/i); if(/\.(?:html|js|css|json|md|txt)$/i.test(file)){ assert.doesNotMatch(fs.readFileSync(file,'utf8'),/-----BEGIN (?:RSA )?PRIVATE KEY-----/); } } }); test('all shipped JavaScript is valid and the editor has no server fetch calls',()=>{ for(const file of walk(path.join(root,'assets')).filter(file=>file.endsWith('.js'))){ const source=fs.readFileSync(file,'utf8'); new vm.Script(source,{filename:file}); if(!file.includes(path.join('assets','vendor'))&&!file.endsWith('arabic-text.js')){ assert.doesNotMatch(source,/\bfetch\s*\(|XMLHttpRequest|sendBeacon|WebSocket/); } } }); test('the page keeps local import and video output without site navigation',()=>{ const html=fs.readFileSync(path.join(root,'index.html'),'utf8'); assert.match(html,/id="flipnote-open-ppm-button"/); assert.match(html,/id="flipnote-audio-file-input"/); assert.match(html,/id="export-btn"/); assert.doesNotMatch(html,/class="site-(?:header|footer)"|{ const files=walk(root).filter(file=>/\.(?:html|css|js)$/.test(file)&&!file.includes(path.sep+'vendor'+path.sep)); for(const file of files){ const text=fs.readFileSync(file,'utf8'); const references=[]; for(const match of text.matchAll(/(?:src|href)=["'](\.\/[^"']+)["']/g))references.push(match[1]); for(const match of text.matchAll(/url\(["']?(\.\/[^)'"\s]+)["']?\)/g))references.push(match[1]); for(const match of text.matchAll(/["'](\.\/assets\/[^"'$`]+)["']/g))references.push(match[1]); for(const reference of references){ const clean=reference.split(/[?#]/)[0]; const base=file.endsWith('.css')?path.dirname(file):root; assert.ok(fs.existsSync(path.resolve(base,clean)),path.relative(root,file)+': missing '+clean); } } });