25 lines
3.0 KiB
JavaScript
25 lines
3.0 KiB
JavaScript
'use strict'
|
|
const fs=require('fs'),vm=require('vm'),assert=require('assert')
|
|
const source=fs.readFileSync('ufutx_love_mp/src/utils/virtual-payment.js','utf8').replace(/export /g,'')
|
|
const context={setTimeout:fn=>fn(),Promise,Error};vm.createContext(context);vm.runInContext(source+';this.buy=buyMembership;',context)
|
|
let payments=0,posts=[],state='FULFILLED',enabled=true,mismatch=false,cancel=false
|
|
const wx={getSystemInfoSync:()=>({platform:'android',system:'Android 14',version:'8.0.70'}),canIUse:()=>true,login:o=>o.success({code:'synthetic-code'}),requestVirtualPayment:o=>{payments++;cancel?o.fail({errMsg:'requestVirtualPayment:fail cancel'}):o.success({})}}
|
|
const api={get:async()=>({enabled,products:[{sub_rank_id:1,product_id:'synthetic',price_fen:100}]}),post:async(path,data)=>{posts.push(path);return path==='/rank/buy/virtual'?{order_no:'local-order',sign_data:JSON.stringify({goodsPrice:mismatch?101:100,buyQuantity:1,productId:'synthetic',outTradeNo:'local-order'}),mode:'short_series_goods',paySig:'synthetic',signature:'synthetic'}:{state}}}
|
|
;(async()=>{
|
|
enabled=false;await assert.rejects(context.buy(wx,api,1,100,()=>{}),/暂不可用/);assert.equal(posts.length,0);assert.equal(payments,0)
|
|
enabled=true;let order;await context.buy(wx,api,1,100,n=>order=n);assert.equal(order,'local-order');assert.equal(payments,1)
|
|
wx.getSystemInfoSync=()=>({platform:'ios',system:'iOS 18',version:'8.0.70'});await context.buy(wx,api,1,100,()=>{});assert.equal(payments,2)
|
|
wx.getSystemInfoSync=()=>({platform:'ios',system:'iOS 14',version:'8.0.70'});await assert.rejects(context.buy(wx,api,1,100,()=>{}),/升级/);assert.equal(payments,2)
|
|
wx.getSystemInfoSync=()=>({platform:'windows',system:'Windows 11',version:'4.0'});await context.buy(wx,api,1,100,()=>{});assert.equal(payments,3)
|
|
wx.getSystemInfoSync=()=>({platform:'ohos',system:'HarmonyOS',version:'8.0.70'});await context.buy(wx,api,1,100,()=>{});assert.equal(payments,4)
|
|
mismatch=true;await assert.rejects(context.buy(wx,api,1,100,()=>{}),/不一致/);assert.equal(payments,4);mismatch=false
|
|
await assert.rejects(context.buy(wx,api,1,200,()=>{}),/价格已更新/)
|
|
cancel=true;const cancelStart=posts.length;let cancelledOrder;await assert.rejects(context.buy(wx,api,1,100,n=>cancelledOrder=n),/取消/);cancel=false
|
|
assert.equal(cancelledOrder,'local-order','cancel must preserve order for later reconciliation')
|
|
assert.deepEqual(posts.slice(cancelStart),['/rank/buy/virtual'],'cancel must not invoke fulfilment or confirmation')
|
|
state='PENDING';const pendingStart=posts.length;await assert.rejects(context.buy(wx,api,1,100,()=>{}),/确认中/)
|
|
assert.equal(posts.slice(pendingStart).filter(p=>p.endsWith('/confirm')).length,5,'pending query must stop after bounded retries')
|
|
assert(!posts.some(p=>p==='/rank/buy' || p.includes('/callback')))
|
|
console.log('PASS: closed purchase, Android/iOS/Windows/HarmonyOS unified virtual pay, unsupported iOS, changed price/order mismatch, cancellation, pending confirmation; no legacy payment callback')
|
|
})().catch(e=>{console.error(e.message);process.exitCode=1})
|