mirror of
https://github.com/langgenius/dify.git
synced 2026-04-11 15:00:21 -04:00
164 lines
4.7 KiB
TypeScript
164 lines
4.7 KiB
TypeScript
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<typeof import('@/utils')>()
|
|
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<string, unknown>) => 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: () => <div data-testid="plugin-tasks">plugin tasks</div>,
|
|
}))
|
|
|
|
vi.mock('@/app/components/plugins/plugin-page/debug-info', () => ({
|
|
default: () => <div data-testid="debug-info">debug info</div>,
|
|
}))
|
|
|
|
vi.mock('@/app/components/plugins/plugin-page/install-plugin-dropdown', () => ({
|
|
default: ({ onSwitchToMarketplaceTab }: { onSwitchToMarketplaceTab: () => void }) => (
|
|
<button type="button" data-testid="install-plugin-dropdown" onClick={onSwitchToMarketplaceTab}>
|
|
install plugin
|
|
</button>
|
|
),
|
|
}))
|
|
|
|
vi.mock('@/app/components/plugins/install-plugin/install-from-marketplace', () => ({
|
|
default: ({
|
|
uniqueIdentifier,
|
|
onClose,
|
|
}: {
|
|
uniqueIdentifier: string
|
|
onClose: () => void
|
|
}) => (
|
|
<div data-testid="install-from-marketplace-modal">
|
|
<span>{uniqueIdentifier}</span>
|
|
<button type="button" onClick={onClose}>close-install-modal</button>
|
|
</div>
|
|
),
|
|
}))
|
|
|
|
const renderPluginPage = (searchParams = '') => {
|
|
return renderWithNuqs(
|
|
<PluginPage
|
|
plugins={<div data-testid="plugins-view">plugins view</div>}
|
|
marketplace={<div data-testid="marketplace-view">marketplace view</div>}
|
|
/>,
|
|
{ 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)
|
|
})
|
|
})
|
|
})
|