Add comprehensive tests for hooks, middleware, and routes
Some checks are pending
Deploy to Test Environment / deploy-to-test (push) Has started running
Some checks are pending
Deploy to Test Environment / deploy-to-test (push) Has started running
- Implement tests for `useFlyers`, `useMasterItems`, `useModal`, `useUserData` hooks to ensure correct functionality and error handling. - Create tests for `fileUpload.middleware` and `validation.middleware` to validate file uploads and request data. - Add tests for `AddressForm` and `AuthView` components to verify rendering, user interactions, and API calls. - Develop tests for `deals.routes` to check authentication and response for best prices on watched items.
This commit is contained in:
@@ -4,42 +4,6 @@ import { DatabaseError, UniqueConstraintError, ForeignKeyConstraintError, NotFou
|
||||
import crypto from 'crypto';
|
||||
import { logger } from '../services/logger.server';
|
||||
|
||||
// --- Helper Functions for Secure Logging ---
|
||||
|
||||
/**
|
||||
* Sanitizes an object by redacting values of sensitive keys.
|
||||
* @param obj The object to sanitize.
|
||||
* @returns A new object with sensitive values redacted.
|
||||
*/
|
||||
const sanitizeObject = (obj: Record<string, any>): Record<string, any> => {
|
||||
if (!obj || typeof obj !== 'object') return {};
|
||||
const sensitiveKeys = ['password', 'token', 'authorization', 'cookie', 'newPassword', 'currentPassword'];
|
||||
const sanitizedObj: Record<string, any> = {};
|
||||
for (const key in obj) {
|
||||
if (Object.prototype.hasOwnProperty.call(obj, key)) {
|
||||
if (sensitiveKeys.some(sensitiveKey => key.toLowerCase().includes(sensitiveKey))) {
|
||||
sanitizedObj[key] = '[REDACTED]';
|
||||
} else {
|
||||
sanitizedObj[key] = obj[key];
|
||||
}
|
||||
}
|
||||
}
|
||||
return sanitizedObj;
|
||||
};
|
||||
|
||||
/**
|
||||
* Extracts user information from the request object for logging.
|
||||
* @param req The Express request object.
|
||||
* @returns An object with user details or null if no user is authenticated.
|
||||
*/
|
||||
const getLoggableUser = (req: Request): { id: string; email?: string } | null => {
|
||||
const user = req.user as { user_id?: string; email?: string };
|
||||
if (user && user.user_id) {
|
||||
return { id: user.user_id, email: user.email };
|
||||
}
|
||||
return null;
|
||||
};
|
||||
|
||||
interface HttpError extends Error {
|
||||
status?: number;
|
||||
}
|
||||
@@ -50,6 +14,9 @@ export const errorHandler = (err: HttpError, req: Request, res: Response, next:
|
||||
return next(err);
|
||||
}
|
||||
|
||||
// Use the request-scoped logger if available, otherwise fall back to the global logger.
|
||||
const log = req.log || logger;
|
||||
|
||||
// --- 1. Determine Final Status Code and Message ---
|
||||
let statusCode = err.status ?? 500;
|
||||
let message = err.message;
|
||||
@@ -77,25 +44,16 @@ export const errorHandler = (err: HttpError, req: Request, res: Response, next:
|
||||
// Log the full error details for debugging, especially for server errors.
|
||||
if (statusCode >= 500) {
|
||||
errorId = crypto.randomBytes(4).toString('hex');
|
||||
logger.error(`Unhandled API Error (ID: ${errorId}):`, {
|
||||
// Log sanitized data for security
|
||||
error: err.stack || err.message,
|
||||
path: req.path,
|
||||
method: req.method,
|
||||
body: sanitizeObject(req.body),
|
||||
headers: sanitizeObject(req.headers),
|
||||
user: getLoggableUser(req),
|
||||
});
|
||||
// The request-scoped logger already contains user, IP, and request_id.
|
||||
// We add the full error and the request object itself.
|
||||
// Pino's `redact` config will automatically sanitize sensitive fields in `req`.
|
||||
log.error({ err, errorId, req: { method: req.method, url: req.originalUrl, headers: req.headers, body: req.body } }, `Unhandled API Error (ID: ${errorId})`);
|
||||
} else {
|
||||
// For 4xx errors, log at a lower level (e.g., 'warn') to avoid flooding error trackers.
|
||||
logger.warn(`Client Error: ${statusCode} on ${req.method} ${req.path}`, {
|
||||
// Including the specific message can be helpful for debugging client errors.
|
||||
errorMessage: err.message,
|
||||
user: getLoggableUser(req),
|
||||
path: req.path,
|
||||
method: req.method,
|
||||
ip: req.ip,
|
||||
});
|
||||
// The request-scoped logger already contains the necessary context.
|
||||
// We log the error itself to capture its message and properties.
|
||||
// No need to log the full request for client errors unless desired for debugging.
|
||||
log.warn({ err }, `Client Error: ${statusCode} on ${req.method} ${req.path}`);
|
||||
}
|
||||
|
||||
// --- TEST ENVIRONMENT DEBUGGING ---
|
||||
|
||||
Reference in New Issue
Block a user