Optimized requests to retrieve SRs and Actions
This commit is contained in:
109
tests/productActivities.test.cjs
Normal file
109
tests/productActivities.test.cjs
Normal file
@@ -0,0 +1,109 @@
|
||||
const assert = require("node:assert/strict");
|
||||
const { test } = require("node:test");
|
||||
const { loadApplication } = require("./support/application.cjs");
|
||||
const flush = () => new Promise(resolve => setImmediate(resolve));
|
||||
|
||||
function setup() {
|
||||
let listener;
|
||||
const app = loadApplication("content", {
|
||||
document: { getElementById: () => null }, window: { requestAnimationFrame() {} },
|
||||
chrome: { runtime: { onMessage: { addListener(fn) { listener = fn; } } } }
|
||||
});
|
||||
const calls = [];
|
||||
app.opportunityCrmServiceRequests.reset = () => calls.push("reset SR");
|
||||
app.opportunityWorkloadActions.reset = () => calls.push("reset Act");
|
||||
app.opportunityCrmServiceRequests.load = async token => calls.push(`SR ${token}`);
|
||||
app.opportunityWorkloadActions.loadProducts = products => calls.push(products.items[0]?.RevnId || "empty products");
|
||||
app.platformContentMessages.sendRuntimeMessage = async () => ({ ok: true });
|
||||
app.productsContentJobs.ensureProductsBackgroundMessageHandler();
|
||||
function start(token = "token") {
|
||||
app.productsContentJobs.requestOpptyProductsInBackground([{ OptyNumber: "A" }], token);
|
||||
return app.productsContentState.currentProductsRequestId;
|
||||
}
|
||||
function progress(requestId, data) {
|
||||
listener({ type: "opportunitiesExtension.opptyProductsProgress", requestId, ...data });
|
||||
}
|
||||
return { app, calls, start, progress };
|
||||
}
|
||||
|
||||
test("follow-up calls wait for completion, deduplicate terminal messages and refresh on every new cycle", async () => {
|
||||
const h = setup();
|
||||
const first = h.start();
|
||||
h.progress(first, { state: "running", optyNumber: "A", items: [{ RevnId: "123" }], fromCache: false });
|
||||
assert.deepEqual(h.calls, []);
|
||||
h.progress(first, { state: "complete" });
|
||||
h.progress(first, { state: "complete" });
|
||||
await flush();
|
||||
assert.deepEqual(h.calls, ["reset SR", "123", "SR token"]);
|
||||
const second = h.start("new-token");
|
||||
h.progress(first, { state: "complete", optyNumber: "B", items: [{ RevnId: "old" }] });
|
||||
h.progress(second, { state: "running", optyNumber: "A", items: [{ RevnId: "123" }] });
|
||||
assert.equal(h.calls.filter(value => value === "123").length, 1);
|
||||
h.progress(second, { state: "complete" });
|
||||
await flush();
|
||||
assert.equal(h.calls.filter(value => value === "123").length, 2);
|
||||
assert.ok(h.calls.includes("SR new-token"));
|
||||
assert.equal(h.calls.includes("old"), false);
|
||||
});
|
||||
|
||||
test("partial failures use successful products only; closed, failed and empty cycles have no follow-up", async () => {
|
||||
const h = setup();
|
||||
const first = h.start();
|
||||
h.progress(first, { optyNumber: "A", items: [{ RevnId: "123" }] });
|
||||
h.progress(first, { optyNumber: "B", items: [{ RevnId: "failed" }], error: "Synthetic failure" });
|
||||
h.progress(first, { state: "complete-with-errors" });
|
||||
await flush();
|
||||
assert.equal(h.calls.includes("failed"), false);
|
||||
assert.equal(h.calls.filter(value => value === "SR token").length, 1);
|
||||
const second = h.start();
|
||||
h.progress(second, { optyNumber: "A", error: "Synthetic failure" });
|
||||
h.progress(second, { state: "complete-with-errors" });
|
||||
const third = h.start();
|
||||
h.progress(third, { state: "error" });
|
||||
const fourth = h.start();
|
||||
h.app.productsContentState.currentProductsRequestId = "";
|
||||
h.progress(fourth, { state: "complete", optyNumber: "A", items: [{ RevnId: "closed" }] });
|
||||
h.app.productsContentJobs.requestOpptyProductsInBackground([], "empty");
|
||||
await flush();
|
||||
assert.equal(h.calls.filter(value => value.startsWith("SR ")).length, 1);
|
||||
assert.equal(h.calls.includes("closed"), false);
|
||||
});
|
||||
|
||||
test("cached products never trigger or reset activities; mixed cycles use only fresh products", async () => {
|
||||
const h = setup();
|
||||
const cached = h.start();
|
||||
h.progress(cached, { optyNumber: "A", items: [{ RevnId: "cached" }], fromCache: true });
|
||||
h.progress(cached, { state: "complete" });
|
||||
await flush();
|
||||
assert.deepEqual(h.calls, []);
|
||||
const mixed = h.start();
|
||||
h.progress(mixed, { optyNumber: "A", items: [{ RevnId: "cached" }], fromCache: true });
|
||||
h.progress(mixed, { optyNumber: "B", items: [{ RevnId: "fresh" }], fromCache: false });
|
||||
h.progress(mixed, { state: "complete" });
|
||||
await flush();
|
||||
assert.deepEqual(h.calls, ["reset SR", "fresh", "SR token"]);
|
||||
});
|
||||
|
||||
test("reopening an existing modal does not reload products or reset/query activities", async () => {
|
||||
const modal = { hidden: true, querySelector: () => ({ focus() {} }) };
|
||||
const app = loadApplication("content", {
|
||||
window: {}, document: {
|
||||
getElementById: id => id === "opportunities-extension-modal" ? modal : null,
|
||||
documentElement: { classList: { add() {} } }, addEventListener() {}
|
||||
}
|
||||
});
|
||||
app.contentStyles.ensureExtensionStyles = () => {};
|
||||
app.currentUser.ensure = async () => true;
|
||||
app.authContentSession.requestTokenRelayOnce = async () => "synthetic";
|
||||
app.opportunitiesTable.renderOpportunitiesTable = () => {};
|
||||
const calls = [];
|
||||
app.productsContentJobs.requestOpptyProductsInBackground = () => calls.push("products");
|
||||
app.opportunityCrmServiceRequests.load = () => calls.push("SR");
|
||||
app.opportunityCrmServiceRequests.reset = () => calls.push("reset SR");
|
||||
app.opportunityWorkloadActions.loadProducts = () => calls.push("Actions");
|
||||
app.opportunityWorkloadActions.reset = () => calls.push("reset Actions");
|
||||
app.contentModal.openOpportunitiesModal();
|
||||
await flush();
|
||||
assert.equal(modal.hidden, false);
|
||||
assert.deepEqual(calls, []);
|
||||
});
|
||||
Reference in New Issue
Block a user