100 lines
4.5 KiB
JavaScript
100 lines
4.5 KiB
JavaScript
const assert = require("node:assert/strict");
|
|
const { test } = require("node:test");
|
|
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/features/opportunities/internal-sr-session.js"), "utf8")}\ncreateInternalSrSession`);
|
|
function setup(query) {
|
|
let elapsed = 0;
|
|
const frames = [], removed = [], delays = [], stopped = [];
|
|
const body = { append(frame) { frame.initialSrc = frame.src; frames.push(frame); } };
|
|
const document = { body, createElement(tag) {
|
|
assert.equal(tag, "iframe");
|
|
return { contentWindow: { stop() { stopped.push(true); } }, style: {}, attributes: {}, listeners: {}, setAttribute(k, v) { this.attributes[k] = v; },
|
|
addEventListener(k, fn) { this.listeners[k] = fn; }, remove() { removed.push(this); } };
|
|
} };
|
|
const api = factory({ query, environment: { document, performance: { now: () => elapsed }, setTimeout: (fn, ms) => { delays.push(ms); elapsed += ms; return setImmediate(fn); } } });
|
|
return { api, frames, removed, delays, stopped };
|
|
}
|
|
test("401 initializes a hidden iframe in the calling document and removes it on success", async () => {
|
|
let calls = 0;
|
|
const h = setup(async () => ++calls < 3 ? { ok: false, httpStatus: 401 } : { ok: true, items: [{ SrId: 1 }] });
|
|
const items = await h.api.request("1");
|
|
assert.equal(items[0].SrId, 1);
|
|
assert.equal(h.frames.length, 1);
|
|
const frame = h.frames[0];
|
|
assert.equal(frame.tabIndex, -1);
|
|
assert.equal(frame.attributes["aria-hidden"], "true");
|
|
assert.match(frame.style.cssText, /pointer-events:none/);
|
|
assert.ok(!frame.attributes.sandbox.includes("allow-top-navigation"));
|
|
assert.ok(frame.initialSrc.endsWith("&view=showisr"));
|
|
assert.equal(frame.src, "about:blank");
|
|
assert.equal(h.stopped.length, 1);
|
|
assert.deepEqual(h.delays, [250]);
|
|
assert.equal(h.removed[0], frame);
|
|
});
|
|
|
|
test("an immediately available session stops the iframe without waiting for load or a timer", async () => {
|
|
let calls = 0;
|
|
const h = setup(async () => ++calls === 1 ? { ok: false, httpStatus: 401 } : { ok: true, items: [] });
|
|
await h.api.request("1");
|
|
assert.equal(calls, 2);
|
|
assert.equal(h.delays.length, 0);
|
|
assert.equal(h.stopped.length, 1);
|
|
assert.equal(h.removed.length, 1);
|
|
});
|
|
|
|
test("cross-origin redirects still allow iframe removal when stop is blocked", async () => {
|
|
let calls = 0;
|
|
const h = setup(async () => {
|
|
if (++calls === 1) return { ok: false, httpStatus: 401 };
|
|
h.frames[0].contentWindow.stop = () => { throw new Error("Cross-origin"); };
|
|
return { ok: true, items: [] };
|
|
});
|
|
await h.api.request("1");
|
|
assert.equal(h.frames[0].src, "about:blank");
|
|
assert.equal(h.removed.length, 1);
|
|
});
|
|
test("concurrent queries share one iframe without mixing SR results", async () => {
|
|
let calls = 0;
|
|
const h = setup(async id => ++calls <= 2 ? { ok: false, httpStatus: 401 } : { ok: true, items: [id] });
|
|
const results = await Promise.all([h.api.request("1"), h.api.request("2")]);
|
|
assert.deepEqual(results, [["1"], ["2"]]);
|
|
assert.equal(h.frames.length, 1);
|
|
assert.equal(h.removed.length, 1);
|
|
});
|
|
test("normal success does not mount an iframe; errors and timeout always clean it up", async () => {
|
|
const success = setup(async () => ({ ok: true, items: [] }));
|
|
await success.api.request("1");
|
|
assert.equal(success.frames.length, 0);
|
|
for (const status of [401, 500]) {
|
|
let calls = 0;
|
|
const h = setup(async () => ({ ok: false, httpStatus: ++calls === 1 ? 401 : status }));
|
|
await assert.rejects(h.api.request("1"));
|
|
if (status === 401) {
|
|
assert.ok(calls > 31);
|
|
assert.equal(h.delays.reduce((sum, ms) => sum + ms, 0), 60000);
|
|
} else assert.equal(calls, 2);
|
|
assert.equal(h.removed.length, 1);
|
|
}
|
|
});
|
|
|
|
test("slow session initialization can succeed after the old thirty-attempt limit", async () => {
|
|
let calls = 0;
|
|
const h = setup(async () => ++calls < 45 ? { ok: false, httpStatus: 401 } : { ok: true, items: ["ready"] });
|
|
assert.deepEqual(await h.api.request("1"), ["ready"]);
|
|
assert.equal(calls, 45);
|
|
assert.equal(h.removed.length, 1);
|
|
assert.ok(h.delays.reduce((sum, ms) => sum + ms, 0) < 60000);
|
|
});
|
|
|
|
test("iframe load alone never confirms authentication", async () => {
|
|
let calls = 0;
|
|
const h = setup(async () => {
|
|
if (++calls > 1) h.frames[0].listeners.load();
|
|
return { ok: false, httpStatus: 401 };
|
|
});
|
|
await assert.rejects(h.api.request("1"), /HTTP 401.*load event, but authentication was not confirmed/);
|
|
assert.equal(h.removed.length, 1);
|
|
});
|