Files
2026-07-13 13:12:00 +08:00

148 lines
4.3 KiB
JavaScript

// Unit tests for expired-session recovery (src/session-expiry.js), run with
// `node --test` (no extra deps). Covers the pure redirect matcher and the
// onBeforeRedirect wiring against a fake webRequest.
//
// The real signal (from a live expired Databricks SSO session): every API
// call gets a 303 redirect to the gate's `login.html`. The shell reloads the
// window on that so the gate can re-challenge, since a desktop user has no
// address bar to refresh manually.
const { describe, it } = require("node:test");
const assert = require("node:assert/strict");
const { isLoginRedirect, registerSessionExpiryReload } = require("../src/session-expiry");
describe("isLoginRedirect", () => {
it("matches a 303 redirect to the login page", () => {
assert.equal(
isLoginRedirect({
statusCode: 303,
redirectURL: "https://dbc-x.cloud.databricks.com/login.html?next_url=%2Fajax-api%2F2.0",
}),
true,
);
});
it("matches other 3xx codes to the login page", () => {
assert.equal(
isLoginRedirect({ statusCode: 302, redirectURL: "https://ws.databricks.com/login.html" }),
true,
);
});
it("ignores a redirect that is not to the login page", () => {
// An ordinary same-origin API-to-API redirect must be left alone.
assert.equal(
isLoginRedirect({ statusCode: 303, redirectURL: "https://ws.databricks.com/ajax-api/2.0/x" }),
false,
);
});
it("ignores non-redirect status codes", () => {
assert.equal(
isLoginRedirect({ statusCode: 200, redirectURL: "https://ws.databricks.com/login.html" }),
false,
);
});
it("ignores a missing or unparseable redirect URL", () => {
assert.equal(isLoginRedirect({ statusCode: 303 }), false);
assert.equal(isLoginRedirect({ statusCode: 303, redirectURL: "not a url" }), false);
});
it("does not match a path that merely contains 'login.html' mid-path", () => {
// Only a pathname ending in /login.html counts, so an unrelated route
// like /docs/login.html.md or a query-only match won't trip it.
assert.equal(
isLoginRedirect({
statusCode: 303,
redirectURL: "https://ws.databricks.com/x?p=/login.html",
}),
false,
);
});
});
/** A fake session whose onBeforeRedirect listener can be driven by tests. */
function fakeSession() {
let listener = null;
return {
webRequest: {
onBeforeRedirect: (cb) => {
listener = cb;
},
},
emit: (details) => listener?.(details),
};
}
describe("registerSessionExpiryReload", () => {
const LOGIN_REDIRECT = {
url: "https://ws.databricks.com/ajax-api/2.0/omnigents/v1/sessions",
statusCode: 303,
redirectURL: "https://ws.databricks.com/login.html?next_url=%2Fajax-api",
};
it("reloads the connected origin on a login redirect", () => {
const ses = fakeSession();
const reloaded = [];
registerSessionExpiryReload(
ses,
(origin) => origin === "https://ws.databricks.com",
(origin) => reloaded.push(origin),
);
ses.emit(LOGIN_REDIRECT);
assert.deepEqual(reloaded, ["https://ws.databricks.com"]);
});
it("ignores a login redirect for an origin no window is connected to", () => {
const ses = fakeSession();
const reloaded = [];
registerSessionExpiryReload(
ses,
() => false, // nothing is a connected server
(origin) => reloaded.push(origin),
);
ses.emit(LOGIN_REDIRECT);
assert.deepEqual(reloaded, []);
});
it("ignores a non-login redirect", () => {
const ses = fakeSession();
const reloaded = [];
registerSessionExpiryReload(
ses,
() => true,
(origin) => reloaded.push(origin),
);
ses.emit({
url: "https://ws.databricks.com/ajax-api/2.0/x",
statusCode: 303,
redirectURL: "https://ws.databricks.com/ajax-api/2.0/y",
});
assert.deepEqual(reloaded, []);
});
it("ignores a login redirect whose originating URL is unparseable", () => {
// A malformed request URL must not throw out of the listener; it's
// simply skipped (no origin to attribute the reload to).
const ses = fakeSession();
const reloaded = [];
registerSessionExpiryReload(
ses,
() => true,
(origin) => reloaded.push(origin),
);
ses.emit({ ...LOGIN_REDIRECT, url: "not a url" });
assert.deepEqual(reloaded, []);
});
});