Merge remote-tracking branch 'origin/main' into feat/support-agent-sandbox

# Conflicts:
#	api/uv.lock
#	web/app/components/apps/__tests__/app-card.spec.tsx
#	web/app/components/apps/__tests__/list.spec.tsx
#	web/app/components/datasets/create/__tests__/index.spec.tsx
#	web/app/components/datasets/metadata/metadata-dataset/__tests__/dataset-metadata-drawer.spec.tsx
#	web/app/components/plugins/readme-panel/__tests__/index.spec.tsx
#	web/app/components/rag-pipeline/__tests__/index.spec.tsx
#	web/app/components/rag-pipeline/hooks/__tests__/index.spec.ts
#	web/eslint-suppressions.json
This commit is contained in:
yyh
2026-02-13 15:17:52 +08:00
898 changed files with 58772 additions and 34358 deletions

View File

@ -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()
})
})
})

View File

@ -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()
})
})
})

View File

@ -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()
})
})
})

View File

@ -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')
})
})
})

View File

@ -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 })
})
})
})

View File

@ -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()
})