mirror of
https://github.com/langgenius/dify.git
synced 2026-05-05 18:08:07 +08:00
test: add comprehensive unit and integration tests for dataset module (#32187)
Co-authored-by: CodingOnStar <hanxujiang@dify.com> Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@ -0,0 +1,104 @@
|
||||
import { fireEvent, render, screen } from '@testing-library/react'
|
||||
import { beforeEach, describe, expect, it, vi } from 'vitest'
|
||||
|
||||
// Explicit react-i18next mock so the test stays portable
|
||||
// even if the global vitest.setup changes.
|
||||
|
||||
// Hoisted mocks
|
||||
const mocks = vi.hoisted(() => ({
|
||||
push: vi.fn(),
|
||||
refresh: vi.fn(),
|
||||
setShowExternalKnowledgeAPIModal: vi.fn(),
|
||||
mutateExternalKnowledgeApis: vi.fn(),
|
||||
}))
|
||||
|
||||
vi.mock('next/navigation', () => ({
|
||||
useRouter: () => ({ push: mocks.push, refresh: mocks.refresh }),
|
||||
}))
|
||||
|
||||
vi.mock('@/context/modal-context', () => ({
|
||||
useModalContext: () => ({
|
||||
setShowExternalKnowledgeAPIModal: mocks.setShowExternalKnowledgeAPIModal,
|
||||
}),
|
||||
}))
|
||||
|
||||
vi.mock('@/context/external-knowledge-api-context', () => ({
|
||||
useExternalKnowledgeApi: () => ({
|
||||
mutateExternalKnowledgeApis: mocks.mutateExternalKnowledgeApis,
|
||||
}),
|
||||
}))
|
||||
|
||||
vi.mock('@/app/components/base/icons/src/vender/solid/development', () => ({
|
||||
ApiConnectionMod: (props: Record<string, unknown>) => <span data-testid="api-icon" {...props} />,
|
||||
}))
|
||||
|
||||
const { default: ExternalApiSelect } = await import('../ExternalApiSelect')
|
||||
|
||||
describe('ExternalApiSelect', () => {
|
||||
const items = [
|
||||
{ value: 'api-1', name: 'API One', url: 'https://api1.com' },
|
||||
{ value: 'api-2', name: 'API Two', url: 'https://api2.com' },
|
||||
]
|
||||
const onSelect = vi.fn()
|
||||
|
||||
beforeEach(() => {
|
||||
vi.clearAllMocks()
|
||||
})
|
||||
|
||||
describe('rendering', () => {
|
||||
it('should show placeholder when no value selected', () => {
|
||||
render(<ExternalApiSelect items={items} onSelect={onSelect} />)
|
||||
expect(screen.getByText('dataset.selectExternalKnowledgeAPI.placeholder')).toBeInTheDocument()
|
||||
})
|
||||
|
||||
it('should show selected item name when value matches', () => {
|
||||
render(<ExternalApiSelect items={items} value="api-1" onSelect={onSelect} />)
|
||||
expect(screen.getByText('API One')).toBeInTheDocument()
|
||||
})
|
||||
|
||||
it('should not show dropdown initially', () => {
|
||||
render(<ExternalApiSelect items={items} onSelect={onSelect} />)
|
||||
expect(screen.queryByText('API Two')).not.toBeInTheDocument()
|
||||
})
|
||||
})
|
||||
|
||||
describe('dropdown interactions', () => {
|
||||
it('should open dropdown on click', () => {
|
||||
render(<ExternalApiSelect items={items} onSelect={onSelect} />)
|
||||
fireEvent.click(screen.getByText('dataset.selectExternalKnowledgeAPI.placeholder'))
|
||||
expect(screen.getByText('API One')).toBeInTheDocument()
|
||||
expect(screen.getByText('API Two')).toBeInTheDocument()
|
||||
})
|
||||
|
||||
it('should close dropdown and call onSelect when item clicked', () => {
|
||||
render(<ExternalApiSelect items={items} onSelect={onSelect} />)
|
||||
// Open
|
||||
fireEvent.click(screen.getByText('dataset.selectExternalKnowledgeAPI.placeholder'))
|
||||
// Select
|
||||
fireEvent.click(screen.getByText('API Two'))
|
||||
expect(onSelect).toHaveBeenCalledWith(items[1])
|
||||
// Dropdown should close - selected name should show
|
||||
expect(screen.getByText('API Two')).toBeInTheDocument()
|
||||
})
|
||||
|
||||
it('should show add new API option in dropdown', () => {
|
||||
render(<ExternalApiSelect items={items} onSelect={onSelect} />)
|
||||
fireEvent.click(screen.getByText('dataset.selectExternalKnowledgeAPI.placeholder'))
|
||||
expect(screen.getByText('dataset.createNewExternalAPI')).toBeInTheDocument()
|
||||
})
|
||||
|
||||
it('should call setShowExternalKnowledgeAPIModal when add new clicked', () => {
|
||||
render(<ExternalApiSelect items={items} onSelect={onSelect} />)
|
||||
fireEvent.click(screen.getByText('dataset.selectExternalKnowledgeAPI.placeholder'))
|
||||
fireEvent.click(screen.getByText('dataset.createNewExternalAPI'))
|
||||
expect(mocks.setShowExternalKnowledgeAPIModal).toHaveBeenCalledOnce()
|
||||
})
|
||||
|
||||
it('should show item URLs in dropdown', () => {
|
||||
render(<ExternalApiSelect items={items} onSelect={onSelect} />)
|
||||
fireEvent.click(screen.getByText('dataset.selectExternalKnowledgeAPI.placeholder'))
|
||||
expect(screen.getByText('https://api1.com')).toBeInTheDocument()
|
||||
expect(screen.getByText('https://api2.com')).toBeInTheDocument()
|
||||
})
|
||||
})
|
||||
})
|
||||
@ -0,0 +1,112 @@
|
||||
import { fireEvent, render, screen } from '@testing-library/react'
|
||||
import { beforeEach, describe, expect, it, vi } from 'vitest'
|
||||
|
||||
// Hoisted mocks
|
||||
const mocks = vi.hoisted(() => ({
|
||||
push: vi.fn(),
|
||||
refresh: vi.fn(),
|
||||
setShowExternalKnowledgeAPIModal: vi.fn(),
|
||||
mutateExternalKnowledgeApis: vi.fn(),
|
||||
externalKnowledgeApiList: [] as Array<{ id: string, name: string, settings: { endpoint: string } }>,
|
||||
}))
|
||||
|
||||
vi.mock('next/navigation', () => ({
|
||||
useRouter: () => ({ push: mocks.push, refresh: mocks.refresh }),
|
||||
}))
|
||||
|
||||
vi.mock('@/context/modal-context', () => ({
|
||||
useModalContext: () => ({
|
||||
setShowExternalKnowledgeAPIModal: mocks.setShowExternalKnowledgeAPIModal,
|
||||
}),
|
||||
}))
|
||||
|
||||
vi.mock('@/context/external-knowledge-api-context', () => ({
|
||||
useExternalKnowledgeApi: () => ({
|
||||
externalKnowledgeApiList: mocks.externalKnowledgeApiList,
|
||||
mutateExternalKnowledgeApis: mocks.mutateExternalKnowledgeApis,
|
||||
}),
|
||||
}))
|
||||
|
||||
// Mock ExternalApiSelect as simple stub
|
||||
type MockSelectItem = { value: string, name: string }
|
||||
vi.mock('../ExternalApiSelect', () => ({
|
||||
default: ({ items, value, onSelect }: { items: MockSelectItem[], value?: string, onSelect: (item: MockSelectItem) => void }) => (
|
||||
<div data-testid="external-api-select">
|
||||
<span data-testid="select-value">{value}</span>
|
||||
<span data-testid="select-items-count">{items.length}</span>
|
||||
{items.map((item: MockSelectItem) => (
|
||||
<button key={item.value} data-testid={`select-${item.value}`} onClick={() => onSelect(item)}>
|
||||
{item.name}
|
||||
</button>
|
||||
))}
|
||||
</div>
|
||||
),
|
||||
}))
|
||||
|
||||
const { default: ExternalApiSelection } = await import('../ExternalApiSelection')
|
||||
|
||||
describe('ExternalApiSelection', () => {
|
||||
const defaultProps = {
|
||||
external_knowledge_api_id: '',
|
||||
external_knowledge_id: '',
|
||||
onChange: vi.fn(),
|
||||
}
|
||||
|
||||
beforeEach(() => {
|
||||
vi.clearAllMocks()
|
||||
mocks.externalKnowledgeApiList = [
|
||||
{ id: 'api-1', name: 'API One', settings: { endpoint: 'https://api1.com' } },
|
||||
{ id: 'api-2', name: 'API Two', settings: { endpoint: 'https://api2.com' } },
|
||||
]
|
||||
})
|
||||
|
||||
describe('rendering', () => {
|
||||
it('should render API selection label', () => {
|
||||
render(<ExternalApiSelection {...defaultProps} />)
|
||||
expect(screen.getByText('dataset.externalAPIPanelTitle')).toBeInTheDocument()
|
||||
})
|
||||
|
||||
it('should render knowledge ID label and input', () => {
|
||||
render(<ExternalApiSelection {...defaultProps} />)
|
||||
expect(screen.getByText('dataset.externalKnowledgeId')).toBeInTheDocument()
|
||||
})
|
||||
|
||||
it('should render ExternalApiSelect when APIs exist', () => {
|
||||
render(<ExternalApiSelection {...defaultProps} />)
|
||||
expect(screen.getByTestId('external-api-select')).toBeInTheDocument()
|
||||
expect(screen.getByTestId('select-items-count').textContent).toBe('2')
|
||||
})
|
||||
|
||||
it('should show add button when no APIs exist', () => {
|
||||
mocks.externalKnowledgeApiList = []
|
||||
render(<ExternalApiSelection {...defaultProps} />)
|
||||
expect(screen.getByText('dataset.noExternalKnowledge')).toBeInTheDocument()
|
||||
})
|
||||
})
|
||||
|
||||
describe('interactions', () => {
|
||||
it('should call onChange when API selected', () => {
|
||||
render(<ExternalApiSelection {...defaultProps} />)
|
||||
fireEvent.click(screen.getByTestId('select-api-2'))
|
||||
expect(defaultProps.onChange).toHaveBeenCalledWith(
|
||||
expect.objectContaining({ external_knowledge_api_id: 'api-2' }),
|
||||
)
|
||||
})
|
||||
|
||||
it('should call onChange when knowledge ID input changes', () => {
|
||||
render(<ExternalApiSelection {...defaultProps} />)
|
||||
const input = screen.getByPlaceholderText('dataset.externalKnowledgeIdPlaceholder')
|
||||
fireEvent.change(input, { target: { value: 'kb-123' } })
|
||||
expect(defaultProps.onChange).toHaveBeenCalledWith(
|
||||
expect.objectContaining({ external_knowledge_id: 'kb-123' }),
|
||||
)
|
||||
})
|
||||
|
||||
it('should call setShowExternalKnowledgeAPIModal when add button clicked', () => {
|
||||
mocks.externalKnowledgeApiList = []
|
||||
render(<ExternalApiSelection {...defaultProps} />)
|
||||
fireEvent.click(screen.getByText('dataset.noExternalKnowledge'))
|
||||
expect(mocks.setShowExternalKnowledgeAPIModal).toHaveBeenCalledOnce()
|
||||
})
|
||||
})
|
||||
})
|
||||
@ -0,0 +1,94 @@
|
||||
import { render, screen } from '@testing-library/react'
|
||||
import { beforeEach, describe, expect, it, vi } from 'vitest'
|
||||
import InfoPanel from '../InfoPanel'
|
||||
|
||||
// Mock useDocLink from @/context/i18n
|
||||
vi.mock('@/context/i18n', () => ({
|
||||
useDocLink: () => (path: string) => `https://docs.dify.ai${path}`,
|
||||
}))
|
||||
|
||||
describe('InfoPanel', () => {
|
||||
beforeEach(() => {
|
||||
vi.clearAllMocks()
|
||||
})
|
||||
|
||||
// Rendering: verifies the panel renders all expected content
|
||||
describe('Rendering', () => {
|
||||
it('should render without crashing', () => {
|
||||
render(<InfoPanel />)
|
||||
expect(screen.getByText(/connectDatasetIntro\.title/)).toBeInTheDocument()
|
||||
})
|
||||
|
||||
it('should render the title text', () => {
|
||||
render(<InfoPanel />)
|
||||
expect(screen.getByText(/connectDatasetIntro\.title/)).toBeInTheDocument()
|
||||
})
|
||||
|
||||
it('should render the front content text', () => {
|
||||
render(<InfoPanel />)
|
||||
expect(screen.getByText(/connectDatasetIntro\.content\.front/)).toBeInTheDocument()
|
||||
})
|
||||
|
||||
it('should render the content link', () => {
|
||||
render(<InfoPanel />)
|
||||
expect(screen.getByText(/connectDatasetIntro\.content\.link/)).toBeInTheDocument()
|
||||
})
|
||||
|
||||
it('should render the end content text', () => {
|
||||
render(<InfoPanel />)
|
||||
expect(screen.getByText(/connectDatasetIntro\.content\.end/)).toBeInTheDocument()
|
||||
})
|
||||
|
||||
it('should render the learn more link', () => {
|
||||
render(<InfoPanel />)
|
||||
expect(screen.getByText(/connectDatasetIntro\.learnMore/)).toBeInTheDocument()
|
||||
})
|
||||
|
||||
it('should render the book icon', () => {
|
||||
const { container } = render(<InfoPanel />)
|
||||
const svgIcons = container.querySelectorAll('svg')
|
||||
expect(svgIcons.length).toBeGreaterThanOrEqual(1)
|
||||
})
|
||||
})
|
||||
|
||||
// Props: tests links and their attributes
|
||||
describe('Links', () => {
|
||||
it('should have correct href for external knowledge API doc link', () => {
|
||||
render(<InfoPanel />)
|
||||
const docLink = screen.getByText(/connectDatasetIntro\.content\.link/)
|
||||
expect(docLink).toHaveAttribute('href', 'https://docs.dify.ai/use-dify/knowledge/external-knowledge-api')
|
||||
})
|
||||
|
||||
it('should have correct href for learn more link', () => {
|
||||
render(<InfoPanel />)
|
||||
const learnMoreLink = screen.getByText(/connectDatasetIntro\.learnMore/)
|
||||
expect(learnMoreLink).toHaveAttribute('href', 'https://docs.dify.ai/use-dify/knowledge/connect-external-knowledge-base')
|
||||
})
|
||||
|
||||
it('should open links in new tab', () => {
|
||||
render(<InfoPanel />)
|
||||
const docLink = screen.getByText(/connectDatasetIntro\.content\.link/)
|
||||
expect(docLink).toHaveAttribute('target', '_blank')
|
||||
expect(docLink).toHaveAttribute('rel', 'noopener noreferrer')
|
||||
|
||||
const learnMoreLink = screen.getByText(/connectDatasetIntro\.learnMore/)
|
||||
expect(learnMoreLink).toHaveAttribute('target', '_blank')
|
||||
expect(learnMoreLink).toHaveAttribute('rel', 'noopener noreferrer')
|
||||
})
|
||||
})
|
||||
|
||||
// Styles: checks structural class names
|
||||
describe('Styles', () => {
|
||||
it('should have correct container width', () => {
|
||||
const { container } = render(<InfoPanel />)
|
||||
const wrapper = container.firstChild as HTMLElement
|
||||
expect(wrapper).toHaveClass('w-[360px]')
|
||||
})
|
||||
|
||||
it('should have correct panel background', () => {
|
||||
const { container } = render(<InfoPanel />)
|
||||
const panel = container.querySelector('.bg-background-section')
|
||||
expect(panel).toBeInTheDocument()
|
||||
})
|
||||
})
|
||||
})
|
||||
@ -0,0 +1,153 @@
|
||||
import { fireEvent, render, screen } from '@testing-library/react'
|
||||
import { beforeEach, describe, expect, it, vi } from 'vitest'
|
||||
import KnowledgeBaseInfo from '../KnowledgeBaseInfo'
|
||||
|
||||
describe('KnowledgeBaseInfo', () => {
|
||||
const defaultProps = {
|
||||
name: '',
|
||||
description: '',
|
||||
onChange: vi.fn(),
|
||||
}
|
||||
|
||||
beforeEach(() => {
|
||||
vi.clearAllMocks()
|
||||
})
|
||||
|
||||
// Rendering: verifies all form fields render
|
||||
describe('Rendering', () => {
|
||||
it('should render without crashing', () => {
|
||||
render(<KnowledgeBaseInfo {...defaultProps} />)
|
||||
expect(screen.getByText(/externalKnowledgeName/)).toBeInTheDocument()
|
||||
})
|
||||
|
||||
it('should render the name label', () => {
|
||||
render(<KnowledgeBaseInfo {...defaultProps} />)
|
||||
expect(screen.getByText(/externalKnowledgeName(?!Placeholder)/)).toBeInTheDocument()
|
||||
})
|
||||
|
||||
it('should render the description label', () => {
|
||||
render(<KnowledgeBaseInfo {...defaultProps} />)
|
||||
expect(screen.getByText(/externalKnowledgeDescription(?!Placeholder)/)).toBeInTheDocument()
|
||||
})
|
||||
|
||||
it('should render name input with placeholder', () => {
|
||||
render(<KnowledgeBaseInfo {...defaultProps} />)
|
||||
const input = screen.getByPlaceholderText(/externalKnowledgeNamePlaceholder/)
|
||||
expect(input).toBeInTheDocument()
|
||||
})
|
||||
|
||||
it('should render description textarea with placeholder', () => {
|
||||
render(<KnowledgeBaseInfo {...defaultProps} />)
|
||||
const textarea = screen.getByPlaceholderText(/externalKnowledgeDescriptionPlaceholder/)
|
||||
expect(textarea).toBeInTheDocument()
|
||||
})
|
||||
})
|
||||
|
||||
// Props: tests value display and onChange callbacks
|
||||
describe('Props', () => {
|
||||
it('should display name in the input', () => {
|
||||
render(<KnowledgeBaseInfo {...defaultProps} name="My Knowledge Base" />)
|
||||
const input = screen.getByDisplayValue('My Knowledge Base')
|
||||
expect(input).toBeInTheDocument()
|
||||
})
|
||||
|
||||
it('should display description in the textarea', () => {
|
||||
render(<KnowledgeBaseInfo {...defaultProps} description="A description" />)
|
||||
const textarea = screen.getByDisplayValue('A description')
|
||||
expect(textarea).toBeInTheDocument()
|
||||
})
|
||||
|
||||
it('should call onChange with name when name input changes', () => {
|
||||
const onChange = vi.fn()
|
||||
render(<KnowledgeBaseInfo {...defaultProps} onChange={onChange} />)
|
||||
const input = screen.getByPlaceholderText(/externalKnowledgeNamePlaceholder/)
|
||||
|
||||
fireEvent.change(input, { target: { value: 'New Name' } })
|
||||
|
||||
expect(onChange).toHaveBeenCalledWith({ name: 'New Name' })
|
||||
})
|
||||
|
||||
it('should call onChange with description when textarea changes', () => {
|
||||
const onChange = vi.fn()
|
||||
render(<KnowledgeBaseInfo {...defaultProps} onChange={onChange} />)
|
||||
const textarea = screen.getByPlaceholderText(/externalKnowledgeDescriptionPlaceholder/)
|
||||
|
||||
fireEvent.change(textarea, { target: { value: 'New Description' } })
|
||||
|
||||
expect(onChange).toHaveBeenCalledWith({ description: 'New Description' })
|
||||
})
|
||||
})
|
||||
|
||||
// User Interactions: tests form interactions
|
||||
describe('User Interactions', () => {
|
||||
it('should allow typing in name input', () => {
|
||||
const onChange = vi.fn()
|
||||
render(<KnowledgeBaseInfo {...defaultProps} onChange={onChange} />)
|
||||
const input = screen.getByPlaceholderText(/externalKnowledgeNamePlaceholder/)
|
||||
|
||||
fireEvent.change(input, { target: { value: 'Typed Name' } })
|
||||
|
||||
expect(onChange).toHaveBeenCalledTimes(1)
|
||||
expect(onChange).toHaveBeenCalledWith({ name: 'Typed Name' })
|
||||
})
|
||||
|
||||
it('should allow typing in description textarea', () => {
|
||||
const onChange = vi.fn()
|
||||
render(<KnowledgeBaseInfo {...defaultProps} onChange={onChange} />)
|
||||
const textarea = screen.getByPlaceholderText(/externalKnowledgeDescriptionPlaceholder/)
|
||||
|
||||
fireEvent.change(textarea, { target: { value: 'Typed Desc' } })
|
||||
|
||||
expect(onChange).toHaveBeenCalledTimes(1)
|
||||
expect(onChange).toHaveBeenCalledWith({ description: 'Typed Desc' })
|
||||
})
|
||||
})
|
||||
|
||||
// Edge Cases: tests boundary values
|
||||
describe('Edge Cases', () => {
|
||||
it('should handle empty name', () => {
|
||||
render(<KnowledgeBaseInfo {...defaultProps} name="" />)
|
||||
const input = screen.getByPlaceholderText(/externalKnowledgeNamePlaceholder/)
|
||||
expect(input).toHaveValue('')
|
||||
})
|
||||
|
||||
it('should handle undefined description', () => {
|
||||
render(<KnowledgeBaseInfo {...defaultProps} description={undefined} />)
|
||||
const textarea = screen.getByPlaceholderText(/externalKnowledgeDescriptionPlaceholder/)
|
||||
expect(textarea).toBeInTheDocument()
|
||||
})
|
||||
|
||||
it('should handle very long name', () => {
|
||||
const longName = 'K'.repeat(500)
|
||||
render(<KnowledgeBaseInfo {...defaultProps} name={longName} />)
|
||||
const input = screen.getByDisplayValue(longName)
|
||||
expect(input).toBeInTheDocument()
|
||||
})
|
||||
|
||||
it('should handle very long description', () => {
|
||||
const longDesc = 'D'.repeat(2000)
|
||||
render(<KnowledgeBaseInfo {...defaultProps} description={longDesc} />)
|
||||
const textarea = screen.getByDisplayValue(longDesc)
|
||||
expect(textarea).toBeInTheDocument()
|
||||
})
|
||||
|
||||
it('should handle special characters in name', () => {
|
||||
const specialName = 'Test & "quotes" <angle>'
|
||||
render(<KnowledgeBaseInfo {...defaultProps} name={specialName} />)
|
||||
const input = screen.getByDisplayValue(specialName)
|
||||
expect(input).toBeInTheDocument()
|
||||
})
|
||||
|
||||
it('should apply filled text color class when description has content', () => {
|
||||
const { container } = render(<KnowledgeBaseInfo {...defaultProps} description="has content" />)
|
||||
const textarea = container.querySelector('textarea')
|
||||
expect(textarea).toHaveClass('text-components-input-text-filled')
|
||||
})
|
||||
|
||||
it('should apply placeholder text color class when description is empty', () => {
|
||||
const { container } = render(<KnowledgeBaseInfo {...defaultProps} description="" />)
|
||||
const textarea = container.querySelector('textarea')
|
||||
expect(textarea).toHaveClass('text-components-input-text-placeholder')
|
||||
})
|
||||
})
|
||||
})
|
||||
@ -0,0 +1,92 @@
|
||||
import { fireEvent, render, screen } from '@testing-library/react'
|
||||
import { beforeEach, describe, expect, it, vi } from 'vitest'
|
||||
|
||||
// Mock param items to simplify testing
|
||||
vi.mock('@/app/components/base/param-item/top-k-item', () => ({
|
||||
default: ({ value, onChange, enable }: { value: number, onChange: (key: string, val: number) => void, enable: boolean }) => (
|
||||
<div data-testid="top-k-item">
|
||||
<span data-testid="top-k-value">{value}</span>
|
||||
<button data-testid="top-k-change" onClick={() => onChange('top_k', 8)}>change</button>
|
||||
<span data-testid="top-k-enabled">{String(enable)}</span>
|
||||
</div>
|
||||
),
|
||||
}))
|
||||
|
||||
vi.mock('@/app/components/base/param-item/score-threshold-item', () => ({
|
||||
default: ({ value, onChange, enable, onSwitchChange }: { value: number, onChange: (key: string, val: number) => void, enable: boolean, onSwitchChange: (key: string, val: boolean) => void }) => (
|
||||
<div data-testid="score-threshold-item">
|
||||
<span data-testid="score-value">{value}</span>
|
||||
<button data-testid="score-change" onClick={() => onChange('score_threshold', 0.9)}>change</button>
|
||||
<span data-testid="score-enabled">{String(enable)}</span>
|
||||
<button data-testid="score-switch" onClick={() => onSwitchChange('score_threshold_enabled', true)}>switch</button>
|
||||
</div>
|
||||
),
|
||||
}))
|
||||
|
||||
const { default: RetrievalSettings } = await import('../RetrievalSettings')
|
||||
|
||||
describe('RetrievalSettings', () => {
|
||||
const defaultProps = {
|
||||
topK: 3,
|
||||
scoreThreshold: 0.5,
|
||||
scoreThresholdEnabled: false,
|
||||
onChange: vi.fn(),
|
||||
}
|
||||
|
||||
beforeEach(() => {
|
||||
vi.clearAllMocks()
|
||||
})
|
||||
|
||||
describe('rendering', () => {
|
||||
it('should render TopKItem and ScoreThresholdItem', () => {
|
||||
render(<RetrievalSettings {...defaultProps} />)
|
||||
expect(screen.getByTestId('top-k-item')).toBeInTheDocument()
|
||||
expect(screen.getByTestId('score-threshold-item')).toBeInTheDocument()
|
||||
})
|
||||
|
||||
it('should pass topK value to TopKItem', () => {
|
||||
render(<RetrievalSettings {...defaultProps} />)
|
||||
expect(screen.getByTestId('top-k-value').textContent).toBe('3')
|
||||
})
|
||||
|
||||
it('should pass scoreThreshold to ScoreThresholdItem', () => {
|
||||
render(<RetrievalSettings {...defaultProps} />)
|
||||
expect(screen.getByTestId('score-value').textContent).toBe('0.5')
|
||||
})
|
||||
|
||||
it('should show label when not in hit testing and not in retrieval setting', () => {
|
||||
render(<RetrievalSettings {...defaultProps} />)
|
||||
expect(screen.getByText('dataset.retrievalSettings')).toBeInTheDocument()
|
||||
})
|
||||
|
||||
it('should hide label when isInHitTesting is true', () => {
|
||||
render(<RetrievalSettings {...defaultProps} isInHitTesting />)
|
||||
expect(screen.queryByText('dataset.retrievalSettings')).not.toBeInTheDocument()
|
||||
})
|
||||
|
||||
it('should hide label when isInRetrievalSetting is true', () => {
|
||||
render(<RetrievalSettings {...defaultProps} isInRetrievalSetting />)
|
||||
expect(screen.queryByText('dataset.retrievalSettings')).not.toBeInTheDocument()
|
||||
})
|
||||
})
|
||||
|
||||
describe('user interactions', () => {
|
||||
it('should call onChange with top_k when TopKItem changes', () => {
|
||||
render(<RetrievalSettings {...defaultProps} />)
|
||||
fireEvent.click(screen.getByTestId('top-k-change'))
|
||||
expect(defaultProps.onChange).toHaveBeenCalledWith({ top_k: 8 })
|
||||
})
|
||||
|
||||
it('should call onChange with score_threshold when ScoreThresholdItem changes', () => {
|
||||
render(<RetrievalSettings {...defaultProps} />)
|
||||
fireEvent.click(screen.getByTestId('score-change'))
|
||||
expect(defaultProps.onChange).toHaveBeenCalledWith({ score_threshold: 0.9 })
|
||||
})
|
||||
|
||||
it('should call onChange with score_threshold_enabled when switch changes', () => {
|
||||
render(<RetrievalSettings {...defaultProps} />)
|
||||
fireEvent.click(screen.getByTestId('score-switch'))
|
||||
expect(defaultProps.onChange).toHaveBeenCalledWith({ score_threshold_enabled: true })
|
||||
})
|
||||
})
|
||||
})
|
||||
@ -2,10 +2,9 @@ import type { ExternalAPIItem } from '@/models/datasets'
|
||||
import { fireEvent, render, screen, waitFor } from '@testing-library/react'
|
||||
import userEvent from '@testing-library/user-event'
|
||||
import * as React from 'react'
|
||||
import ExternalKnowledgeBaseCreate from './index'
|
||||
import RetrievalSettings from './RetrievalSettings'
|
||||
import ExternalKnowledgeBaseCreate from '../index'
|
||||
import RetrievalSettings from '../RetrievalSettings'
|
||||
|
||||
// Mock next/navigation
|
||||
const mockReplace = vi.fn()
|
||||
const mockRefresh = vi.fn()
|
||||
vi.mock('next/navigation', () => ({
|
||||
@ -438,7 +437,6 @@ describe('ExternalKnowledgeBaseCreate', () => {
|
||||
const onConnect = vi.fn()
|
||||
renderComponent({ onConnect })
|
||||
|
||||
// Click on the API selector to open dropdown
|
||||
const apiSelector = screen.getByText('Test API 1')
|
||||
await user.click(apiSelector)
|
||||
|
||||
@ -484,7 +482,6 @@ describe('ExternalKnowledgeBaseCreate', () => {
|
||||
mockExternalKnowledgeApiList = []
|
||||
renderComponent()
|
||||
|
||||
// Click the add button
|
||||
const addButton = screen.getByText('dataset.noExternalKnowledge').closest('button')
|
||||
await user.click(addButton!)
|
||||
|
||||
@ -503,7 +500,6 @@ describe('ExternalKnowledgeBaseCreate', () => {
|
||||
mockExternalKnowledgeApiList = []
|
||||
renderComponent()
|
||||
|
||||
// Click the add button
|
||||
const addButton = screen.getByText('dataset.noExternalKnowledge').closest('button')
|
||||
await user.click(addButton!)
|
||||
|
||||
@ -521,7 +517,6 @@ describe('ExternalKnowledgeBaseCreate', () => {
|
||||
mockExternalKnowledgeApiList = []
|
||||
renderComponent()
|
||||
|
||||
// Click the add button
|
||||
const addButton = screen.getByText('dataset.noExternalKnowledge').closest('button')
|
||||
await user.click(addButton!)
|
||||
|
||||
@ -536,7 +531,6 @@ describe('ExternalKnowledgeBaseCreate', () => {
|
||||
const user = userEvent.setup()
|
||||
renderComponent()
|
||||
|
||||
// Click on the API selector to open dropdown
|
||||
const apiSelector = screen.getByText('Test API 1')
|
||||
await user.click(apiSelector)
|
||||
|
||||
@ -549,7 +543,6 @@ describe('ExternalKnowledgeBaseCreate', () => {
|
||||
const user = userEvent.setup()
|
||||
renderComponent()
|
||||
|
||||
// Click on the API selector to open dropdown
|
||||
const apiSelector = screen.getByText('Test API 1')
|
||||
await user.click(apiSelector)
|
||||
|
||||
@ -561,11 +554,9 @@ describe('ExternalKnowledgeBaseCreate', () => {
|
||||
const user = userEvent.setup()
|
||||
renderComponent()
|
||||
|
||||
// Click on the API selector to open dropdown
|
||||
const apiSelector = screen.getByText('Test API 1')
|
||||
await user.click(apiSelector)
|
||||
|
||||
// Click on create new API option
|
||||
const createNewApiOption = screen.getByText('dataset.createNewExternalAPI')
|
||||
await user.click(createNewApiOption)
|
||||
|
||||
@ -582,11 +573,9 @@ describe('ExternalKnowledgeBaseCreate', () => {
|
||||
const user = userEvent.setup()
|
||||
renderComponent()
|
||||
|
||||
// Click on the API selector to open dropdown
|
||||
const apiSelector = screen.getByText('Test API 1')
|
||||
await user.click(apiSelector)
|
||||
|
||||
// Click on create new API option
|
||||
const createNewApiOption = screen.getByText('dataset.createNewExternalAPI')
|
||||
await user.click(createNewApiOption)
|
||||
|
||||
@ -602,11 +591,9 @@ describe('ExternalKnowledgeBaseCreate', () => {
|
||||
const user = userEvent.setup()
|
||||
renderComponent()
|
||||
|
||||
// Click on the API selector to open dropdown
|
||||
const apiSelector = screen.getByText('Test API 1')
|
||||
await user.click(apiSelector)
|
||||
|
||||
// Click on create new API option
|
||||
const createNewApiOption = screen.getByText('dataset.createNewExternalAPI')
|
||||
await user.click(createNewApiOption)
|
||||
|
||||
@ -621,7 +608,6 @@ describe('ExternalKnowledgeBaseCreate', () => {
|
||||
const user = userEvent.setup()
|
||||
renderComponent()
|
||||
|
||||
// Click on the API selector to open dropdown
|
||||
const apiSelector = screen.getByText('Test API 1')
|
||||
await user.click(apiSelector)
|
||||
|
||||
@ -640,12 +626,10 @@ describe('ExternalKnowledgeBaseCreate', () => {
|
||||
const user = userEvent.setup()
|
||||
renderComponent()
|
||||
|
||||
// Click to open
|
||||
const apiSelector = screen.getByText('Test API 1')
|
||||
await user.click(apiSelector)
|
||||
expect(screen.getByText('https://api1.example.com')).toBeInTheDocument()
|
||||
|
||||
// Click again to close
|
||||
await user.click(apiSelector)
|
||||
expect(screen.queryByText('https://api1.example.com')).not.toBeInTheDocument()
|
||||
})
|
||||
Reference in New Issue
Block a user