// Point the DB at a closed port BEFORE requiring anything that builds the pool. // The only code path here that reaches the database (the empty-honeypot case → // username lookup) then fails fast with ECONNREFUSED instead of opening a real // pooled connection that would keep this test process alive and hang the runner. process.env.DB_HOST = '127.0.0.1' process.env.DB_PORT = '59999' const { test, beforeEach, after } = require('node:test') const assert = require('node:assert/strict') const authCtrl = require('../src/router/v1/auth/auth.controller') const botScore = require('../src/middleware/botScore') const lp = require('../src/middleware/loginProtection') const db = require('../src/utils/db') // Release the DB pool so the process can exit cleanly even if a connection was // created during module load. after(() => db.close()) // Minimal res double capturing status/json; set() is a no-op for headers. function mockRes() { return { statusCode: 200, body: null, status(c) { this.statusCode = c return this }, json(b) { this.body = b return this }, set() { return this }, } } beforeEach(() => { botScore._reset() lp._reset() }) test('honeypot field name matches what the client renders', () => { assert.equal(authCtrl.HONEYPOT_FIELD, 'company') }) test('a filled honeypot fails generically and bans the IP', async () => { const ip = '203.0.113.70' const req = { ip, body: { username: 'admin', password: 'whatever', [authCtrl.HONEYPOT_FIELD]: 'Acme Corp' }, } const res = mockRes() await authCtrl.login(req, res) // Generic failure — never says the honeypot was the reason. assert.equal(res.statusCode, 401) assert.match(res.body.message, /incorrect username or password/i) assert.doesNotMatch(res.body.message, /honeypot|bot|company/i) // Scored as an unambiguous bot: instant ban + backoff started. assert.equal(botScore.isBanned(ip), true) assert.ok(lp.retryAfterMs(ip) > 0) }) test('an empty honeypot does NOT trigger bot scoring (branch not taken)', async () => { const ip = '203.0.113.71' const req = { ip, body: { username: 'admin', password: 'whatever', [authCtrl.HONEYPOT_FIELD]: '' } } const res = mockRes() // With an empty honeypot the code proceeds to the DB lookup, which has no // connection in this unit test and is caught → 500. The point of this test is // only that the honeypot branch did not fire, so the IP is not banned. await authCtrl.login(req, res) assert.equal(botScore.isBanned(ip), false) })