const assert = require("node:assert/strict"); const vm = require("node:vm"); const { composeScript } = require("./support/application.cjs"); function createResponse(body, contentType) { return { ok: true, status: 200, statusText: "OK", headers: { get(name) { return name.toLowerCase() === "content-type" ? contentType : null; }, forEach(callback) { callback(contentType, "content-type"); } }, text: async () => body }; } function loadBackground(responses, createdTabs, removedTabs, options = {}) { let listener; const source = composeScript("background"); const context = { chrome: { runtime: { onMessage: { addListener(callback) { listener = callback; } } }, tabs: { async create(details) { createdTabs.push(details); if (options.createTab) { return options.createTab(details); } return { id: 27 }; }, async remove(tabId) { removedTabs.push(tabId); } } }, fetch: async () => { if (options.onFetch) { options.onFetch(); } const response = responses.shift(); if (!response) { throw new Error("Unexpected fetch call."); } return response; }, Date, Error, JSON, Map, Set, Promise, String, Array, Object, Number, Math, setTimeout: options.setTimeout || setTimeout, clearTimeout }; vm.runInNewContext(source, context); return listener; } function dispatch(listener) { return new Promise((resolve) => { assert.equal(listener({ type: "opportunitiesExtension.requestConsumerTokenService" }, { tab: { windowId: 1 } }, resolve), true); }); } async function run() { const createdTabs = []; const removedTabs = []; const listener = loadBackground([ createResponse("Fallback", "text/html"), createResponse(JSON.stringify([ { tokenService: "ACCP-TS", uiaasHeader: { label: "Account-Ti-Authorization", value: "account-token" } }, { tokenService: "OCICONS-TS", uiaasHeader: { label: "G2m-Authorization", value: "consumption-token" } } ]), "application/json") ], createdTabs, removedTabs); const response = await dispatch(listener); assert.equal(response.ok, true); assert.equal(response.authorizations.accountSummary.value, "account-token"); assert.equal(response.authorizations.accountPlans.value, "consumption-token"); assert.equal(createdTabs.length, 1); assert.equal(createdTabs[0].active, false); assert.equal( createdTabs[0].url, "https://spa.oracle.com/oalcrm/web/api/g2m-consumer-application/ui/index.html?ojr=whitespace" ); assert.deepEqual(removedTabs, [27]); assert.equal(response.debugRequests.length, 2); assert.equal(response.debugRequests[0].status, "failed"); assert.equal(response.debugRequests[0].metadata.sessionBootstrapState, "opened-inactive-tab"); assert.equal(response.debugRequests[1].metadata.sessionBootstrapState, "closed-after-valid-json"); // Even six opening failures must leave the second token request available. const retryTabs = []; const retryRemovedTabs = []; const delays = []; let tokenRequests = 0; let openAttempts = 0; const retryListener = loadBackground([ createResponse("Fallback", "text/html"), createResponse(JSON.stringify([ { tokenService: "ACCP-TS", uiaasHeader: { value: "account-token" } }, { tokenService: "OCICONS-TS", uiaasHeader: { value: "consumption-token" } } ]), "application/json") ], retryTabs, retryRemovedTabs, { onFetch() { tokenRequests += 1; }, createTab() { assert.equal(tokenRequests, 1, "Token requests must wait for the tab to open"); openAttempts += 1; if (openAttempts <= 6) { throw new Error("Temporary tab creation failure"); } return { id: 81 }; }, setTimeout(callback, delay) { delays.push(delay); return setTimeout(callback, 0); } }); const retryResponse = await dispatch(retryListener); assert.equal(retryResponse.ok, true); assert.equal(tokenRequests, 2); assert.equal(openAttempts, 7); assert.deepEqual(retryRemovedTabs, [81]); assert.deepEqual(delays.slice(0, 6), [750, 1500, 3000, 4000, 4000, 4000]); assert.ok(retryTabs.every(tab => tab.active === false && tab.windowId === 1)); assert.equal(retryResponse.debugRequests[0].metadata.sessionTabOpenAttempt, "7"); assert.equal(retryResponse.debugRequests[0].metadata.sessionTabLastOpenError, "Temporary tab creation failure"); assert.equal(retryResponse.debugRequests[0].metadata.sessionTabNextRetryDelayMs, undefined); const failedTabs = []; const failedRemovedTabs = []; const exhausted = await dispatch(loadBackground( Array.from({ length: 5 }, () => createResponse("Fallback", "text/html")), failedTabs, failedRemovedTabs, { setTimeout: callback => setTimeout(callback, 0) } )); assert.equal(exhausted.ok, false); assert.match(exhausted.error, /after 5 attempts/); assert.equal(failedTabs.length, 1); assert.deepEqual(failedRemovedTabs, [27]); console.log("Consumer token session retry tests passed."); } run().catch((error) => { console.error(error); process.exitCode = 1; });