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.
This commit is contained in:
parent
be2cdce823
commit
1311bed5e9
170 changed files with 19698 additions and 2495 deletions
34
tests/mms.test.mjs
Normal file
34
tests/mms.test.mjs
Normal file
|
|
@ -0,0 +1,34 @@
|
|||
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)}}]}));
|
||||
});
|
||||
Loading…
Reference in a new issue