import {test} from 'node:test'; import assert from 'node:assert/strict'; import {readFile} from 'node:fs/promises'; import ts from 'typescript'; async function moduleUrl(path,transform=code=>code){ const source=await readFile(new URL(path,import.meta.url),'utf8'); const {outputText}=ts.transpileModule(source,{compilerOptions:{target:ts.ScriptTarget.ES2022,module:ts.ModuleKind.ESNext}}); return 'data:text/javascript;base64,'+Buffer.from(transform(outputText)).toString('base64'); } const protocolUrl=await moduleUrl('../src/lib/api/protocol.ts'); const appDownloadUrl=await moduleUrl('../src/lib/app-download.ts',code=>code.replace(/from ['"]\.\/api\/protocol['"]/,`from '${protocolUrl}'`)); const {downloadUrl}=await import(appDownloadUrl); const clientUrl=await moduleUrl('../src/lib/client/download.ts',code=>code.replace(/from ['"]\.\.\/app-download['"]/,`from '${appDownloadUrl}'`)); const {configureDownloadLinks,shouldUseDownloadDialog}=await import(clientUrl); const click={defaultPrevented:false,button:0,metaKey:false,ctrlKey:false,shiftKey:false,altKey:false}; test('download configuration selects the first valid HTTP URL and rejects empty or unsafe values',()=>{ assert.equal(downloadUrl({}),''); assert.equal(downloadUrl({config:{appAddr:''}}),''); assert.equal(downloadUrl({config:{officialAppAddr:'javascript:alert(1)',appAddr:'https://example.com/app.apk'}}),'https://example.com/app.apk'); assert.equal(downloadUrl({config:{appAddr:' '},newAddressInfo:{appAddr:'https://example.com/fallback.apk'}}),'https://example.com/fallback.apk'); assert.equal(downloadUrl({config:{officialAppAddr:'https://example.com/official',appAddr:'https://example.com/other'}}),'https://example.com/official'); for(const value of ['javascript:alert(1)','data:text/plain,app','ftp://example.com/app','https://user:password@example.com/app']){ assert.equal(downloadUrl({config:{appAddr:value}}),''); } }); test('all download entries stay hidden until configured and are hidden again if configuration is removed',()=>{ const entries=Array.from({length:4},()=>({hidden:true})); const links=Array.from({length:4},()=>({href:undefined,removeAttribute(name){if(name==='href')this.href=undefined;}})); const root={querySelectorAll:selector=>selector==='[data-app-download-entry]'?entries:links}; configureDownloadLinks({},root);assert.ok(entries.every(entry=>entry.hidden));assert.ok(links.every(link=>link.href===undefined)); configureDownloadLinks({config:{appAddr:'https://example.com/app.apk'}},root); assert.ok(entries.every(entry=>!entry.hidden));assert.ok(links.every(link=>link.href==='https://example.com/app.apk')); const dynamicEntry={hidden:true},dynamicLink={href:undefined,removeAttribute(name){if(name==='href')this.href=undefined;}}; entries.push(dynamicEntry);links.push(dynamicLink); configureDownloadLinks({config:{appAddr:'https://example.com/new.apk'}},root); assert.equal(dynamicEntry.hidden,false);assert.equal(dynamicLink.href,'https://example.com/new.apk'); configureDownloadLinks({},root);assert.ok(entries.every(entry=>entry.hidden));assert.ok(links.every(link=>link.href===undefined)); }); test('desktop downloads use the link directly regardless of touch support',()=>{ for(const agent of ['Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7)','Mozilla/5.0 (Windows NT 10.0; Win64; x64)','Mozilla/5.0 (X11; Linux x86_64)']){ assert.equal(shouldUseDownloadDialog(click,agent,0),false); } assert.equal(shouldUseDownloadDialog(click,'Mozilla/5.0 (Windows NT 10.0; Win64; x64)',5),false); assert.equal(click.defaultPrevented,false); }); test('mobile click dialogs preserve modified clicks and other native browser actions',()=>{ const phone='Mozilla/5.0 (iPhone; CPU iPhone OS 18_0 like Mac OS X) Mobile'; assert.equal(shouldUseDownloadDialog(click,phone,5),true); assert.equal(shouldUseDownloadDialog(click,'Mozilla/5.0 (Linux; Android 14)',5),true); assert.equal(shouldUseDownloadDialog(click,'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7)',5),true); for(const key of ['defaultPrevented','metaKey','ctrlKey','shiftKey','altKey'])assert.equal(shouldUseDownloadDialog({...click,[key]:true},phone,5),false); assert.equal(shouldUseDownloadDialog({...click,button:1},phone,5),false); });