fix(tests): resolve last OIDC test issues
This commit is contained in:
parent
12cdd0ffd6
commit
0b6d96df03
|
|
@ -1,5 +1,5 @@
|
||||||
import { render, screen, waitFor } from '@testing-library/react';
|
import { render, screen, waitFor, fireEvent } from '@testing-library/react';
|
||||||
import { BrowserRouter } from 'react-router-dom';
|
import { MemoryRouter, Route, Routes } from 'react-router-dom';
|
||||||
import { vi } from 'vitest';
|
import { vi } from 'vitest';
|
||||||
import OidcCallback from '../OidcCallback';
|
import OidcCallback from '../OidcCallback';
|
||||||
import { AuthProvider } from '../../../contexts/AuthContext';
|
import { AuthProvider } from '../../../contexts/AuthContext';
|
||||||
|
|
@ -17,16 +17,14 @@ vi.mock('../../../services/api', () => ({
|
||||||
}
|
}
|
||||||
}));
|
}));
|
||||||
|
|
||||||
// Mock useNavigate and useSearchParams
|
// Mock useNavigate
|
||||||
const mockNavigate = vi.fn();
|
const mockNavigate = vi.fn();
|
||||||
const mockUseSearchParams = vi.fn(() => [new URLSearchParams('code=test-code&state=test-state')]);
|
|
||||||
|
|
||||||
vi.mock('react-router-dom', async () => {
|
vi.mock('react-router-dom', async () => {
|
||||||
const actual = await vi.importActual('react-router-dom');
|
const actual = await vi.importActual('react-router-dom');
|
||||||
return {
|
return {
|
||||||
...actual,
|
...actual,
|
||||||
useNavigate: () => mockNavigate,
|
useNavigate: () => mockNavigate
|
||||||
useSearchParams: mockUseSearchParams
|
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
@ -66,6 +64,11 @@ const MockAuthProvider = ({ children }: { children: React.ReactNode }) => (
|
||||||
describe('OidcCallback', () => {
|
describe('OidcCallback', () => {
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
vi.clearAllMocks();
|
vi.clearAllMocks();
|
||||||
|
window.location.href = '';
|
||||||
|
// Clear API mocks
|
||||||
|
(api.get as any).mockClear();
|
||||||
|
// Reset API mocks to default implementation
|
||||||
|
(api.get as any).mockResolvedValue({ data: { token: 'default-token' } });
|
||||||
|
|
||||||
// Mock window.matchMedia
|
// Mock window.matchMedia
|
||||||
Object.defineProperty(window, 'matchMedia', {
|
Object.defineProperty(window, 'matchMedia', {
|
||||||
|
|
@ -83,18 +86,24 @@ describe('OidcCallback', () => {
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
const renderOidcCallback = () => {
|
const renderOidcCallback = (search = '') => {
|
||||||
return render(
|
return render(
|
||||||
<BrowserRouter>
|
<MemoryRouter initialEntries={[`/auth/oidc/callback${search}`]}>
|
||||||
<MockAuthProvider>
|
<MockAuthProvider>
|
||||||
<OidcCallback />
|
<Routes>
|
||||||
|
<Route path="/auth/oidc/callback" element={<OidcCallback />} />
|
||||||
|
<Route path="/login" element={<div>Login Page</div>} />
|
||||||
|
</Routes>
|
||||||
</MockAuthProvider>
|
</MockAuthProvider>
|
||||||
</BrowserRouter>
|
</MemoryRouter>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
it('shows loading state initially', () => {
|
it('shows loading state initially', async () => {
|
||||||
renderOidcCallback();
|
// Mock the API call to delay so we can see the loading state
|
||||||
|
(api.get as any).mockImplementation(() => new Promise(() => {})); // Never resolves
|
||||||
|
|
||||||
|
renderOidcCallback('?code=test-code&state=test-state');
|
||||||
|
|
||||||
expect(screen.getByText('Completing Authentication')).toBeInTheDocument();
|
expect(screen.getByText('Completing Authentication')).toBeInTheDocument();
|
||||||
expect(screen.getByText('Please wait while we process your authentication...')).toBeInTheDocument();
|
expect(screen.getByText('Please wait while we process your authentication...')).toBeInTheDocument();
|
||||||
|
|
@ -114,7 +123,7 @@ describe('OidcCallback', () => {
|
||||||
|
|
||||||
(api.get as any).mockResolvedValueOnce(mockResponse);
|
(api.get as any).mockResolvedValueOnce(mockResponse);
|
||||||
|
|
||||||
renderOidcCallback();
|
renderOidcCallback('?code=test-code&state=test-state');
|
||||||
|
|
||||||
await waitFor(() => {
|
await waitFor(() => {
|
||||||
expect(api.get).toHaveBeenCalledWith('/auth/oidc/callback?code=test-code&state=test-state');
|
expect(api.get).toHaveBeenCalledWith('/auth/oidc/callback?code=test-code&state=test-state');
|
||||||
|
|
@ -125,39 +134,30 @@ describe('OidcCallback', () => {
|
||||||
});
|
});
|
||||||
|
|
||||||
it('handles authentication error from URL params', () => {
|
it('handles authentication error from URL params', () => {
|
||||||
// Mock useSearchParams to return error
|
renderOidcCallback('?error=access_denied&error_description=User+denied+access');
|
||||||
mockUseSearchParams.mockReturnValueOnce([
|
|
||||||
new URLSearchParams('error=access_denied&error_description=User+denied+access')
|
|
||||||
]);
|
|
||||||
|
|
||||||
renderOidcCallback();
|
|
||||||
|
|
||||||
expect(screen.getByText('Authentication Error')).toBeInTheDocument();
|
expect(screen.getByText('Authentication Error')).toBeInTheDocument();
|
||||||
expect(screen.getByText('Authentication failed: access_denied')).toBeInTheDocument();
|
expect(screen.getByText('Authentication failed: access_denied')).toBeInTheDocument();
|
||||||
});
|
});
|
||||||
|
|
||||||
it('handles missing authorization code', () => {
|
it('handles missing authorization code', () => {
|
||||||
// Mock useSearchParams to return no code
|
renderOidcCallback('');
|
||||||
mockUseSearchParams.mockReturnValueOnce([
|
|
||||||
new URLSearchParams('')
|
|
||||||
]);
|
|
||||||
|
|
||||||
renderOidcCallback();
|
|
||||||
|
|
||||||
expect(screen.getByText('Authentication Error')).toBeInTheDocument();
|
expect(screen.getByText('Authentication Error')).toBeInTheDocument();
|
||||||
expect(screen.getByText('No authorization code received')).toBeInTheDocument();
|
expect(screen.getByText('No authorization code received')).toBeInTheDocument();
|
||||||
});
|
});
|
||||||
|
|
||||||
it('handles API error during callback', async () => {
|
it('handles API error during callback', async () => {
|
||||||
(api.get as any).mockRejectedValueOnce({
|
const error = {
|
||||||
response: {
|
response: {
|
||||||
data: {
|
data: {
|
||||||
error: 'Invalid authorization code'
|
error: 'Invalid authorization code'
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
};
|
||||||
|
(api.get as any).mockRejectedValueOnce(error);
|
||||||
|
|
||||||
renderOidcCallback();
|
renderOidcCallback('?code=test-code&state=test-state');
|
||||||
|
|
||||||
await waitFor(() => {
|
await waitFor(() => {
|
||||||
expect(screen.getByText('Authentication Error')).toBeInTheDocument();
|
expect(screen.getByText('Authentication Error')).toBeInTheDocument();
|
||||||
|
|
@ -173,7 +173,7 @@ describe('OidcCallback', () => {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
renderOidcCallback();
|
renderOidcCallback('?code=test-code&state=test-state');
|
||||||
|
|
||||||
await waitFor(() => {
|
await waitFor(() => {
|
||||||
expect(screen.getByText('Authentication Error')).toBeInTheDocument();
|
expect(screen.getByText('Authentication Error')).toBeInTheDocument();
|
||||||
|
|
@ -184,14 +184,19 @@ describe('OidcCallback', () => {
|
||||||
it('provides return to login button on error', async () => {
|
it('provides return to login button on error', async () => {
|
||||||
(api.get as any).mockRejectedValueOnce(new Error('Network error'));
|
(api.get as any).mockRejectedValueOnce(new Error('Network error'));
|
||||||
|
|
||||||
renderOidcCallback();
|
renderOidcCallback('?code=test-code&state=test-state');
|
||||||
|
|
||||||
await waitFor(() => {
|
await waitFor(() => {
|
||||||
expect(screen.getByText('Return to Login')).toBeInTheDocument();
|
expect(screen.getByText('Return to Login')).toBeInTheDocument();
|
||||||
});
|
});
|
||||||
|
|
||||||
// Test clicking return to login
|
// Test clicking return to login
|
||||||
screen.getByText('Return to Login').click();
|
const returnButton = screen.getByText('Return to Login');
|
||||||
expect(mockNavigate).toHaveBeenCalledWith('/login');
|
fireEvent.click(returnButton);
|
||||||
|
|
||||||
|
// Check if navigation to login page occurred by looking for login page content
|
||||||
|
await waitFor(() => {
|
||||||
|
expect(screen.getByText('Login Page')).toBeInTheDocument();
|
||||||
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
@ -325,7 +325,7 @@ mod tests {
|
||||||
create_user,
|
create_user,
|
||||||
&test_subject,
|
&test_subject,
|
||||||
"https://provider.example.com",
|
"https://provider.example.com",
|
||||||
"oidc@example.com",
|
&test_email,
|
||||||
).await.unwrap();
|
).await.unwrap();
|
||||||
|
|
||||||
assert_eq!(user.username, test_username);
|
assert_eq!(user.username, test_username);
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue