Replace virtual payments with WeChat Pay API v3 and verify callbacks and order polling. Cache WeChat access tokens in Redis and write structured Zap logs. Support configurable capacity plans across the API, admin and mini program, with purchase snapshots and quota enforcement. Allow personal albums before binding and share them with the current partner. Update deployment configuration and domain routing.
62 lines
4.6 KiB
JavaScript
62 lines
4.6 KiB
JavaScript
const test = require('node:test');
|
|
const assert = require('node:assert/strict');
|
|
const fs = require('node:fs');
|
|
const vm = require('node:vm');
|
|
const path = require('node:path');
|
|
function load(file, wx) {
|
|
return require('./load-module.cjs')({wx, console, Promise, Date})(path.join(__dirname, '..', file));
|
|
}
|
|
test('GET business parameters and POST bodies use clean paths with auth', async () => {
|
|
const calls=[];
|
|
const {api}=load('utils/request.js', { getStorageSync:()=> 'test-token', hideLoading(){}, request(o){calls.push(o);o.success({statusCode:200,data:{items:[], pageSize:20}});} });
|
|
const response = await api.diaryList({page:2,page_size:20});
|
|
assert.equal(response.page_size,20);
|
|
await api.periodVisibleSet({period_visible:0});
|
|
assert.equal(calls[0].url,'https://we.sundynix.cn/api/diaryList?page=2&pageSize=20');
|
|
assert.equal(calls[0].header.Authorization,'Bearer test-token');
|
|
assert.equal(calls[1].url,'https://we.sundynix.cn/api/periodVisibleSet');
|
|
assert.equal(calls[1].data.periodVisible,0);
|
|
});
|
|
test('multipart upload retains action and token when Android omits headers',async()=>{
|
|
let upload;
|
|
const {uploadFileCompat}=load('utils/request.js',{getStorageSync:()=> 'test-token',compressImage(o){o.fail();},uploadFile(o){upload=o;o.success({statusCode:200,data:'{"success":true,"path":"uploads/test.jpg"}'});} });
|
|
await uploadFileCompat({url:'https://we.sundynix.cn/api/uploadPartnerAvatar',filePath:'test.jpg',name:'file',formData:{partner_id:87}});
|
|
assert.equal(upload.url,'https://we.sundynix.cn/api/uploadPartnerAvatar?token=test-token');
|
|
assert.equal(upload.formData.action,'uploadPartnerAvatar');
|
|
assert.equal(upload.formData.token,'test-token');
|
|
assert.equal(upload.formData.partnerId,87);
|
|
assert.equal(upload.formData.partner_id,undefined);
|
|
});
|
|
test('navigation responds to phone statusbar and capsule geometry, with fallback',()=>{
|
|
for(const device of [{status:20,top:24,height:32,width:360,left:263},{status:54,top:58,height:32,width:393,left:285}]){
|
|
const {getLayout}=load('utils/layout.js',{getWindowInfo:()=>({statusBarHeight:device.status,windowWidth:device.width}),getMenuButtonBoundingClientRect:()=>({top:device.top,height:device.height,left:device.left})});
|
|
const layout=getLayout();assert.equal(layout.navHeight,device.status+40);assert.equal(layout.navSide,device.width-device.left+12);
|
|
}
|
|
const {getLayout}=load('utils/layout.js',{});assert.equal(getLayout().navHeight,64);
|
|
});
|
|
test('failed homepage load ends the recent-record spinner',async()=>{
|
|
let definition;
|
|
const api={coupleInfo:async()=>{throw { _statusCode:404 };}};
|
|
vm.runInNewContext(fs.readFileSync(path.join(__dirname,'../pages/index/index.js'),'utf8'),{
|
|
Page(p){definition=p;},require(name){return name.endsWith('/list-pagination')?require('../utils/list-pagination'):name.endsWith('/page-cache')?{withDataCache:p=>p}:name.endsWith('/request')?{api,getImageUrl:v=>v}:name.endsWith('/layout')?{getLayout:()=>({})}:{saveScrollPosition(){},getScrollPosition(){return 0;}};},
|
|
wx:{getStorageSync:()=> 'test-token'}, console:{error(){}}, Date, setTimeout
|
|
});
|
|
const page={...definition,data:{...definition.data},setData(data){Object.assign(this.data,data);}};
|
|
await page.loadData();
|
|
assert.equal(page.data.homeError,true);assert.equal(page.data.statsLoading,false);assert.equal(page.data.statsError,true);assert.equal(page._loadingData,false);
|
|
});
|
|
|
|
test('unbound newcomer loads homepage records without requesting couple-only pets',async()=>{
|
|
let definition;let petCalls=0;
|
|
const api={coupleInfo:async()=>({not_bound:true,partner1:{nickname:'新用户'}}),timelineList:async()=>[],albumList:async()=>[],diaryList:async()=>({items:[],total:0}),songsList:async()=>[],checkinList:async()=>({items:[]}),petInfo:async()=>{petCalls++;throw Error('请先绑定情侣');}};
|
|
vm.runInNewContext(fs.readFileSync(path.join(__dirname,'../pages/index/index.js'),'utf8'),{
|
|
Page(p){definition=p;},require(name){return name.endsWith('/list-pagination')?require('../utils/list-pagination'):name.endsWith('/page-cache')?{withDataCache:p=>p}:name.endsWith('/request')?{api,getImageUrl:v=>v}:name.endsWith('/layout')?{getLayout:()=>({})}:name.endsWith('/journal')?{diaryEntry:v=>v}:{};},
|
|
wx:{getStorageSync:()=>1,removeStorageSync(){}},console,Date,setTimeout
|
|
});
|
|
const page={...definition,data:{...definition.data,coupleId:99},setData(data){Object.assign(this.data,data);}};
|
|
await page.loadData();
|
|
assert.equal(petCalls,0);assert.equal(page.data.coupleId,null);
|
|
assert.equal(page.data.homeError,false);assert.equal(page.data.statsError,false);assert.equal(page.data.statsLoading,false);
|
|
assert.equal(page.data.recentDiary.length,0);assert.equal(page.data.stats.pet,0);
|
|
});
|