Allow V3 native projects up to 128 screens and 300000 pixels in total height while preserving web draft limits. Cover the full-canvas boundary and both existing 40-item warning lists with focused contract tests.
49 lines
4.0 KiB
JavaScript
49 lines
4.0 KiB
JavaScript
import assert from 'node:assert/strict'
|
|
import {test} from 'node:test'
|
|
import {desktopAuthorization,desktopPortal,desktopProjectBody} from '../lib/desktop-client/contract.mjs'
|
|
|
|
test('desktop authorization requires S256 and an exact loopback callback',()=>{
|
|
const request={client_id:'jiansun-detail-desktop',response_type:'code',code_challenge_method:'S256',state:'a'.repeat(32),code_challenge:'b'.repeat(43),redirect_uri:'http://127.0.0.1:40001/oauth/callback'}
|
|
assert.equal(desktopAuthorization(request).redirectUri,request.redirect_uri)
|
|
for(const redirect_uri of ['https://example.com/oauth/callback','http://localhost:40001/oauth/callback','http://127.0.0.1:80/oauth/callback','http://127.0.0.1:40001/oauth/callback?next=elsewhere','http://127.0.0.1:40001/other']){
|
|
assert.throws(()=>desktopAuthorization({...request,redirect_uri}))
|
|
}
|
|
assert.throws(()=>desktopAuthorization({...request,code_challenge_method:'plain'}))
|
|
assert.throws(()=>desktopAuthorization({...request,state:'short'}))
|
|
})
|
|
|
|
test('desktop portal allowlist excludes unrelated services and credentials in URLs',()=>{
|
|
assert.equal(desktopPortal('https://sc.jiansun.vip'),'https://sc.jiansun.vip')
|
|
assert.equal(desktopPortal('http://127.0.0.1:3138'),'http://127.0.0.1:3138')
|
|
for(const value of ['https://api.vip98k.com','http://sc.jiansun.vip','https://sc.jiansun.vip/other','https://user@sc.jiansun.vip'])assert.throws(()=>desktopPortal(value))
|
|
})
|
|
|
|
test('native draft contract preserves chat and unsent input with bounded 1440px canvases',()=>{
|
|
const value={document:{version:1,id:'acceptance',name:'验收草稿',screens:[{width:1440,height:1800,layers:[]}]},revision:0,status:'draft',conversation:[{id:'one',role:'user',text:'保留品牌字体'}],composer:'尚未发送的要求'}
|
|
assert.equal(desktopProjectBody(value).composer,value.composer)
|
|
assert.deepEqual(desktopProjectBody(value).conversation,value.conversation)
|
|
assert.throws(()=>desktopProjectBody({...value,document:{...value.document,screens:[{width:4096,height:1800,layers:[]}]}}))
|
|
assert.throws(()=>desktopProjectBody({...value,revision:-1}))
|
|
assert.throws(()=>desktopProjectBody({...value,composer:'x'.repeat(6001)}))
|
|
})
|
|
|
|
test('native template projects preserve the complete long canvas while web draft limits stay unchanged',()=>{
|
|
const file=(path,sha)=>({path,sha256:sha.repeat(64),source:'native:'+sha.repeat(64),size:512})
|
|
const native={format:'photocraft',schemaVersion:1,documentSource:'native:'+'a'.repeat(64),files:[file('canvas.pcraft','a'),file('context.json','b'),file('session-backup.json','c')]}
|
|
const heights=Array.from({length:22},(_,i)=>i===21?2830:2100)
|
|
const document={version:3,id:'long-template',name:'完整详情模板',native,screens:heights.map((height,i)=>({id:'s'+i,width:1440,height,previewSource:'local:screen-'+i}))}
|
|
const input={document,revision:1,status:'draft'}
|
|
const accepted=desktopProjectBody(input).document
|
|
assert.equal(accepted.screens.length,22)
|
|
assert.equal(accepted.screens.reduce((sum,s)=>sum+s.height,0),46930)
|
|
const full=Array.from({length:128},(_,i)=>({id:'s'+i,width:1440,height:i===127?2820:2340,previewSource:'local:screen-'+i}))
|
|
assert.equal(desktopProjectBody({...input,document:{...document,screens:full}}).document.screens.length,128)
|
|
assert.equal(full.reduce((sum,s)=>sum+s.height,0),300000)
|
|
assert.throws(()=>desktopProjectBody({...input,document:{...document,screens:[...full,{id:'s128',width:1440,height:400}]}}))
|
|
assert.throws(()=>desktopProjectBody({...input,document:{...document,screens:full.map((s,i)=>i===127?{...s,height:2821}:s)}}))
|
|
for(const version of [1,2])assert.throws(()=>desktopProjectBody({...input,document:{...document,version}}))
|
|
assert.throws(()=>desktopProjectBody({...input,document:{...document,screens:Array.from({length:101},(_,i)=>({id:'s'+i,width:1440,height:3000}))}}))
|
|
assert.throws(()=>desktopProjectBody({...input,document:{...document,native:{...native,files:[...native.files,file('outside.json','d')]}}}))
|
|
assert.throws(()=>desktopProjectBody({...input,document:{...document,native:{...native,files:native.files.map((f,i)=>i?f:{...f,size:512*1024*1024+1})}}}))
|
|
})
|