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:
99
docs/adr/0026-standardized-client-side-structured-logging.md
Normal file
99
docs/adr/0026-standardized-client-side-structured-logging.md
Normal file
@@ -0,0 +1,99 @@
|
||||
# ADR-026: Standardized Client-Side Structured Logging
|
||||
|
||||
**Date**: 2025-12-14
|
||||
|
||||
**Status**: Proposed
|
||||
|
||||
## Context
|
||||
|
||||
Following the standardization of backend logging in `ADR-004`, it is clear that our frontend components also require a consistent logging strategy. Currently, components either use `console.log` directly or a simple wrapper, but without a formal standard, this can lead to inconsistent log formats and difficulty in debugging user-facing issues.
|
||||
|
||||
While the frontend does not have the concept of a "request-scoped" logger, the principles of structured, context-rich logging are equally important for:
|
||||
|
||||
1. **Effective Debugging**: Understanding the state of a component or the sequence of user interactions that led to an error.
|
||||
2. **Integration with Monitoring Tools**: Sending structured logs to services like Datadog, Sentry, or LogRocket allows for powerful analysis and error tracking in production.
|
||||
3. **Clean Test Outputs**: Uncontrolled logging can pollute test runner output, making it difficult to spot actual test failures.
|
||||
|
||||
An existing client-side logger at `src/services/logger.client.ts` already provides a simple, structured logging interface. This ADR formalizes its use as the application standard.
|
||||
|
||||
## Decision
|
||||
|
||||
We will adopt a standardized, application-wide structured logging policy for all client-side (React) code.
|
||||
|
||||
**1. Mandatory Use of the Global Client Logger**: All frontend components, hooks, and services **MUST** use the global logger singleton exported from `src/services/logger.client.ts`. Direct use of `console.log`, `console.error`, etc., is discouraged.
|
||||
|
||||
**2. Pino-like API for Structured Logging**: The client logger mimics the `pino` API, which is the standard on the backend. It supports two primary call signatures:
|
||||
|
||||
* `logger.info('A simple message');`
|
||||
* `logger.info({ key: 'value' }, 'A message with a structured data payload');`
|
||||
|
||||
The second signature, which includes a data object as the first argument, is **strongly preferred**, especially for logging errors or complex state.
|
||||
|
||||
**3. Mocking in Tests**: All Jest/Vitest tests for components or hooks that use the logger **MUST** mock the `src/services/logger.client.ts` module. This prevents logs from appearing in test output and allows for assertions that the logger was called correctly.
|
||||
|
||||
### Example Usage
|
||||
|
||||
**Logging an Error in a Component:**
|
||||
|
||||
```typescriptreact
|
||||
// In a React component or hook
|
||||
import { logger } from '../services/logger.client';
|
||||
import { notifyError } from '../services/notificationService';
|
||||
|
||||
const fetchData = async () => {
|
||||
try {
|
||||
const data = await apiClient.getData();
|
||||
return data;
|
||||
} catch (err) {
|
||||
// Log the full error object for context, along with a descriptive message.
|
||||
logger.error({ err }, 'Failed to fetch component data');
|
||||
notifyError('Something went wrong. Please try again.');
|
||||
}
|
||||
};
|
||||
```
|
||||
|
||||
**Mocking the Logger in a Test File:**
|
||||
|
||||
```typescript
|
||||
// In a *.test.tsx file
|
||||
import { vi } from 'vitest';
|
||||
|
||||
// Mock the logger at the top of the test file
|
||||
vi.mock('../services/logger.client', () => ({
|
||||
logger: {
|
||||
info: vi.fn(),
|
||||
warn: vi.fn(),
|
||||
error: vi.fn(),
|
||||
debug: vi.fn(),
|
||||
},
|
||||
}));
|
||||
|
||||
describe('MyComponent', () => {
|
||||
beforeEach(() => {
|
||||
vi.clearAllMocks(); // Clear mocks between tests
|
||||
});
|
||||
|
||||
it('should log an error when fetching fails', async () => {
|
||||
// ... test setup to make fetch fail ...
|
||||
|
||||
// Assert that the logger was called with the expected structure
|
||||
expect(logger.error).toHaveBeenCalledWith(
|
||||
expect.objectContaining({ err: expect.any(Error) }), // Check for the error object
|
||||
'Failed to fetch component data' // Check for the message
|
||||
);
|
||||
});
|
||||
});
|
||||
```
|
||||
|
||||
## Consequences
|
||||
|
||||
### Positive
|
||||
|
||||
**Consistency**: All client-side logs will have a predictable structure, making them easier to read and parse.
|
||||
**Debuggability**: Errors logged with a full object (`{ err }`) capture the stack trace and other properties, which is invaluable for debugging.
|
||||
**Testability**: Components that log are easier to test without polluting CI/CD output. We can also assert that logging occurs when expected.
|
||||
**Future-Proof**: If we later decide to send client-side logs to a remote service, we only need to modify the central `logger.client.ts` file instead of every component.
|
||||
|
||||
### Negative
|
||||
|
||||
**Minor Boilerplate**: Requires importing the logger in every file that needs it and mocking it in every corresponding test file. However, this is a small and consistent effort.
|
||||
Reference in New Issue
Block a user