import { fireEvent, screen, waitFor } from '@testing-library/react' import { beforeEach, describe, expect, it, vi } from 'vitest' import PluginPage from '@/app/components/plugins/plugin-page' import { renderWithNuqs } from '@/test/nuqs-testing' const mockFetchManifestFromMarketPlace = vi.fn() vi.mock('react-i18next', () => ({ useTranslation: () => ({ t: (key: string, options?: { ns?: string }) => options?.ns ? `${options.ns}.${key}` : key, }), })) vi.mock('@/utils', async (importOriginal) => { const actual = await importOriginal() return { ...actual, sleep: vi.fn(() => Promise.resolve()), } }) vi.mock('@/hooks/use-document-title', () => ({ __esModule: true, default: vi.fn(), })) vi.mock('@/context/i18n', () => ({ useDocLink: () => (path: string) => `https://docs.example.com${path}`, })) vi.mock('@/context/app-context', () => ({ useAppContext: () => ({ isCurrentWorkspaceManager: false, isCurrentWorkspaceOwner: false, }), })) vi.mock('@/context/global-public-context', () => ({ useGlobalPublicStore: (selector: (state: Record) => unknown) => selector({ systemFeatures: { enable_marketplace: true, plugin_installation_permission: { restrict_to_marketplace_only: false, }, }, }), })) vi.mock('@/service/use-plugins', () => ({ useReferenceSettings: () => ({ data: { permission: { install_permission: 'everyone', debug_permission: 'noOne', }, }, }), useMutationReferenceSettings: () => ({ mutate: vi.fn(), isPending: false, }), useInvalidateReferenceSettings: () => vi.fn(), useInstalledPluginList: () => ({ data: { total: 2, }, }), })) vi.mock('@/service/plugins', () => ({ fetchManifestFromMarketPlace: (...args: unknown[]) => mockFetchManifestFromMarketPlace(...args), fetchBundleInfoFromMarketPlace: vi.fn(), })) vi.mock('@/app/components/plugins/plugin-page/plugin-tasks', () => ({ default: () =>
plugin tasks
, })) vi.mock('@/app/components/plugins/plugin-page/debug-info', () => ({ default: () =>
debug info
, })) vi.mock('@/app/components/plugins/plugin-page/install-plugin-dropdown', () => ({ default: ({ onSwitchToMarketplaceTab }: { onSwitchToMarketplaceTab: () => void }) => ( ), })) vi.mock('@/app/components/plugins/install-plugin/install-from-marketplace', () => ({ default: ({ uniqueIdentifier, onClose, }: { uniqueIdentifier: string onClose: () => void }) => (
{uniqueIdentifier}
), })) const renderPluginPage = (searchParams = '') => { return renderWithNuqs( plugins view} marketplace={
marketplace view
} />, { searchParams }, ) } describe('Plugin Page Shell Flow', () => { beforeEach(() => { vi.clearAllMocks() mockFetchManifestFromMarketPlace.mockResolvedValue({ data: { plugin: { org: 'langgenius', name: 'plugin-demo', }, version: { version: '1.0.0', }, }, }) }) it('switches from installed plugins to marketplace and syncs the active tab into the URL', async () => { const { onUrlUpdate } = renderPluginPage() expect(screen.getByTestId('plugins-view')).toBeInTheDocument() expect(screen.queryByTestId('marketplace-view')).not.toBeInTheDocument() fireEvent.click(screen.getByTestId('tab-item-discover')) await waitFor(() => { expect(screen.getByTestId('marketplace-view')).toBeInTheDocument() }) const tabUpdate = onUrlUpdate.mock.calls[onUrlUpdate.mock.calls.length - 1][0] expect(tabUpdate.searchParams.get('tab')).toBe('discover') }) it('hydrates marketplace installation from query params and clears the install state when closed', async () => { const { onUrlUpdate } = renderPluginPage('?package-ids=%5B%22langgenius%2Fplugin-demo%22%5D') await waitFor(() => { expect(mockFetchManifestFromMarketPlace).toHaveBeenCalledWith('langgenius%2Fplugin-demo') expect(screen.getByTestId('install-from-marketplace-modal')).toBeInTheDocument() }) fireEvent.click(screen.getByRole('button', { name: 'close-install-modal' })) await waitFor(() => { const clearUpdate = onUrlUpdate.mock.calls[onUrlUpdate.mock.calls.length - 1][0] expect(clearUpdate.searchParams.has('package-ids')).toBe(false) }) }) })