VulpesOS/tests/mms.test.mjs
OverSu 1311bed5e9 Release Preview 20 shared desktop, Android and Sargo updates
Restore Gaia settings and media workflows, extend native network adapters, and align the APK payload. Generate French/English changelogs and website entries from the simplified JSON source.

Validation: shared JS and Tundra unit tests; desktop workflows and persistence; signed APK payload parity; Sargo RAM and installed startup with boot readback. Android runtime qualification is recorded separately.
2026-10-13 00:19:45 +02:00

34 lines
2.8 KiB
JavaScript

import test from 'node:test';
import assert from 'node:assert/strict';
import {Messages} from '../host/Messages.sys.mjs';
import {mmsPayload,receivedMms} from '../services/mms.mjs';
const app={manifest:{permissions:{sms:{}}}};
const part={id:'photo.jpg',location:'photo.jpg',content:{__vulpesBlobV1:true,type:'image/jpeg',base64:'/9j/2Q=='}};
const payload={receivers:['+15550199'],subject:'Photo',smil:'',attachments:[part]};
function store(){let rows=[];return {run:async(_,op,args)=>op==='get'?{value:structuredClone(rows)}:(rows=structuredClone(args[0]))};}
test('MMS remains pending until MMSC acceptance and keeps attachments',async()=>{
const events=[];let status={state:'pending'};
const mms={validate:mmsPayload,send:async p=>{assert.deepEqual(p,payload);return {path:'id',state:'pending'};},status:async()=>status};
const s=new Messages(store(),null,(t,m)=>events.push([t,m]),null,mms);
const message=await s.request(app,{operation:'sendMMS',args:[payload]});assert.equal(message.delivery,'sending');
await s.refreshOutgoing();assert.equal(events.length,1);
status={state:'sent'};await s.refreshOutgoing();assert.equal(events.at(-1)[0],'sent');
assert.deepEqual(events.at(-1)[1].attachments,[part]);
assert.deepEqual((await s.request(app,{operation:'getThreads'}))[0].participants,payload.receivers);
});
test('bearer failure retains failed MMS bubble without a sent event',async()=>{
const events=[];const s=new Messages(store(),null,t=>events.push(t),null,{validate:mmsPayload,send:async()=>({path:'id'}),status:async()=>({state:'failed',error:'MMS_DATA_UNAVAILABLE'})});
await s.request(app,{operation:'sendMMS',args:[payload]});await s.refreshOutgoing();
const m=(await s.request(app,{operation:'getMessages'}))[0];assert.equal(m.delivery,'error');assert.equal(m.error,'MMS_DATA_UNAVAILABLE');assert.deepEqual(m.attachments,[part]);assert.deepEqual(events,['sending','failed']);
});
test('incoming MMS is deduplicated and preserves native attachment blobs',async()=>{
const row=receivedMms({receipt:'push-1',type:'mms',sender:'+15550199',receivers:[],parts:[{id:'photo.jpg',type:'image/jpeg',data:'/9j/2Q=='},{id:'text.txt',type:'text/plain',data:btoa('Hello')}]});
const s=new Messages(store());const a=await s.receive(row),b=await s.receive(row);
assert.equal(a.id,b.id);assert.equal(a.body,'Hello');assert.equal(a.type,'mms');assert.equal(a.attachments[0].content.base64,part.content.base64);
assert.equal((await s.request(app,{operation:'getThreads'}))[0].lastMessageType,'mms');
});
test('reject invalid recipients, missing blobs and oversized MMS',()=>{
assert.throws(()=>mmsPayload({...payload,receivers:['file:///etc/passwd']}));
assert.throws(()=>mmsPayload({...payload,attachments:[{content:{}}]}));
assert.throws(()=>mmsPayload({...payload,attachments:[{...part,content:{...part.content,base64:'A'.repeat(900000)}}]}));
});