Loading comcipapic to establish a session for SR requests
This commit is contained in:
@@ -2,6 +2,227 @@ const assert = require("node:assert/strict");
|
||||
const { test } = require("node:test");
|
||||
const { loadBackground, response } = require("./support/characterization.cjs");
|
||||
const type = "opportunitiesExtension.requestInternalServiceRequest";
|
||||
|
||||
test("preparation reuses an existing unexpired cookie pair without navigation or API calls", async () => {
|
||||
const domain = "comcipapic-oalprod.integration.ocp.oraclecloud.com";
|
||||
const h = loadBackground({
|
||||
fetch: async () => assert.fail("No API calls during preparation"),
|
||||
cookies: () => [1, 2].map(part => ({ name: `ORA_OCIS_CG_SESSION_idcs-existing_${domain}_${part}`, value: `secret-${part}`, domain }))
|
||||
});
|
||||
const result = await h.dispatch({ type: "opportunitiesExtension.prepareSrSession" });
|
||||
assert.equal(result.ok, true);
|
||||
assert.equal(h.tabs.length, 0);
|
||||
assert.equal(h.removedTabs.length, 0);
|
||||
});
|
||||
|
||||
test("preparation closes immediately on the second cookie event even while getAll is pending", { timeout: 2000 }, async () => {
|
||||
const fs = require("node:fs"), vm = require("node:vm"), path = require("node:path");
|
||||
const factory = vm.runInNewContext(`${fs.readFileSync(path.join(__dirname, "../src/services/fusion/sr-details.js"), "utf8")}\ncreateFusionSrDetails`);
|
||||
const listeners = new Set();
|
||||
let reads = 0, closed = 0;
|
||||
const domain = "comcipapic-oalprod.integration.ocp.oraclecloud.com";
|
||||
const cookie = part => ({ name: `ORA_OCIS_CG_SESSION_idcs-new_${domain}_${part}`, value: `secret-${part}`, domain, storeId: "store" });
|
||||
const emit = change => { for (const listener of listeners) listener(change); };
|
||||
const api = factory({
|
||||
fetchJson: async () => assert.fail("No API calls during preparation"),
|
||||
cookieChanges: { addListener: fn => listeners.add(fn), removeListener: fn => listeners.delete(fn) },
|
||||
cookiesGetAll: () => ++reads === 1 ? Promise.resolve([]) : new Promise(() => {}),
|
||||
tabsCreate: async () => {
|
||||
setImmediate(() => {
|
||||
emit({ cookie: cookie(1) });
|
||||
emit({ cookie: { ...cookie(2), storeId: "other" } });
|
||||
assert.equal(closed, 0);
|
||||
emit({ cookie: cookie(2), removed: true });
|
||||
assert.equal(closed, 0);
|
||||
emit({ cookie: cookie(2) });
|
||||
});
|
||||
return { id: 7 };
|
||||
},
|
||||
tabsRemove: async id => { assert.equal(id, 7); closed += 1; },
|
||||
supportsFirefoxCookieStoreTabs: () => false,
|
||||
wait: () => new Promise(() => {})
|
||||
});
|
||||
assert.equal((await api.prepareSession({ tab: { cookieStoreId: "store" } })).ok, true);
|
||||
assert.equal(closed, 1);
|
||||
assert.equal(listeners.size, 0);
|
||||
});
|
||||
|
||||
test("explicit preparation opens SeaaS initiation and observes cookies without any API requests", async () => {
|
||||
let calls = 0;
|
||||
let reads = 0;
|
||||
const domain = "comcipapic-oalprod.integration.ocp.oraclecloud.com";
|
||||
const pair = [1, 2].map(part => ({ name: `ORA_OCIS_CG_SESSION_idcs-new_${domain}_${part}`, value: `secret-${part}`, domain }));
|
||||
const h = loadBackground({ fetch: async () => {
|
||||
calls += 1;
|
||||
assert.fail("Opening the main modal must not trigger any session-dependent API request");
|
||||
}, cookies: () => {
|
||||
reads += 1;
|
||||
if (reads === 1) return [];
|
||||
assert.equal(h.tabs.length, 1);
|
||||
if (reads === 2) return pair.slice(0, 1);
|
||||
if (reads === 3) return pair.map(cookie => ({ ...cookie, expirationDate: 1 }));
|
||||
return pair;
|
||||
} });
|
||||
const result = await h.dispatch({ type: "opportunitiesExtension.prepareSrSession" });
|
||||
assert.equal(result.ok, true);
|
||||
assert.equal(calls, 0);
|
||||
assert.equal(reads, 4);
|
||||
assert.deepEqual(result.debugRequests, []);
|
||||
assert.ok(!JSON.stringify(result).includes("secret"));
|
||||
assert.equal(h.tabs[0].active, false);
|
||||
assert.equal(h.tabs[0].url, "https://comcipapic-oalprod.integration.ocp.oraclecloud.com/ic/builder/rt/SeaaS_initiation/live/webApps/external/");
|
||||
assert.deepEqual(h.removedTabs, [91]);
|
||||
});
|
||||
|
||||
test("proactive preparation times out without issuing lookup probes", async () => {
|
||||
let calls = 0;
|
||||
const h = loadBackground({ messageTimeout: 10000, fetch: async () => { calls += 1; assert.fail("No probes allowed"); } });
|
||||
const result = await h.dispatch({ type: "opportunitiesExtension.prepareSrSession" });
|
||||
assert.equal(result.ok, false);
|
||||
assert.equal(calls, 0);
|
||||
assert.match(result.error, /session could not be established/);
|
||||
assert.deepEqual(h.removedTabs, [91]);
|
||||
});
|
||||
|
||||
test("cookie change wakes recovery without waiting for a polling timer and removes its listener", { timeout: 2000 }, async () => {
|
||||
const fs = require("node:fs");
|
||||
const vm = require("node:vm");
|
||||
const path = require("node:path");
|
||||
const factory = vm.runInNewContext(`${fs.readFileSync(path.join(__dirname, "../src/services/fusion/sr-details.js"), "utf8")}\ncreateFusionSrDetails`);
|
||||
const listeners = new Set();
|
||||
let ready = false;
|
||||
let calls = 0;
|
||||
let closed = 0;
|
||||
const domain = "comcipapic-oalprod.integration.ocp.oraclecloud.com";
|
||||
const cookies = [1, 2].map(part => ({ name: `ORA_OCIS_CG_SESSION_idcs-new_${domain}_${part}`, value: `secret-${part}`, domain, storeId: "store" }));
|
||||
const api = factory({
|
||||
cookieChanges: { addListener: fn => listeners.add(fn), removeListener: fn => listeners.delete(fn) },
|
||||
cookiesGetAll: async () => ready ? cookies : [],
|
||||
tabsCreate: async () => {
|
||||
setImmediate(() => {
|
||||
ready = true;
|
||||
for (const listener of listeners) listener({ cookie: cookies[1] });
|
||||
});
|
||||
return { id: 7 };
|
||||
},
|
||||
tabsRemove: async () => { closed += 1; },
|
||||
supportsFirefoxCookieStoreTabs: () => false,
|
||||
wait: () => new Promise(() => {})
|
||||
});
|
||||
const result = await api.requestLookupWithSession(async () => {
|
||||
calls += 1;
|
||||
if (!ready) { const error = new Error("Unauthorized"); error.httpStatus = 401; throw error; }
|
||||
return { ok: true, items: [] };
|
||||
}, {}, { tab: { cookieStoreId: "store" } });
|
||||
assert.equal(result.ok, true);
|
||||
assert.equal(calls, 2);
|
||||
assert.equal(closed, 1);
|
||||
assert.equal(listeners.size, 0);
|
||||
});
|
||||
|
||||
test("renewed matching cookie fragments trigger an early retry without leaking session values", async () => {
|
||||
let reads = 0;
|
||||
let calls = 0;
|
||||
const domain = "comcipapic-oalprod.integration.ocp.oraclecloud.com";
|
||||
const cookie = (id, part, value) => ({ name: `ORA_OCIS_CG_SESSION_idcs-${id}_${domain}_${part}`, value, domain, path: "/", session: true });
|
||||
const h = loadBackground({
|
||||
cookies: () => {
|
||||
reads += 1;
|
||||
if (reads < 3) return [cookie("old", 1, "old-secret-1"), cookie("old", 2, "old-secret-2")];
|
||||
if (reads === 3) return [cookie("new", 1, "new-secret-1"), cookie("other", 2, "wrong-pair")];
|
||||
return [cookie("new", 1, "new-secret-1"), cookie("new", 2, "new-secret-2")];
|
||||
},
|
||||
fetch: async (_, options) => {
|
||||
calls += 1;
|
||||
assert.equal(options.credentials, "include");
|
||||
assert.equal(options.headers.Cookie, undefined);
|
||||
if (calls === 1) return response({}, 401);
|
||||
assert.equal(reads, 4, "retry immediately when both renewed parts match, not on a partial pair");
|
||||
return response({ items: [] });
|
||||
}
|
||||
});
|
||||
const result = await h.dispatch({ type: "opportunitiesExtension.requestSrLookupLanguage" });
|
||||
assert.equal(result.ok, true);
|
||||
assert.equal(calls, 2);
|
||||
assert.ok(!JSON.stringify(result).includes("secret"));
|
||||
assert.ok(h.cookieQueries.every(query => query.domain === domain && query.storeId === "test-store"));
|
||||
assert.deepEqual(h.removedTabs, [91]);
|
||||
});
|
||||
|
||||
for (const family of ["chrome", "firefox"]) {
|
||||
test(`${family}: simultaneous lookup 401s share an inactive session tab and close it after successful retries`, async () => {
|
||||
const counts = new Map();
|
||||
const h = loadBackground({ family, fetch: async url => {
|
||||
const count = (counts.get(url) || 0) + 1;
|
||||
counts.set(url, count);
|
||||
return count < 3 ? response({}, 401) : response({ items: [] });
|
||||
} });
|
||||
const results = await Promise.all(["PrimaryPillar", "Language", "TechPlatform", "OpportunityBusiness"].map(name =>
|
||||
h.dispatch({ type: `opportunitiesExtension.requestSrLookup${name}`, emailAddress: "test@example.invalid" })));
|
||||
assert.ok(results.every(result => result.ok));
|
||||
assert.ok(results.every(result => result.debugRequests.length === 3));
|
||||
assert.equal(h.tabs.length, 1);
|
||||
assert.equal(h.tabs[0].active, false);
|
||||
assert.equal(h.tabs[0].windowId, 3);
|
||||
assert.equal(h.tabs[0].url, "https://comcipapic-oalprod.integration.ocp.oraclecloud.com/ic/builder/rt/SeaaS_initiation/live/webApps/external/");
|
||||
assert.equal(h.tabs[0].cookieStoreId, family === "firefox" ? "test-store" : undefined);
|
||||
assert.deepEqual(h.removedTabs, [91]);
|
||||
});
|
||||
}
|
||||
|
||||
test("lookup authentication timeout closes the temporary tab and returns a clear error", async () => {
|
||||
const h = loadBackground({ messageTimeout: 10000, fetch: async () => response({}, 401) });
|
||||
const result = await h.dispatch({ type: "opportunitiesExtension.requestSrLookupLanguage" });
|
||||
assert.equal(result.ok, false);
|
||||
assert.match(result.error, /session could not be established/);
|
||||
assert.equal(h.tabs.length, 1);
|
||||
assert.deepEqual(h.removedTabs, [91]);
|
||||
});
|
||||
test("SR language, platform and services use fixed Session endpoints and dynamic email", async () => {
|
||||
const calls = [];
|
||||
const h = loadBackground({ fetch: async (url, options) => {
|
||||
calls.push({ url, options });
|
||||
return response({ items: url.includes("/services?")
|
||||
? [{ Id: 123, RecordName: "Consumption", Abstract_c: "Service summary" }]
|
||||
: [{ code: "CODE", name: "Label", enabledFlag: "Y", displaySequence: 1 }] });
|
||||
} });
|
||||
for (const [name, lookup] of [["requestSrLookupLanguage", "SENGG_LANGUAGE"], ["requestSrLookupTechPlatform", "SENGG_TECH_PLATFORM"]]) {
|
||||
const result = await h.dispatch({ type: `opportunitiesExtension.${name}` });
|
||||
assert.deepEqual(result.items, [{ code: "CODE", name: "Label" }]);
|
||||
assert.equal(new URL(calls.at(-1).url).searchParams.get("lookupType"), lookup);
|
||||
assert.equal(result.debugRequests[0].name, name);
|
||||
}
|
||||
const result = await h.dispatch({ type: "opportunitiesExtension.requestSrLookupOpportunityBusiness", emailAddress: "user+test@example.invalid" });
|
||||
assert.deepEqual(result.items, [{ Id: "123", RecordName: "Consumption", Abstract_c: "Service summary" }]);
|
||||
const url = new URL(calls.at(-1).url);
|
||||
assert.equal(url.searchParams.get("emailAddress"), "user+test@example.invalid");
|
||||
assert.equal(url.searchParams.get("salesObject"), "OPPORTUNITY");
|
||||
assert.equal(url.searchParams.get("serviceType"), "BUSINESS");
|
||||
assert.ok(calls.every(call => call.options.headers.Authorization === "Session" && call.options.method === "GET"));
|
||||
assert.equal((await h.dispatch({ type: "opportunitiesExtension.requestSrLookupOpportunityBusiness" })).ok, false);
|
||||
assert.equal(calls.length, 3);
|
||||
});
|
||||
test("Primary pillar lookup uses Session, orders enabled name/code options and rejects invalid data", async () => {
|
||||
const calls = [];
|
||||
const h = loadBackground({ fetch: async (url, options) => {
|
||||
calls.push({ url, options });
|
||||
return response({ items: [
|
||||
{ code: "B", name: "Second", displaySequence: 20, enabledFlag: "Y" },
|
||||
{ code: "N", name: "Disabled", displaySequence: 1, enabledFlag: "N" },
|
||||
{ code: "A", name: "First", displaySequence: 10, enabledFlag: "Y" }
|
||||
] });
|
||||
} });
|
||||
const result = await h.dispatch({ type: "opportunitiesExtension.requestSrLookupPrimaryPillar" });
|
||||
assert.equal(result.ok, true);
|
||||
assert.deepEqual(result.items, [{ code: "A", name: "First" }, { code: "B", name: "Second" }]);
|
||||
assert.ok(calls[0].url.includes("SeaaS_initiation/live;profile=PROD"));
|
||||
assert.ok(calls[0].url.endsWith("lookupType=SENGG_PRIMARY_PILLAR&type=STANDARD"));
|
||||
assert.equal(calls[0].options.headers.Authorization, "Session");
|
||||
assert.equal(calls[0].options.method, "GET");
|
||||
for (const fetch of [async () => response({ items: [{}] }), async () => response({}, 401)]) {
|
||||
assert.equal((await loadBackground({ fetch, messageTimeout: 10000 }).dispatch({ type: "opportunitiesExtension.requestSrLookupPrimaryPillar" })).ok, false);
|
||||
}
|
||||
});
|
||||
for (const family of ["chrome", "firefox"]) {
|
||||
test(`${family}: 401 is returned to the caller without opening tabs`, async () => {
|
||||
let count = 0;
|
||||
|
||||
Reference in New Issue
Block a user