Refactor useAuth hook, settings components, and docs for formatting and readability improvements
- Consolidated multi-line arguments into single lines where appropriate in `useAuth`. - Improved spacing and readability in data processing across components (`ProfileSettingsForm`, `PasswordChangeForm`, `SessionCard`). - Applied consistent table and markdown formatting in design system docs (e.g., `README.md`, `08-ai-guidelines.md`, `00-quick-start.md`). - Updated code snippets to ensure adherence to Prettier rules and streamlined JSX structures.
This commit is contained in:
@@ -56,9 +56,7 @@ describe('API Error Handling', () => {
|
||||
const errorsWithField: APIError[] = [
|
||||
{ code: 'VAL_001', message: 'Invalid input', field: 'email' },
|
||||
];
|
||||
const errorsWithoutField: APIError[] = [
|
||||
{ code: 'AUTH_001', message: 'Invalid credentials' },
|
||||
];
|
||||
const errorsWithoutField: APIError[] = [{ code: 'AUTH_001', message: 'Invalid credentials' }];
|
||||
|
||||
expect(isAPIErrorArray(errorsWithField)).toBe(true);
|
||||
expect(isAPIErrorArray(errorsWithoutField)).toBe(true);
|
||||
@@ -110,9 +108,7 @@ describe('API Error Handling', () => {
|
||||
|
||||
it('should handle strings', () => {
|
||||
const result = parseAPIError('some error string');
|
||||
expect(result).toEqual([
|
||||
{ code: 'UNKNOWN', message: ERROR_MESSAGES['UNKNOWN'] },
|
||||
]);
|
||||
expect(result).toEqual([{ code: 'UNKNOWN', message: ERROR_MESSAGES['UNKNOWN'] }]);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -448,9 +444,7 @@ describe('API Error Handling', () => {
|
||||
response: {
|
||||
status: 401,
|
||||
data: {
|
||||
errors: [
|
||||
{ code: 'CUSTOM_ERROR', message: 'Custom structured error' },
|
||||
],
|
||||
errors: [{ code: 'CUSTOM_ERROR', message: 'Custom structured error' }],
|
||||
},
|
||||
statusText: 'Unauthorized',
|
||||
headers: {},
|
||||
@@ -461,9 +455,7 @@ describe('API Error Handling', () => {
|
||||
const result = parseAPIError(axiosError);
|
||||
|
||||
// Should return structured error, not the 401 default
|
||||
expect(result).toEqual([
|
||||
{ code: 'CUSTOM_ERROR', message: 'Custom structured error' },
|
||||
]);
|
||||
expect(result).toEqual([{ code: 'CUSTOM_ERROR', message: 'Custom structured error' }]);
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -554,9 +546,7 @@ describe('API Error Handling', () => {
|
||||
});
|
||||
|
||||
it('should use error code message if message is missing', () => {
|
||||
const errors: APIError[] = [
|
||||
{ code: 'VAL_002', message: '', field: 'email' },
|
||||
];
|
||||
const errors: APIError[] = [{ code: 'VAL_002', message: '', field: 'email' }];
|
||||
|
||||
const result = getFieldErrors(errors);
|
||||
|
||||
@@ -605,9 +595,7 @@ describe('API Error Handling', () => {
|
||||
});
|
||||
|
||||
it('should use error code message if message is missing', () => {
|
||||
const errors: APIError[] = [
|
||||
{ code: 'AUTH_001', message: '' },
|
||||
];
|
||||
const errors: APIError[] = [{ code: 'AUTH_001', message: '' }];
|
||||
|
||||
const result = getGeneralError(errors);
|
||||
|
||||
|
||||
@@ -34,7 +34,9 @@ jest.mock('@/lib/api/client');
|
||||
jest.mock('@/lib/auth/AuthContext');
|
||||
|
||||
const mockAdminListUsers = adminListUsers as jest.MockedFunction<typeof adminListUsers>;
|
||||
const mockAdminListOrganizations = adminListOrganizations as jest.MockedFunction<typeof adminListOrganizations>;
|
||||
const mockAdminListOrganizations = adminListOrganizations as jest.MockedFunction<
|
||||
typeof adminListOrganizations
|
||||
>;
|
||||
const mockAdminListSessions = adminListSessions as jest.MockedFunction<typeof adminListSessions>;
|
||||
const mockUseAuth = useAuth as jest.MockedFunction<typeof useAuth>;
|
||||
|
||||
@@ -53,19 +55,13 @@ describe('useAdmin hooks', () => {
|
||||
});
|
||||
|
||||
const wrapper = ({ children }: { children: React.ReactNode }) => (
|
||||
<QueryClientProvider client={queryClient}>
|
||||
{children}
|
||||
</QueryClientProvider>
|
||||
<QueryClientProvider client={queryClient}>{children}</QueryClientProvider>
|
||||
);
|
||||
|
||||
describe('useAdminStats', () => {
|
||||
const mockUsersData = {
|
||||
data: {
|
||||
data: [
|
||||
{ is_active: true },
|
||||
{ is_active: true },
|
||||
{ is_active: false },
|
||||
],
|
||||
data: [{ is_active: true }, { is_active: true }, { is_active: false }],
|
||||
pagination: { total: 3, page: 1, limit: 10000 },
|
||||
},
|
||||
};
|
||||
@@ -358,7 +354,7 @@ describe('useAdmin hooks', () => {
|
||||
limit: 20,
|
||||
search: 'admin',
|
||||
is_active: true,
|
||||
is_superuser: false
|
||||
is_superuser: false,
|
||||
},
|
||||
throwOnError: false,
|
||||
});
|
||||
@@ -476,7 +472,15 @@ describe('useAdmin hooks', () => {
|
||||
it('creates a user successfully', async () => {
|
||||
const mockCreateUser = adminCreateUser as jest.MockedFunction<typeof adminCreateUser>;
|
||||
mockCreateUser.mockResolvedValue({
|
||||
data: { id: '1', email: 'newuser@example.com', first_name: 'New', last_name: 'User', is_active: true, is_superuser: false, created_at: '2025-01-01T00:00:00Z' },
|
||||
data: {
|
||||
id: '1',
|
||||
email: 'newuser@example.com',
|
||||
first_name: 'New',
|
||||
last_name: 'User',
|
||||
is_active: true,
|
||||
is_superuser: false,
|
||||
created_at: '2025-01-01T00:00:00Z',
|
||||
},
|
||||
} as any);
|
||||
|
||||
const { result } = renderHook(() => useCreateUser(), { wrapper });
|
||||
@@ -524,7 +528,15 @@ describe('useAdmin hooks', () => {
|
||||
it('updates a user successfully', async () => {
|
||||
const mockUpdateUser = adminUpdateUser as jest.MockedFunction<typeof adminUpdateUser>;
|
||||
mockUpdateUser.mockResolvedValue({
|
||||
data: { id: '1', email: 'updated@example.com', first_name: 'Updated', last_name: 'User', is_active: true, is_superuser: false, created_at: '2025-01-01T00:00:00Z' },
|
||||
data: {
|
||||
id: '1',
|
||||
email: 'updated@example.com',
|
||||
first_name: 'Updated',
|
||||
last_name: 'User',
|
||||
is_active: true,
|
||||
is_superuser: false,
|
||||
created_at: '2025-01-01T00:00:00Z',
|
||||
},
|
||||
} as any);
|
||||
|
||||
const { result } = renderHook(() => useUpdateUser(), { wrapper });
|
||||
@@ -618,7 +630,9 @@ describe('useAdmin hooks', () => {
|
||||
|
||||
describe('useDeactivateUser', () => {
|
||||
it('deactivates a user successfully', async () => {
|
||||
const mockDeactivateUser = adminDeactivateUser as jest.MockedFunction<typeof adminDeactivateUser>;
|
||||
const mockDeactivateUser = adminDeactivateUser as jest.MockedFunction<
|
||||
typeof adminDeactivateUser
|
||||
>;
|
||||
mockDeactivateUser.mockResolvedValue({ data: { success: true } } as any);
|
||||
|
||||
const { result } = renderHook(() => useDeactivateUser(), { wrapper });
|
||||
@@ -634,7 +648,9 @@ describe('useAdmin hooks', () => {
|
||||
});
|
||||
|
||||
it('handles deactivate error', async () => {
|
||||
const mockDeactivateUser = adminDeactivateUser as jest.MockedFunction<typeof adminDeactivateUser>;
|
||||
const mockDeactivateUser = adminDeactivateUser as jest.MockedFunction<
|
||||
typeof adminDeactivateUser
|
||||
>;
|
||||
mockDeactivateUser.mockResolvedValue({ error: 'Deactivate failed' } as any);
|
||||
|
||||
const { result } = renderHook(() => useDeactivateUser(), { wrapper });
|
||||
|
||||
@@ -6,11 +6,7 @@
|
||||
|
||||
import { renderHook } from '@testing-library/react';
|
||||
import { QueryClient, QueryClientProvider } from '@tanstack/react-query';
|
||||
import {
|
||||
useIsAuthenticated,
|
||||
useCurrentUser,
|
||||
useIsAdmin,
|
||||
} from '@/lib/api/hooks/useAuth';
|
||||
import { useIsAuthenticated, useCurrentUser, useIsAdmin } from '@/lib/api/hooks/useAuth';
|
||||
import { AuthProvider } from '@/lib/auth/AuthContext';
|
||||
|
||||
// Mock auth state (Context-injected)
|
||||
@@ -52,9 +48,7 @@ const createWrapper = () => {
|
||||
|
||||
return ({ children }: { children: React.ReactNode }) => (
|
||||
<QueryClientProvider client={queryClient}>
|
||||
<AuthProvider store={mockStoreHook}>
|
||||
{children}
|
||||
</AuthProvider>
|
||||
<AuthProvider store={mockStoreHook}>{children}</AuthProvider>
|
||||
</QueryClientProvider>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -59,9 +59,7 @@ describe('useSession hooks', () => {
|
||||
});
|
||||
|
||||
const wrapper = ({ children }: { children: React.ReactNode }) => (
|
||||
<QueryClientProvider client={queryClient}>
|
||||
{children}
|
||||
</QueryClientProvider>
|
||||
<QueryClientProvider client={queryClient}>{children}</QueryClientProvider>
|
||||
);
|
||||
|
||||
describe('useListSessions', () => {
|
||||
|
||||
@@ -33,9 +33,7 @@ describe('useUser hooks', () => {
|
||||
|
||||
const wrapper = ({ children }: { children: React.ReactNode }) => (
|
||||
<QueryClientProvider client={queryClient}>
|
||||
<AuthProvider>
|
||||
{children}
|
||||
</AuthProvider>
|
||||
<AuthProvider>{children}</AuthProvider>
|
||||
</QueryClientProvider>
|
||||
);
|
||||
|
||||
|
||||
@@ -130,7 +130,9 @@ describe('Storage Module', () => {
|
||||
};
|
||||
|
||||
// When setItem throws, isLocalStorageAvailable() returns false
|
||||
await expect(saveTokens(tokens)).rejects.toThrow('localStorage not available - cannot save tokens');
|
||||
await expect(saveTokens(tokens)).rejects.toThrow(
|
||||
'localStorage not available - cannot save tokens'
|
||||
);
|
||||
|
||||
Storage.prototype.setItem = originalSetItem;
|
||||
});
|
||||
@@ -171,7 +173,6 @@ describe('Storage Module', () => {
|
||||
|
||||
localStorage.removeItem = originalRemoveItem;
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
describe('Storage method handling', () => {
|
||||
|
||||
@@ -51,11 +51,7 @@ describe('Auth Store', () => {
|
||||
const invalidUser = createMockUser({ id: '' });
|
||||
|
||||
await expect(
|
||||
useAuthStore.getState().setAuth(
|
||||
invalidUser,
|
||||
'valid.access.token',
|
||||
'valid.refresh.token'
|
||||
)
|
||||
useAuthStore.getState().setAuth(invalidUser, 'valid.access.token', 'valid.refresh.token')
|
||||
).rejects.toThrow('Invalid user object');
|
||||
});
|
||||
|
||||
@@ -63,11 +59,7 @@ describe('Auth Store', () => {
|
||||
const invalidUser = createMockUser({ id: ' ' });
|
||||
|
||||
await expect(
|
||||
useAuthStore.getState().setAuth(
|
||||
invalidUser,
|
||||
'valid.access.token',
|
||||
'valid.refresh.token'
|
||||
)
|
||||
useAuthStore.getState().setAuth(invalidUser, 'valid.access.token', 'valid.refresh.token')
|
||||
).rejects.toThrow('Invalid user object');
|
||||
});
|
||||
|
||||
@@ -75,11 +67,7 @@ describe('Auth Store', () => {
|
||||
const invalidUser = createMockUser({ email: '' });
|
||||
|
||||
await expect(
|
||||
useAuthStore.getState().setAuth(
|
||||
invalidUser,
|
||||
'valid.access.token',
|
||||
'valid.refresh.token'
|
||||
)
|
||||
useAuthStore.getState().setAuth(invalidUser, 'valid.access.token', 'valid.refresh.token')
|
||||
).rejects.toThrow('Invalid user object');
|
||||
});
|
||||
|
||||
@@ -101,11 +89,9 @@ describe('Auth Store', () => {
|
||||
(storage.saveTokens as jest.Mock).mockResolvedValue(undefined);
|
||||
|
||||
await expect(
|
||||
useAuthStore.getState().setAuth(
|
||||
validUser,
|
||||
'header.payload.signature',
|
||||
'header.payload.signature'
|
||||
)
|
||||
useAuthStore
|
||||
.getState()
|
||||
.setAuth(validUser, 'header.payload.signature', 'header.payload.signature')
|
||||
).resolves.not.toThrow();
|
||||
|
||||
const state = useAuthStore.getState();
|
||||
@@ -145,11 +131,9 @@ describe('Auth Store', () => {
|
||||
(storage.saveTokens as jest.Mock).mockResolvedValue(undefined);
|
||||
|
||||
await expect(
|
||||
useAuthStore.getState().setAuth(
|
||||
validUser,
|
||||
'header.payload.signature',
|
||||
'header.payload.signature'
|
||||
)
|
||||
useAuthStore
|
||||
.getState()
|
||||
.setAuth(validUser, 'header.payload.signature', 'header.payload.signature')
|
||||
).resolves.not.toThrow();
|
||||
});
|
||||
});
|
||||
@@ -264,11 +248,9 @@ describe('Auth Store', () => {
|
||||
// First set auth
|
||||
const validUser = createMockUser();
|
||||
|
||||
await useAuthStore.getState().setAuth(
|
||||
validUser,
|
||||
'header.payload.signature',
|
||||
'header.payload.signature'
|
||||
);
|
||||
await useAuthStore
|
||||
.getState()
|
||||
.setAuth(validUser, 'header.payload.signature', 'header.payload.signature');
|
||||
|
||||
expect(useAuthStore.getState().isAuthenticated).toBe(true);
|
||||
|
||||
@@ -298,20 +280,14 @@ describe('Auth Store', () => {
|
||||
describe('setTokens', () => {
|
||||
it('should update tokens while preserving user state', async () => {
|
||||
// First set initial auth with user
|
||||
await useAuthStore.getState().setAuth(
|
||||
createMockUser({ id: 'user-1' }),
|
||||
'old.access.token',
|
||||
'old.refresh.token'
|
||||
);
|
||||
await useAuthStore
|
||||
.getState()
|
||||
.setAuth(createMockUser({ id: 'user-1' }), 'old.access.token', 'old.refresh.token');
|
||||
|
||||
const oldUser = useAuthStore.getState().user;
|
||||
|
||||
// Now update just the tokens
|
||||
await useAuthStore.getState().setTokens(
|
||||
'new.access.token',
|
||||
'new.refresh.token',
|
||||
900
|
||||
);
|
||||
await useAuthStore.getState().setTokens('new.access.token', 'new.refresh.token', 900);
|
||||
|
||||
const state = useAuthStore.getState();
|
||||
expect(state.accessToken).toBe('new.access.token');
|
||||
@@ -344,16 +320,18 @@ describe('Auth Store', () => {
|
||||
describe('setUser', () => {
|
||||
it('should update user while preserving auth state', async () => {
|
||||
// First set initial auth
|
||||
await useAuthStore.getState().setAuth(
|
||||
createMockUser({ id: 'user-1' }),
|
||||
'valid.access.token',
|
||||
'valid.refresh.token'
|
||||
);
|
||||
await useAuthStore
|
||||
.getState()
|
||||
.setAuth(createMockUser({ id: 'user-1' }), 'valid.access.token', 'valid.refresh.token');
|
||||
|
||||
const oldToken = useAuthStore.getState().accessToken;
|
||||
|
||||
// Update just the user
|
||||
const newUser = createMockUser({ id: 'user-1', email: 'updated@example.com', is_superuser: true });
|
||||
const newUser = createMockUser({
|
||||
id: 'user-1',
|
||||
email: 'updated@example.com',
|
||||
is_superuser: true,
|
||||
});
|
||||
useAuthStore.getState().setUser(newUser);
|
||||
|
||||
const state = useAuthStore.getState();
|
||||
@@ -478,18 +456,11 @@ describe('Auth Store', () => {
|
||||
const consoleErrorSpy = jest.spyOn(console, 'error').mockImplementation();
|
||||
|
||||
await expect(
|
||||
useAuthStore.getState().setAuth(
|
||||
mockUser,
|
||||
'valid.access.token',
|
||||
'valid.refresh.token'
|
||||
)
|
||||
useAuthStore.getState().setAuth(mockUser, 'valid.access.token', 'valid.refresh.token')
|
||||
).rejects.toThrow('Storage error');
|
||||
|
||||
// Verify error was logged before throwing
|
||||
expect(consoleErrorSpy).toHaveBeenCalledWith(
|
||||
'Failed to save auth state:',
|
||||
expect.any(Error)
|
||||
);
|
||||
expect(consoleErrorSpy).toHaveBeenCalledWith('Failed to save auth state:', expect.any(Error));
|
||||
|
||||
consoleErrorSpy.mockRestore();
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user