nuthatch/web/test/dev-boundary.test.mjs

60 lines
1.9 KiB
JavaScript

import assert from 'node:assert/strict';
import { createServer as createHttpServer } from 'node:http';
import test from 'node:test';
import { createServer as createViteServer } from 'vite';
test('development server proxies login, API, and logout to one backend', async () => {
const seen = [];
const backend = createHttpServer((request, response) => {
seen.push(`${request.method} ${request.url}`);
response.writeHead(request.url === '/login' ? 303 : 200, {
'Content-Type': 'application/json',
Location: '/oidc'
});
response.end('{}');
});
await listen(backend);
const address = backend.address();
if (address === null || typeof address === 'string') {
throw new Error('backend did not bind a TCP port');
}
const previous = process.env.NUTHATCH_DEV_BACKEND;
process.env.NUTHATCH_DEV_BACKEND = `http://127.0.0.1:${address.port}`;
const vite = await createViteServer({
server: { host: '127.0.0.1', port: 0 }
});
try {
await vite.listen();
const origin = vite.resolvedUrls?.local[0];
if (origin === undefined) throw new Error('Vite did not publish a local URL');
await fetch(new URL('/api/session', origin));
await fetch(new URL('/login', origin), { redirect: 'manual' });
await fetch(new URL('/logout', origin), { method: 'POST' });
assert.deepEqual(seen, [
'GET /api/session',
'GET /login',
'POST /logout'
]);
} finally {
await vite.close();
await close(backend);
if (previous === undefined) {
delete process.env.NUTHATCH_DEV_BACKEND;
} else {
process.env.NUTHATCH_DEV_BACKEND = previous;
}
}
});
function listen(server) {
return new Promise((resolve, reject) => {
server.once('error', reject);
server.listen(0, '127.0.0.1', resolve);
});
}
function close(server) {
return new Promise((resolve, reject) => {
server.close((error) => (error === undefined ? resolve() : reject(error)));
});
}