Gate record features and storage entry points with invitation guidance; enforce record access in the backend. Add homepage greetings, right-swipe profile dismissal, and move the smoking switch to settings. Simplify API base configuration and remove the unused legacy tab bar component.
61 lines
4.4 KiB
JavaScript
61 lines
4.4 KiB
JavaScript
const test=require('node:test');
|
|
const assert=require('node:assert/strict');
|
|
const path=require('node:path');
|
|
function loadPage(file,api,wxExtra={}) {
|
|
let definition;
|
|
const storage=new Map([['userId',1],['coupleId',10]]),intervals=[];
|
|
const wx={getStorageSync:k=>storage.get(k),setStorageSync:(k,v)=>storage.set(k,v),removeStorageSync:k=>storage.delete(k),showToast(){},...wxExtra};
|
|
const loader=require('./load-module.cjs')({Page:p=>definition=p,wx,console,Date,Promise,setTimeout,clearTimeout,setInterval:fn=>{intervals.push(fn);return intervals.length;},clearInterval(){}},{'../../utils/request':{api},'../../utils/layout':{getLayout:()=>({})}});
|
|
loader(path.join(__dirname,'../pages',file));
|
|
const page={...definition,data:JSON.parse(JSON.stringify(definition.data)),setData(v){Object.assign(this.data,v);}};
|
|
return {page,storage,intervals,wx};
|
|
}
|
|
const tick=async()=>{for(let i=0;i<20;i++)await Promise.resolve();};
|
|
const journal=overrides=>({cycles:[],daily:[],sex_records:[],can_access:true,has_couple:true,partner_user_id:2,period_visible:0,...overrides});
|
|
test('legacy shared journal displays returned cycles and clears them when access closes',async()=>{
|
|
let denied=false;
|
|
const {page}=loadPage('period/period.js',{periodList:async()=>journal({can_access:!denied,cycles:denied?[]:[{id:7,start_date:'2026-10-01',end_date:'2026-10-05'}]})});
|
|
page.calculateStats=()=>{};page.buildCalendar=()=>{};
|
|
await page.loadData();assert.equal(page.data.accessDenied,false);assert.equal(page.data.savedCycles.length,1);
|
|
denied=true;await page.loadData();assert.equal(page.data.accessDenied,true);assert.equal(page.data.savedCycles.length,0);
|
|
});
|
|
test('cooling keeps the relationship and server completion clears it',async()=>{
|
|
let status='cooling';const {page,storage}=loadPage('unbind/unbind.js',{unbindStatus:async()=>({status,remaining_seconds:259200,is_requester:false})});page._visible=true;
|
|
await page.loadStatus();await tick();assert.equal(page.data.status,'cooling');assert.equal(storage.get('coupleId'),10);assert.equal(page.data.timerText,'72时 0分 0秒');
|
|
status='completed';await page.loadStatus();await tick();assert.equal(storage.has('coupleId'),false);assert.equal(page.data.status,'completed');
|
|
});
|
|
test('server relation changes discard cached data before another read',async()=>{
|
|
const storage=new Map([['userId',1],['coupleId',10],['token','private']]);let redirects=0,reads=0;
|
|
const wx={getStorageSync:k=>storage.get(k),setStorageSync:(k,v)=>storage.set(k,v),hideLoading(){},request(o){
|
|
if(o.url.includes('/diaryList')){reads++;o.success({statusCode:200,data:{items:[{title:reads===1?'old space':'new space'}]}});}
|
|
else o.success({statusCode:200,header:{'X-Couple-ID':'22','X-User-ID':'1'},data:{loggedIn:true}});
|
|
}};
|
|
const loader=require('./load-module.cjs')({wx,console,Date,Promise,getApp:()=>({onRelationChanged(){redirects++;}})});
|
|
const {api,getImageUrl}=loader(path.join(__dirname,'../utils/request.js'));
|
|
await api.diaryList();await api.diaryList();assert.equal(reads,1);
|
|
await api.checkAuth();assert.equal(storage.get('coupleId'),'22');assert.equal(redirects,1);
|
|
const fresh=await api.diaryList();assert.equal(reads,2);assert.equal(fresh.items[0].title,'new space');
|
|
assert.equal(getImageUrl('/api/files/6083e119-6b26-441b-8b70-44d224366238'),require('../config/env').API_BASE+'/files/6083e119-6b26-441b-8b70-44d224366238');
|
|
});
|
|
|
|
test('settings and profile consent retain couple cache and lead into cooling',async()=>{
|
|
for (const file of ['settings/settings.js','profile/profile.js']) {
|
|
let agreed=0;
|
|
const e=loadPage(file,{unbindRespond:async()=>{agreed++;}}, {
|
|
showActionSheet:o=>o.success({tapIndex:0}),showModal:o=>o.success({confirm:true}),showLoading(){},hideLoading(){},navigateTo(){}
|
|
});
|
|
e.page.loadUnbindStatus=()=>{};
|
|
e.page.doRespondUnbind();await tick();
|
|
assert.equal(agreed,1);assert.equal(e.storage.get('coupleId'),10);
|
|
}
|
|
});
|
|
test('either partner can use cooling withdrawal and state refresh preserves binding',async()=>{
|
|
for (const isRequester of [true,false]) {
|
|
let cancelled=0;
|
|
const e=loadPage('unbind/unbind.js',{unbindCancel:async()=>{cancelled++;},unbindStatus:async()=>({status:'cancelled',is_requester:isRequester})},{showModal:o=>o.success({confirm:true}),showLoading(){},hideLoading(){}});
|
|
e.page._visible=true;e.page.data.status='cooling';e.page.data.isRequester=isRequester;
|
|
e.page.cancelUnbind();await tick();
|
|
assert.equal(cancelled,1);assert.equal(e.page.data.status,'cancelled');assert.equal(e.storage.get('coupleId'),10);
|
|
}
|
|
});
|