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)})) })