import { cleanup, render, screen, within } from '@testing-library/react'; import userEvent from '@testing-library/user-event'; import { afterEach, expect, it, vi } from 'vitest'; import Admin from './Admin'; afterEach(() => { cleanup(); vi.unstubAllGlobals(); }); it('signs in with a password, creates an owned agent key and changes the password', async () => { const fetchMock = vi.fn(async (path: string, init?: RequestInit) => { if (path === '/v1/session' && init?.method === 'GET') return { ok: false, status: 401, json: async () => ({}) }; let result: unknown = []; if (path === '/v1/users/session') result = { csrf_token: 'user-csrf' }; if (path === '/v1/projects') result = ['pilot']; if (path === '/v1/me/agent-credentials' && init?.method === 'POST') result = { credential_id: 'agent:codex:fixture', token: 'agent-fixture-secret' }; if (path === '/v1/me/password') result = { status: 'password_changed' }; return { ok: true, json: async () => result }; }); vi.stubGlobal('fetch', fetchMock); const user = userEvent.setup(); render(); await user.type(await screen.findByLabelText('Username'), 'alice'); await user.type(screen.getByLabelText('Password'), 'initial-password-fixture'); await user.click(screen.getByRole('button', { name: 'Sign in' })); await screen.findByRole('heading', { name: 'Add an agent' }); expect(fetchMock).toHaveBeenCalledWith('/v1/users/session', expect.objectContaining({ method: 'POST', credentials: 'same-origin', body: JSON.stringify({ username: 'alice', password: 'initial-password-fixture' }), })); expect(screen.queryByRole('heading', { name: 'User accounts' })).toBeNull(); await user.type(screen.getByLabelText('Agent name'), 'codex-laptop'); await user.click(screen.getByLabelText('pilot')); await user.click(screen.getByRole('button', { name: 'Create agent key' })); expect(await screen.findByLabelText('New bearer credential')).toHaveValue('agent-fixture-secret'); expect(fetchMock).toHaveBeenCalledWith('/v1/me/agent-credentials', expect.objectContaining({ headers: expect.objectContaining({ 'X-GEWU-CSRF': 'user-csrf' }), body: JSON.stringify({ name: 'codex-laptop', project_ids: ['pilot'] }), })); await user.type(screen.getByLabelText('Current password'), 'initial-password-fixture'); await user.type(screen.getByLabelText('New password'), 'changed-password-fixture'); await user.type(screen.getByLabelText('Confirm new password'), 'changed-password-fixture'); await user.click(screen.getByRole('button', { name: 'Change password' })); expect(await screen.findByLabelText('Username')).toBeVisible(); expect(screen.queryByLabelText('New bearer credential')).toBeNull(); expect(screen.getByRole('status')).toHaveTextContent('Password changed.'); }); it('lets the existing administrator create the first password account', async () => { const fetchMock = vi.fn(async (path: string, init?: RequestInit) => { if (path === '/v1/session' && init?.method === 'GET') return { ok: false, status: 401, json: async () => ({}) }; const result = path === '/v1/session' ? { csrf_token: 'operator-csrf' } : []; return { ok: true, json: async () => result }; }); vi.stubGlobal('fetch', fetchMock); const user = userEvent.setup(); render(); await user.click(await screen.findByRole('button', { name: 'Use an existing credential' })); await user.type(screen.getByLabelText('GEWU administrator credential'), 'operator-fixture'); await user.click(screen.getByRole('button', { name: 'Connect' })); await user.click(await screen.findByRole('tab', { name: 'Users' })); const accounts = await screen.findByRole('region', { name: 'User accounts' }); await user.type(within(accounts).getByLabelText('New username'), 'vasily'); await user.type(within(accounts).getByLabelText('Initial password'), 'chosen-password-fixture'); await user.selectOptions(within(accounts).getByLabelText('Account role'), 'admin'); await user.click(within(accounts).getByRole('button', { name: 'Create user' })); await screen.findByText(/Account created for vasily/); expect(fetchMock).toHaveBeenCalledWith('/v1/admin/users', expect.objectContaining({ body: JSON.stringify({ username: 'vasily', password: 'chosen-password-fixture', role: 'admin', project_ids: [] }), })); expect(within(accounts).getByLabelText('Initial password')).toHaveValue(''); });