import { test, expect } from '@playwright/test' test.describe('Admin - User Management (/admin/rbac)', () => { test('renders admin tabs and user table', async ({ page }) => { await page.goto('/admin/rbac') // Admin navigation tabs await expect(page.getByRole('tab', { name: 'User Management' })).toBeVisible() await expect(page.getByRole('tab', { name: 'Audit Log' })).toBeVisible() await expect(page.getByRole('tab', { name: 'OIDC' })).toBeVisible() // User Management sub-tabs await expect(page.getByRole('tab', { name: 'Users' })).toBeVisible() await expect(page.getByRole('tab', { name: 'Groups' })).toBeVisible() await expect(page.getByRole('tab', { name: 'Roles' })).toBeVisible() // TopBar breadcrumb await expect(page.getByLabel('Breadcrumb').getByText('User Management')).toBeVisible() }) test('switching between Users, Groups, and Roles tabs', async ({ page }) => { await page.goto('/admin/rbac') // Default tab is Users await expect(page.getByRole('tab', { name: 'Users' })).toBeVisible() // Switch to Groups tab await page.getByRole('tab', { name: 'Groups' }).click() await page.waitForTimeout(300) // Switch to Roles tab await page.getByRole('tab', { name: 'Roles' }).click() await page.waitForTimeout(300) // Switch back to Users await page.getByRole('tab', { name: 'Users' }).click() }) test('navigating between admin sections via tabs', async ({ page }) => { await page.goto('/admin/rbac') // Click Audit Log tab await page.getByRole('tab', { name: 'Audit Log' }).click() await expect(page).toHaveURL(/\/admin\/audit/) // Click OIDC tab await page.getByRole('tab', { name: 'OIDC' }).click() await expect(page).toHaveURL(/\/admin\/oidc/) // Back to User Management await page.getByRole('tab', { name: 'User Management' }).click() await expect(page).toHaveURL(/\/admin\/rbac/) }) }) test.describe('Admin - Audit Log (/admin/audit)', () => { test('renders audit table with filters', async ({ page }) => { await page.goto('/admin/audit') // Table headers await expect(page.getByRole('columnheader', { name: 'Timestamp' })).toBeVisible() await expect(page.getByRole('columnheader', { name: 'User' })).toBeVisible() await expect(page.getByRole('columnheader', { name: 'Category' })).toBeVisible() await expect(page.getByRole('columnheader', { name: 'Action' })).toBeVisible() await expect(page.getByRole('columnheader', { name: 'Result' })).toBeVisible() // Table has data const rows = page.locator('table tbody tr') expect(await rows.count()).toBeGreaterThan(0) // Filter inputs exist await expect(page.getByPlaceholder('Filter by user...')).toBeVisible() await expect(page.getByPlaceholder('Search action or target...')).toBeVisible() }) test('filtering audit events by search', async ({ page }) => { await page.goto('/admin/audit') const searchInput = page.getByPlaceholder('Search action or target...') await searchInput.fill('deploy') // Table should update await page.waitForTimeout(300) const rows = page.locator('table tbody tr') const count = await rows.count() expect(count).toBeGreaterThanOrEqual(0) }) }) test.describe('Admin - OIDC Config (/admin/oidc)', () => { test('renders OIDC form with all fields', async ({ page }) => { await page.goto('/admin/oidc') // Section headers await expect(page.getByText('Behavior')).toBeVisible() await expect(page.getByText('Provider Settings')).toBeVisible() await expect(page.getByText('Claim Mapping')).toBeVisible() await expect(page.getByText('Default Roles')).toBeVisible() await expect(page.getByText('Danger Zone')).toBeVisible() // Form fields by id await expect(page.locator('#issuer')).toBeVisible() await expect(page.locator('#client-id')).toBeVisible() await expect(page.locator('#client-secret')).toBeVisible() await expect(page.locator('#roles-claim')).toBeVisible() await expect(page.locator('#name-claim')).toBeVisible() // Buttons await expect(page.getByRole('button', { name: 'Test Connection' })).toBeVisible() await expect(page.getByRole('button', { name: 'Save' })).toBeVisible() await expect(page.getByRole('button', { name: /Delete OIDC/i })).toBeVisible() // Default roles tags await expect(page.getByText('USER').first()).toBeVisible() await expect(page.getByText('VIEWER').first()).toBeVisible() }) test('toggling Enabled switch', async ({ page }) => { await page.goto('/admin/oidc') // The Toggle's checkbox is visually hidden — click the label wrapper instead const enabledLabel = page.locator('label').filter({ hasText: 'Enabled' }) await enabledLabel.click() // Should not crash; label still visible await expect(enabledLabel).toBeVisible() }) test('adding and removing a role tag', async ({ page }) => { await page.goto('/admin/oidc') // Add a new role const roleInput = page.getByPlaceholder('Add role...') await roleInput.fill('EDITOR') // Use the Add button next to the input (scoped to same row) await roleInput.press('Enter') // New role tag should appear await expect(page.getByText('EDITOR')).toBeVisible() // Remove it via aria-label on the tag's remove button await page.getByRole('button', { name: 'Remove EDITOR' }).click() // EDITOR tag should be gone await expect(page.getByText('EDITOR')).not.toBeVisible() }) test('Save button shows success toast', async ({ page }) => { await page.goto('/admin/oidc') await page.getByRole('button', { name: 'Save' }).click() // Toast notification await expect(page.getByText('Settings saved')).toBeVisible() }) test('Delete button shows confirmation dialog', async ({ page }) => { await page.goto('/admin/oidc') await page.getByRole('button', { name: /Delete OIDC/i }).click() // Confirmation dialog should appear await expect(page.getByText('Delete OIDC configuration?')).toBeVisible() }) })