138 lines
4.3 KiB
JavaScript
138 lines
4.3 KiB
JavaScript
import { test, describe } from 'node:test';
|
|
import assert from 'node:assert/strict';
|
|
import vm from 'node:vm';
|
|
import http from 'node:http';
|
|
import { readFileSync } from 'node:fs';
|
|
import { fileURLToPath } from 'node:url';
|
|
import { dirname, join } from 'node:path';
|
|
import axios from 'axios';
|
|
|
|
const __filename = fileURLToPath(import.meta.url);
|
|
const __dirname = dirname(__filename);
|
|
|
|
const proxyPath = join(__dirname, '../../src/proxyScripts/kmeContentSourceAdapter.js');
|
|
const proxyCode = readFileSync(proxyPath, 'utf-8');
|
|
const proxyScript = new vm.Script(proxyCode, { filename: 'kmeContentSourceAdapter.js' });
|
|
|
|
/**
|
|
* Start a minimal HTTP server that handles all POST requests with a fixed JSON body.
|
|
* @param {number} statusCode
|
|
* @param {object} responseBody
|
|
* @returns {Promise<{ server: http.Server, url: string, close: () => Promise<void> }>}
|
|
*/
|
|
function startMockTokenServer(statusCode, responseBody) {
|
|
return new Promise((resolve, reject) => {
|
|
const server = http.createServer((req, res) => {
|
|
res.writeHead(statusCode, { 'Content-Type': 'application/json' });
|
|
res.end(JSON.stringify(responseBody));
|
|
});
|
|
server.listen(0, '127.0.0.1', () => {
|
|
const { port } = server.address();
|
|
const url = `http://127.0.0.1:${port}`;
|
|
const close = () => new Promise((res, rej) => server.close(err => err ? rej(err) : res()));
|
|
resolve({ server, url, close });
|
|
});
|
|
server.once('error', reject);
|
|
});
|
|
}
|
|
|
|
/** Build an in-memory Redis fake. */
|
|
function makeRedisFake() {
|
|
const _store = {};
|
|
return {
|
|
hSet: async (key, field, value) => { _store[`${key}:${field}`] = value; return 1; },
|
|
hGet: async (key, field) => _store[`${key}:${field}`] ?? null,
|
|
};
|
|
}
|
|
|
|
/** Build a capturable res object. */
|
|
function makeRes() {
|
|
let statusCode = null;
|
|
let body = '';
|
|
const headers = {};
|
|
return {
|
|
writeHead: (code, hdrs = {}) => { statusCode = code; Object.assign(headers, hdrs); },
|
|
end: (b = '') => { body += String(b); },
|
|
get statusCode() { return statusCode; },
|
|
get body() { return body; },
|
|
get headers() { return headers; },
|
|
};
|
|
}
|
|
|
|
// ---------------------------------------------------------------------------
|
|
// Contract: 200 OK — successful OIDC token fetch
|
|
// ---------------------------------------------------------------------------
|
|
|
|
describe('proxy HTTP contract: 200 OK', () => {
|
|
test('fresh token fetch → 200 Authorized with Content-Type text/plain', async () => {
|
|
const mock = await startMockTokenServer(200, {
|
|
id_token: 'contract-token',
|
|
expires_in: 9_999_999_999,
|
|
});
|
|
|
|
try {
|
|
const res = makeRes();
|
|
const ctx = vm.createContext({
|
|
URLSearchParams,
|
|
console,
|
|
axios,
|
|
redis: makeRedisFake(),
|
|
kme_CSA_settings: {
|
|
tokenUrl: mock.url,
|
|
username: 'user',
|
|
password: 'pass',
|
|
clientId: 'client',
|
|
scope: 'openid',
|
|
},
|
|
req: { url: '/', method: 'GET', headers: {} },
|
|
res,
|
|
});
|
|
|
|
await proxyScript.runInContext(ctx);
|
|
|
|
assert.strictEqual(res.statusCode, 200);
|
|
assert.strictEqual(res.body, 'Authorized');
|
|
assert.strictEqual(res.headers['Content-Type'], 'text/plain');
|
|
} finally {
|
|
await mock.close();
|
|
}
|
|
});
|
|
});
|
|
|
|
// ---------------------------------------------------------------------------
|
|
// Contract: 401 Unauthorized — token service returns 4xx
|
|
// ---------------------------------------------------------------------------
|
|
|
|
describe('proxy HTTP contract: 401 Unauthorized', () => {
|
|
test('token service 401 → proxy 401 with Unauthorized: prefix', async () => {
|
|
const mock = await startMockTokenServer(401, {});
|
|
|
|
try {
|
|
const res = makeRes();
|
|
const ctx = vm.createContext({
|
|
URLSearchParams,
|
|
console,
|
|
axios,
|
|
redis: makeRedisFake(),
|
|
kme_CSA_settings: {
|
|
tokenUrl: mock.url,
|
|
username: 'bad-user',
|
|
password: 'bad-pass',
|
|
clientId: 'client',
|
|
scope: 'openid',
|
|
},
|
|
req: { url: '/', method: 'GET', headers: {} },
|
|
res,
|
|
});
|
|
|
|
await proxyScript.runInContext(ctx);
|
|
|
|
assert.strictEqual(res.statusCode, 401);
|
|
assert.match(res.body, /^Unauthorized: .+/);
|
|
assert.strictEqual(res.headers['Content-Type'], 'text/plain');
|
|
} finally {
|
|
await mock.close();
|
|
}
|
|
});
|
|
});
|