'use strict' const { test, describe, before, after } = require('node:test') const assert = require('node:assert/strict') const http = require('node:http') const { initDb } = require('../db.js') const { createServer } = require('../server.js') function request(server, method, path, body, headers = {}) { return new Promise((resolve, reject) => { const addr = server.address() const opts = { hostname: '127.0.0.1', port: addr.port, path, method, headers: { 'Content-Type': 'application/json', ...headers }, } const req = http.request(opts, res => { let data = '' res.on('data', c => { data += c }) res.on('end', () => { let json = null try { json = JSON.parse(data) } catch {} resolve({ status: res.statusCode, headers: res.headers, body: json, raw: data }) }) }) req.on('error', reject) if (body) req.write(JSON.stringify(body)) req.end() }) } let db, server before(() => { db = initDb(':memory:') server = createServer(db) return new Promise(resolve => server.listen(0, resolve)) }) after(() => { db._db.close() return new Promise(resolve => server.close(resolve)) }) describe('POST /api/auth/request', () => { test('returns 200 ok for valid email', async () => { const r = await request(server, 'POST', '/api/auth/request', { email: 'test@example.com' }) assert.equal(r.status, 200) assert.equal(r.body.ok, true) }) test('creates profile if new email', async () => { await request(server, 'POST', '/api/auth/request', { email: 'new@example.com' }) const p = db.findProfileByEmail('new@example.com') assert.ok(p) assert.equal(p.email, 'new@example.com') }) test('returns 400 if email missing', async () => { const r = await request(server, 'POST', '/api/auth/request', {}) assert.equal(r.status, 400) }) }) describe('GET /api/auth/verify', () => { let profileId before(() => { const p = db.createProfile('verify@example.com', 'Verify') profileId = p.id db.createMagicToken('testtoken123', profileId, Date.now() + 86400000) }) test('redirects to /?session=... on valid token', async () => { const r = await request(server, 'GET', '/api/auth/verify?token=testtoken123', null, {}) assert.equal(r.status, 302) assert.ok(r.headers.location?.startsWith('/?session=')) }) test('returns 400 for invalid token', async () => { const r = await request(server, 'GET', '/api/auth/verify?token=badtoken', null) assert.equal(r.status, 400) }) test('returns 400 for already-used token', async () => { // testtoken123 was already used in the first verify test const r = await request(server, 'GET', '/api/auth/verify?token=testtoken123', null) assert.equal(r.status, 400) }) }) describe('GET /api/auth/me', () => { let sessionToken before(() => { const p = db.createProfile('me@example.com', 'Me') sessionToken = 'sessmetoken' db.createSession(sessionToken, p.id) }) test('returns profile for valid session', async () => { const r = await request(server, 'GET', '/api/auth/me', null, { Authorization: `Bearer ${sessionToken}`, }) assert.equal(r.status, 200) assert.equal(r.body.email, 'me@example.com') }) test('returns 401 without auth header', async () => { const r = await request(server, 'GET', '/api/auth/me', null) assert.equal(r.status, 401) }) }) describe('DELETE /api/auth/session', () => { let sessionToken before(() => { const p = db.createProfile('logout@example.com', 'Logout') sessionToken = 'sesslogouttoken' db.createSession(sessionToken, p.id) }) test('returns 200 and session is gone', async () => { const r = await request(server, 'DELETE', '/api/auth/session', null, { Authorization: `Bearer ${sessionToken}`, }) assert.equal(r.status, 200) assert.equal(db.getSession(sessionToken), null) }) test('returns 401 without auth header', async () => { const r = await request(server, 'DELETE', '/api/auth/session', null) assert.equal(r.status, 401) }) test('returns 401 when using deleted session token', async () => { const r = await request(server, 'GET', '/api/auth/me', null, { Authorization: `Bearer ${sessionToken}`, }) assert.equal(r.status, 401) }) })