chore: show no empty logic

This commit is contained in:
Joel
2026-05-14 16:20:55 +08:00
committed by Jingyi-Dify
parent 939bdde373
commit 0e366c7300
2 changed files with 98 additions and 11 deletions

View File

@ -59,7 +59,7 @@ vi.mock('@/hooks/use-knowledge', () => ({
vi.mock('@/service/knowledge/use-dataset', () => ({
useDatasetList: vi.fn(() => ({
data: { pages: [{ data: [] }] },
data: { pages: [{ data: [], total: 1 }] },
fetchNextPage: vi.fn(),
hasNextPage: false,
isFetching: false,
@ -135,10 +135,18 @@ vi.mock('@/app/components/datasets/create/website/base/checkbox-with-label', ()
}))
describe('List', () => {
beforeEach(() => {
beforeEach(async () => {
vi.clearAllMocks()
mockBrandingEnabled = false
mockSearchParams = new URLSearchParams()
const { useDatasetList } = await import('@/service/knowledge/use-dataset')
vi.mocked(useDatasetList).mockReturnValue({
data: { pages: [{ data: [], total: 1 }] },
fetchNextPage: vi.fn(),
hasNextPage: false,
isFetching: false,
isFetchingNextPage: false,
} as unknown as ReturnType<typeof useDatasetList>)
})
describe('Rendering', () => {
@ -190,19 +198,34 @@ describe('List', () => {
})
describe('Props', () => {
it('should pass includeAll prop to Datasets', () => {
it('should query datasets with includeAll disabled initially', async () => {
const { useDatasetList } = await import('@/service/knowledge/use-dataset')
render(<List />)
expect(screen.getByTestId('include-all')).toHaveTextContent('false')
expect(useDatasetList).toHaveBeenCalledWith(expect.objectContaining({
include_all: false,
}))
})
it('should pass empty keywords initially', () => {
it('should query datasets with empty keywords initially', async () => {
const { useDatasetList } = await import('@/service/knowledge/use-dataset')
render(<List />)
expect(screen.getByTestId('keywords')).toHaveTextContent('')
expect(useDatasetList).toHaveBeenCalledWith(expect.objectContaining({
keyword: '',
}))
})
it('should pass empty tags initially', () => {
it('should query datasets with empty tags initially', async () => {
const { useDatasetList } = await import('@/service/knowledge/use-dataset')
render(<List />)
expect(screen.getByTestId('tags')).toHaveTextContent('')
expect(useDatasetList).toHaveBeenCalledWith(expect.objectContaining({
tag_ids: [],
}))
})
})
@ -256,6 +279,57 @@ describe('List', () => {
// Should render without errors even with empty data
expect(screen.getByTestId('datasets-component')).toBeInTheDocument()
})
it('should render first empty state when there are no datasets and no active filters', async () => {
const { useDatasetList } = await import('@/service/knowledge/use-dataset')
vi.mocked(useDatasetList).mockReturnValue({
data: { pages: [{ data: [], total: 0 }] },
fetchNextPage: vi.fn(),
hasNextPage: false,
isFetching: false,
isFetchingNextPage: false,
} as unknown as ReturnType<typeof useDatasetList>)
render(<List />)
expect(screen.getByText('dataset.firstEmpty.title')).toBeInTheDocument()
expect(screen.queryByTestId('datasets-component')).not.toBeInTheDocument()
expect(screen.queryByTestId('dataset-footer')).not.toBeInTheDocument()
})
it('should not render first empty state before the first dataset page resolves', async () => {
const { useDatasetList } = await import('@/service/knowledge/use-dataset')
vi.mocked(useDatasetList).mockReturnValue({
data: { pages: [] },
fetchNextPage: vi.fn(),
hasNextPage: false,
isFetching: false,
isFetchingNextPage: false,
} as unknown as ReturnType<typeof useDatasetList>)
render(<List />)
expect(screen.queryByText('dataset.firstEmpty.title')).not.toBeInTheDocument()
expect(screen.getByTestId('datasets-component')).toBeInTheDocument()
})
it('should keep the regular list for empty filtered results', async () => {
const { useDatasetList } = await import('@/service/knowledge/use-dataset')
vi.mocked(useDatasetList).mockImplementation(params => ({
data: { pages: [{ data: [], total: params.include_all ? 0 : 1 }] },
fetchNextPage: vi.fn(),
hasNextPage: false,
isFetching: false,
isFetchingNextPage: false,
} as unknown as ReturnType<typeof useDatasetList>))
render(<List />)
fireEvent.click(screen.getByTestId('include-all-checkbox'))
expect(screen.getByTestId('datasets-component')).toBeInTheDocument()
expect(screen.queryByText('dataset.firstEmpty.title')).not.toBeInTheDocument()
})
})
describe('Branch Coverage', () => {

View File

@ -5,7 +5,7 @@ import { useSuspenseQuery } from '@tanstack/react-query'
import { useBoolean, useDebounceFn } from 'ahooks'
// Libraries
import { useState } from 'react'
import { useMemo, useState } from 'react'
import { useTranslation } from 'react-i18next'
import Input from '@/app/components/base/input'
import CheckboxWithLabel from '@/app/components/datasets/create/website/base/checkbox-with-label'
@ -15,7 +15,7 @@ import { TagFilter } from '@/features/tag-management/components/tag-filter'
import { TagManagementModal } from '@/features/tag-management/components/tag-management-modal'
import useDocumentTitle from '@/hooks/use-document-title'
import { useSearchParams } from '@/next/navigation'
import { useDatasetApiBaseUrl, useInvalidDatasetList } from '@/service/knowledge/use-dataset'
import { useDatasetApiBaseUrl, useDatasetList, useInvalidDatasetList } from '@/service/knowledge/use-dataset'
import { systemFeaturesQueryOptions } from '@/service/system-features'
// Components
import ExternalAPIPanel from '../external-api/external-api-panel'
@ -55,8 +55,21 @@ const List = () => {
}
const isCurrentWorkspaceManager = useAppContextSelector(state => state.isCurrentWorkspaceManager)
const isCurrentWorkspaceEditor = useAppContextSelector(state => state.isCurrentWorkspaceEditor)
const { data: apiBaseInfo } = useDatasetApiBaseUrl()
const showEmptyDataList = searchParams.get('emptyDataList') === 'true'
const emptyDataList = searchParams.get('emptyDataList') === 'true'
const datasetListQuery = useDatasetList({
initialPage: 1,
tag_ids: tagIDs,
limit: 30,
include_all: includeAll,
keyword: searchKeywords,
})
const pages = useMemo(() => emptyDataList ? [{ data: [], total: 0 }] : datasetListQuery.data?.pages ?? [], [datasetListQuery.data?.pages, emptyDataList])
const hasResolvedFirstPage = pages.length > 0
const hasAnyDataset = (pages[0]?.total ?? 0) > 0
const hasActiveFilters = tagIDs.length > 0 || keywords.trim().length > 0 || searchKeywords.trim().length > 0 || includeAll
const showEmptyDataList = !hasAnyDataset && isCurrentWorkspaceEditor && (emptyDataList || (hasResolvedFirstPage && !hasActiveFilters))
return (
<div className="relative flex grow flex-col overflow-y-auto bg-background-body">