-
{t('filter.sortBy', { ns: 'appLog' })}
-
- {triggerContent}
-
+
+
{t('filter.sortBy', { ns: 'appLog' })}
+
+ {triggerContent}
-
+
= ({
+
diff --git a/web/app/components/datasets/common/retrieval-method-info/__tests__/index.spec.tsx b/web/app/components/datasets/common/retrieval-method-info/__tests__/index.spec.tsx
index ad230fb596..3aa2849b49 100644
--- a/web/app/components/datasets/common/retrieval-method-info/__tests__/index.spec.tsx
+++ b/web/app/components/datasets/common/retrieval-method-info/__tests__/index.spec.tsx
@@ -1,21 +1,8 @@
-import type { ReactNode } from 'react'
import { render, screen } from '@testing-library/react'
import { RETRIEVE_METHOD } from '@/types/app'
import { retrievalIcon } from '../../../create/icons'
import RetrievalMethodInfo, { getIcon } from '../index'
-// Mock RadioCard
-vi.mock('@/app/components/base/radio-card', () => ({
- default: ({ title, description, chosenConfig, icon }: { title: string, description: string, chosenConfig: ReactNode, icon: ReactNode }) => (
-
-
{title}
-
{description}
-
{icon}
-
{chosenConfig}
-
- ),
-}))
-
// Mock icons
vi.mock('../../../create/icons', () => ({
retrievalIcon: {
@@ -45,11 +32,9 @@ describe('RetrievalMethodInfo', () => {
it('should render correctly with full config', () => {
const { container } = render(
)
- expect(screen.getByTestId('radio-card')).toBeInTheDocument()
-
// Check Title & Description (mocked i18n returns key prefixed with ns)
- expect(screen.getByTestId('card-title')).toHaveTextContent('dataset.retrieval.semantic_search.title')
- expect(screen.getByTestId('card-description')).toHaveTextContent('dataset.retrieval.semantic_search.description')
+ expect(screen.getByText('dataset.retrieval.semantic_search.title')).toBeInTheDocument()
+ expect(screen.getByText('dataset.retrieval.semantic_search.description')).toBeInTheDocument()
// Check Icon
const icon = container.querySelector('img')
@@ -82,7 +67,7 @@ describe('RetrievalMethodInfo', () => {
const hybridConfig = { ...defaultConfig, search_method: RETRIEVE_METHOD.hybrid }
const { container, unmount } = render(
)
- expect(screen.getByTestId('card-title')).toHaveTextContent('dataset.retrieval.hybrid_search.title')
+ expect(screen.getByText('dataset.retrieval.hybrid_search.title')).toBeInTheDocument()
expect(container.querySelector('img')).toHaveAttribute('src', 'hybrid-icon.png')
unmount()
@@ -90,7 +75,7 @@ describe('RetrievalMethodInfo', () => {
// Test FullText
const fullTextConfig = { ...defaultConfig, search_method: RETRIEVE_METHOD.fullText }
const { container: fullTextContainer } = render(
)
- expect(screen.getByTestId('card-title')).toHaveTextContent('dataset.retrieval.full_text_search.title')
+ expect(screen.getByText('dataset.retrieval.full_text_search.title')).toBeInTheDocument()
expect(fullTextContainer.querySelector('img')).toHaveAttribute('src', 'fulltext-icon.png')
})
diff --git a/web/app/components/datasets/common/retrieval-param-config/__tests__/index.spec.tsx b/web/app/components/datasets/common/retrieval-param-config/__tests__/index.spec.tsx
index ac5112ad22..93e5b4c712 100644
--- a/web/app/components/datasets/common/retrieval-param-config/__tests__/index.spec.tsx
+++ b/web/app/components/datasets/common/retrieval-param-config/__tests__/index.spec.tsx
@@ -103,25 +103,6 @@ vi.mock('@/app/components/base/param-item/score-threshold-item', () => ({
),
}))
-vi.mock('@/app/components/base/radio-card', () => ({
- default: ({ isChosen, onChosen, title, description }: {
- isChosen: boolean
- onChosen: () => void
- title: string
- description: string
- }) => (
-
- {title}
- {description}
-
- ),
-}))
-
vi.mock('@langgenius/dify-ui/switch', () => ({
Switch: ({ checked, onCheckedChange }: { checked: boolean, onCheckedChange?: (v: boolean) => void }) => (
-
}
- title={t('stepTwo.paragraph', { ns: 'datasetCreation' })}
- description={t('stepTwo.paragraphTip', { ns: 'datasetCreation' })}
- isChosen={parentChildConfig.chunkForContext === 'paragraph'}
- onChosen={() => onChunkForContextChange('paragraph')}
- chosenConfig={(
-
- onParentDelimiterChange(e.target.value)}
- />
-
-
- )}
- />
-
}
- title={t('stepTwo.fullDoc', { ns: 'datasetCreation' })}
- description={t('stepTwo.fullDocTip', { ns: 'datasetCreation' })}
- onChosen={() => onChunkForContextChange('full-doc')}
- isChosen={parentChildConfig.chunkForContext === 'full-doc'}
- />
+
+ aria-label={t('stepTwo.parentChunkForContext', { ns: 'datasetCreation' })}
+ value={parentChildConfig.chunkForContext}
+ onValueChange={value => onChunkForContextChange(value)}
+ className="mt-1 flex-col items-stretch gap-2"
+ >
+ }
+ title={t('stepTwo.paragraph', { ns: 'datasetCreation' })}
+ description={t('stepTwo.paragraphTip', { ns: 'datasetCreation' })}
+ chosenConfig={(
+
+ onParentDelimiterChange(e.target.value)}
+ />
+
+
+ )}
+ />
+ }
+ title={t('stepTwo.fullDoc', { ns: 'datasetCreation' })}
+ description={t('stepTwo.fullDocTip', { ns: 'datasetCreation' })}
+ />
+
{/* Child chunk for retrieval */}
diff --git a/web/app/components/datasets/documents/create-from-pipeline/data-source/online-drive/file-list/header/breadcrumbs/dropdown/__tests__/index.spec.tsx b/web/app/components/datasets/documents/create-from-pipeline/data-source/online-drive/file-list/header/breadcrumbs/dropdown/__tests__/index.spec.tsx
index d57e8340e9..d93de876e7 100644
--- a/web/app/components/datasets/documents/create-from-pipeline/data-source/online-drive/file-list/header/breadcrumbs/dropdown/__tests__/index.spec.tsx
+++ b/web/app/components/datasets/documents/create-from-pipeline/data-source/online-drive/file-list/header/breadcrumbs/dropdown/__tests__/index.spec.tsx
@@ -368,9 +368,9 @@ describe('Dropdown', () => {
// Act - Open dropdown
fireEvent.click(button)
- // Assert - Open state: should have bg-state-base-hover
+ // Assert - Open state is exposed declaratively via data-popup-open
await waitFor(() => {
- expect(button)!.toHaveClass('bg-state-base-hover')
+ expect(button).toHaveAttribute('data-popup-open')
})
})
})
diff --git a/web/app/components/datasets/documents/create-from-pipeline/data-source/online-drive/file-list/header/breadcrumbs/dropdown/__tests__/item.spec.tsx b/web/app/components/datasets/documents/create-from-pipeline/data-source/online-drive/file-list/header/breadcrumbs/dropdown/__tests__/item.spec.tsx
index 4437305ad4..fd582a3bae 100644
--- a/web/app/components/datasets/documents/create-from-pipeline/data-source/online-drive/file-list/header/breadcrumbs/dropdown/__tests__/item.spec.tsx
+++ b/web/app/components/datasets/documents/create-from-pipeline/data-source/online-drive/file-list/header/breadcrumbs/dropdown/__tests__/item.spec.tsx
@@ -1,7 +1,19 @@
+import type { ReactElement } from 'react'
+import { DropdownMenu, DropdownMenuContent } from '@langgenius/dify-ui/dropdown-menu'
import { fireEvent, render, screen } from '@testing-library/react'
import { beforeEach, describe, expect, it, vi } from 'vitest'
import Item from '../item'
+const renderItem = (ui: ReactElement) => {
+ return render(
+
+
+ {ui}
+
+ ,
+ )
+}
+
describe('Item', () => {
const defaultProps = {
name: 'Documents',
@@ -16,7 +28,7 @@ describe('Item', () => {
// Rendering: verify the breadcrumb name is displayed
describe('Rendering', () => {
it('should render breadcrumb name', () => {
- render( )
+ renderItem( )
expect(screen.getByText('Documents')).toBeInTheDocument()
})
@@ -25,7 +37,7 @@ describe('Item', () => {
// User interactions: clicking triggers callback with correct index
describe('User Interactions', () => {
it('should call onBreadcrumbClick with correct index on click', () => {
- render( )
+ renderItem( )
fireEvent.click(screen.getByText('Documents'))
@@ -34,7 +46,7 @@ describe('Item', () => {
})
it('should pass different index values correctly', () => {
- render( )
+ renderItem( )
fireEvent.click(screen.getByText('Documents'))
diff --git a/web/app/components/datasets/documents/create-from-pipeline/data-source/online-drive/file-list/header/breadcrumbs/dropdown/__tests__/menu.spec.tsx b/web/app/components/datasets/documents/create-from-pipeline/data-source/online-drive/file-list/header/breadcrumbs/dropdown/__tests__/menu.spec.tsx
index c8c6b8fec3..80c6f7bfb0 100644
--- a/web/app/components/datasets/documents/create-from-pipeline/data-source/online-drive/file-list/header/breadcrumbs/dropdown/__tests__/menu.spec.tsx
+++ b/web/app/components/datasets/documents/create-from-pipeline/data-source/online-drive/file-list/header/breadcrumbs/dropdown/__tests__/menu.spec.tsx
@@ -1,7 +1,19 @@
+import type { ReactElement } from 'react'
+import { DropdownMenu, DropdownMenuContent } from '@langgenius/dify-ui/dropdown-menu'
import { fireEvent, render, screen } from '@testing-library/react'
import { beforeEach, describe, expect, it, vi } from 'vitest'
import Menu from '../menu'
+const renderMenu = (ui: ReactElement) => {
+ return render(
+
+
+ {ui}
+
+ ,
+ )
+}
+
describe('Menu', () => {
const defaultProps = {
breadcrumbs: ['Folder A', 'Folder B', 'Folder C'],
@@ -16,7 +28,7 @@ describe('Menu', () => {
// Rendering: verify all breadcrumb items are displayed
describe('Rendering', () => {
it('should render all breadcrumb items', () => {
- render()
+ renderMenu()
expect(screen.getByText('Folder A')).toBeInTheDocument()
expect(screen.getByText('Folder B')).toBeInTheDocument()
@@ -36,7 +48,7 @@ describe('Menu', () => {
// Index mapping: startIndex offsets are applied correctly
describe('Index Mapping', () => {
it('should pass correct index (startIndex + offset) to each item', () => {
- render()
+ renderMenu()
fireEvent.click(screen.getByText('Folder A'))
expect(defaultProps.onBreadcrumbClick).toHaveBeenCalledWith(1)
@@ -49,7 +61,7 @@ describe('Menu', () => {
})
it('should offset from startIndex of zero', () => {
- render(
+ renderMenu(
/
diff --git a/web/app/components/datasets/documents/create-from-pipeline/data-source/online-drive/file-list/header/breadcrumbs/dropdown/item.tsx b/web/app/components/datasets/documents/create-from-pipeline/data-source/online-drive/file-list/header/breadcrumbs/dropdown/item.tsx
index 6f04ede88a..beb217f6b7 100644
--- a/web/app/components/datasets/documents/create-from-pipeline/data-source/online-drive/file-list/header/breadcrumbs/dropdown/item.tsx
+++ b/web/app/components/datasets/documents/create-from-pipeline/data-source/online-drive/file-list/header/breadcrumbs/dropdown/item.tsx
@@ -1,5 +1,5 @@
+import { DropdownMenuItem } from '@langgenius/dify-ui/dropdown-menu'
import * as React from 'react'
-import { useCallback } from 'react'
type ItemProps = {
name: string
@@ -12,17 +12,13 @@ const Item = ({
index,
onBreadcrumbClick,
}: ItemProps) => {
- const handleClick = useCallback(() => {
- onBreadcrumbClick(index)
- }, [index, onBreadcrumbClick])
-
return (
-
onBreadcrumbClick(index)}
>
{name}
-
+
)
}
diff --git a/web/app/components/datasets/documents/create-from-pipeline/data-source/online-drive/file-list/list/__tests__/index.spec.tsx b/web/app/components/datasets/documents/create-from-pipeline/data-source/online-drive/file-list/list/__tests__/index.spec.tsx
index 5b80b8ef31..04b8e16f17 100644
--- a/web/app/components/datasets/documents/create-from-pipeline/data-source/online-drive/file-list/list/__tests__/index.spec.tsx
+++ b/web/app/components/datasets/documents/create-from-pipeline/data-source/online-drive/file-list/list/__tests__/index.spec.tsx
@@ -1,5 +1,6 @@
import type { Mock } from 'vitest'
import type { OnlineDriveFile } from '@/models/pipeline'
+import { RadioGroup } from '@langgenius/dify-ui/radio-group'
import { fireEvent, render, screen, waitFor } from '@testing-library/react'
import * as React from 'react'
import { OnlineDriveFileType } from '@/models/pipeline'
@@ -1378,7 +1379,11 @@ describe('Item', () => {
it('should show radio as checked when isSelected is true', () => {
const props = createItemProps({ isSelected: true, isMultipleChoice: false })
- render(
)
+ render(
+
+
+ ,
+ )
const radio = getRadio()
expect(radio).toHaveAttribute('aria-checked', 'true')
})
@@ -1481,7 +1486,17 @@ describe('Item', () => {
const onSelect = vi.fn()
const file = createMockOnlineDriveFile()
const props = createItemProps({ file, onSelect, isMultipleChoice: false })
- render(
)
+ render(
+
{
+ if (fileId === file.id)
+ onSelect(file)
+ }}
+ >
+
+ ,
+ )
const radio = getRadio()
fireEvent.click(radio)
expect(onSelect).toHaveBeenCalledWith(file)
diff --git a/web/app/components/datasets/documents/create-from-pipeline/data-source/online-drive/file-list/list/__tests__/item.spec.tsx b/web/app/components/datasets/documents/create-from-pipeline/data-source/online-drive/file-list/list/__tests__/item.spec.tsx
index f4ad53bbe7..a2bdd69d58 100644
--- a/web/app/components/datasets/documents/create-from-pipeline/data-source/online-drive/file-list/list/__tests__/item.spec.tsx
+++ b/web/app/components/datasets/documents/create-from-pipeline/data-source/online-drive/file-list/list/__tests__/item.spec.tsx
@@ -1,14 +1,9 @@
import type { OnlineDriveFile } from '@/models/pipeline'
+import { RadioGroup } from '@langgenius/dify-ui/radio-group'
import { fireEvent, render, screen } from '@testing-library/react'
import { beforeEach, describe, expect, it, vi } from 'vitest'
import Item from '../item'
-vi.mock('@/app/components/base/radio/ui', () => ({
- default: ({ isChecked, onCheck }: { isChecked: boolean, onCheck: () => void }) => (
-
- ),
-}))
-
vi.mock('../file-icon', () => ({
default: () =>
,
}))
@@ -43,8 +38,13 @@ describe('Item', () => {
})
it('should render radio for file type in single choice mode', () => {
- render(
)
- expect(screen.getByTestId('radio')).toBeInTheDocument()
+ render(
+
+
+ ,
+ )
+
+ expect(screen.getByRole('radio', { name: 'test.pdf' })).toBeInTheDocument()
})
it('should not render checkbox for bucket type', () => {
diff --git a/web/app/components/datasets/documents/create-from-pipeline/data-source/online-drive/file-list/list/index.tsx b/web/app/components/datasets/documents/create-from-pipeline/data-source/online-drive/file-list/list/index.tsx
index 00386ec135..a74fd74324 100644
--- a/web/app/components/datasets/documents/create-from-pipeline/data-source/online-drive/file-list/list/index.tsx
+++ b/web/app/components/datasets/documents/create-from-pipeline/data-source/online-drive/file-list/list/index.tsx
@@ -1,4 +1,5 @@
import type { OnlineDriveFile } from '@/models/pipeline'
+import { RadioGroup } from '@langgenius/dify-ui/radio-group'
import { RiLoader2Line } from '@remixicon/react'
import * as React from 'react'
import { useEffect, useRef } from 'react'
@@ -53,6 +54,25 @@ const List = ({
const isPartialLoading = isLoading && fileList.length > 0
const isEmptyFolder = !isLoading && fileList.length === 0 && keywords.length === 0
const isSearchResultEmpty = !isLoading && fileList.length === 0 && keywords.length > 0
+ const selectedFileId = selectedFileIds[0]
+ const handleRadioChange = (fileId: string) => {
+ const selectedFile = fileList.find(file => file.id === fileId)
+ if (selectedFile)
+ handleSelectFile(selectedFile)
+ }
+ const fileItems = fileList.map((file) => {
+ const isSelected = selectedFileIds.includes(file.id)
+ return (
+
+ )
+ })
return (
@@ -73,21 +93,18 @@ const List = ({
}
{fileList.length > 0 && (
- {
- fileList.map((file) => {
- const isSelected = selectedFileIds.includes(file.id)
- return (
-
- )
- })
- }
+ {supportBatchUpload
+ ? fileItems
+ : (
+
+ {fileItems}
+
+ )}
{
isPartialLoading && (
| React.KeyboardEvent
) => {
- e.stopPropagation()
- onSelect(file)
- }, [file, onSelect])
-
const handleCheckboxSelect = useCallback(() => {
onSelect(file)
}, [file, onSelect])
@@ -70,12 +65,14 @@ const Item = ({
)}
{!isBucket && !isMultipleChoice && (
-
+ event.stopPropagation()}>
+
+
)}
{disabled
? (
diff --git a/web/app/components/datasets/documents/create-from-pipeline/data-source/website-crawl/base/__tests__/crawled-result-item.spec.tsx b/web/app/components/datasets/documents/create-from-pipeline/data-source/website-crawl/base/__tests__/crawled-result-item.spec.tsx
index b1bfc208d0..ea7ef85a78 100644
--- a/web/app/components/datasets/documents/create-from-pipeline/data-source/website-crawl/base/__tests__/crawled-result-item.spec.tsx
+++ b/web/app/components/datasets/documents/create-from-pipeline/data-source/website-crawl/base/__tests__/crawled-result-item.spec.tsx
@@ -1,4 +1,5 @@
import type { CrawlResultItem as CrawlResultItemType } from '@/models/datasets'
+import { RadioGroup } from '@langgenius/dify-ui/radio-group'
import { render, screen } from '@testing-library/react'
import { beforeEach, describe, expect, it, vi } from 'vitest'
import CrawledResultItem from '../crawled-result-item'
@@ -9,12 +10,6 @@ vi.mock('@langgenius/dify-ui/button', () => ({
),
}))
-vi.mock('@/app/components/base/radio/ui', () => ({
- default: ({ isChecked, onCheck }: { isChecked: boolean, onCheck: () => void }) => (
-
- ),
-}))
-
describe('CrawledResultItem', () => {
const defaultProps = {
payload: {
@@ -47,8 +42,13 @@ describe('CrawledResultItem', () => {
})
it('should render radio in single choice mode', () => {
- render()
- expect(screen.getByTestId('radio')).toBeInTheDocument()
+ render(
+
+
+ ,
+ )
+
+ expect(screen.getByRole('radio', { name: /Test Page/ })).toBeInTheDocument()
})
it('should show preview button when showPreview is true', () => {
diff --git a/web/app/components/datasets/documents/create-from-pipeline/data-source/website-crawl/base/__tests__/index.spec.tsx b/web/app/components/datasets/documents/create-from-pipeline/data-source/website-crawl/base/__tests__/index.spec.tsx
index f594f5c918..c6f86e3ada 100644
--- a/web/app/components/datasets/documents/create-from-pipeline/data-source/website-crawl/base/__tests__/index.spec.tsx
+++ b/web/app/components/datasets/documents/create-from-pipeline/data-source/website-crawl/base/__tests__/index.spec.tsx
@@ -1,4 +1,5 @@
import type { CrawlResultItem as CrawlResultItemType } from '@/models/datasets'
+import { RadioGroup } from '@langgenius/dify-ui/radio-group'
import { fireEvent, render, screen } from '@testing-library/react'
import userEvent from '@testing-library/user-event'
import * as React from 'react'
@@ -260,18 +261,24 @@ describe('CrawledResultItem', () => {
it('should toggle radio state when isMultipleChoice is false', () => {
const mockOnCheckChange = vi.fn()
- const { container } = render(
- ,
+ render(
+ {
+ if (sourceUrl === defaultProps.payload.source_url)
+ mockOnCheckChange(true)
+ }}
+ >
+
+ ,
)
- // Act - Radio uses size-4 rounded-full classes
- const radio = container.querySelector('.size-4.rounded-full')!
- fireEvent.click(radio)
+ fireEvent.click(screen.getByRole('radio', { name: /Test Page Title/ }))
expect(mockOnCheckChange).toHaveBeenCalledWith(true)
})
diff --git a/web/app/components/datasets/documents/create-from-pipeline/data-source/website-crawl/base/crawled-result-item.tsx b/web/app/components/datasets/documents/create-from-pipeline/data-source/website-crawl/base/crawled-result-item.tsx
index a1df2ed33c..d7ca87ef88 100644
--- a/web/app/components/datasets/documents/create-from-pipeline/data-source/website-crawl/base/crawled-result-item.tsx
+++ b/web/app/components/datasets/documents/create-from-pipeline/data-source/website-crawl/base/crawled-result-item.tsx
@@ -3,10 +3,9 @@ import type { CrawlResultItem as CrawlResultItemType } from '@/models/datasets'
import { Button } from '@langgenius/dify-ui/button'
import { Checkbox } from '@langgenius/dify-ui/checkbox'
import { cn } from '@langgenius/dify-ui/cn'
+import { Radio } from '@langgenius/dify-ui/radio'
import * as React from 'react'
-import { useCallback } from 'react'
import { useTranslation } from 'react-i18next'
-import Radio from '@/app/components/base/radio/ui'
type CrawledResultItemProps = {
payload: CrawlResultItemType
@@ -29,10 +28,6 @@ const CrawledResultItem = ({
}: CrawledResultItemProps) => {
const { t } = useTranslation()
- const handleCheckChange = useCallback(() => {
- onCheckChange(!isChecked)
- }, [isChecked, onCheckChange])
-
return (
)
: (
- <>
+