MatchMaster/server/laf-cloud/functions/goldMiner/tests/payment-page.test.mjs

43 lines
2.6 KiB
JavaScript

import test from 'node:test';
import assert from 'node:assert/strict';
import { readFileSync } from 'node:fs';
import { runInNewContext } from 'node:vm';
const html = readFileSync(new URL('../web/order3.html', import.meta.url), 'utf8');
const script = html.match(/<script>([\s\S]*?)<\/script>/)[1];
async function page(params = {}, response = true, bridgeReady = true) {
const calls = [], payments = [], alerts = [], events = {};
const data = {name:'黄金矿工 100%',openid:'owner',outTradeNo:'order',time:'scoped-ticket',price:123,quantity:1,
body:{appId:'app',timeStamp:'100',nonceStr:'nonce',package:'prepay_id=prepay',paySign:'sig'},...params};
const bridge = {invoke(method,body) {payments.push({method,body});}};
const context = {window:{location:{hash:'#data='+encodeURIComponent(JSON.stringify(data))}},URL,URLSearchParams,
document:{addEventListener(name,fn){events[name]=fn;}},alert(value){alerts.push(value);},console,
setTimeout(fn){fn();},fetch:async(url,options)=>{calls.push({url,body:JSON.parse(options.body)});return {json:async()=>response};},
...(bridgeReady ? {WeixinJSBridge:bridge} : {})};
runInNewContext(script,context); events.DOMContentLoaded();
await new Promise(resolve=>setImmediate(resolve));
return {calls,payments,alerts,ready(){context.WeixinJSBridge=bridge;events.WeixinJSBridgeReady();}};
}
test('payment page forwards scoped ticket and uses configured test application',async()=>{
const r=await page({checkUrl:'https://test.invalid/wx/checkIos'});
assert.equal(r.calls[0].url,'https://test.invalid/wx/checkIos');
assert.deepEqual(r.calls[0].body,{openid:'owner',time:'scoped-ticket',outTradeNo:'order'});
assert.equal(r.payments.length,1); assert.equal(r.alerts.length,0);
});
test('payment page requires explicit true before invoking payment',async()=>{
for(const response of [false,{code:0},null,'true']) {
const r=await page({},response);assert.equal(r.payments.length,0);assert.equal(r.alerts.length,1);
}
});
test('payment page retains ordinary channel default and waits for Weixin bridge',async()=>{
const r=await page({},true,false);
assert.equal(r.calls[0].url,'https://q6rvwvtnga.sealoshzh.site/wx/checkIos');
assert.equal(r.payments.length,0);assert.equal(r.alerts.length,0);
r.ready();assert.equal(r.payments.length,1);
});
test('payment page rejects malformed and insecure endpoints without network requests',async()=>{
for(const checkUrl of ['invalid','http://test.invalid/wx/checkIos','https://test.invalid/other','https://user:pass@test.invalid/wx/checkIos']) {
const r=await page({checkUrl});assert.equal(r.calls.length,0);assert.equal(r.alerts.length,1);
}
});