update:翻译备份
This commit is contained in:
@@ -0,0 +1,136 @@
|
||||
// 段位多语言集成回归:请求使用本地桩,缓存通过真实 Pinia 持久化插件恢复。
|
||||
const assert = require('node:assert/strict');
|
||||
const fs = require('node:fs');
|
||||
const path = require('node:path');
|
||||
const { createPinia, defineStore } = require('pinia');
|
||||
const { createSSRApp } = require('vue');
|
||||
const persist = require('pinia-plugin-persistedstate').default;
|
||||
const root = path.resolve(__dirname, '..');
|
||||
const read = file => fs.readFileSync(path.join(root, file), 'utf8');
|
||||
const requests = [];
|
||||
let hasToken = true;
|
||||
let nextFailure;
|
||||
const rank = {rankLvl: 1, rankName: 'Bronze I', rankIcon: 'https://example.test/青铜1.png'};
|
||||
const apiUni = {
|
||||
getAccountInfoSync: () => ({miniProgram: {envVersion: 'trial'}}),
|
||||
getStorageSync: key => hasToken && key === 'trial_token' ? 'existing-token' : '',
|
||||
request(options) {
|
||||
requests.push(options);
|
||||
if (options.url.endsWith('/user/device/aimRenew')) return {};
|
||||
if (nextFailure) {
|
||||
const error = nextFailure;
|
||||
nextFailure = undefined;
|
||||
options.success({statusCode: 200, data: error});
|
||||
return;
|
||||
}
|
||||
const data = options.url.includes('/myHome')
|
||||
? {...rank, user: {id: 42, scores: 150, rankLvl: 1, nickName: '原昵称'}}
|
||||
: {list: [{...rank}], randInfos: [{rank_id: 1, upgrade_scores: 100, name: 'Bronze I', icoin: rank.rankIcon}]};
|
||||
options.success({statusCode: 200, data: {code: 0, data}});
|
||||
},
|
||||
};
|
||||
const apiCode = read('src/apis.js').replace(/^import .*;\r?\n/gm, '').replace(/^export /gm, '');
|
||||
const api = new Function('uni', 't', 'normalizeBattleApiResult', apiCode + `
|
||||
return {request, getAppConfig, getHomeData, getScoreRankList, getTenRingRankList, getMvpRankList,
|
||||
getMyScoreRank, getMyTenRingRank, getMyMvpRank, getSeasonStats, getProvinceData, getDailyCountAPI, aimRenewAPI};
|
||||
`)(apiUni, key => key, data => data);
|
||||
|
||||
const storeCode = read('src/store.js').replace(/^import .*;\r?\n/gm, '').replace('export default defineStore', 'return defineStore');
|
||||
function restore(cached) {
|
||||
const storage = new Map([
|
||||
['store', JSON.stringify(cached)],
|
||||
['trial_token', 'existing-token'],
|
||||
['point-book', JSON.stringify({draft: true})],
|
||||
]);
|
||||
const uni = {getStorageSync: key => storage.get(key), setStorageSync: (key, value) => storage.set(key, value)};
|
||||
const useStore = new Function('defineStore', 'uni', storeCode)(defineStore, uni);
|
||||
const pinia = createPinia();
|
||||
pinia.use(persist);
|
||||
createSSRApp({}).use(pinia);
|
||||
return {store: useStore(pinia), storage};
|
||||
}
|
||||
|
||||
async function main() {
|
||||
const config = await api.getAppConfig();
|
||||
const home = await api.getHomeData(42);
|
||||
await api.getScoreRankList(42, 2, 20);
|
||||
await api.getTenRingRankList(42, 2, 20);
|
||||
await api.getMvpRankList(42, 2, 20);
|
||||
await api.getMyScoreRank(42);
|
||||
await api.getMyTenRingRank(42);
|
||||
await api.getMyMvpRank(42);
|
||||
await api.getSeasonStats(0);
|
||||
await api.request('GET', '/index/myHome?seasonId=42');
|
||||
for (const request of requests) {
|
||||
assert.equal(request.header['Accept-Language'], 'en-US');
|
||||
assert.equal(request.header.Authorization, 'Bearer existing-token');
|
||||
assert.equal(request.method, 'GET');
|
||||
assert(request.url.startsWith('https://apitest.shelingxingqiu.com/api/shoot/'));
|
||||
}
|
||||
assert(requests[1].url.endsWith('/user/myHome?seasonId=42'), 'Existing home route must remain unchanged');
|
||||
assert.deepEqual(requests[2].data, {seasonId: 42, page: 2, perPage: 20});
|
||||
assert.deepEqual(requests[8].data, {seasonId: 0});
|
||||
assert.equal(home.user.rankName, rank.rankName);
|
||||
assert.equal(home.user.rankIcon, rank.rankIcon);
|
||||
assert.equal(home.user.nickName, '原昵称');
|
||||
await api.getProvinceData();
|
||||
await api.getDailyCountAPI();
|
||||
await api.request('GET', '/index/appConfig/other');
|
||||
await api.request('POST', '/index/appConfig');
|
||||
await api.request('PUT', '/test/update', {value: 0});
|
||||
await api.request('DELETE', '/test/delete', {id: 42});
|
||||
for (const request of requests.slice(10)) {
|
||||
assert.equal(request.header['Accept-Language'], 'en-US', 'All HTTP requests must declare English');
|
||||
assert.equal(request.header.Authorization, 'Bearer existing-token');
|
||||
}
|
||||
assert.deepEqual(requests.at(-2).data, {value: 0});
|
||||
assert.deepEqual(requests.at(-1).data, {id: 42});
|
||||
// 续期请求即使未收到响应,也必须保持同步返回且不弹失败提示。
|
||||
assert.equal(api.aimRenewAPI(), undefined);
|
||||
assert.equal(requests.at(-1).header['Accept-Language'], 'en-US');
|
||||
assert.equal(requests.at(-1).header.Authorization, 'Bearer existing-token');
|
||||
assert.equal(requests.at(-1).method, 'POST');
|
||||
assert.deepEqual(requests.at(-1).data, {});
|
||||
assert.equal(requests.at(-1).timeout, 10000);
|
||||
assert.equal(requests.at(-1).fail({errMsg: 'timeout'}), undefined);
|
||||
hasToken = false;
|
||||
await api.getAppConfig();
|
||||
assert.deepEqual(requests.at(-1).header, {'Accept-Language': 'en-US'});
|
||||
assert.equal(api.aimRenewAPI(), undefined);
|
||||
assert.deepEqual(requests.at(-1).header, {'Accept-Language': 'en-US'});
|
||||
hasToken = true;
|
||||
nextFailure = {code: 400, message: '设备未连接', data: {reason: 'offline'}};
|
||||
await assert.rejects(api.request('POST', '/test/error', {}, undefined, undefined, {showErrorToast: false}),
|
||||
error => error.code === 400 && error.message === '设备未连接' && error.data.reason === 'offline');
|
||||
assert.equal(requests.at(-1).header['Accept-Language'], 'en-US');
|
||||
|
||||
const legacy = {
|
||||
user: {id: 42, nickName: '原昵称', avatar: 'avatar.png', trio: 1, scores: 150, rankLvl: 1,
|
||||
lvlName: '倔强青铜I', rankName: '倔强青铜I', nextRankName: '倔强青铜II',
|
||||
rankIcon: rank.rankIcon, nextRankIcon: 'next.png', lvlImage: 'level.png', vip: true},
|
||||
device: {deviceId: 'unchanged-device', deviceName: '我的弓'},
|
||||
};
|
||||
const {store, storage} = restore(legacy);
|
||||
for (const [field, value] of Object.entries(legacy.user)) {
|
||||
assert.deepEqual(store.user[field], ['lvlName','rankName','nextRankName'].includes(field) ? '' : value);
|
||||
}
|
||||
assert.deepEqual({...store.device}, legacy.device);
|
||||
assert.equal(storage.get('trial_token'), 'existing-token');
|
||||
assert.equal(storage.get('point-book'), JSON.stringify({draft: true}));
|
||||
assert.deepEqual([...storage.keys()].sort(), ['store', 'trial_token', 'point-book'].sort());
|
||||
await store.updateConfig(config);
|
||||
await store.updateUser(home.user);
|
||||
assert.equal(store.user.rankName, 'Bronze I');
|
||||
assert.equal(store.user.lvlName, 'Bronze I');
|
||||
assert.equal(store.user.scores, 150);
|
||||
assert.equal(store.user.rankLvl, 1);
|
||||
store.$persist();
|
||||
const next = restore(JSON.parse(storage.get('store'))).store;
|
||||
assert.equal(next.user.rankName, 'Bronze I', 'English cached labels must survive cold start');
|
||||
assert.equal(next.user.lvlName, 'Bronze I');
|
||||
assert.equal(next.user.nickName, '原昵称');
|
||||
assert.deepEqual({...next.device}, legacy.device);
|
||||
assert.equal(restore({user: {id: 7, rankName: '', lvlName: null}, device: {}}).store.user.lvlName, null);
|
||||
console.log('Rank i18n checks passed: global HTTP English headers (GET/POST/PUT/DELETE + aim renewal), auth/query/pagination and original errors preserved; non-blocking renewal and real Pinia cache hydration verified.');
|
||||
}
|
||||
main().catch(error => {console.error(error); process.exitCode = 1;});
|
||||
Reference in New Issue
Block a user