'use strict'; process.env.S3_BUCKET = process.env.S3_BUCKET || 'terraform-registry'; const test = require('node:test'); const assert = require('node:assert'); const { Readable } = require('node:stream'); const { getDocsCandidates, contentTypeFor, server, s3 } = require('../server.js'); async function withServer(fn) { await new Promise((resolve) => server.listen(0, '127.0.0.1', resolve)); const base = `http://127.0.0.1:${server.address().port}`; try { await fn(base); } finally { await new Promise((resolve) => server.close(resolve)); } } // --- getDocsCandidates (URL -> S3 keys) --- test('candidates: trailing slash -> index.html', () => { assert.deepStrictEqual( getDocsCandidates('/docs/nubes/nubes/1.0.0/'), ['docs/nubes/nubes/1.0.0/index.html'] ); }); test('candidates: file with extension -> exact + root index fallback', () => { assert.deepStrictEqual( getDocsCandidates('/docs/nubes/nubes/1.0.0/page.html'), ['docs/nubes/nubes/1.0.0/page.html', 'docs/nubes/nubes/1.0.0/index.html'] ); }); test('candidates: directory-style path -> exact + index.html + root index', () => { assert.deepStrictEqual( getDocsCandidates('/docs/nubes/nubes/1.0.0/guides/getting-started'), [ 'docs/nubes/nubes/1.0.0/guides/getting-started', 'docs/nubes/nubes/1.0.0/guides/getting-started/index.html', 'docs/nubes/nubes/1.0.0/index.html', ] ); }); // --- contentTypeFor --- test('contentTypeFor: known and unknown extensions', () => { assert.strictEqual(contentTypeFor('index.html'), 'text/html; charset=utf-8'); assert.strictEqual(contentTypeFor('style.css'), 'text/css; charset=utf-8'); assert.strictEqual(contentTypeFor('app.js'), 'application/javascript; charset=utf-8'); assert.strictEqual(contentTypeFor('logo.png'), 'image/png'); assert.strictEqual(contentTypeFor('data.json'), 'application/json; charset=utf-8'); assert.strictEqual(contentTypeFor('file.unknown'), 'application/octet-stream'); }); // --- /health --- test('GET /health -> 200 ok when S3 available', async () => { const originalSend = s3.send; s3.send = async () => ({ $metadata: { httpStatusCode: 200 } }); await withServer(async (base) => { const res = await fetch(`${base}/health`); assert.strictEqual(res.status, 200); assert.strictEqual(await res.text(), 'ok'); }); s3.send = originalSend; }); test('GET /health -> 503 when S3 unreachable', async () => { const originalSend = s3.send; s3.send = async () => { throw new Error('boom'); }; await withServer(async (base) => { const res = await fetch(`${base}/health`); assert.strictEqual(res.status, 503); assert.match(await res.text(), /s3 unreachable/); }); s3.send = originalSend; }); // --- /docs --- test('GET /docs/... -> 200 streams body with content-type', async () => { const originalSend = s3.send; s3.send = async (cmd) => { if (cmd.input && cmd.input.Key) { return { Body: Readable.from(['ok']), ContentType: 'text/html' }; } return { $metadata: { httpStatusCode: 200 } }; }; await withServer(async (base) => { const res = await fetch(`${base}/docs/nubes/nubes/1.0.0/`); assert.strictEqual(res.status, 200); assert.match(res.headers.get('content-type') || '', /text\/html/); assert.strictEqual(await res.text(), 'ok'); }); s3.send = originalSend; }); test('GET /docs/... -> 404 when no key found', async () => { const originalSend = s3.send; s3.send = async (cmd) => { if (cmd.input && cmd.input.Key) { const err = new Error('Not Found'); err.name = 'NoSuchKey'; throw err; } return { $metadata: { httpStatusCode: 200 } }; }; await withServer(async (base) => { const res = await fetch(`${base}/docs/nubes/nubes/1.0.0/missing`); assert.strictEqual(res.status, 404); }); s3.send = originalSend; });