43 lines
2.6 KiB
JavaScript
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);
|
|
}
|
|
});
|