mirror of
https://github.com/langgenius/dify.git
synced 2026-08-28 20:33:21 +08:00
Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: fatelei <fatelei@gmail.com> Co-authored-by: Copilot <198982749+Copilot@users.noreply.github.com> Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com> Co-authored-by: 盐粒 Yanli <yanli@dify.ai> Co-authored-by: Charles Yao <chongbinyao33@gmail.com> Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com> Co-authored-by: yunlu.wen <yunlu.wen@dify.ai> Co-authored-by: yyh <92089059+lyzno1@users.noreply.github.com> Co-authored-by: Jingyi <jingyi.qi@dify.ai> Co-authored-by: yyh <yuanyouhuilyz@gmail.com> Co-authored-by: Joel <iamjoel007@gmail.com> Co-authored-by: hjlarry <hjlarry@163.com> Co-authored-by: Asuka Minato <i@asukaminato.eu.org> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Xiyuan Chen <52963600+GareArc@users.noreply.github.com> Co-authored-by: gigglewang <gigglewang@dify.ai> Co-authored-by: chariri <w@chariri.moe> Co-authored-by: Evan <2869018789@qq.com> Co-authored-by: zyssyz123 <916125788@qq.com>
659 lines
19 KiB
TypeScript
659 lines
19 KiB
TypeScript
import type { ReactNode } from 'react'
|
|
import type { ActionItem, SearchResult } from '../actions/types'
|
|
import { act, render, screen, waitFor } from '@testing-library/react'
|
|
import userEvent from '@testing-library/user-event'
|
|
import { createStore, Provider } from 'jotai'
|
|
import * as React from 'react'
|
|
import { GotoAnything } from '../index'
|
|
|
|
type TestSearchResult = Omit<SearchResult, 'icon' | 'data'> & {
|
|
icon?: ReactNode
|
|
data?: Record<string, unknown>
|
|
}
|
|
|
|
const routerPush = vi.fn()
|
|
vi.mock('@/next/navigation', () => ({
|
|
useRouter: () => ({
|
|
push: routerPush,
|
|
}),
|
|
usePathname: () => '/',
|
|
}))
|
|
|
|
type KeyPressEvent = {
|
|
preventDefault: () => void
|
|
target?: EventTarget
|
|
}
|
|
|
|
type HotkeyRegistration = {
|
|
handler: (event: KeyPressEvent) => void
|
|
options?: { enabled?: boolean }
|
|
}
|
|
|
|
const hotkeyHandlers: Record<string, HotkeyRegistration> = {}
|
|
vi.mock('ahooks', () => ({
|
|
useDebounce: <T,>(value: T) => value,
|
|
}))
|
|
|
|
vi.mock('@tanstack/react-hotkeys', async (importOriginal) => {
|
|
const actual = await importOriginal<typeof import('@tanstack/react-hotkeys')>()
|
|
return {
|
|
...actual,
|
|
useHotkey: (
|
|
hotkey: string,
|
|
handler: (event: KeyPressEvent) => void,
|
|
options?: HotkeyRegistration['options'],
|
|
) => {
|
|
hotkeyHandlers[hotkey] = { handler, options }
|
|
},
|
|
}
|
|
})
|
|
|
|
const HOTKEY_ALIAS: Record<string, string> = {
|
|
'ctrl.k': 'Mod+K',
|
|
}
|
|
|
|
const triggerKeyPress = (combo: string) => {
|
|
const hotkey = HOTKEY_ALIAS[combo] ?? combo
|
|
const registration = hotkeyHandlers[hotkey]
|
|
if (registration && registration.options?.enabled !== false) {
|
|
act(() => {
|
|
registration.handler({ preventDefault: vi.fn(), target: document.body })
|
|
})
|
|
}
|
|
}
|
|
|
|
let mockQueryResult = { data: [] as TestSearchResult[], isLoading: false, isError: false, error: null as Error | null }
|
|
vi.mock('@tanstack/react-query', () => ({
|
|
useQuery: () => mockQueryResult,
|
|
}))
|
|
|
|
vi.mock('@/context/i18n', () => ({
|
|
useGetLanguage: () => 'en_US',
|
|
}))
|
|
|
|
vi.mock('@/app/components/plugins/install-plugin/hooks/use-workspace-plugin-install-permission', () => ({
|
|
default: () => ({
|
|
canInstallPlugin: true,
|
|
currentDifyVersion: '1.0.0',
|
|
}),
|
|
}))
|
|
|
|
const contextValue = { isWorkflowPage: false, isRagPipelinePage: false }
|
|
vi.mock('../context', () => ({
|
|
useGotoAnythingContext: () => contextValue,
|
|
GotoAnythingProvider: ({ children }: { children: React.ReactNode }) => <>{children}</>,
|
|
}))
|
|
|
|
const createActionItem = (key: ActionItem['key'], shortcut: string): ActionItem => ({
|
|
key,
|
|
shortcut,
|
|
title: `${key} title`,
|
|
description: `${key} desc`,
|
|
action: vi.fn(),
|
|
search: vi.fn(),
|
|
})
|
|
|
|
const actionsMock = {
|
|
slash: createActionItem('/', '/'),
|
|
app: createActionItem('@app', '@app'),
|
|
plugin: createActionItem('@plugin', '@plugin'),
|
|
}
|
|
|
|
const createActionsMock = vi.fn(() => actionsMock)
|
|
const matchActionMock = vi.fn(() => undefined)
|
|
const searchAnythingMock = vi.fn(async () => mockQueryResult.data)
|
|
|
|
vi.mock('../actions', () => ({
|
|
createActions: () => createActionsMock(),
|
|
matchAction: () => matchActionMock(),
|
|
searchAnything: () => searchAnythingMock(),
|
|
}))
|
|
|
|
vi.mock('../actions/commands/slash-provider', () => ({
|
|
SlashCommandProvider: () => null,
|
|
}))
|
|
|
|
type MockSlashCommand = {
|
|
mode: string
|
|
execute?: () => void
|
|
isAvailable?: () => boolean
|
|
} | null
|
|
|
|
let mockFindCommand: MockSlashCommand = null
|
|
vi.mock('../actions/commands/registry', () => ({
|
|
slashCommandRegistry: {
|
|
findCommand: () => mockFindCommand,
|
|
getAvailableCommands: () => [],
|
|
getAllCommands: () => [],
|
|
},
|
|
}))
|
|
|
|
vi.mock('@/app/components/workflow/utils/node-navigation', () => ({
|
|
selectWorkflowNode: vi.fn(),
|
|
}))
|
|
|
|
vi.mock('../../plugins/install-plugin/install-from-marketplace', () => ({
|
|
default: (props: { manifest?: { name?: string }, onClose: () => void, onSuccess: () => void }) => (
|
|
<div data-testid="install-modal">
|
|
<span>{props.manifest?.name}</span>
|
|
<button onClick={props.onClose} data-testid="close-install">close</button>
|
|
<button onClick={props.onSuccess} data-testid="success-install">success</button>
|
|
</div>
|
|
),
|
|
}))
|
|
|
|
const renderGotoAnything = (ui: React.ReactElement) => {
|
|
const store = createStore()
|
|
|
|
return render(
|
|
<Provider store={store}>
|
|
{ui}
|
|
</Provider>,
|
|
)
|
|
}
|
|
|
|
describe('GotoAnything', () => {
|
|
beforeEach(() => {
|
|
routerPush.mockClear()
|
|
Object.keys(hotkeyHandlers).forEach(key => delete hotkeyHandlers[key])
|
|
mockQueryResult = { data: [], isLoading: false, isError: false, error: null }
|
|
matchActionMock.mockReset()
|
|
searchAnythingMock.mockClear()
|
|
mockFindCommand = null
|
|
})
|
|
|
|
describe('modal behavior', () => {
|
|
it('should open modal via Ctrl+K shortcut', async () => {
|
|
renderGotoAnything(<GotoAnything />)
|
|
|
|
triggerKeyPress('ctrl.k')
|
|
|
|
await waitFor(() => {
|
|
expect(screen.getByPlaceholderText('app.gotoAnything.searchPlaceholder')).toBeInTheDocument()
|
|
})
|
|
})
|
|
|
|
it('should close modal via ESC key', async () => {
|
|
const user = userEvent.setup()
|
|
renderGotoAnything(<GotoAnything />)
|
|
|
|
triggerKeyPress('ctrl.k')
|
|
await waitFor(() => {
|
|
expect(screen.getByPlaceholderText('app.gotoAnything.searchPlaceholder')).toBeInTheDocument()
|
|
})
|
|
|
|
await user.keyboard('{Escape}')
|
|
await waitFor(() => {
|
|
expect(screen.queryByPlaceholderText('app.gotoAnything.searchPlaceholder')).not.toBeInTheDocument()
|
|
})
|
|
})
|
|
|
|
it('should toggle modal when pressing Ctrl+K twice', async () => {
|
|
renderGotoAnything(<GotoAnything />)
|
|
|
|
triggerKeyPress('ctrl.k')
|
|
await waitFor(() => {
|
|
expect(screen.getByPlaceholderText('app.gotoAnything.searchPlaceholder')).toBeInTheDocument()
|
|
})
|
|
|
|
triggerKeyPress('ctrl.k')
|
|
await waitFor(() => {
|
|
expect(screen.queryByPlaceholderText('app.gotoAnything.searchPlaceholder')).not.toBeInTheDocument()
|
|
})
|
|
})
|
|
|
|
it('should call onHide when modal closes', async () => {
|
|
const user = userEvent.setup()
|
|
const onHide = vi.fn()
|
|
renderGotoAnything(<GotoAnything onHide={onHide} />)
|
|
|
|
triggerKeyPress('ctrl.k')
|
|
await waitFor(() => {
|
|
expect(screen.getByPlaceholderText('app.gotoAnything.searchPlaceholder')).toBeInTheDocument()
|
|
})
|
|
|
|
await user.keyboard('{Escape}')
|
|
await waitFor(() => {
|
|
expect(onHide).toHaveBeenCalled()
|
|
})
|
|
})
|
|
|
|
it('should reset search query when modal opens', async () => {
|
|
const user = userEvent.setup()
|
|
renderGotoAnything(<GotoAnything />)
|
|
|
|
triggerKeyPress('ctrl.k')
|
|
await waitFor(() => {
|
|
expect(screen.getByPlaceholderText('app.gotoAnything.searchPlaceholder')).toBeInTheDocument()
|
|
})
|
|
|
|
const input = screen.getByPlaceholderText('app.gotoAnything.searchPlaceholder')
|
|
await user.type(input, 'test')
|
|
|
|
await user.keyboard('{Escape}')
|
|
await waitFor(() => {
|
|
expect(screen.queryByPlaceholderText('app.gotoAnything.searchPlaceholder')).not.toBeInTheDocument()
|
|
})
|
|
|
|
triggerKeyPress('ctrl.k')
|
|
await waitFor(() => {
|
|
const newInput = screen.getByPlaceholderText('app.gotoAnything.searchPlaceholder')
|
|
expect(newInput).toHaveValue('')
|
|
})
|
|
})
|
|
})
|
|
|
|
describe('search functionality', () => {
|
|
it('should navigate to selected result', async () => {
|
|
const user = userEvent.setup()
|
|
mockQueryResult = {
|
|
data: [{
|
|
id: 'app-1',
|
|
type: 'app',
|
|
title: 'Sample App',
|
|
description: 'desc',
|
|
path: '/apps/1',
|
|
icon: <div data-testid="icon">🧩</div>,
|
|
data: {},
|
|
}],
|
|
isLoading: false,
|
|
isError: false,
|
|
error: null,
|
|
}
|
|
|
|
renderGotoAnything(<GotoAnything />)
|
|
triggerKeyPress('ctrl.k')
|
|
|
|
await waitFor(() => {
|
|
expect(screen.getByPlaceholderText('app.gotoAnything.searchPlaceholder')).toBeInTheDocument()
|
|
})
|
|
|
|
const input = screen.getByPlaceholderText('app.gotoAnything.searchPlaceholder')
|
|
await user.type(input, 'app')
|
|
|
|
const result = await screen.findByText('Sample App')
|
|
await user.click(result)
|
|
|
|
expect(routerPush).toHaveBeenCalledWith('/apps/1')
|
|
})
|
|
|
|
it('should clear selection when typing without prefix', async () => {
|
|
const user = userEvent.setup()
|
|
renderGotoAnything(<GotoAnything />)
|
|
triggerKeyPress('ctrl.k')
|
|
|
|
await waitFor(() => {
|
|
expect(screen.getByPlaceholderText('app.gotoAnything.searchPlaceholder')).toBeInTheDocument()
|
|
})
|
|
|
|
const input = screen.getByPlaceholderText('app.gotoAnything.searchPlaceholder')
|
|
await user.type(input, 'test query')
|
|
|
|
expect(input).toHaveValue('test query')
|
|
})
|
|
})
|
|
|
|
describe('empty states', () => {
|
|
it('should show loading state', async () => {
|
|
const user = userEvent.setup()
|
|
mockQueryResult = {
|
|
data: [],
|
|
isLoading: true,
|
|
isError: false,
|
|
error: null,
|
|
}
|
|
|
|
renderGotoAnything(<GotoAnything />)
|
|
triggerKeyPress('ctrl.k')
|
|
|
|
await waitFor(() => {
|
|
expect(screen.getByPlaceholderText('app.gotoAnything.searchPlaceholder')).toBeInTheDocument()
|
|
})
|
|
|
|
const input = screen.getByPlaceholderText('app.gotoAnything.searchPlaceholder')
|
|
await user.type(input, 'search')
|
|
|
|
const searchingTexts = screen.getAllByText('app.gotoAnything.searching')
|
|
expect(searchingTexts.length).toBeGreaterThanOrEqual(1)
|
|
})
|
|
|
|
it('should show error state', async () => {
|
|
const user = userEvent.setup()
|
|
const testError = new Error('Search failed')
|
|
mockQueryResult = {
|
|
data: [],
|
|
isLoading: false,
|
|
isError: true,
|
|
error: testError,
|
|
}
|
|
|
|
renderGotoAnything(<GotoAnything />)
|
|
triggerKeyPress('ctrl.k')
|
|
|
|
await waitFor(() => {
|
|
expect(screen.getByPlaceholderText('app.gotoAnything.searchPlaceholder')).toBeInTheDocument()
|
|
})
|
|
|
|
const input = screen.getByPlaceholderText('app.gotoAnything.searchPlaceholder')
|
|
await user.type(input, 'search')
|
|
|
|
expect(screen.getByText('app.gotoAnything.searchFailed')).toBeInTheDocument()
|
|
})
|
|
|
|
it('should show default state when no query', async () => {
|
|
renderGotoAnything(<GotoAnything />)
|
|
triggerKeyPress('ctrl.k')
|
|
|
|
await waitFor(() => {
|
|
expect(screen.getByPlaceholderText('app.gotoAnything.searchPlaceholder')).toBeInTheDocument()
|
|
})
|
|
|
|
expect(screen.getByText('app.gotoAnything.searchTitle')).toBeInTheDocument()
|
|
})
|
|
|
|
it('should show no results state when search returns empty', async () => {
|
|
const user = userEvent.setup()
|
|
mockQueryResult = {
|
|
data: [],
|
|
isLoading: false,
|
|
isError: false,
|
|
error: null,
|
|
}
|
|
|
|
renderGotoAnything(<GotoAnything />)
|
|
triggerKeyPress('ctrl.k')
|
|
|
|
await waitFor(() => {
|
|
expect(screen.getByPlaceholderText('app.gotoAnything.searchPlaceholder')).toBeInTheDocument()
|
|
})
|
|
|
|
const input = screen.getByPlaceholderText('app.gotoAnything.searchPlaceholder')
|
|
await user.type(input, 'nonexistent')
|
|
|
|
expect(screen.getByText('app.gotoAnything.noResults')).toBeInTheDocument()
|
|
})
|
|
})
|
|
|
|
describe('plugin installation', () => {
|
|
it('should open plugin installer when selecting plugin result', async () => {
|
|
const user = userEvent.setup()
|
|
mockQueryResult = {
|
|
data: [{
|
|
id: 'plugin-1',
|
|
type: 'plugin',
|
|
title: 'Plugin Item',
|
|
description: 'desc',
|
|
path: '',
|
|
icon: <div />,
|
|
data: {
|
|
name: 'Plugin Item',
|
|
latest_package_identifier: 'pkg',
|
|
},
|
|
}],
|
|
isLoading: false,
|
|
isError: false,
|
|
error: null,
|
|
}
|
|
|
|
renderGotoAnything(<GotoAnything />)
|
|
triggerKeyPress('ctrl.k')
|
|
|
|
await waitFor(() => {
|
|
expect(screen.getByPlaceholderText('app.gotoAnything.searchPlaceholder')).toBeInTheDocument()
|
|
})
|
|
|
|
const input = screen.getByPlaceholderText('app.gotoAnything.searchPlaceholder')
|
|
await user.type(input, 'plugin')
|
|
|
|
const pluginItem = await screen.findByText('Plugin Item')
|
|
await user.click(pluginItem)
|
|
|
|
expect(await screen.findByTestId('install-modal')).toHaveTextContent('Plugin Item')
|
|
})
|
|
|
|
it('should close plugin installer via close button', async () => {
|
|
const user = userEvent.setup()
|
|
mockQueryResult = {
|
|
data: [{
|
|
id: 'plugin-1',
|
|
type: 'plugin',
|
|
title: 'Plugin Item',
|
|
description: 'desc',
|
|
path: '',
|
|
icon: <div />,
|
|
data: {
|
|
name: 'Plugin Item',
|
|
latest_package_identifier: 'pkg',
|
|
},
|
|
}],
|
|
isLoading: false,
|
|
isError: false,
|
|
error: null,
|
|
}
|
|
|
|
renderGotoAnything(<GotoAnything />)
|
|
triggerKeyPress('ctrl.k')
|
|
|
|
await waitFor(() => {
|
|
expect(screen.getByPlaceholderText('app.gotoAnything.searchPlaceholder')).toBeInTheDocument()
|
|
})
|
|
|
|
const input = screen.getByPlaceholderText('app.gotoAnything.searchPlaceholder')
|
|
await user.type(input, 'plugin')
|
|
|
|
const pluginItem = await screen.findByText('Plugin Item')
|
|
await user.click(pluginItem)
|
|
|
|
const closeBtn = await screen.findByTestId('close-install')
|
|
await user.click(closeBtn)
|
|
|
|
await waitFor(() => {
|
|
expect(screen.queryByTestId('install-modal')).not.toBeInTheDocument()
|
|
})
|
|
})
|
|
|
|
it('should close plugin installer on success', async () => {
|
|
const user = userEvent.setup()
|
|
mockQueryResult = {
|
|
data: [{
|
|
id: 'plugin-1',
|
|
type: 'plugin',
|
|
title: 'Plugin Item',
|
|
description: 'desc',
|
|
path: '',
|
|
icon: <div />,
|
|
data: {
|
|
name: 'Plugin Item',
|
|
latest_package_identifier: 'pkg',
|
|
},
|
|
}],
|
|
isLoading: false,
|
|
isError: false,
|
|
error: null,
|
|
}
|
|
|
|
renderGotoAnything(<GotoAnything />)
|
|
triggerKeyPress('ctrl.k')
|
|
|
|
await waitFor(() => {
|
|
expect(screen.getByPlaceholderText('app.gotoAnything.searchPlaceholder')).toBeInTheDocument()
|
|
})
|
|
|
|
const input = screen.getByPlaceholderText('app.gotoAnything.searchPlaceholder')
|
|
await user.type(input, 'plugin')
|
|
|
|
const pluginItem = await screen.findByText('Plugin Item')
|
|
await user.click(pluginItem)
|
|
|
|
const successBtn = await screen.findByTestId('success-install')
|
|
await user.click(successBtn)
|
|
|
|
await waitFor(() => {
|
|
expect(screen.queryByTestId('install-modal')).not.toBeInTheDocument()
|
|
})
|
|
})
|
|
})
|
|
|
|
describe('slash command handling', () => {
|
|
it('should execute direct slash command on Enter', async () => {
|
|
const user = userEvent.setup()
|
|
const executeMock = vi.fn()
|
|
mockFindCommand = {
|
|
mode: 'direct',
|
|
execute: executeMock,
|
|
isAvailable: () => true,
|
|
}
|
|
|
|
renderGotoAnything(<GotoAnything />)
|
|
triggerKeyPress('ctrl.k')
|
|
|
|
await waitFor(() => {
|
|
expect(screen.getByPlaceholderText('app.gotoAnything.searchPlaceholder')).toBeInTheDocument()
|
|
})
|
|
|
|
const input = screen.getByPlaceholderText('app.gotoAnything.searchPlaceholder')
|
|
await user.type(input, '/theme')
|
|
await user.keyboard('{Enter}')
|
|
|
|
expect(executeMock).toHaveBeenCalled()
|
|
})
|
|
|
|
it('should NOT execute unavailable slash command', async () => {
|
|
const user = userEvent.setup()
|
|
const executeMock = vi.fn()
|
|
mockFindCommand = {
|
|
mode: 'direct',
|
|
execute: executeMock,
|
|
isAvailable: () => false,
|
|
}
|
|
|
|
renderGotoAnything(<GotoAnything />)
|
|
triggerKeyPress('ctrl.k')
|
|
|
|
await waitFor(() => {
|
|
expect(screen.getByPlaceholderText('app.gotoAnything.searchPlaceholder')).toBeInTheDocument()
|
|
})
|
|
|
|
const input = screen.getByPlaceholderText('app.gotoAnything.searchPlaceholder')
|
|
await user.type(input, '/theme')
|
|
await user.keyboard('{Enter}')
|
|
|
|
expect(executeMock).not.toHaveBeenCalled()
|
|
})
|
|
|
|
it('should NOT execute non-direct mode slash command on Enter', async () => {
|
|
const user = userEvent.setup()
|
|
const executeMock = vi.fn()
|
|
mockFindCommand = {
|
|
mode: 'submenu',
|
|
execute: executeMock,
|
|
}
|
|
|
|
renderGotoAnything(<GotoAnything />)
|
|
triggerKeyPress('ctrl.k')
|
|
|
|
await waitFor(() => {
|
|
expect(screen.getByPlaceholderText('app.gotoAnything.searchPlaceholder')).toBeInTheDocument()
|
|
})
|
|
|
|
const input = screen.getByPlaceholderText('app.gotoAnything.searchPlaceholder')
|
|
await user.type(input, '/language')
|
|
await user.keyboard('{Enter}')
|
|
|
|
expect(executeMock).not.toHaveBeenCalled()
|
|
})
|
|
|
|
it('should close modal after executing direct slash command', async () => {
|
|
const user = userEvent.setup()
|
|
mockFindCommand = {
|
|
mode: 'direct',
|
|
execute: vi.fn(),
|
|
isAvailable: () => true,
|
|
}
|
|
|
|
renderGotoAnything(<GotoAnything />)
|
|
triggerKeyPress('ctrl.k')
|
|
|
|
await waitFor(() => {
|
|
expect(screen.getByPlaceholderText('app.gotoAnything.searchPlaceholder')).toBeInTheDocument()
|
|
})
|
|
|
|
const input = screen.getByPlaceholderText('app.gotoAnything.searchPlaceholder')
|
|
await user.type(input, '/theme')
|
|
await user.keyboard('{Enter}')
|
|
|
|
await waitFor(() => {
|
|
expect(screen.queryByPlaceholderText('app.gotoAnything.searchPlaceholder')).not.toBeInTheDocument()
|
|
})
|
|
})
|
|
})
|
|
|
|
describe('result navigation', () => {
|
|
it('should handle knowledge result navigation', async () => {
|
|
const user = userEvent.setup()
|
|
mockQueryResult = {
|
|
data: [{
|
|
id: 'kb-1',
|
|
type: 'knowledge',
|
|
title: 'Knowledge Base',
|
|
description: 'desc',
|
|
path: '/datasets/kb-1',
|
|
icon: <div />,
|
|
data: {},
|
|
}],
|
|
isLoading: false,
|
|
isError: false,
|
|
error: null,
|
|
}
|
|
|
|
renderGotoAnything(<GotoAnything />)
|
|
triggerKeyPress('ctrl.k')
|
|
|
|
await waitFor(() => {
|
|
expect(screen.getByPlaceholderText('app.gotoAnything.searchPlaceholder')).toBeInTheDocument()
|
|
})
|
|
|
|
const input = screen.getByPlaceholderText('app.gotoAnything.searchPlaceholder')
|
|
await user.type(input, 'knowledge')
|
|
|
|
const result = await screen.findByText('Knowledge Base')
|
|
await user.click(result)
|
|
|
|
expect(routerPush).toHaveBeenCalledWith('/datasets/kb-1')
|
|
})
|
|
|
|
it('should NOT navigate when result has no path', async () => {
|
|
const user = userEvent.setup()
|
|
mockQueryResult = {
|
|
data: [{
|
|
id: 'item-1',
|
|
type: 'app',
|
|
title: 'No Path Item',
|
|
description: 'desc',
|
|
path: '',
|
|
icon: <div />,
|
|
data: {},
|
|
}],
|
|
isLoading: false,
|
|
isError: false,
|
|
error: null,
|
|
}
|
|
|
|
renderGotoAnything(<GotoAnything />)
|
|
triggerKeyPress('ctrl.k')
|
|
|
|
await waitFor(() => {
|
|
expect(screen.getByPlaceholderText('app.gotoAnything.searchPlaceholder')).toBeInTheDocument()
|
|
})
|
|
|
|
const input = screen.getByPlaceholderText('app.gotoAnything.searchPlaceholder')
|
|
await user.type(input, 'no path')
|
|
|
|
const result = await screen.findByText('No Path Item')
|
|
await user.click(result)
|
|
|
|
expect(routerPush).not.toHaveBeenCalled()
|
|
})
|
|
})
|
|
})
|