Revoking the admin role.
}); + + const dialog = screen.getByRole('dialog'); + const describedBy = dialog.getAttribute('aria-describedby'); + expect(describedBy).not.toBeNull(); + expect(document.getElementById(describedBy ?? '')).toHaveTextContent( + 'Revoking the admin role.', + ); + }); + + it('renders extra children inside the dialog', () => { + renderDialog({ children:Amount: 1,000 BCC
}); + + expect(screen.getByTestId('extra')).toBeInTheDocument(); + }); + + it('renders nothing but the controls when there is no body at all', () => { + renderDialog({ description: undefined }); + + const dialog = screen.getByRole('dialog'); + expect(dialog).not.toHaveAttribute('aria-describedby'); + expect(screen.queryByTestId('confirmation-dialog-body')).not.toBeInTheDocument(); + }); + + it('keeps confirm disabled until the checkbox is ticked', () => { + const { onConfirm } = renderDialog({ confirmationMode: 'checkbox' }); + + const confirm = screen.getByTestId('confirmation-dialog-confirm'); + expect(confirm).toBeDisabled(); + + fireEvent.click(confirm); + expect(onConfirm).not.toHaveBeenCalled(); + + const checkbox = screen.getByTestId('confirmation-dialog-checkbox'); + expect(checkbox).not.toBeChecked(); + fireEvent.click(checkbox); + + expect(checkbox).toBeChecked(); + expect(confirm).not.toBeDisabled(); + + fireEvent.click(confirm); + expect(onConfirm).toHaveBeenCalledTimes(1); + }); + + it('re-locks confirm when the checkbox is unticked', () => { + renderDialog({ confirmationMode: 'checkbox' }); + + const checkbox = screen.getByTestId('confirmation-dialog-checkbox'); + fireEvent.click(checkbox); + expect(screen.getByTestId('confirmation-dialog-confirm')).not.toBeDisabled(); + + fireEvent.click(checkbox); + expect(screen.getByTestId('confirmation-dialog-confirm')).toBeDisabled(); + }); + + it('exposes the checkbox as a focusable form control', () => { + const { onConfirm } = renderDialog({ confirmationMode: 'checkbox' }); + + const checkbox = screen.getByTestId('confirmation-dialog-checkbox'); + checkbox.focus(); + expect(document.activeElement).toBe(checkbox); + + fireEvent.click(checkbox); + expect(screen.getByTestId('confirmation-dialog-confirm')).not.toBeDisabled(); + + fireEvent.click(screen.getByTestId('confirmation-dialog-confirm')); + expect(onConfirm).toHaveBeenCalledTimes(1); + }); + + it('is the checkbox mode by default', () => { + renderDialog(); + + expect(screen.getByTestId('confirmation-dialog-checkbox')).toBeInTheDocument(); + expect(screen.queryByTestId('confirmation-dialog-keyword-input')).not.toBeInTheDocument(); + }); + + it('keeps confirm disabled until the keyword is typed', () => { + const { onConfirm } = renderDialog({ + confirmationMode: 'keyword', + confirmationKeyword: 'BURN', + }); + + const input = screen.getByTestId('confirmation-dialog-keyword-input'); + const confirm = screen.getByTestId('confirmation-dialog-confirm'); + expect(confirm).toBeDisabled(); + + fireEvent.change(input, { target: { value: 'burn' } }); + expect(confirm).not.toBeDisabled(); + + fireEvent.click(confirm); + expect(onConfirm).toHaveBeenCalledTimes(1); + }); + + it('does not unlock on a partial or wrong keyword', () => { + renderDialog({ confirmationMode: 'keyword', confirmationKeyword: 'REVOKE' }); + + const input = screen.getByTestId('confirmation-dialog-keyword-input'); + const confirm = screen.getByTestId('confirmation-dialog-confirm'); + + fireEvent.change(input, { target: { value: 'rev' } }); + expect(confirm).toBeDisabled(); + + fireEvent.change(input, { target: { value: 'revoked' } }); + expect(confirm).toBeDisabled(); + + fireEvent.change(input, { target: { value: ' REVOKE ' } }); + expect(confirm).not.toBeDisabled(); + }); + + it('falls back to the default keyword in keyword mode', () => { + renderDialog({ confirmationMode: 'keyword' }); + + expect( + screen.getByText(`Type ${DEFAULT_CONFIRMATION_KEYWORD} to confirm this action.`), + ).toBeInTheDocument(); + + fireEvent.change(screen.getByTestId('confirmation-dialog-keyword-input'), { + target: { value: DEFAULT_CONFIRMATION_KEYWORD }, + }); + expect(screen.getByTestId('confirmation-dialog-confirm')).not.toBeDisabled(); + }); + + it('accepts a custom keyword prompt', () => { + renderDialog({ confirmationMode: 'keyword', keywordLabel: 'Type the token symbol' }); + + expect(screen.getByLabelText('Type the token symbol')).toBe( + screen.getByTestId('confirmation-dialog-keyword-input'), + ); + }); + + it('needs no gate at all in none mode', () => { + const { onConfirm } = renderDialog({ confirmationMode: 'none' }); + + expect(screen.queryByTestId('confirmation-dialog-checkbox')).not.toBeInTheDocument(); + expect(screen.queryByTestId('confirmation-dialog-keyword-input')).not.toBeInTheDocument(); + expect(screen.getByTestId('confirmation-dialog-confirm')).not.toBeDisabled(); + + fireEvent.click(screen.getByTestId('confirmation-dialog-confirm')); + expect(onConfirm).toHaveBeenCalledTimes(1); + }); + + it('uses custom confirm and cancel labels', () => { + const { onClose } = renderDialog({ confirmLabel: 'Burn it', cancelLabel: 'Keep supply' }); + + expect(screen.getByRole('button', { name: 'Burn it' })).toBeInTheDocument(); + + fireEvent.click(screen.getByRole('button', { name: 'Keep supply' })); + expect(onClose).toHaveBeenCalledTimes(1); + }); + + it('uses a custom checkbox label', () => { + renderDialog({ confirmationLabel: 'I accept the loss of supply.' }); + + expect(screen.getByText('I accept the loss of supply.')).toBeInTheDocument(); + }); + + it('locks both buttons and shows the busy label while busy', () => { + renderDialog({ confirmationMode: 'none', busy: true, busyLabel: 'Submitting…' }); + + expect(screen.getByTestId('confirmation-dialog-confirm')).toBeDisabled(); + expect(screen.getByTestId('confirmation-dialog-confirm')).toHaveTextContent('Submitting…'); + expect(screen.getByTestId('confirmation-dialog-cancel')).toBeDisabled(); + }); + + it('does not close on Escape while busy', () => { + const { onClose } = renderDialog({ confirmationMode: 'none', busy: true }); + + fireEvent.keyDown(document, { key: 'Escape' }); + + expect(onClose).not.toHaveBeenCalled(); + }); + + it('closes on Escape when not busy', () => { + const { onClose } = renderDialog(); + + fireEvent.keyDown(document, { key: 'Escape' }); + + expect(onClose).toHaveBeenCalledTimes(1); + }); + + it('does not close on Escape when closeOnEscape is off', () => { + const { onClose } = renderDialog({ closeOnEscape: false }); + + fireEvent.keyDown(document, { key: 'Escape' }); + + expect(onClose).not.toHaveBeenCalled(); + }); + + it('ignores other keys', () => { + const { onClose } = renderDialog(); + + fireEvent.keyDown(document, { key: 'Enter' }); + + expect(onClose).not.toHaveBeenCalled(); + }); + + it('closes on a backdrop click but not on a click inside the panel', () => { + const { onClose } = renderDialog(); + + fireEvent.click(screen.getByTestId('confirmation-dialog-title')); + expect(onClose).not.toHaveBeenCalled(); + + fireEvent.click(screen.getByTestId('confirmation-dialog-backdrop')); + expect(onClose).toHaveBeenCalledTimes(1); + }); + + it('does not close on a backdrop click when closeOnBackdropClick is off', () => { + const { onClose } = renderDialog({ closeOnBackdropClick: false }); + + fireEvent.click(screen.getByTestId('confirmation-dialog-backdrop')); + + expect(onClose).not.toHaveBeenCalled(); + }); + + it('moves focus onto the panel when it opens', () => { + renderDialog(); + + expect(document.activeElement).toBe(screen.getByTestId('confirmation-dialog')); + }); + + it('restores focus to the previously focused element when it closes', async () => { + const trigger = document.createElement('button'); + trigger.type = 'button'; + document.body.appendChild(trigger); + trigger.focus(); + + const { rerender } = render( ++ {description} +
+ ) : null} + {children} +