const test = require('node:test'); const assert = require('node:assert/strict'); const registerUsersRoutes = require('../src/web/routes/admin/users'); test('user create route allows users without roles', async () => { const handlers = {}; const app = { get() {}, post(path, ...routeHandlers) { handlers[path] = routeHandlers; } }; let insertedArgs = null; let syncedRoles = null; const deps = { pool: { async query(sql) { if (sql.includes('SELECT id FROM a_users WHERE username = ? LIMIT 1')) { return [[]]; } return [[]]; }, async getConnection() { return { async beginTransaction() {}, async query(sql, args) { if (sql.includes('INSERT INTO a_users')) { insertedArgs = args; return [{ insertId: 11 }]; } return [[]]; }, async commit() {}, async rollback() {}, release() {} }; } }, common: { validateMaxLength(value) { return String(value || '').trim(); }, fetchDuplicateName: async () => null }, pages: { renderUsersAddPage() { return ''; } }, formatDashboardDate: () => '', getAuditUserId: () => 1, hashPassword: () => ({ hash: 'hash', salt: 'salt', iterations: 1 }), validatePasswordStrength: () => '', readArrayField: () => [], rbacData: { fetchRoles: async () => ([]), fetchUsersWithRolesPage: async () => ({ users: [], totalItems: 0, currentPage: 1 }), syncUserRoles: async (_connection, userId, roleIds) => { syncedRoles = { userId, roleIds }; } }, requirePermission() { return function (_req, _res, next) { next(); }; } }; registerUsersRoutes(app, deps); const routeHandlers = handlers['/users']; assert.equal(Array.isArray(routeHandlers), true); const req = { body: { name: 'No Roles User', username: 'noroles', password: 'ValidPass!1', confirm_password: 'ValidPass!1' }, currentUser: { id: 1 } }; const res = { redirect(url) { this.redirectedTo = url; }, status() { return this; }, send() { return this; } }; await routeHandlers[1](req, res, () => {}); assert.ok(insertedArgs); assert.deepEqual(syncedRoles, { userId: 11, roleIds: [] }); assert.equal(res.redirectedTo, '/users/11/edit?message=User%20created.'); }); test('user create save and new goes to the blank create page', async () => { const handlers = {}; const app = { get() {}, post(path, ...routeHandlers) { handlers[path] = routeHandlers; } }; const deps = { pool: { async query(sql) { if (sql.includes('SELECT id FROM a_users WHERE username = ? LIMIT 1')) { return [[]]; } return [[]]; }, async getConnection() { return { async beginTransaction() {}, async query(sql) { if (sql.includes('INSERT INTO a_users')) { return [{ insertId: 15 }]; } return [[]]; }, async commit() {}, async rollback() {}, release() {} }; } }, common: { validateMaxLength(value) { return String(value || '').trim(); }, fetchDuplicateName: async () => null }, pages: { renderUsersAddPage() { return ''; } }, formatDashboardDate: () => '', getAuditUserId: () => 1, hashPassword: () => ({ hash: 'hash', salt: 'salt', iterations: 1 }), validatePasswordStrength: () => '', readArrayField: () => [], rbacData: { fetchRoles: async () => ([]), fetchUsersWithRolesPage: async () => ({ users: [], totalItems: 0, currentPage: 1 }), syncUserRoles: async () => {} }, requirePermission() { return function (_req, _res, next) { next(); }; } }; registerUsersRoutes(app, deps); const routeHandlers = handlers['/users']; const req = { body: { name: 'No Roles User', username: 'noroles', password: 'ValidPass!1', confirm_password: 'ValidPass!1', save_action: 'new' }, currentUser: { id: 1 } }; const res = { redirect(url) { this.redirectedTo = url; }, status() { return this; }, send() { return this; } }; await routeHandlers[1](req, res, () => {}); assert.equal(res.redirectedTo, '/users/new?message=User%20created.'); });