import test from 'node:test'; import assert from 'node:assert/strict'; import { LoginAccounts, nicknameHash } from '../../YouleNexus/assets/framework/adapters/native/login-accounts.ts'; import { resolveLoginPolicy } from '../../YouleNexus/assets/framework/presentation/login-policy.ts'; import { buildLoginRequest } from '../../YouleNexus/assets/framework/protocol/contracts/login-contract.ts'; test('native authorization preserves provider numbers, agreement guard, callback and cache', () => { const values=new Map();const calls:number[]=[];const submitted:any[]=[];const tips:string[]=[]; const service=new LoginAccounts({storage:{getItem:k=>values.get(k)??null,setItem:(k,v)=>{values.set(k,v);}}, settings:{accreditlogin:p=>calls.push(p),getcompareCode:()=>0},random:()=>0.2,now:()=>100, gameid:'g',agentid:'a',policy:resolveLoginPolicy({raw:{},getValue:()=>null}),submit:(a,d)=>submitted.push([a,d]),tip:t=>tips.push(t)}); service.setAgreement(false);service.authorize('wechat');assert.deepEqual(calls,[]);assert.deepEqual(tips,['未同意协议']); service.setAgreement(true);service.authorize('wechat');service.authorize('qq');assert.deepEqual(calls,[2,1]); service.acceptNative({openid:'o',headimgurl:'a',nickname:'n',sex:1,city:'c',Province:'p',unionid:'u'},'bridge'); assert.equal(submitted[0][0].avatar,'a');assert.equal(submitted[0][0].province,'p'); assert.ok(values.has('tsgame_wxinfo'));assert.equal(service.cached()?.nickname,'n'); }); test('all login paths require the current agreement and rejected paths have no side effects',()=>{ const values=new Map(),tips:string[]=[],submitted:unknown[]=[],native:number[]=[]; const service=new LoginAccounts({storage:{getItem:k=>values.get(k)??null,setItem:(k,v)=>{values.set(k,v);}}, settings:{getcompareCode:()=>0,accreditlogin:p=>native.push(p)},random:()=>0.2,now:()=>100, gameid:'g',agentid:'a',policy:resolveLoginPolicy({raw:{},getValue:()=>null}),submit:a=>submitted.push(a),tip:t=>tips.push(t)}); assert.equal(service.agreed,true);service.setAgreement(false); service.authorize('wechat');service.authorize('qq');service.visitor();service.device();service.phone('00123','000456');service.autoLogin(); service.acceptNative({},'global');service.acceptNative({},'bridge'); for(let i=0;i<5;i++)service.hiddenFirst();service.hiddenSecond(); assert.equal(tips.length,9);assert.ok(tips.every(t=>t==='未同意协议')); assert.equal(values.size,0);assert.equal(submitted.length,0);assert.equal(native.length,0); service.setAgreement(true);service.visitor();assert.equal(submitted.length,1); }); test('successful device login persists server identity for the next automatic login', () => { const values=new Map();const submitted:any[]=[]; const service=new LoginAccounts({storage:{getItem:k=>values.get(k)??null,setItem:(k,v)=>{values.set(k,v);}}, random:()=>0.2,now:()=>100,gameid:'g',agentid:'a',policy:{...resolveLoginPolicy({raw:{},getValue:()=>null}),deviceLogin:true}, submit:(a,d)=>submitted.push([a,d]),tip:()=>{}}); service.loginSucceeded({state:0,playerid:42,openid:'server-o',avatar:'server-a',nickname:'server-n',sex:2,city:'c',province:'p',unionid:'u',tel:'13800138000'}, {enabled:true,telphone:'13800138000'}); service.autoLogin();assert.equal(submitted[0][0].openid,'server-o'); assert.deepEqual(submitted[0][1],{enabled:true,telphone:'13800138000'}); assert.equal(values.get('tsgame_playerid_ga'),'42');assert.equal(values.get('tsgame_dLogin'),'1'); }); test('visitor login and cached visitor stay phone-free when both login buttons are enabled', () => { const values=new Map();const submitted:any[]=[]; const options={storage:{getItem:(k:string)=>values.get(k)??null,setItem:(k:string,v:string)=>{values.set(k,v);}}, random:()=>0.2,now:()=>100,gameid:'g',agentid:'a',policy:{...resolveLoginPolicy({raw:{},getValue:()=>null}),showVisitor:true,deviceLogin:true}, submit:(a:unknown,d:unknown)=>submitted.push([a,d]),tip:()=>{}}; const service=new LoginAccounts(options); service.visitor();assert.deepEqual(submitted[0][1],{enabled:false}); assert.doesNotThrow(()=>service.loginSucceeded({state:0,playerid:42},submitted[0][1])); assert.equal(values.get('tsgame_playerid_ga'),'42'); assert.equal(values.has('tsgame_devicePlayer'),false);assert.equal(values.has('tsgame_dLogin'),false); const reloaded=new LoginAccounts(options);reloaded.autoLogin(); assert.deepEqual(submitted[1],[submitted[0][0],{enabled:false}]); assert.doesNotThrow(()=>reloaded.loginSucceeded({state:0,playerid:42},submitted[1][1])); }); test('global and WVJB authorization retain their distinct legacy cache destinations', () => { const values=new Map(); const service=new LoginAccounts({storage:{getItem:k=>values.get(k)??null,setItem:(k,v)=>{values.set(k,v);}}, random:()=>0.2,now:()=>100,gameid:'g',agentid:'a',policy:{...resolveLoginPolicy({raw:{},getValue:()=>null}),showVisitor:true},submit:()=>{},tip:()=>{}}); const data={openid:'o',headimgurl:'a',nickname:'n',sex:1,city:'c',Province:'p',unionid:'u'}; service.acceptNative(data,'global');assert.ok(values.has('tsgame_visitorinfo'));assert.equal(values.has('tsgame_wxinfo'),false); service.acceptNative(data,'bridge');assert.ok(values.has('tsgame_wxinfo')); }); test('legacy nickname MD5 matches standard vectors',()=>{ assert.equal(nicknameHash(''),'d41d8cd98f00b204e9800998ecf8427e'); assert.equal(nicknameHash('abc'),'900150983cd24fb0d6963f7d28e17f72'); }); test('phone login emits original sms fields and does not masquerade as cached auto login', () => { const values=new Map();const submitted:any[]=[]; const service=new LoginAccounts({storage:{getItem:k=>values.get(k)??null,setItem:(k,v)=>{values.set(k,v);}}, random:()=>0.2,now:()=>100,gameid:'g',agentid:'a',policy:resolveLoginPolicy({raw:{},getValue:()=>null}), submit:(a,d)=>submitted.push([a,d]),tip:()=>{}}); service.phone('13800138000','123456'); const [account,mode]=submitted[0];assert.equal(account.unionid,'phone_13800138000'); const result=buildLoginRequest({identity:{agentid:'a',gameid:'g',channelid:'c',marketid:4,version:1}},account, {location:null,machineid:'m',machineroom:'',deviceLogin:mode,loginPlayerId:{enabled:false}}); assert.equal(result.data.telphone,'13800138000');assert.equal(result.data.smmcode,'123456');assert.equal(result.data.telphoneAuto,false); });