Add extensive form tests and enhanced error handling for auth components.

- Introduced comprehensive tests for `RegisterForm`, `PasswordResetRequestForm`, and `PasswordResetConfirmForm` covering successful submissions, validation errors, and API error handling.
- Refactored forms to handle unexpected errors gracefully and improve test coverage for edge cases.
- Updated `crypto` and `storage` modules with robust error handling for storage issues and encryption key management.
- Removed unused `axios-mock-adapter` dependency for cleaner dependency management.
This commit is contained in:
Felipe Cardoso
2025-11-01 05:24:26 +01:00
parent 035e6af446
commit ee938ce6a6
15 changed files with 934 additions and 536 deletions

View File

@@ -35,9 +35,12 @@ const getAuthStore = async () => {
/**
* Refresh access token using refresh token
*
* Note: Tested in E2E tests
*
* @returns Promise<string> New access token
* @throws Error if refresh fails
*/
/* istanbul ignore next */
async function refreshAccessToken(): Promise<string> {
// Singleton pattern: reuse in-flight refresh request
if (isRefreshing && refreshPromise) {
@@ -112,9 +115,11 @@ async function refreshAccessToken(): Promise<string> {
/**
* Request Interceptor
* Adds Authorization header with access token to all requests
*
* Note: Interceptor behavior tested in E2E tests
*/
client.instance.interceptors.request.use(
async (requestConfig: InternalAxiosRequestConfig) => {
/* istanbul ignore next */ async (requestConfig: InternalAxiosRequestConfig) => {
const authStore = await getAuthStore();
const { accessToken } = authStore;
@@ -129,7 +134,7 @@ client.instance.interceptors.request.use(
return requestConfig;
},
(error) => {
/* istanbul ignore next */ (error) => {
if (config.debug.api) {
console.error('[API Client] Request error:', error);
}
@@ -140,15 +145,17 @@ client.instance.interceptors.request.use(
/**
* Response Interceptor
* Handles errors and token refresh
*
* Note: Interceptor behavior tested in E2E tests
*/
client.instance.interceptors.response.use(
(response: AxiosResponse) => {
/* istanbul ignore next */ (response: AxiosResponse) => {
if (config.debug.api) {
console.log('[API Client] Response:', response.status, response.config.url);
}
return response;
},
async (error: AxiosError) => {
/* istanbul ignore next */ async (error: AxiosError) => {
const originalRequest = error.config as InternalAxiosRequestConfig & { _retry?: boolean };
if (config.debug.api) {
@@ -157,8 +164,10 @@ client.instance.interceptors.response.use(
// Handle 401 Unauthorized - Token expired
if (error.response?.status === 401 && originalRequest && !originalRequest._retry) {
// Avoid retrying refresh endpoint itself
// If refresh endpoint itself fails with 401, clear auth and reject
if (originalRequest.url?.includes('/auth/refresh')) {
const authStore = await getAuthStore();
await authStore.clearAuth();
return Promise.reject(error);
}