Files
past-go/weapp/tests/auth.test.cjs
T
2026-10-07 09:28:43 +08:00

72 lines
4.2 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 setup() {
const storage = new Map();
const logins = [], requests = [];
let app;
const wx = {
getStorageSync: key => storage.get(key), setStorageSync: (key,value) => storage.set(key,value),
removeStorageSync: key => storage.delete(key), getStorageInfoSync: () => ({keys:[...storage.keys()]}),
login: options => logins.push(options), request: options => requests.push(options),
getNetworkType: options => options.success({networkType:'wifi'}), onNetworkStatusChange(){},
hideLoading(){}, showToast(){}
};
const ctx = {wx, getApp:()=>app, console, Promise, setTimeout, clearTimeout,
module:{exports:{}}, require: name => require(path.join(__dirname,'../utils', name))};
vm.runInNewContext(fs.readFileSync(path.join(__dirname,'../utils/request.js'),'utf8'),ctx);
const request = ctx.module.exports;
ctx.require = () => request;
ctx.App = definition => {app=definition;};
vm.runInNewContext('(function(){' + fs.readFileSync(path.join(__dirname,'../app.js'),'utf8') + '\n})()',ctx);
return {app,wx,storage,logins,requests,api:request.api};
}
const flush = async()=> {for(let i=0;i<12;i++) await Promise.resolve();};
async function finishLogin(env, token='fresh') {
env.logins.at(-1).success({code:'wechat-code'});
await flush();
const login = env.requests.findLast(req=>req.url.endsWith('/wechatLogin'));
assert.ok(login, 'login endpoint bypasses auth gate');
login.success({statusCode:200,data:{token,userId:87}});
await flush();
}
test('cold start refreshes even cached token and holds concurrent business requests until login completes',async()=>{
const env=setup(); env.storage.set('token','old'); env.app.onLaunch();
const first=env.api.coupleInfo(), second=env.api.diaryList();
await flush(); assert.equal(env.logins.length,1); assert.equal(env.requests.length,0);
await finishLogin(env);
assert.equal(env.app.globalData.authState,'ready');
const business=env.requests.filter(req=>!req.url.endsWith('/wechatLogin'));
assert.equal(business.length,2); business.forEach(req=>{assert.equal(req.header.Authorization,'Bearer fresh');req.success({statusCode:200,data:[]});});
await Promise.all([first,second]);
});
test('first launch without any stored token issues no anonymous business request',async()=>{
const env=setup();env.app.onLaunch();const pending=env.api.periodList();
await flush();assert.equal(env.requests.length,0);assert.equal(env.logins.length,1);
await finishLogin(env);const business=env.requests.find(req=>req.url.endsWith('/periodList'));
assert.equal(business.header.Authorization,'Bearer fresh');
business.success({statusCode:200,data:{cycles:[],canAccess:true}});await pending;
});
test('login failure rejects waiting loads and explicit retry obtains a usable token',async()=>{
const env=setup();env.app.onLaunch();
const failed=assert.rejects(env.api.diaryList(),error=>error.authFailed===true);
env.logins[0].success({});await failed;await flush();
assert.equal(env.app.globalData.authState,'error');assert.equal(env.requests.length,0);
await assert.rejects(env.app.ensureAuth());assert.equal(env.logins.length,1);
const retry=env.app.silentLogin();await finishLogin(env);await retry;
assert.equal(env.storage.get('token'),'fresh');
});
test('parallel 401 responses share token refresh and retry at most once',async()=>{
const env=setup();env.app.onLaunch();await finishLogin(env,'first');
const one=env.api.coupleInfo(),two=env.api.diaryList();await flush();
const old=env.requests.filter(req=>!req.url.endsWith('/wechatLogin'));
old.forEach(req=>req.success({statusCode:401,data:{error:'expired'}}));await flush();
assert.equal(env.logins.length,2);await finishLogin(env,'second');
const retried=env.requests.filter(req=>req.header.Authorization==='Bearer second');assert.equal(retried.length,2);
const failed=assert.rejects(one,error=>error._statusCode===401);
retried[0].success({statusCode:401,data:{error:'still unauthorized'}});retried[1].success({statusCode:200,data:[]});
await failed;await two;assert.equal(env.logins.length,2);
});