import * as React from 'react'import { render, screen, fireEvent, waitFor } from '@testing-library/react'import { Form } from 'react-final-form'import { describe, it, expect, vi, beforeEach } from 'vitest'import ApiKeyInput from './ApiKeyInput'const hooks = vi.hoisted(() => ({ notify: vi.fn() }))const KEY = 'nds_0123456789abcdefghijkl'const KEY_FORMAT = /^nds_[0-9A-Za-z]{22}$/vi.mock('react-admin', async () => {const actual = await vi.importActual('react-admin')return {...actual,useNotify: () => hooks.notify,useTranslate: () => (key) => key,}})const renderInput = ({record,initialValues = {},isCreate = false,fullWidth,}) => {let valuesconst utils = render(<FormonSubmit={() => {}}initialValues={initialValues}render={({ values: v }) => {values = vreturn (<ApiKeyInputsource="apiKey"record={record}isCreate={isCreate}fullWidth={fullWidth}/>)}}/>,)return { ...utils, values: () => values }}const text = (key) => screen.queryByText(key)describe('ApiKeyInput', () => {beforeEach(() => {vi.clearAllMocks()localStorage.setItem('userId', 'owner')localStorage.setItem('role', 'regular')})it('shows a pending key with copy and regenerate on create', () => {const { values } = renderInput({record: {},isCreate: true,initialValues: { apiKey: KEY },})expect(screen.getByDisplayValue(KEY)).toBeInTheDocument()expect(text('resources.player.message.apiKeyPending')).toBeInTheDocument()expect(screen.getByRole('button', {name: 'resources.player.actions.copyApiKey',}),).toBeInTheDocument()expect(text('resources.player.actions.revokeApiKey'),).not.toBeInTheDocument()fireEvent.click(screen.getByText('resources.player.actions.regenerateApiKey'),)expect(values().apiKey).toMatch(KEY_FORMAT)expect(values().apiKey).not.toBe(KEY)})it('masks a saved key and lets the owner regenerate or revoke', () => {const { values } = renderInput({record: { id: 'p1', userId: 'owner', hasApiKey: true },})expect(screen.queryByDisplayValue(/^nds_/)).not.toBeInTheDocument()expect(text('resources.player.message.apiKeyActive')).toBeInTheDocument()expect(text('resources.player.actions.regenerateApiKey'),).toBeInTheDocument()fireEvent.click(screen.getByText('resources.player.actions.revokeApiKey'))expect(values().apiKey).toBe('')expect(text('resources.player.message.apiKeyRevokePending'),).toBeInTheDocument()expect(text('resources.player.actions.generateApiKey')).toBeInTheDocument()})it('lets the owner generate a key when there is none', () => {const { values } = renderInput({record: { id: 'p1', userId: 'owner', hasApiKey: false },})expect(values().apiKey).toBeUndefined()expect(text('resources.player.message.apiKeyNone')).toBeInTheDocument()fireEvent.click(screen.getByText('resources.player.actions.generateApiKey'))expect(values().apiKey).toMatch(KEY_FORMAT)expect(text('resources.player.message.apiKeyPending')).toBeInTheDocument()})it('lets an admin revoke but not set a key on another user player', () => {localStorage.setItem('role', 'admin')renderInput({ record: { id: 'p1', userId: 'someone', hasApiKey: true } })expect(text('resources.player.actions.regenerateApiKey'),).not.toBeInTheDocument()expect(text('resources.player.actions.revokeApiKey')).toBeInTheDocument()})it('falls back to a prompt when the clipboard write fails', async () => {vi.stubGlobal('isSecureContext', true)vi.stubGlobal('prompt', vi.fn())Object.defineProperty(navigator, 'clipboard', {configurable: true,value: { writeText: vi.fn().mockRejectedValue(new Error('denied')) },})try {renderInput({record: {},isCreate: true,initialValues: { apiKey: KEY },})fireEvent.click(screen.getByRole('button', {name: 'resources.player.actions.copyApiKey',}),)await waitFor(() =>expect(window.prompt).toHaveBeenCalledWith('message.shareCopyToClipboard',KEY,),)expect(hooks.notify).not.toHaveBeenCalled()} finally {vi.unstubAllGlobals()delete navigator.clipboard}})it('shows a neutral message to an admin viewing another user player with no key', () => {localStorage.setItem('role', 'admin')renderInput({ record: { id: 'p1', userId: 'someone', hasApiKey: false } })expect(text('resources.player.message.apiKeyNoneOther')).toBeInTheDocument()expect(text('resources.player.message.apiKeyNone')).not.toBeInTheDocument()expect(screen.queryAllByRole('button')).toHaveLength(0)})it('shows no actions to another regular user', () => {renderInput({ record: { id: 'p1', userId: 'someone', hasApiKey: true } })expect(screen.queryAllByRole('button')).toHaveLength(0)})it('is not full width unless asked', () => {const record = { id: 'p1', userId: 'owner', hasApiKey: true }const { container, unmount } = renderInput({ record })expect(container.querySelector('.MuiFormControl-fullWidth')).toBeNull()unmount()const { container: wide } = renderInput({ record, fullWidth: true })expect(wide.querySelector('.MuiFormControl-fullWidth')).not.toBeNull()})})