After the DC-005 module reorganization (41 files moved into src/ subdirs),
138 test suites failed because the refactor script's path-rewrite logic
missed three categories:
1. Files inside src/ doing 'require("./src/...")' — should be 'require("../...")'
2. Files in src/X/Y/ doing 'require("../../../src/...")' — should be 'require("../../...")'
3. Test files in __tests__/ with leftover 'require("../../../src/...")' paths
Root cause: the original refactor script ran before all files were moved,
so it computed relative paths against stale filesystem state.
Result:
- 30/30 test suites pass
- 879/879 tests pass (was: 18/30 suites, 614/687 tests)
Also fixed:
- routes/apps/restore.js: wrong responses import path
- routes/*/*.js: '../../src/utilities/X' → '../src/utilities/X' (depth 2 routes)
141 lines
3.7 KiB
JavaScript
141 lines
3.7 KiB
JavaScript
/**
|
|
* Shared test utilities for DashCaddy test suite
|
|
*/
|
|
const express = require('express');
|
|
|
|
/**
|
|
* Create a mock credential manager
|
|
*/
|
|
function createMockCredentialManager() {
|
|
return {
|
|
store: jest.fn().mockResolvedValue(true),
|
|
retrieve: jest.fn().mockResolvedValue(null),
|
|
delete: jest.fn().mockResolvedValue(true),
|
|
list: jest.fn().mockResolvedValue([]),
|
|
getMetadata: jest.fn().mockResolvedValue(null),
|
|
rotateEncryptionKey: jest.fn().mockResolvedValue(true),
|
|
exportBackup: jest.fn().mockResolvedValue('encrypted-backup'),
|
|
importBackup: jest.fn().mockResolvedValue(true),
|
|
};
|
|
}
|
|
|
|
/**
|
|
* Create a mock crypto utils module
|
|
*/
|
|
function createMockCryptoUtils() {
|
|
const fixedKey = Buffer.alloc(32, 'a');
|
|
return {
|
|
encrypt: jest.fn(data => `mock-iv:mock-tag:${Buffer.from(String(data)).toString('base64')}`),
|
|
decrypt: jest.fn(data => {
|
|
const parts = data.split(':');
|
|
return Buffer.from(parts[2], 'base64').toString('utf8');
|
|
}),
|
|
isEncrypted: jest.fn(data => typeof data === 'string' && data.split(':').length === 3),
|
|
encryptFields: jest.fn((obj, fields) => ({ ...obj, _encrypted: true, _encryptedFields: fields })),
|
|
decryptFields: jest.fn(obj => {
|
|
const result = { ...obj };
|
|
delete result._encrypted;
|
|
delete result._encryptedFields;
|
|
return result;
|
|
}),
|
|
loadOrCreateKey: jest.fn(() => fixedKey),
|
|
clearCachedKey: jest.fn(),
|
|
rotateKey: jest.fn(() => ({ oldKey: fixedKey, newKey: Buffer.alloc(32, 'b') })),
|
|
deriveKey: jest.fn().mockResolvedValue(fixedKey),
|
|
decryptWithKey: jest.fn(data => {
|
|
const parts = data.split(':');
|
|
return Buffer.from(parts[2], 'base64').toString('utf8');
|
|
}),
|
|
readEncryptedFile: jest.fn().mockReturnValue(null),
|
|
writeEncryptedFile: jest.fn(),
|
|
migrateToEncrypted: jest.fn(obj => obj),
|
|
};
|
|
}
|
|
|
|
/**
|
|
* Create a mock state manager
|
|
*/
|
|
function createMockStateManager() {
|
|
let data = [];
|
|
return {
|
|
read: jest.fn().mockResolvedValue(data),
|
|
write: jest.fn().mockResolvedValue(),
|
|
update: jest.fn(async fn => { data = fn(data); return data; }),
|
|
addItem: jest.fn().mockResolvedValue(),
|
|
removeItem: jest.fn().mockResolvedValue(),
|
|
updateItem: jest.fn().mockResolvedValue(),
|
|
findItem: jest.fn().mockResolvedValue(null),
|
|
_setData: (newData) => { data = newData; },
|
|
};
|
|
}
|
|
|
|
/**
|
|
* Create a mock logger
|
|
*/
|
|
function createMockLogger() {
|
|
return {
|
|
info: jest.fn(),
|
|
warn: jest.fn(),
|
|
error: jest.fn(),
|
|
debug: jest.fn(),
|
|
};
|
|
}
|
|
|
|
/**
|
|
* Build a minimal Express app for route testing with supertest
|
|
*/
|
|
function buildTestApp(routeFactory, deps, prefix = '/api') {
|
|
const app = express();
|
|
app.use(express.json());
|
|
const router = routeFactory(deps);
|
|
app.use(prefix, router);
|
|
// Error handler
|
|
const { errorMiddleware } = require('../../../src/utilities/error-handler');
|
|
app.use(errorMiddleware);
|
|
return app;
|
|
}
|
|
|
|
/**
|
|
* Create mock Express req/res/next for middleware testing
|
|
*/
|
|
function createMockReqRes(overrides = {}) {
|
|
const req = {
|
|
method: 'GET',
|
|
path: '/test',
|
|
headers: {},
|
|
cookies: {},
|
|
ip: '127.0.0.1',
|
|
protocol: 'https',
|
|
secure: true,
|
|
body: {},
|
|
params: {},
|
|
query: {},
|
|
get: jest.fn(header => req.headers[header.toLowerCase()]),
|
|
...overrides,
|
|
};
|
|
|
|
const res = {
|
|
status: jest.fn().mockReturnThis(),
|
|
json: jest.fn().mockReturnThis(),
|
|
send: jest.fn().mockReturnThis(),
|
|
set: jest.fn().mockReturnThis(),
|
|
cookie: jest.fn().mockReturnThis(),
|
|
setHeader: jest.fn().mockReturnThis(),
|
|
getHeader: jest.fn(),
|
|
end: jest.fn(),
|
|
};
|
|
|
|
const next = jest.fn();
|
|
|
|
return { req, res, next };
|
|
}
|
|
|
|
module.exports = {
|
|
createMockCredentialManager,
|
|
createMockCryptoUtils,
|
|
createMockStateManager,
|
|
createMockLogger,
|
|
buildTestApp,
|
|
createMockReqRes,
|
|
};
|