mirror of
https://github.com/tdurieux/anonymous_github.git
synced 2026-10-18 13:50:50 +02:00
* perf: bound request work and resource usage * fix: address performance review regressions * fix: guard content expiration and dashboard state * fix: tolerate cache outages and retire derived paths * fix: revalidate expiration claims and status pagination * fix: retry interrupted repository metadata cleanup * fix: retire obsolete content cache storage * fix: activate tree metadata and recheck expiration claims * fix: fence cache publication across expiration * fix: recover staged trees and enforce cache lifecycle cleanup * fix: prune expired transforms during database outages * fix: finish conference removals and reload expiration candidates
67 lines
3.1 KiB
JavaScript
67 lines
3.1 KiB
JavaScript
const { expect } = require("chai");
|
|
const fs = require("fs");
|
|
const vm = require("vm");
|
|
const { setImmediate } = require("timers");
|
|
const source = fs.readFileSync(require("path").join(__dirname, "../public/script/app.js"), "utf8");
|
|
const actions = source.slice(source.indexOf(" function waitRepoToBeReady("), source.indexOf(" state.itemFilter ="));
|
|
|
|
describe("dashboard refresh feedback", () => {
|
|
async function run({ statuses = [], postError, getError } = {}) {
|
|
let toast;
|
|
const item = { _type: "repo", _id: "restore-me", repoId: "restore-me", status: "removed" };
|
|
const state = { items: [item], addToast: value => { toast = value; },
|
|
needsAttention: item => item.status === "error" || (item._statusKey === "progress" && item._stale) };
|
|
const pending = [];
|
|
let reloads = 0;
|
|
vm.runInNewContext(actions, {
|
|
state, legacyDashboard: true, reactive: value => value,
|
|
statusKey: status => ["ready", "error", "removed", "expired"].includes(status) ? status : "progress",
|
|
http: {
|
|
post: async () => { if (postError) throw postError; return {}; },
|
|
get: async () => { if (getError) throw getError; return { data: statuses.shift() }; },
|
|
},
|
|
timers: { timeout: callback => pending.push(callback) },
|
|
loadAll: () => { reloads++; },
|
|
});
|
|
state.refreshItem(item);
|
|
await new Promise(resolve => setImmediate(resolve));
|
|
while (pending.length) {
|
|
pending.shift()();
|
|
await new Promise(resolve => setImmediate(resolve));
|
|
}
|
|
return { toast, item, reloads };
|
|
}
|
|
|
|
it("reports success after preparation reaches ready", async () => {
|
|
const result = await run({ statuses: [{ status: "preparing" }, { status: "ready" }] });
|
|
expect(result.toast.title).to.equal("restore-me is refreshed.");
|
|
expect(result.item.status).to.equal("ready");
|
|
expect(result.reloads).to.equal(0);
|
|
});
|
|
for (const status of ["error", "removed", "expired"]) {
|
|
it(`reports ${status} as a failed refresh`, async () => {
|
|
const result = await run({ statuses: [{ status, statusMessage: "token_expired" }] });
|
|
expect(result.toast.title).to.equal("Error during the refresh of restore-me.");
|
|
expect(result.toast.body).to.equal("token_expired");
|
|
expect(result.item.statusMessage).to.equal("token_expired");
|
|
expect(result.reloads).to.equal(1);
|
|
});
|
|
}
|
|
it("explains a terminal status without a status message", async () => {
|
|
const result = await run({ statuses: [{ status: "expired" }] });
|
|
expect(result.toast.body).to.equal("The repository is expired.");
|
|
});
|
|
for (const stage of ["postError", "getError"]) {
|
|
it(`shows the API error from ${stage}`, async () => {
|
|
const result = await run({ [stage]: { data: { error: "not_connected" } } });
|
|
expect(result.toast.title).to.equal("Error during the refresh of restore-me.");
|
|
expect(result.toast.body).to.equal("not_connected");
|
|
});
|
|
}
|
|
it("reports a polling network failure", async () => {
|
|
const result = await run({ getError: new Error("Network failure") });
|
|
expect(result.toast.title).to.equal("Error during the refresh of restore-me.");
|
|
expect(result.toast.body).to.include("Please try again");
|
|
});
|
|
});
|