const test = require("node:test"); const assert = require("node:assert/strict"); const fs = require("node:fs"); const vm = require("node:vm"); function runtime(storage = new Map()) { const counts = { location: 0, request: 0 }; let fail = false; let release; const module = { exports: {} }; vm.runInNewContext(fs.readFileSync("pets-fe/utils/environment.js", "utf8"), { module, wx: { getStorageSync: (key) => storage.get(key), setStorageSync: (key, value) => storage.set(key, value), getSetting: (opts) => opts.success({ authSetting: {} }), getLocation: (opts) => { counts.location++; opts.success({ latitude: 25, longitude: 102 }); }, }, require: () => ({ secure: async () => { counts.request++; if (fail) throw new Error("offline"); if (release) await release; return { location_name: "昆明市 · 五华区", weather: { description: "晴", temperature: "22" }, }; }, }), }); return { api: module.exports, counts, storage, fail: () => { fail = true; }, hold: (promise) => { release = promise; }, }; } test("页面重建与返回复用同一轮天气请求,点击可以刷新", async () => { const r = runtime(); let finish; r.hold( new Promise((resolve) => { finish = resolve; }), ); const first = r.api.refresh(); assert.equal(r.api.refresh(), first); finish(); await first; await r.api.refresh(); await r.api.refresh(); assert.equal(r.counts.location, 1); assert.equal(r.counts.request, 1); await r.api.refresh(true); assert.equal(r.counts.request, 2); assert.equal(r.api.cached().weatherLabel, "晴 22°C"); const saved = r.storage.get("pet_environment_v1"); assert.equal("latitude" in saved, false); assert.equal("longitude" in saved, false); }); test("冷启动先读取上次缓存,再请求一次;失败保留缓存且不会返回就重试", async () => { const previous = runtime(); await previous.api.refresh(); const next = runtime(previous.storage); assert.equal(next.api.cached().locationName, "昆明市 · 五华区"); assert.equal(next.counts.request, 0); next.fail(); await assert.rejects(next.api.refresh(), /offline/); await assert.rejects(next.api.refresh(), /offline/); assert.equal(next.counts.request, 1); assert.equal(next.api.cached().weatherLabel, "晴 22°C"); await assert.rejects(next.api.refresh(true), /offline/); assert.equal(next.counts.request, 2); });