/** * Integration Test: Plugin Authentication Flow * * Tests the integration between PluginAuth, usePluginAuth hook, * Authorize/Authorized components, and credential management. * Verifies the complete auth flow from checking authorization status * to rendering the correct UI state. */ import { cleanup, render, screen } from '@testing-library/react' import { beforeEach, describe, expect, it, vi } from 'vitest' import { AuthCategory, CredentialTypeEnum } from '@/app/components/plugins/plugin-auth/types' vi.mock('react-i18next', () => ({ useTranslation: () => ({ t: (key: string) => { const map: Record = { 'plugin.auth.setUpTip': 'Set up your credentials', 'plugin.auth.authorized': 'Authorized', 'plugin.auth.apiKey': 'API Key', 'plugin.auth.oauth': 'OAuth', } return map[key] ?? key }, }), })) vi.mock('@/context/app-context', () => ({ useAppContext: () => ({ isCurrentWorkspaceManager: true, }), })) vi.mock('@/utils/classnames', () => ({ cn: (...args: unknown[]) => args.filter(Boolean).join(' '), })) const mockUsePluginAuth = vi.fn() vi.mock('@/app/components/plugins/plugin-auth/hooks/use-plugin-auth', () => ({ usePluginAuth: (...args: unknown[]) => mockUsePluginAuth(...args), })) vi.mock('@/app/components/plugins/plugin-auth/authorize', () => ({ default: ({ pluginPayload, canOAuth, canApiKey }: { pluginPayload: { provider: string } canOAuth: boolean canApiKey: boolean }) => (
{pluginPayload.provider} {canOAuth && OAuth available} {canApiKey && API Key available}
), })) vi.mock('@/app/components/plugins/plugin-auth/authorized', () => ({ default: ({ pluginPayload, credentials }: { pluginPayload: { provider: string } credentials: Array<{ id: string, name: string }> }) => (
{pluginPayload.provider} {credentials.length} {' '} credentials
), })) const { default: PluginAuth } = await import('@/app/components/plugins/plugin-auth/plugin-auth') describe('Plugin Authentication Flow Integration', () => { beforeEach(() => { vi.clearAllMocks() cleanup() }) const basePayload = { category: AuthCategory.tool, provider: 'test-provider', } describe('Unauthorized State', () => { it('renders Authorize component when not authorized', () => { mockUsePluginAuth.mockReturnValue({ isAuthorized: false, canOAuth: false, canApiKey: true, credentials: [], disabled: false, invalidPluginCredentialInfo: vi.fn(), notAllowCustomCredential: false, }) render() expect(screen.getByTestId('authorize-component')).toBeInTheDocument() expect(screen.queryByTestId('authorized-component')).not.toBeInTheDocument() expect(screen.getByTestId('auth-apikey')).toBeInTheDocument() }) it('shows OAuth option when plugin supports it', () => { mockUsePluginAuth.mockReturnValue({ isAuthorized: false, canOAuth: true, canApiKey: true, credentials: [], disabled: false, invalidPluginCredentialInfo: vi.fn(), notAllowCustomCredential: false, }) render() expect(screen.getByTestId('auth-oauth')).toBeInTheDocument() expect(screen.getByTestId('auth-apikey')).toBeInTheDocument() }) it('applies className to wrapper when not authorized', () => { mockUsePluginAuth.mockReturnValue({ isAuthorized: false, canOAuth: false, canApiKey: true, credentials: [], disabled: false, invalidPluginCredentialInfo: vi.fn(), notAllowCustomCredential: false, }) const { container } = render( , ) expect(container.firstChild).toHaveClass('custom-class') }) }) describe('Authorized State', () => { it('renders Authorized component when authorized and no children', () => { mockUsePluginAuth.mockReturnValue({ isAuthorized: true, canOAuth: false, canApiKey: true, credentials: [ { id: 'cred-1', name: 'My API Key', is_default: true }, ], disabled: false, invalidPluginCredentialInfo: vi.fn(), notAllowCustomCredential: false, }) render() expect(screen.queryByTestId('authorize-component')).not.toBeInTheDocument() expect(screen.getByTestId('authorized-component')).toBeInTheDocument() expect(screen.getByTestId('auth-credential-count')).toHaveTextContent('1 credentials') }) it('renders children instead of Authorized when authorized and children provided', () => { mockUsePluginAuth.mockReturnValue({ isAuthorized: true, canOAuth: false, canApiKey: true, credentials: [{ id: 'cred-1', name: 'Key', is_default: true }], disabled: false, invalidPluginCredentialInfo: vi.fn(), notAllowCustomCredential: false, }) render(
Custom authorized view
, ) expect(screen.queryByTestId('authorize-component')).not.toBeInTheDocument() expect(screen.queryByTestId('authorized-component')).not.toBeInTheDocument() expect(screen.getByTestId('custom-children')).toBeInTheDocument() }) it('does not apply className when authorized', () => { mockUsePluginAuth.mockReturnValue({ isAuthorized: true, canOAuth: false, canApiKey: true, credentials: [{ id: 'cred-1', name: 'Key', is_default: true }], disabled: false, invalidPluginCredentialInfo: vi.fn(), notAllowCustomCredential: false, }) const { container } = render( , ) expect(container.firstChild).not.toHaveClass('custom-class') }) }) describe('Auth Category Integration', () => { it('passes correct provider to usePluginAuth for tool category', () => { mockUsePluginAuth.mockReturnValue({ isAuthorized: false, canOAuth: false, canApiKey: true, credentials: [], disabled: false, invalidPluginCredentialInfo: vi.fn(), notAllowCustomCredential: false, }) const toolPayload = { category: AuthCategory.tool, provider: 'google-search-provider', } render() expect(mockUsePluginAuth).toHaveBeenCalledWith(toolPayload, true) expect(screen.getByTestId('auth-provider')).toHaveTextContent('google-search-provider') }) it('passes correct provider to usePluginAuth for datasource category', () => { mockUsePluginAuth.mockReturnValue({ isAuthorized: false, canOAuth: true, canApiKey: false, credentials: [], disabled: false, invalidPluginCredentialInfo: vi.fn(), notAllowCustomCredential: false, }) const dsPayload = { category: AuthCategory.datasource, provider: 'notion-datasource', } render() expect(mockUsePluginAuth).toHaveBeenCalledWith(dsPayload, true) expect(screen.getByTestId('auth-oauth')).toBeInTheDocument() expect(screen.queryByTestId('auth-apikey')).not.toBeInTheDocument() }) }) describe('Multiple Credentials', () => { it('shows credential count when multiple credentials exist', () => { mockUsePluginAuth.mockReturnValue({ isAuthorized: true, canOAuth: true, canApiKey: true, credentials: [ { id: 'cred-1', name: 'API Key 1', is_default: true }, { id: 'cred-2', name: 'API Key 2', is_default: false }, { id: 'cred-3', name: 'OAuth Token', is_default: false, credential_type: CredentialTypeEnum.OAUTH2 }, ], disabled: false, invalidPluginCredentialInfo: vi.fn(), notAllowCustomCredential: false, }) render() expect(screen.getByTestId('auth-credential-count')).toHaveTextContent('3 credentials') }) }) })