const assert = require("node:assert/strict"); const { test } = require("node:test"); const { loadApplication } = require("./support/application.cjs"); const { response } = require("./support/characterization.cjs"); function setup(fetch) { const app = loadApplication("content", { fetch }); app.currentUser.allowsCrmActivities = () => true; app.opportunitiesQueryState.periodRequestVersion = 1; app.debugContentView.renderDebugPanel = () => {}; app.activityProgress.update = () => {}; app.productsContentJobs.renderProductsProgress = () => {}; app.productsContentJobs.queueProductsTableRender = () => {}; app.authContentSession.requestConsumerTokenServiceOnce = async () => ({ workloadActions: { value: "synthetic" } }); const actions = []; app.platformContentMessages.sendRuntimeMessage = async message => { actions.push(message); return { ok: true, actions: [], hasNext: false }; }; async function cycle(id) { app.productsContentState.currentProductsRequestId = id; app.productsContentState.opptyProductsByNumber.set("A", { items: [{ RevnId: "123" }], cachedAt: Date.now(), fromCache: false }); app.productActivities.begin(id, "synthetic"); await app.productActivities.complete(id); } return { app, actions, cycle }; } test("SR succeeds on fifth attempt, is shared in flight and reused across Reference/product reloads", async () => { let calls = 0; const h = setup(async () => { calls += 1; if (calls < 5) throw new Error("Synthetic offline"); return response({ items: [], hasMore: false }); }); const first = h.app.opportunityCrmServiceRequests.load("synthetic", 1); assert.equal(h.app.opportunityCrmServiceRequests.load("synthetic", 1), first); assert.equal(await first, true); assert.equal(calls, 5); await h.cycle("current-quarter"); h.app.opportunitiesQueryState.periodRequestVersion += 1; await h.cycle("next-quarter"); assert.equal(calls, 5); assert.equal(h.actions.length, 2); assert.equal(h.app.debugState.requestLog.filter(entry => entry.name === "resquestCrmServiceRequest").length, 5); h.app.opportunityCrmServiceRequests.reset(); await h.cycle("explicit-refresh"); assert.equal(calls, 6); }); for (const failure of [() => new Response("Denied", { status: 403 }), () => new Response("Login")]) { test("SR exhausting five attempts blocks Actions and preserves the last completed timestamp", async () => { let calls = 0; const h = setup(async () => { calls += 1; return failure(); }); h.app.productsContentState.productsLastCachedAt = 123; await h.cycle("failed"); assert.equal(calls, 5); assert.equal(h.actions.length, 0); assert.equal(h.app.opportunityCrmServiceRequests.getSummary("A").state, "error"); assert.equal(h.app.productsContentState.productsLastCachedAt, 123); h.app.authSessionState.principal = "synthetic@example.invalid"; assert.equal(h.app.opportunityWorkloadActions.getSummary("A").state, "error"); }); } test("pagination retries only the failed SR page, with no duplicate records", async () => { const offsets = []; let failures = 0; const h = setup(async (_url, options) => { const { offset } = JSON.parse(options.body); offsets.push(offset); if (offset === 1 && failures++ < 2) return response({ invalid: true }); return response({ items: [{ SrNumber: `SR${offset}`, ReportedHours_c: 2, OpportunityName_Id_c: { OptyNumber: "A" } }], offset, count: 1, hasMore: offset === 0 }); }); await h.cycle("paged"); assert.deepEqual(offsets, [0, 1, 1, 1]); assert.equal(h.app.opportunityCrmServiceRequests.getSummary("A").reportedHours, 4); assert.equal(h.actions.length, 1); }); test("Actions retries each workload up to five times and stops as soon as it succeeds", async () => { const h = setup(async () => response({ items: [], hasMore: false })); let attempts = 0; h.app.platformContentMessages.sendRuntimeMessage = async () => { attempts += 1; return attempts < 3 ? { ok: false, error: "Synthetic" } : { ok: true, actions: [], hasNext: false }; }; await h.cycle("success"); assert.equal(attempts, 3); attempts = 0; h.app.platformContentMessages.sendRuntimeMessage = async () => { attempts += 1; throw new Error("Synthetic"); }; await h.cycle("failed-actions"); assert.equal(attempts, 5); }); test("an invalidated SR request does not continue retrying or launch Actions", async () => { let reject, calls = 0; const h = setup(() => { calls += 1; return new Promise((_resolve, fail) => { reject = fail; }); }); const pending = h.cycle("old"); await new Promise(resolve => setImmediate(resolve)); h.app.opportunityCrmServiceRequests.reset(); h.app.productsContentState.currentProductsRequestId = "new"; reject(new Error("Synthetic")); await pending; assert.equal(calls, 1); assert.equal(h.actions.length, 0); });