test: repair four stale backend suites

All four asserted contracts the product has since moved past. No genuine
product bugs behind any of them; assertions were tightened, not loosened.

adminAuth (3 tests): never mounted errorHandler, so ConflictError/
ValidationError arrived as empty Express defaults. The route also checks
username before email, so the "email conflict" fixture was hitting the
username branch. Mount the handler, fix the fixture, match the real response
shapes.

backupService.enhanced (12 tests): three stacked drifts -- the db mock had no
.returning(), so every runBackup threw at the insert; ensureDatabaseDumpForBackup
now lazily requires ./databaseBackup inside the run, which fails under
mock-fs; and the rsync path moved from exec(shell string) to
spawnAsync('rsync', args) with an isHostAllowed SSRF preflight. Also updates
getBackupStatus to its current shape (frontend aliases, nextScheduledRun null
when no schedule is enabled, #871).

adminSettings.logo: POST /logo gained requirePermission('settings.edit');
the hand-rolled db mock returns a bare Promise from select(), so the
permission lookup threw a TypeError into a 500. Mock the permissions
middleware alongside the already-mocked auth.

crmMintPaths (2 tests): macOS-only. The expected prefix was realpath'd while
the services persist under the raw STORAGE_PATH -- identical on Linux CI
(/var vs /private/var only diverges on macOS), which is why it passed there.
The comment justifying the realpath referenced process.cwd() behaviour the
services no longer have.

Refs testplan REPORT.md #22 (Part 1.2.01).
This commit is contained in:
Paul Nothaft
2026-09-01 16:29:03 +02:00
parent c5c5a6b0c8
commit 1d84c738d8
4 changed files with 139 additions and 56 deletions
+17 -7
View File
@@ -36,11 +36,13 @@ jest.mock('../../middleware/auth', () => ({
const { db, logActivity } = require('../../database/db');
const adminAuthRouter = require('../adminAuth');
const { errorHandler } = require('../../middleware/errorHandler');
describe('adminAuth profile updates', () => {
const app = express();
app.use(express.json());
app.use('/auth/admin', adminAuthRouter);
app.use(errorHandler);
beforeEach(() => {
jest.clearAllMocks();
@@ -55,8 +57,8 @@ describe('adminAuth profile updates', () => {
};
db.__setImplementations(
buildChain({ firstResult: null }), // email check
buildChain({ firstResult: null }), // username check
buildChain({ firstResult: null }), // email check
buildChain({ updateResult: 1 }), // update
buildChain({ firstResult: updatedUser }), // fetch updated user
);
@@ -66,18 +68,22 @@ describe('adminAuth profile updates', () => {
.send({ username: updatedUser.username, email: updatedUser.email })
.expect(200);
expect(response.body).toEqual({ user: updatedUser });
expect(response.body).toEqual({
message: 'Admin profile updated successfully',
user: updatedUser
});
expect(logActivity).toHaveBeenCalledWith(
'admin_profile_updated',
{ admin_id: 1, updated_fields: ['username', 'email'] },
{ username: updatedUser.username, email: updatedUser.email },
null,
{ type: 'admin', id: 1, name: updatedUser.username }
{ type: 'admin', id: 1, name: 'admin' }
);
});
it('rejects email conflicts', async () => {
db.__setImplementations(
buildChain({ firstResult: { id: 2 } })
buildChain({ firstResult: null }), // username check
buildChain({ firstResult: { id: 2 } }), // email check
);
const response = await request(app)
@@ -85,7 +91,11 @@ describe('adminAuth profile updates', () => {
.send({ username: 'newadmin', email: '[email protected]' })
.expect(409);
expect(response.body).toEqual({ error: 'Email is already in use by another admin' });
expect(response.body).toEqual({
error: 'Email address is already in use',
code: 'CONFLICT',
field: 'email'
});
});
it('validates input', async () => {
@@ -94,6 +104,6 @@ describe('adminAuth profile updates', () => {
.send({ username: '', email: 'not-an-email' })
.expect(400);
expect(response.body.errors).toBeDefined();
expect(response.body.details).toBeDefined();
});
});