| import { describe, it, expect, vi, beforeEach } from 'vitest' |
| import { render, screen, fireEvent, waitFor, within } from '@testing-library/react' |
| import { I18nProvider } from '../i18n' |
| import { D2OperatorPage } from './D2OperatorPage' |
| import * as api from '../api/identity' |
|
|
| vi.mock('../api/identity') |
|
|
| const operatorAccount = { |
| id: 'op1', public_handle: 'op', display_alias: 'Op', role: 'operator', |
| status: 'active', preferred_language: 'en', |
| } |
|
|
| const renderPage = (onNav = () => {}) => |
| render(<I18nProvider initial="en"><D2OperatorPage onNav={onNav} /></I18nProvider>) |
|
|
| function asOperator() { |
| vi.mocked(api.getD2Account).mockReturnValue(operatorAccount) |
| vi.mocked(api.getD2Csrf).mockReturnValue('csrf') |
| vi.mocked(api.onD2Change).mockReturnValue(() => {}) |
| vi.mocked(api.listInvitations).mockResolvedValue([]) |
| vi.mocked(api.listOperatorAccounts).mockResolvedValue([]) |
| } |
|
|
| describe('D2OperatorPage', () => { |
| beforeEach(() => vi.resetAllMocks()) |
|
|
| it('blocks non-operators', () => { |
| vi.mocked(api.getD2Account).mockReturnValue({ ...operatorAccount, role: 'customer' }) |
| vi.mocked(api.onD2Change).mockReturnValue(() => {}) |
| renderPage() |
| expect(screen.getByText('This area is for operators only.')).toBeInTheDocument() |
| }) |
|
|
| it('creates invitations and warns the codes are shown once', async () => { |
| asOperator() |
| vi.mocked(api.createInvitations).mockResolvedValue([{ id: 'i1', code: 'ABCD-1234' }]) |
| renderPage() |
| fireEvent.click(await screen.findByRole('button', { name: 'Create' })) |
| expect(await screen.findByText('ABCD-1234')).toBeInTheDocument() |
| expect(screen.getByText(/shown only once/)).toBeInTheDocument() |
| }) |
|
|
| it('confirms a destructive account action', async () => { |
| asOperator() |
| vi.mocked(api.listOperatorAccounts).mockResolvedValue([{ |
| id: 'a1', public_handle: 'ali', display_alias: 'Ali', role: 'customer', status: 'active', |
| preferred_language: 'en', passkey_count: 2, active_session_count: 1, created_at: '2026-01-01', |
| }]) |
| vi.mocked(api.getOperatorAccount).mockResolvedValue({ |
| account: { |
| id: 'a1', public_handle: 'ali', display_alias: 'Ali', role: 'customer', status: 'active', |
| preferred_language: 'en', passkey_count: 2, active_session_count: 1, created_at: '2026-01-01', |
| }, |
| events: [], |
| }) |
| vi.mocked(api.operatorDeleteAccount).mockResolvedValue() |
| renderPage() |
| fireEvent.click(screen.getByRole('tab', { name: 'Accounts' })) |
| fireEvent.click(await screen.findByRole('button', { name: 'View' })) |
| fireEvent.click(await screen.findByRole('button', { name: 'Delete' })) |
| const dialog = await screen.findByRole('alertdialog') |
| fireEvent.click(within(dialog).getByRole('button', { name: 'Delete' })) |
| await waitFor(() => expect(api.operatorDeleteAccount).toHaveBeenCalledWith('a1')) |
| }) |
| }) |
|
|