tinfo-web-server / test /authProtect.test.js
Faridaqurr
initial backend
e8c33fa
Raw
History Blame Contribute Delete
5.2 kB
// server/test/authProtect.test.js
// Tests for protect and adminOnly middleware (authMiddleware.js)
// Uses node:test + node:assert/strict β€” no real DB or server required.
// Set JWT_SECRET BEFORE any module require so configs/env.js captures it.
// (If authLogin.test.js already set it in this process, this is a no-op
// because the value is the same.)
process.env.JWT_SECRET = 'test-secret-for-auth-login-tests-min32ch';
const test = require('node:test');
const assert = require('node:assert/strict');
const jwt = require('jsonwebtoken');
const { protect, adminOnly } = require('../middleware/authMiddleware');
const AdminUser = require('../models/AdminUser');
// Secret used by authMiddleware β€” must match what was set in process.env above
// at the time the module was first loaded (or in authLogin.test.js).
const TEST_SECRET = 'test-secret-for-auth-login-tests-min32ch';
// ─── Helpers ──────────────────────────────────────────────────────────────────
function makeProtectRes() {
const res = {
_status: null,
_body: null,
status(code) { this._status = code; return this; },
json(body) { this._body = body; return this; },
};
return res;
}
// ─── protect tests ────────────────────────────────────────────────────────────
test('protect rejects request with no cookie', async () => {
const req = { cookies: {} }; // no token
const res = makeProtectRes();
let nextCalled = false;
await protect(req, res, () => { nextCalled = true; });
assert.equal(nextCalled, false, 'next() must not be called when no token is present');
assert.equal(res._status, 401, 'should respond 401 when no cookie token');
});
test('protect rejects invalid/expired JWT', async () => {
const req = { cookies: { token: 'this.is.not.a.valid.jwt' } };
const res = makeProtectRes();
let nextCalled = false;
await protect(req, res, () => { nextCalled = true; });
assert.equal(nextCalled, false, 'next() must not be called for invalid token');
assert.equal(res._status, 401, 'should respond 401 for invalid/expired JWT');
});
test('protect rejects deactivated user', async () => {
// Create a valid token signed with the test secret
const token = jwt.sign(
{ id: '507f1f77bcf86cd799439011' },
TEST_SECRET,
{ expiresIn: '1h' }
);
const originalFindById = AdminUser.findById.bind(AdminUser);
// Simulate the chained .select('-passwordHash').lean() call
AdminUser.findById = () => ({
select: () => ({
lean: async () => ({
_id: '507f1f77bcf86cd799439011',
username: 'deactivated',
name: 'Deactivated User',
role: 'admin',
isActive: false,
}),
}),
});
try {
const req = { cookies: { token } };
const res = makeProtectRes();
let nextCalled = false;
await protect(req, res, () => { nextCalled = true; });
assert.equal(nextCalled, false, 'next() must not be called for deactivated user');
assert.equal(res._status, 403, 'should respond 403 for deactivated user');
} finally {
AdminUser.findById = originalFindById;
}
});
test('protect passes and sets req.user for valid active user', async () => {
const token = jwt.sign(
{ id: '507f1f77bcf86cd799439011' },
TEST_SECRET,
{ expiresIn: '1h' }
);
const originalFindById = AdminUser.findById.bind(AdminUser);
AdminUser.findById = () => ({
select: () => ({
lean: async () => ({
_id: '507f1f77bcf86cd799439011',
username: 'admin',
name: 'Administrator',
role: 'admin',
isActive: true,
}),
}),
});
try {
const req = { cookies: { token } };
const res = makeProtectRes();
let nextCalled = false;
await protect(req, res, () => { nextCalled = true; });
assert.equal(nextCalled, true, 'next() must be called for valid active user');
assert.ok(req.user, 'req.user must be set');
assert.equal(req.user.username, 'admin');
} finally {
AdminUser.findById = originalFindById;
}
});
// ─── adminOnly tests ──────────────────────────────────────────────────────────
test('adminOnly rejects non-admin role', () => {
const req = { user: { role: 'user' } };
const res = makeProtectRes();
let nextCalled = false;
adminOnly(req, res, () => { nextCalled = true; });
assert.equal(nextCalled, false, 'next() must not be called for non-admin role');
assert.equal(res._status, 403, 'should respond 403 for non-admin role');
});
test('adminOnly passes for admin role', () => {
const req = { user: { role: 'admin' } };
const res = makeProtectRes();
let nextCalled = false;
adminOnly(req, res, () => { nextCalled = true; });
assert.equal(nextCalled, true, 'next() must be called for admin role');
assert.equal(res._status, null, 'no error response should be set for admin role');
});