import { describe, it, expect, vi, beforeEach } from 'vitest';
import { render, screen, fireEvent, waitFor, cleanup } from '@testing-library/react';
import OIDCTestConnectionPanel from './OIDCTestConnectionPanel';
// Audit 2026-05-11 Fix 09 — OIDCTestConnectionPanel regression coverage.
// Mocks authOIDCTestProvider so the test is hermetic (no real network).
// Pins: button-disabled-without-issuer, happy-path renders all checks
// green, failure-path renders the errors list, iss_param_supported=false
// renders the informational `·` glyph rather than ✗ (since RFC 9207 is
// SHOULD, not MUST).
vi.mock('../../api/client', () => ({
authOIDCTestProvider: vi.fn(),
}));
import * as client from '../../api/client';
beforeEach(() => {
vi.clearAllMocks();
cleanup();
});
describe('OIDCTestConnectionPanel', () => {
it('RunButton — disabled until issuer URL is non-empty', () => {
render();
const btn = screen.getByTestId('oidc-test-connection-run-default') as HTMLButtonElement;
expect(btn.disabled).toBe(true);
});
it('RunButton — enabled when issuer URL is non-empty', () => {
render(
,
);
const btn = screen.getByTestId('oidc-test-connection-run-default') as HTMLButtonElement;
expect(btn.disabled).toBe(false);
});
it('RunButton — also disabled when issuer URL is whitespace-only', () => {
render();
const btn = screen.getByTestId('oidc-test-connection-run-default') as HTMLButtonElement;
expect(btn.disabled).toBe(true);
});
it('HappyPath — renders all four primary checks green when discovery succeeds', async () => {
vi.mocked(client.authOIDCTestProvider).mockResolvedValue({
discovery_succeeded: true,
jwks_reachable: true,
supported_alg_values: ['RS256', 'ES256'],
iss_param_supported: true,
issuer_echo: 'https://idp.example.com',
authorization_url: 'https://idp.example.com/authorize',
token_url: 'https://idp.example.com/token',
jwks_uri: 'https://idp.example.com/jwks',
userinfo_endpoint: 'https://idp.example.com/userinfo',
errors: [],
});
render(
,
);
fireEvent.click(screen.getByTestId('oidc-test-connection-run-default'));
await waitFor(() => screen.getByTestId('oidc-test-connection-result-default'));
// All four primary checks visible + green.
expect(screen.getByTestId('oidc-test-connection-check-discovery-default').textContent)
.toContain('✓');
expect(screen.getByTestId('oidc-test-connection-check-jwks-default').textContent)
.toContain('✓');
expect(screen.getByTestId('oidc-test-connection-check-algs-default').textContent)
.toContain('✓');
// iss_param SUPPORTED → ✓, not `·`.
expect(screen.getByTestId('oidc-test-connection-check-iss-param-default').textContent)
.toContain('✓');
// Detail rows present.
expect(screen.getByTestId('oidc-test-connection-detail-authz-url-default')).toBeTruthy();
expect(screen.getByTestId('oidc-test-connection-detail-token-url-default')).toBeTruthy();
expect(screen.getByTestId('oidc-test-connection-detail-userinfo-url-default')).toBeTruthy();
// No errors block on happy path.
expect(screen.queryByTestId('oidc-test-connection-errors-list-default')).toBeNull();
// The mocked POST received the staged input.
expect(client.authOIDCTestProvider).toHaveBeenCalledTimes(1);
expect(client.authOIDCTestProvider).toHaveBeenCalledWith({
issuer_url: 'https://idp.example.com',
client_id: 'certctl',
scopes: ['openid', 'profile', 'email'],
});
});
it('FailurePath — renders the errors list when discovery_succeeded is false', async () => {
vi.mocked(client.authOIDCTestProvider).mockResolvedValue({
discovery_succeeded: false,
jwks_reachable: false,
supported_alg_values: [],
iss_param_supported: false,
errors: ['discovery fetch failed: connection refused', 'jwks_uri not advertised'],
});
render(
,
);
fireEvent.click(screen.getByTestId('oidc-test-connection-run-default'));
await waitFor(() => screen.getByTestId('oidc-test-connection-result-default'));
// Discovery + JWKS marked ✗.
expect(screen.getByTestId('oidc-test-connection-check-discovery-default').textContent)
.toContain('✗');
expect(screen.getByTestId('oidc-test-connection-check-jwks-default').textContent)
.toContain('✗');
// Empty alg list → ⚠ warning, not ✗ (the IdP responded but advertised nothing).
expect(screen.getByTestId('oidc-test-connection-check-algs-default').textContent)
.toContain('⚠');
// Errors list rendered with both entries.
const errs = screen.getByTestId('oidc-test-connection-errors-list-default');
expect(errs.textContent).toContain('connection refused');
expect(errs.textContent).toContain('jwks_uri not advertised');
});
it('IssParamFalse — renders the informational `·` glyph when iss_param_supported is false', async () => {
vi.mocked(client.authOIDCTestProvider).mockResolvedValue({
discovery_succeeded: true,
jwks_reachable: true,
supported_alg_values: ['RS256'],
iss_param_supported: false,
issuer_echo: 'https://idp.example.com',
jwks_uri: 'https://idp.example.com/jwks',
errors: [],
});
render(
,
);
fireEvent.click(screen.getByTestId('oidc-test-connection-run-default'));
await waitFor(() => screen.getByTestId('oidc-test-connection-result-default'));
const issRow = screen.getByTestId('oidc-test-connection-check-iss-param-default');
expect(issRow.textContent).toContain('·');
// Must NOT be ✗ — RFC 9207 is SHOULD, not MUST; the panel must
// not visually mark this as a failure.
expect(issRow.textContent).not.toContain('✗');
// Body should explain that this is informational.
expect(issRow.textContent).toContain('informational');
});
it('FetchError — renders a top-level error when authOIDCTestProvider throws', async () => {
vi.mocked(client.authOIDCTestProvider).mockRejectedValue(new Error('network down'));
render(
,
);
fireEvent.click(screen.getByTestId('oidc-test-connection-run-default'));
await waitFor(() => screen.getByTestId('oidc-test-connection-error-default'));
expect(screen.getByTestId('oidc-test-connection-error-default').textContent)
.toContain('network down');
// The success result panel must NOT render alongside an error.
expect(screen.queryByTestId('oidc-test-connection-result-default')).toBeNull();
});
it('TestIDSuffix — same component renders twice on a page without colliding test IDs', async () => {
vi.mocked(client.authOIDCTestProvider).mockResolvedValue({
discovery_succeeded: true,
jwks_reachable: true,
supported_alg_values: ['RS256'],
iss_param_supported: false,
});
render(
<>
>,
);
// Both panels visible with distinct test IDs — no DOM-id collisions.
expect(screen.getByTestId('oidc-test-connection-panel-create')).toBeTruthy();
expect(screen.getByTestId('oidc-test-connection-panel-edit')).toBeTruthy();
expect(screen.getByTestId('oidc-test-connection-run-create')).toBeTruthy();
expect(screen.getByTestId('oidc-test-connection-run-edit')).toBeTruthy();
});
});