import type { CustomCollectionBackend, CustomParamSchema } from '@/app/components/tools/types' import { act, fireEvent, render, screen, waitFor } from '@testing-library/react' import { beforeEach, describe, expect, it, vi } from 'vitest' import { AuthHeaderPrefix, AuthType } from '@/app/components/tools/types' import { testAPIAvailable } from '@/service/tools' import TestApi from './test-api' vi.mock('@/service/tools', () => ({ testAPIAvailable: vi.fn(), })) vi.mock('@/context/i18n', () => ({ useLocale: vi.fn(() => 'en-US'), })) const testAPIAvailableMock = vi.mocked(testAPIAvailable) describe('TestApi', () => { const customCollection: CustomCollectionBackend = { provider: 'custom', credentials: { auth_type: AuthType.none, }, schema_type: 'openapi', schema: '{ }', icon: { background: '', content: '' }, privacy_policy: '', custom_disclaimer: '', id: 'test-id', labels: [], } const tool: CustomParamSchema = { operation_id: 'testOp', summary: 'summary', method: 'GET', server_url: 'https://api.example.com', parameters: [{ name: 'limit', label: { en_US: 'Limit', zh_Hans: '限制', }, } as CustomParamSchema['parameters'][0]], } const mockOnHide = vi.fn() const renderTestApi = (props?: { customCollection?: CustomCollectionBackend tool?: CustomParamSchema positionCenter?: boolean }) => { return render( , ) } beforeEach(() => { vi.clearAllMocks() testAPIAvailableMock.mockReset() }) // Tests for basic rendering describe('Rendering', () => { it('should render without crashing', async () => { await act(async () => { renderTestApi() }) expect(screen.getByText('tools.test.testResult')).toBeInTheDocument() }) it('should display tool name in the title', async () => { await act(async () => { renderTestApi() }) expect(screen.getByText(/testOp/)).toBeInTheDocument() }) it('should render parameters table', async () => { await act(async () => { renderTestApi() }) expect(screen.getByText('tools.test.parameters')).toBeInTheDocument() expect(screen.getByText('tools.test.value')).toBeInTheDocument() expect(screen.getByText('Limit')).toBeInTheDocument() }) it('should render test result placeholder', async () => { await act(async () => { renderTestApi() }) expect(screen.getByText('tools.test.testResultPlaceholder')).toBeInTheDocument() }) it('should render with positionCenter prop', async () => { await act(async () => { renderTestApi({ positionCenter: true }) }) expect(screen.getByText('tools.test.testResult')).toBeInTheDocument() }) }) // Tests for API test execution describe('API Test Execution', () => { it('should run API test with parameters and show result', async () => { testAPIAvailableMock.mockResolvedValueOnce({ result: 'ok' }) renderTestApi() const parameterInput = screen.getAllByRole('textbox')[0] fireEvent.change(parameterInput, { target: { value: '5' } }) fireEvent.click(screen.getByRole('button', { name: 'tools.test.title' })) await waitFor(() => { expect(testAPIAvailableMock).toHaveBeenCalledWith({ provider_name: customCollection.provider, tool_name: tool.operation_id, credentials: { auth_type: AuthType.none, }, schema_type: customCollection.schema_type, schema: customCollection.schema, parameters: { limit: '5', }, }) expect(screen.getByText('ok')).toBeInTheDocument() }) }) it('should display error result when API returns error', async () => { testAPIAvailableMock.mockResolvedValueOnce({ error: 'API Error occurred' }) renderTestApi() fireEvent.click(screen.getByRole('button', { name: 'tools.test.title' })) await waitFor(() => { expect(screen.getByText('API Error occurred')).toBeInTheDocument() }) }) it('should call API when test button is clicked', async () => { testAPIAvailableMock.mockResolvedValueOnce({ result: 'test completed' }) await act(async () => { renderTestApi() }) // Click test button await act(async () => { fireEvent.click(screen.getByRole('button', { name: 'tools.test.title' })) }) // API should have been called await waitFor(() => { expect(testAPIAvailableMock).toHaveBeenCalledTimes(1) expect(screen.getByText('test completed')).toBeInTheDocument() }) }) it('should strip extra credential fields when auth_type is none', async () => { const collectionWithExtraFields: CustomCollectionBackend = { ...customCollection, credentials: { auth_type: AuthType.none, api_key_header: 'X-Api-Key', api_key_header_prefix: AuthHeaderPrefix.bearer, api_key_value: 'secret', }, } testAPIAvailableMock.mockResolvedValueOnce({ result: 'success' }) renderTestApi({ customCollection: collectionWithExtraFields }) fireEvent.click(screen.getByRole('button', { name: 'tools.test.title' })) await waitFor(() => { expect(testAPIAvailableMock).toHaveBeenCalledWith( expect.objectContaining({ credentials: { auth_type: AuthType.none, }, }), ) }) }) }) // Tests for credentials modal describe('Credentials Modal', () => { it('should show auth method display text', async () => { await act(async () => { renderTestApi() }) // Check that the auth method is displayed expect(screen.getByText('tools.createTool.authMethod.types.none')).toBeInTheDocument() }) it('should display current auth type in the button', async () => { const collectionWithHeader: CustomCollectionBackend = { ...customCollection, credentials: { auth_type: AuthType.apiKeyHeader, api_key_header: 'X-Api-Key', api_key_header_prefix: AuthHeaderPrefix.bearer, api_key_value: 'token', }, } await act(async () => { renderTestApi({ customCollection: collectionWithHeader }) }) // Check that the auth method display shows the correct type expect(screen.getByText('tools.createTool.authMethod.types.api_key_header')).toBeInTheDocument() }) }) // Tests for multiple parameters describe('Multiple Parameters', () => { it('should handle multiple parameters', async () => { const toolWithMultipleParams: CustomParamSchema = { ...tool, parameters: [ { name: 'limit', label: { en_US: 'Limit', zh_Hans: '限制' }, } as CustomParamSchema['parameters'][0], { name: 'offset', label: { en_US: 'Offset', zh_Hans: '偏移' }, } as CustomParamSchema['parameters'][0], ], } testAPIAvailableMock.mockResolvedValueOnce({ result: 'multi-param success' }) renderTestApi({ tool: toolWithMultipleParams }) const inputs = screen.getAllByRole('textbox') fireEvent.change(inputs[0], { target: { value: '10' } }) fireEvent.change(inputs[1], { target: { value: '20' } }) fireEvent.click(screen.getByRole('button', { name: 'tools.test.title' })) await waitFor(() => { expect(testAPIAvailableMock).toHaveBeenCalledWith( expect.objectContaining({ parameters: { limit: '10', offset: '20', }, }), ) }) }) it('should handle empty parameters', async () => { testAPIAvailableMock.mockResolvedValueOnce({ result: 'empty params success' }) renderTestApi() // Don't fill in any parameters fireEvent.click(screen.getByRole('button', { name: 'tools.test.title' })) await waitFor(() => { expect(testAPIAvailableMock).toHaveBeenCalledWith( expect.objectContaining({ parameters: {}, }), ) }) }) }) // Tests for different auth types describe('Different Auth Types', () => { it('should pass apiKeyHeader credentials to API', async () => { const collectionWithHeader: CustomCollectionBackend = { ...customCollection, credentials: { auth_type: AuthType.apiKeyHeader, api_key_header: 'Authorization', api_key_header_prefix: AuthHeaderPrefix.bearer, api_key_value: 'test-token', }, } testAPIAvailableMock.mockResolvedValueOnce({ result: 'header auth success' }) renderTestApi({ customCollection: collectionWithHeader }) fireEvent.click(screen.getByRole('button', { name: 'tools.test.title' })) await waitFor(() => { expect(testAPIAvailableMock).toHaveBeenCalledWith( expect.objectContaining({ credentials: { auth_type: AuthType.apiKeyHeader, api_key_header: 'Authorization', api_key_header_prefix: AuthHeaderPrefix.bearer, api_key_value: 'test-token', }, }), ) }) }) it('should pass apiKeyQuery credentials to API', async () => { const collectionWithQuery: CustomCollectionBackend = { ...customCollection, credentials: { auth_type: AuthType.apiKeyQuery, api_key_query_param: 'api_key', api_key_value: 'query-token', }, } testAPIAvailableMock.mockResolvedValueOnce({ result: 'query auth success' }) renderTestApi({ customCollection: collectionWithQuery }) fireEvent.click(screen.getByRole('button', { name: 'tools.test.title' })) await waitFor(() => { expect(testAPIAvailableMock).toHaveBeenCalledWith( expect.objectContaining({ credentials: { auth_type: AuthType.apiKeyQuery, api_key_query_param: 'api_key', api_key_value: 'query-token', }, }), ) }) }) }) })