Files
past-go/weapp/tests/album.test.cjs
T
Blizzard 4c9708b562 feat: add WeChat Pay, Redis logging, storage tiers and personal albums
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.
2026-11-02 23:40:49 +08:00

72 lines
7.2 KiB
JavaScript

const test=require('node:test');
const assert=require('node:assert/strict');
const path=require('node:path');
const createLoader=require('./load-module.cjs');
const {metadataRows}=require('../utils/photo-metadata');
function setup(update=async()=>({success:true})) {
let definition;const calls=[],toasts=[],prompts=[];
const wx={getStorageSync:key=>key==='userId'?1:2,showToast:v=>toasts.push(v),showModal:v=>prompts.push(v)};
const api={photoUpdate:async data=>{calls.push(data);return update(data);}};
const load=createLoader({wx,console,Promise,Date,Page:p=>definition=p},{'../../utils/request':{api,getImageUrl:v=>v}, '../../utils/user-location':{currentUserLocation:async()=>({location:'',lat:0,lng:0})}});
load(path.join(__dirname,'../pages/album/album.js'));
const photos=[{id:1,url:'one.jpg',taken_at:'2026-10-07',location:'公园',activity:'散步',lat:23},{id:2,url:'two.jpg',taken_at:'',location:'',activity:''}];
const page={...definition,data:{...definition.data,batches:[{batch_id:'batch',photos,metadata:metadataRows(photos)}]},setData(v){Object.assign(this.data,v);}};
return {page,calls,toasts,prompts};
}
const event=(dataset,value)=>({currentTarget:{dataset},detail:{value}});
test('card combines identical information and labels individual photos when their stories differ',()=>{
assert.deepEqual(metadataRows([{id:1},{id:2}]),[]);
const same=metadataRows([{id:1,location:'公园'},{id:2,location:'公园'}]);assert.equal(same.length,1);assert.equal(same[0].label,'');
const different=metadataRows([{id:1,activity:'散步'},{id:2,location:'公园'}]);assert.equal(different.length,2);assert.equal(different[1].label,'第 2 张');
});
test('saving updates only the chosen photo and preview while preserving the list and coordinates',async()=>{
const e=setup(),p=e.page;p.onPhotoTap(event({batch:0,index:0}));assert.equal(p.data.previewImages[0].location,'公园');
p.openPhotoEditor(event({batch:0}));p.onEditPhotoInput(event({field:'activity'},'第一次一起看日落'));await p.savePhotoInfo();
assert.equal(e.calls.length,1);assert.equal(e.calls[0].id,1);assert.equal(p.data.batches[0].photos[0].activity,'第一次一起看日落');assert.equal(p.data.batches[0].photos[0].lat,23);
assert.equal(p.data.batches[0].photos[1].activity,'');assert.equal(p.data.previewImages[0].activity,'第一次一起看日落');assert.equal(p.data.showPhotoEditor,false);assert.equal(p.data.savingPhoto,false);
});
test('failed saves keep the draft and original card; switching photos confirms discarding changes',async()=>{
const e=setup(async()=>{throw {error:'保存失败'};}),p=e.page;p.openPhotoEditor(event({batch:0}));p.onEditPhotoInput(event({field:'location'},'新的地点'));
p.selectEditPhoto(event({index:1}));assert.equal(e.prompts.length,1);assert.equal(p.data.editPhotoIdx,0);e.prompts[0].success({confirm:false});assert.equal(p.data.editForm.location,'新的地点');
await p.savePhotoInfo();assert.equal(p.data.showPhotoEditor,true);assert.equal(p.data.savingPhoto,false);assert.equal(p.data.editForm.location,'新的地点');assert.equal(p.data.batches[0].photos[0].location,'公园');
p.selectEditPhoto(event({index:1}));e.prompts[1].success({confirm:true});assert.equal(p.data.editPhotoIdx,1);assert.equal(p.data.editForm.location,'');
});
test('date and optional fields can be cleared without duplicate saves',async()=>{
let resolve;const e=setup(()=>new Promise(done=>resolve=done)),p=e.page;p.openPhotoEditor(event({batch:0}));p.clearPhotoDate();
p.onEditPhotoInput(event({field:'location'},''));p.onEditPhotoInput(event({field:'activity'},''));const saving=p.savePhotoInfo();await p.savePhotoInfo();assert.equal(e.calls.length,1);assert.equal(e.calls[0].taken_at,'');
resolve({success:true});await saving;assert.equal(p.data.batches[0].metadata.length,0);
});
test('blank edit address uses current user location; a supplied address wins',async()=>{
const e=setup(),p=e.page;
// 使用实际页面的保存逻辑和可控的地址提供者。
let definition;
const loader=createLoader({wx:{getStorageSync:()=>1,showToast(){}},Date,Promise,console,Page:d=>definition=d},{'../../utils/request':{api:{photoUpdate:async data=>{e.calls.push(data);return {success:true,location:data.location};}},getImageUrl:v=>v},'../../utils/user-location':{currentUserLocation:async()=>({location:'当前用户地址',lat:25,lng:102})}});
loader(path.join(__dirname,'../pages/album/album.js'));
p.savePhotoInfo=definition.savePhotoInfo;
p.openPhotoEditor(event({batch:0}));p.onEditPhotoInput(event({field:'location'},' '));await p.savePhotoInfo();assert.equal(e.calls[0].location,'当前用户地址');assert.equal(e.calls[0].lat,25);assert.equal(p.data.batches[0].photos[0].location,'当前用户地址');
p.openPhotoEditor(event({batch:0}));p.onEditPhotoInput(event({field:'location'},' 手填地址 '));await p.savePhotoInfo();assert.equal(e.calls[1].location,'手填地址');assert.equal(e.calls[1].lat,0);
});
function uploadSetup(auth) {
let definition;const calls=[],modals=[],toasts=[];
const wx={getStorageSync:()=>'',showToast:v=>toasts.push(v),showModal:v=>modals.push(v),showLoading(){},hideLoading(){},switchTab:v=>calls.push(['switchTab',v]),redirectTo:v=>calls.push(['redirectTo',v]),chooseImage:()=>calls.push(['picker'])};
const api={checkAuth:async()=>auth(),storageInfo:async()=>({is_unlimited:true}),albumList:async()=>({items:[]}),albumAdd:async()=>{calls.push(['albumAdd']);return {id:'c224bc8c-0848-442d-abf6-350fab34d669'};},photoAdd:async data=>{calls.push(['photoAdd',data]);return {success:true};}};
const load=createLoader({wx,console,Date,Promise,Page:p=>definition=p},{'../../utils/request':{api,getImageUrl:v=>v,API_BASE:'https://we.sundynix.cn/api',uploadFileCompat:async()=>{calls.push(['upload']);return {file_id:'6487966a-28ac-41d1-97b6-26f279b11fa9'};}},'../../utils/user-location':{currentUserLocation:async()=>({location:'',lat:0,lng:0})}});
load(path.join(__dirname,'../pages/album/album.js'));
const page={...definition,data:{...definition.data,albumId:'c224bc8c-0848-442d-abf6-350fab34d669',uploadFilePaths:['photo.jpg'],photoFormList:[{}]},setData(v){Object.assign(this.data,v);},loadData(){calls.push(['reload']);}};
return {page,calls,modals,toasts};
}
test('unbound users upload and save photos in their own UUID album',async()=>{
const e=uploadSetup(()=>({logged_in:true,user:{couple_id:null}}));await e.page.uploadAll();
assert.equal(e.calls[0][0],'upload');assert.equal(e.calls[1][0],'photoAdd');assert.equal(e.calls[1][1].path,'6487966a-28ac-41d1-97b6-26f279b11fa9');assert.equal(e.calls[2][0],'reload');assert.equal(e.page.data.showUploadModal,false);assert.equal(e.modals.length,0);
});
test('bound users keep uploading to the existing shared album',async()=>{
const e=uploadSetup(()=>({logged_in:true,user:{couple_id:'bound'}}));await e.page.uploadAll();
assert.equal(e.calls[1][0],'photoAdd');assert.equal(e.calls[1][1].album_id,'c224bc8c-0848-442d-abf6-350fab34d669');
});
test('stale demo album is replaced with a real personal album before transferring photos',async()=>{
const e=uploadSetup(()=>({logged_in:true,user:{couple_id:null}}));e.page.data.albumId=-1;await e.page.uploadAll();
assert.equal(e.calls[0][0],'albumAdd');assert.equal(e.calls[1][0],'upload');assert.equal(e.calls[2][0],'photoAdd');assert.equal(e.calls[2][1].album_id,'c224bc8c-0848-442d-abf6-350fab34d669');
});