const assert = require("node:assert/strict"); const { test } = require("node:test"); const { loadBackground, response } = require("./support/characterization.cjs"); const currentUser = "opportunitiesExtension.requestCurrentUser"; const consumer = "opportunitiesExtension.requestConsumerTokenService"; const identity = { user: { id: "test@example.invalid", name: "Test User", roles: [] }, token: "synthetic-token" }; const tokens = [ { tokenService: "ACCP-TS", uiaasHeader: { value: "synthetic-account" } }, { tokenService: "OCICONS-TS", uiaasHeader: { value: "synthetic-consumption" } } ]; const html = () => new Response("Sign in"); function navigation(app, overrides = {}) { const observer = app.responseHeaderListeners.find(item => item.filter.types.includes("main_frame")); assert.ok(observer); observer.listener({ tabId: 91, type: "main_frame", statusCode: 401, url: "https://spa.oracle.com/cloudgate/v1/oauth2/callback?code=do-not-replay", ...overrides }); } for (const family of ["chrome", "firefox"]) { for (const type of [currentUser, consumer]) { test(`${family}: ${type} restarts a rejected callback at SPA home in the same inactive tab`, async () => { let calls = 0; const app = loadBackground({ family, fetch: async () => { calls++; if (calls === 1) return html(); if (calls === 2) { navigation(app); return html(); } assert.deepEqual(app.updatedTabs, [{ id: 91, details: { url: "https://spa.oracle.com/oalcrm/web/api/g2m-consumer-application/ui/index.html?ojr=whitespace", active: false } }]); return response(type === currentUser ? identity : tokens); } }); const result = await app.dispatch({ type }); assert.equal(result.ok, true); assert.equal(app.tabs.length, 1); assert.deepEqual(app.removedTabs, [91]); assert.equal(result.debugRequests[1].metadata.sessionBootstrapReloadState, "restarted-at-spa-home"); assert.match(result.debugRequests[1].metadata.sessionBootstrapReloadReason, /401/); assert.doesNotMatch(JSON.stringify(result.debugRequests), /do-not-replay/); assert.equal(app.responseHeaderListeners.filter(item => item.filter.types.includes("main_frame")).length, 0); }); } test(`${family}: failed navigation is recorded and retried after the cooldown without opening another tab`, async () => { let calls = 0; const app = loadBackground({ family, updateTabError: true, fetch: async () => { calls++; if (calls === 2) navigation(app, { statusCode: 403 }); return calls < 5 ? html() : response(identity); } }); const result = await app.dispatch({ type: currentUser }); assert.equal(result.ok, false); assert.equal(calls, 2, "failed navigation must never release another identity probe"); assert.equal(app.updatedTabs.length, 3, "at most three restart attempts per session wait"); assert.equal(app.tabs.length, 1); assert.match(result.debugRequests[1].metadata.sessionBootstrapReloadState, /restart-failed/); assert.equal(result.debugRequests[1].metadata.sessionBootstrapReloadCount, "3"); assert.deepEqual(app.removedTabs, [91]); }); } test("only errors in the owned SPA document trigger navigation, never other tabs, frames or hosts", async () => { let calls = 0; const app = loadBackground({ fetch: async () => { if (++calls === 1) return html(); if (calls === 2) { navigation(app, { tabId: 7 }); navigation(app, { type: "sub_frame" }); navigation(app, { type: "xmlhttprequest" }); navigation(app, { url: "https://other.example.invalid/callback" }); navigation(app, { statusCode: 302 }); assert.equal(app.updatedTabs.length, 0); } return response(identity); } }); assert.equal((await app.dispatch({ type: currentUser })).ok, true); }); test("a successful SPA navigation clears an earlier failure before it can be restarted", async () => { let calls = 0; const app = loadBackground({ fetch: async () => { if (++calls === 1) return html(); if (calls === 2) { navigation(app); navigation(app, { url: "https://spa.oracle.com/oalcrm/web/api/g2m-consumer-application/ui/index.html?ojr=whitespace", statusCode: 200 }); assert.equal(app.updatedTabs.length, 0); } return response(identity); } }); assert.equal((await app.dispatch({ type: currentUser })).ok, true); });