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:
@ -3,11 +3,7 @@ import type { InitialDocumentDetail } from '@/models/pipeline'
|
||||
import { render, screen } from '@testing-library/react'
|
||||
import * as React from 'react'
|
||||
import { DatasourceType } from '@/models/pipeline'
|
||||
import Processing from './index'
|
||||
|
||||
// ==========================================
|
||||
// Mock External Dependencies
|
||||
// ==========================================
|
||||
import Processing from '../index'
|
||||
|
||||
// Mock useDocLink - returns a function that generates doc URLs
|
||||
// Strips leading slash from path to match actual implementation behavior
|
||||
@ -33,7 +29,7 @@ vi.mock('@/context/dataset-detail', () => ({
|
||||
|
||||
// Mock the EmbeddingProcess component to track props
|
||||
let embeddingProcessProps: Record<string, unknown> = {}
|
||||
vi.mock('./embedding-process', () => ({
|
||||
vi.mock('../embedding-process', () => ({
|
||||
default: (props: Record<string, unknown>) => {
|
||||
embeddingProcessProps = props
|
||||
return (
|
||||
@ -48,9 +44,7 @@ vi.mock('./embedding-process', () => ({
|
||||
},
|
||||
}))
|
||||
|
||||
// ==========================================
|
||||
// Test Data Factory Functions
|
||||
// ==========================================
|
||||
|
||||
/**
|
||||
* Creates a mock InitialDocumentDetail for testing
|
||||
@ -80,10 +74,6 @@ const createMockDocuments = (count: number): InitialDocumentDetail[] =>
|
||||
position: index,
|
||||
}))
|
||||
|
||||
// ==========================================
|
||||
// Test Suite
|
||||
// ==========================================
|
||||
|
||||
describe('Processing', () => {
|
||||
beforeEach(() => {
|
||||
vi.clearAllMocks()
|
||||
@ -98,47 +88,36 @@ describe('Processing', () => {
|
||||
}
|
||||
})
|
||||
|
||||
// ==========================================
|
||||
// Rendering Tests
|
||||
// ==========================================
|
||||
describe('Rendering', () => {
|
||||
// Tests basic rendering functionality
|
||||
it('should render without crashing', () => {
|
||||
// Arrange
|
||||
const props = {
|
||||
batchId: 'batch-123',
|
||||
documents: createMockDocuments(2),
|
||||
}
|
||||
|
||||
// Act
|
||||
render(<Processing {...props} />)
|
||||
|
||||
// Assert
|
||||
expect(screen.getByTestId('embedding-process')).toBeInTheDocument()
|
||||
})
|
||||
|
||||
it('should render the EmbeddingProcess component', () => {
|
||||
// Arrange
|
||||
const props = {
|
||||
batchId: 'batch-456',
|
||||
documents: createMockDocuments(3),
|
||||
}
|
||||
|
||||
// Act
|
||||
render(<Processing {...props} />)
|
||||
|
||||
// Assert
|
||||
expect(screen.getByTestId('embedding-process')).toBeInTheDocument()
|
||||
})
|
||||
|
||||
it('should render the side tip section with correct content', () => {
|
||||
// Arrange
|
||||
const props = {
|
||||
batchId: 'batch-123',
|
||||
documents: createMockDocuments(1),
|
||||
}
|
||||
|
||||
// Act
|
||||
render(<Processing {...props} />)
|
||||
|
||||
// Assert - verify translation keys are rendered
|
||||
@ -148,16 +127,13 @@ describe('Processing', () => {
|
||||
})
|
||||
|
||||
it('should render the documentation link with correct attributes', () => {
|
||||
// Arrange
|
||||
const props = {
|
||||
batchId: 'batch-123',
|
||||
documents: createMockDocuments(1),
|
||||
}
|
||||
|
||||
// Act
|
||||
render(<Processing {...props} />)
|
||||
|
||||
// Assert
|
||||
const link = screen.getByRole('link', { name: 'datasetPipeline.addDocuments.stepThree.learnMore' })
|
||||
expect(link).toHaveAttribute('href', 'https://docs.dify.ai/en-US/use-dify/knowledge/knowledge-pipeline/authorize-data-source')
|
||||
expect(link).toHaveAttribute('target', '_blank')
|
||||
@ -165,13 +141,11 @@ describe('Processing', () => {
|
||||
})
|
||||
|
||||
it('should render the book icon in the side tip', () => {
|
||||
// Arrange
|
||||
const props = {
|
||||
batchId: 'batch-123',
|
||||
documents: createMockDocuments(1),
|
||||
}
|
||||
|
||||
// Act
|
||||
const { container } = render(<Processing {...props} />)
|
||||
|
||||
// Assert - check for icon container with shadow styling
|
||||
@ -180,45 +154,35 @@ describe('Processing', () => {
|
||||
})
|
||||
})
|
||||
|
||||
// ==========================================
|
||||
// Props Testing
|
||||
// ==========================================
|
||||
describe('Props', () => {
|
||||
// Tests that props are correctly passed to child components
|
||||
it('should pass batchId to EmbeddingProcess', () => {
|
||||
// Arrange
|
||||
const testBatchId = 'test-batch-id-789'
|
||||
const props = {
|
||||
batchId: testBatchId,
|
||||
documents: createMockDocuments(1),
|
||||
}
|
||||
|
||||
// Act
|
||||
render(<Processing {...props} />)
|
||||
|
||||
// Assert
|
||||
expect(screen.getByTestId('ep-batch-id')).toHaveTextContent(testBatchId)
|
||||
expect(embeddingProcessProps.batchId).toBe(testBatchId)
|
||||
})
|
||||
|
||||
it('should pass documents to EmbeddingProcess', () => {
|
||||
// Arrange
|
||||
const documents = createMockDocuments(5)
|
||||
const props = {
|
||||
batchId: 'batch-123',
|
||||
documents,
|
||||
}
|
||||
|
||||
// Act
|
||||
render(<Processing {...props} />)
|
||||
|
||||
// Assert
|
||||
expect(screen.getByTestId('ep-documents-count')).toHaveTextContent('5')
|
||||
expect(embeddingProcessProps.documents).toEqual(documents)
|
||||
})
|
||||
|
||||
it('should pass datasetId from context to EmbeddingProcess', () => {
|
||||
// Arrange
|
||||
mockDataset = {
|
||||
id: 'context-dataset-id',
|
||||
indexing_technique: 'high_quality',
|
||||
@ -229,16 +193,13 @@ describe('Processing', () => {
|
||||
documents: createMockDocuments(1),
|
||||
}
|
||||
|
||||
// Act
|
||||
render(<Processing {...props} />)
|
||||
|
||||
// Assert
|
||||
expect(screen.getByTestId('ep-dataset-id')).toHaveTextContent('context-dataset-id')
|
||||
expect(embeddingProcessProps.datasetId).toBe('context-dataset-id')
|
||||
})
|
||||
|
||||
it('should pass indexingType from context to EmbeddingProcess', () => {
|
||||
// Arrange
|
||||
mockDataset = {
|
||||
id: 'dataset-123',
|
||||
indexing_technique: 'economy',
|
||||
@ -249,16 +210,13 @@ describe('Processing', () => {
|
||||
documents: createMockDocuments(1),
|
||||
}
|
||||
|
||||
// Act
|
||||
render(<Processing {...props} />)
|
||||
|
||||
// Assert
|
||||
expect(screen.getByTestId('ep-indexing-type')).toHaveTextContent('economy')
|
||||
expect(embeddingProcessProps.indexingType).toBe('economy')
|
||||
})
|
||||
|
||||
it('should pass retrievalMethod from context to EmbeddingProcess', () => {
|
||||
// Arrange
|
||||
mockDataset = {
|
||||
id: 'dataset-123',
|
||||
indexing_technique: 'high_quality',
|
||||
@ -269,16 +227,13 @@ describe('Processing', () => {
|
||||
documents: createMockDocuments(1),
|
||||
}
|
||||
|
||||
// Act
|
||||
render(<Processing {...props} />)
|
||||
|
||||
// Assert
|
||||
expect(screen.getByTestId('ep-retrieval-method')).toHaveTextContent('keyword_search')
|
||||
expect(embeddingProcessProps.retrievalMethod).toBe('keyword_search')
|
||||
})
|
||||
|
||||
it('should handle different document types', () => {
|
||||
// Arrange
|
||||
const documents = [
|
||||
createMockDocument({
|
||||
id: 'doc-local',
|
||||
@ -301,63 +256,49 @@ describe('Processing', () => {
|
||||
documents,
|
||||
}
|
||||
|
||||
// Act
|
||||
render(<Processing {...props} />)
|
||||
|
||||
// Assert
|
||||
expect(screen.getByTestId('ep-documents-count')).toHaveTextContent('3')
|
||||
expect(embeddingProcessProps.documents).toEqual(documents)
|
||||
})
|
||||
})
|
||||
|
||||
// ==========================================
|
||||
// Edge Cases
|
||||
// ==========================================
|
||||
describe('Edge Cases', () => {
|
||||
// Tests for boundary conditions and unusual inputs
|
||||
it('should handle empty documents array', () => {
|
||||
// Arrange
|
||||
const props = {
|
||||
batchId: 'batch-123',
|
||||
documents: [],
|
||||
}
|
||||
|
||||
// Act
|
||||
render(<Processing {...props} />)
|
||||
|
||||
// Assert
|
||||
expect(screen.getByTestId('embedding-process')).toBeInTheDocument()
|
||||
expect(screen.getByTestId('ep-documents-count')).toHaveTextContent('0')
|
||||
expect(embeddingProcessProps.documents).toEqual([])
|
||||
})
|
||||
|
||||
it('should handle empty batchId', () => {
|
||||
// Arrange
|
||||
const props = {
|
||||
batchId: '',
|
||||
documents: createMockDocuments(1),
|
||||
}
|
||||
|
||||
// Act
|
||||
render(<Processing {...props} />)
|
||||
|
||||
// Assert
|
||||
expect(screen.getByTestId('embedding-process')).toBeInTheDocument()
|
||||
expect(screen.getByTestId('ep-batch-id')).toHaveTextContent('')
|
||||
})
|
||||
|
||||
it('should handle undefined dataset from context', () => {
|
||||
// Arrange
|
||||
mockDataset = undefined
|
||||
const props = {
|
||||
batchId: 'batch-123',
|
||||
documents: createMockDocuments(1),
|
||||
}
|
||||
|
||||
// Act
|
||||
render(<Processing {...props} />)
|
||||
|
||||
// Assert
|
||||
expect(screen.getByTestId('embedding-process')).toBeInTheDocument()
|
||||
expect(embeddingProcessProps.datasetId).toBeUndefined()
|
||||
expect(embeddingProcessProps.indexingType).toBeUndefined()
|
||||
@ -365,7 +306,6 @@ describe('Processing', () => {
|
||||
})
|
||||
|
||||
it('should handle dataset with undefined id', () => {
|
||||
// Arrange
|
||||
mockDataset = {
|
||||
id: undefined,
|
||||
indexing_technique: 'high_quality',
|
||||
@ -376,16 +316,13 @@ describe('Processing', () => {
|
||||
documents: createMockDocuments(1),
|
||||
}
|
||||
|
||||
// Act
|
||||
render(<Processing {...props} />)
|
||||
|
||||
// Assert
|
||||
expect(screen.getByTestId('embedding-process')).toBeInTheDocument()
|
||||
expect(embeddingProcessProps.datasetId).toBeUndefined()
|
||||
})
|
||||
|
||||
it('should handle dataset with undefined indexing_technique', () => {
|
||||
// Arrange
|
||||
mockDataset = {
|
||||
id: 'dataset-123',
|
||||
indexing_technique: undefined,
|
||||
@ -396,16 +333,13 @@ describe('Processing', () => {
|
||||
documents: createMockDocuments(1),
|
||||
}
|
||||
|
||||
// Act
|
||||
render(<Processing {...props} />)
|
||||
|
||||
// Assert
|
||||
expect(screen.getByTestId('embedding-process')).toBeInTheDocument()
|
||||
expect(embeddingProcessProps.indexingType).toBeUndefined()
|
||||
})
|
||||
|
||||
it('should handle dataset with undefined retrieval_model_dict', () => {
|
||||
// Arrange
|
||||
mockDataset = {
|
||||
id: 'dataset-123',
|
||||
indexing_technique: 'high_quality',
|
||||
@ -416,16 +350,13 @@ describe('Processing', () => {
|
||||
documents: createMockDocuments(1),
|
||||
}
|
||||
|
||||
// Act
|
||||
render(<Processing {...props} />)
|
||||
|
||||
// Assert
|
||||
expect(screen.getByTestId('embedding-process')).toBeInTheDocument()
|
||||
expect(embeddingProcessProps.retrievalMethod).toBeUndefined()
|
||||
})
|
||||
|
||||
it('should handle dataset with empty retrieval_model_dict', () => {
|
||||
// Arrange
|
||||
mockDataset = {
|
||||
id: 'dataset-123',
|
||||
indexing_technique: 'high_quality',
|
||||
@ -436,31 +367,25 @@ describe('Processing', () => {
|
||||
documents: createMockDocuments(1),
|
||||
}
|
||||
|
||||
// Act
|
||||
render(<Processing {...props} />)
|
||||
|
||||
// Assert
|
||||
expect(screen.getByTestId('embedding-process')).toBeInTheDocument()
|
||||
expect(embeddingProcessProps.retrievalMethod).toBeUndefined()
|
||||
})
|
||||
|
||||
it('should handle large number of documents', () => {
|
||||
// Arrange
|
||||
const props = {
|
||||
batchId: 'batch-123',
|
||||
documents: createMockDocuments(100),
|
||||
}
|
||||
|
||||
// Act
|
||||
render(<Processing {...props} />)
|
||||
|
||||
// Assert
|
||||
expect(screen.getByTestId('embedding-process')).toBeInTheDocument()
|
||||
expect(screen.getByTestId('ep-documents-count')).toHaveTextContent('100')
|
||||
})
|
||||
|
||||
it('should handle documents with error status', () => {
|
||||
// Arrange
|
||||
const documents = [
|
||||
createMockDocument({
|
||||
id: 'doc-error',
|
||||
@ -474,16 +399,13 @@ describe('Processing', () => {
|
||||
documents,
|
||||
}
|
||||
|
||||
// Act
|
||||
render(<Processing {...props} />)
|
||||
|
||||
// Assert
|
||||
expect(screen.getByTestId('embedding-process')).toBeInTheDocument()
|
||||
expect(embeddingProcessProps.documents).toEqual(documents)
|
||||
})
|
||||
|
||||
it('should handle documents with special characters in names', () => {
|
||||
// Arrange
|
||||
const documents = [
|
||||
createMockDocument({
|
||||
id: 'doc-special',
|
||||
@ -495,36 +417,28 @@ describe('Processing', () => {
|
||||
documents,
|
||||
}
|
||||
|
||||
// Act
|
||||
render(<Processing {...props} />)
|
||||
|
||||
// Assert
|
||||
expect(screen.getByTestId('embedding-process')).toBeInTheDocument()
|
||||
expect(embeddingProcessProps.documents).toEqual(documents)
|
||||
})
|
||||
|
||||
it('should handle batchId with special characters', () => {
|
||||
// Arrange
|
||||
const props = {
|
||||
batchId: 'batch-123-abc_xyz:456',
|
||||
documents: createMockDocuments(1),
|
||||
}
|
||||
|
||||
// Act
|
||||
render(<Processing {...props} />)
|
||||
|
||||
// Assert
|
||||
expect(screen.getByTestId('ep-batch-id')).toHaveTextContent('batch-123-abc_xyz:456')
|
||||
})
|
||||
})
|
||||
|
||||
// ==========================================
|
||||
// Context Integration Tests
|
||||
// ==========================================
|
||||
describe('Context Integration', () => {
|
||||
// Tests for proper context usage
|
||||
it('should correctly use context selectors for all dataset properties', () => {
|
||||
// Arrange
|
||||
mockDataset = {
|
||||
id: 'full-dataset-id',
|
||||
indexing_technique: 'high_quality',
|
||||
@ -535,10 +449,8 @@ describe('Processing', () => {
|
||||
documents: createMockDocuments(1),
|
||||
}
|
||||
|
||||
// Act
|
||||
render(<Processing {...props} />)
|
||||
|
||||
// Assert
|
||||
expect(embeddingProcessProps.datasetId).toBe('full-dataset-id')
|
||||
expect(embeddingProcessProps.indexingType).toBe('high_quality')
|
||||
expect(embeddingProcessProps.retrievalMethod).toBe('hybrid_search')
|
||||
@ -556,7 +468,6 @@ describe('Processing', () => {
|
||||
documents: createMockDocuments(1),
|
||||
}
|
||||
|
||||
// Act
|
||||
const { rerender } = render(<Processing {...props} />)
|
||||
|
||||
// Assert economy indexing
|
||||
@ -577,19 +488,14 @@ describe('Processing', () => {
|
||||
})
|
||||
})
|
||||
|
||||
// ==========================================
|
||||
// Layout Tests
|
||||
// ==========================================
|
||||
describe('Layout', () => {
|
||||
// Tests for proper layout and structure
|
||||
it('should render with correct layout structure', () => {
|
||||
// Arrange
|
||||
const props = {
|
||||
batchId: 'batch-123',
|
||||
documents: createMockDocuments(1),
|
||||
}
|
||||
|
||||
// Act
|
||||
const { container } = render(<Processing {...props} />)
|
||||
|
||||
// Assert - Check for flex layout with proper widths
|
||||
@ -606,13 +512,11 @@ describe('Processing', () => {
|
||||
})
|
||||
|
||||
it('should render side tip card with correct styling', () => {
|
||||
// Arrange
|
||||
const props = {
|
||||
batchId: 'batch-123',
|
||||
documents: createMockDocuments(1),
|
||||
}
|
||||
|
||||
// Act
|
||||
const { container } = render(<Processing {...props} />)
|
||||
|
||||
// Assert - Check for card container with rounded corners and background
|
||||
@ -621,28 +525,22 @@ describe('Processing', () => {
|
||||
})
|
||||
|
||||
it('should constrain max-width for EmbeddingProcess container', () => {
|
||||
// Arrange
|
||||
const props = {
|
||||
batchId: 'batch-123',
|
||||
documents: createMockDocuments(1),
|
||||
}
|
||||
|
||||
// Act
|
||||
const { container } = render(<Processing {...props} />)
|
||||
|
||||
// Assert
|
||||
const maxWidthContainer = container.querySelector('.max-w-\\[640px\\]')
|
||||
expect(maxWidthContainer).toBeInTheDocument()
|
||||
})
|
||||
})
|
||||
|
||||
// ==========================================
|
||||
// Document Variations Tests
|
||||
// ==========================================
|
||||
describe('Document Variations', () => {
|
||||
// Tests for different document configurations
|
||||
it('should handle documents with all indexing statuses', () => {
|
||||
// Arrange
|
||||
const statuses: DocumentIndexingStatus[] = [
|
||||
'waiting',
|
||||
'parsing',
|
||||
@ -666,16 +564,13 @@ describe('Processing', () => {
|
||||
documents,
|
||||
}
|
||||
|
||||
// Act
|
||||
render(<Processing {...props} />)
|
||||
|
||||
// Assert
|
||||
expect(screen.getByTestId('ep-documents-count')).toHaveTextContent(String(statuses.length))
|
||||
expect(embeddingProcessProps.documents).toEqual(documents)
|
||||
})
|
||||
|
||||
it('should handle documents with enabled and disabled states', () => {
|
||||
// Arrange
|
||||
const documents = [
|
||||
createMockDocument({ id: 'doc-enabled', enable: true }),
|
||||
createMockDocument({ id: 'doc-disabled', enable: false }),
|
||||
@ -685,16 +580,13 @@ describe('Processing', () => {
|
||||
documents,
|
||||
}
|
||||
|
||||
// Act
|
||||
render(<Processing {...props} />)
|
||||
|
||||
// Assert
|
||||
expect(screen.getByTestId('ep-documents-count')).toHaveTextContent('2')
|
||||
expect(embeddingProcessProps.documents).toEqual(documents)
|
||||
})
|
||||
|
||||
it('should handle documents from online drive source', () => {
|
||||
// Arrange
|
||||
const documents = [
|
||||
createMockDocument({
|
||||
id: 'doc-drive',
|
||||
@ -708,16 +600,13 @@ describe('Processing', () => {
|
||||
documents,
|
||||
}
|
||||
|
||||
// Act
|
||||
render(<Processing {...props} />)
|
||||
|
||||
// Assert
|
||||
expect(screen.getByTestId('embedding-process')).toBeInTheDocument()
|
||||
expect(embeddingProcessProps.documents).toEqual(documents)
|
||||
})
|
||||
|
||||
it('should handle documents with complex data_source_info', () => {
|
||||
// Arrange
|
||||
const documents = [
|
||||
createMockDocument({
|
||||
id: 'doc-notion',
|
||||
@ -735,23 +624,18 @@ describe('Processing', () => {
|
||||
documents,
|
||||
}
|
||||
|
||||
// Act
|
||||
render(<Processing {...props} />)
|
||||
|
||||
// Assert
|
||||
expect(embeddingProcessProps.documents).toEqual(documents)
|
||||
})
|
||||
})
|
||||
|
||||
// ==========================================
|
||||
// Retrieval Method Variations
|
||||
// ==========================================
|
||||
describe('Retrieval Method Variations', () => {
|
||||
// Tests for different retrieval methods
|
||||
const retrievalMethods = ['semantic_search', 'keyword_search', 'hybrid_search', 'full_text_search']
|
||||
|
||||
it.each(retrievalMethods)('should handle %s retrieval method', (method) => {
|
||||
// Arrange
|
||||
mockDataset = {
|
||||
id: 'dataset-123',
|
||||
indexing_technique: 'high_quality',
|
||||
@ -762,23 +646,18 @@ describe('Processing', () => {
|
||||
documents: createMockDocuments(1),
|
||||
}
|
||||
|
||||
// Act
|
||||
render(<Processing {...props} />)
|
||||
|
||||
// Assert
|
||||
expect(embeddingProcessProps.retrievalMethod).toBe(method)
|
||||
})
|
||||
})
|
||||
|
||||
// ==========================================
|
||||
// Indexing Technique Variations
|
||||
// ==========================================
|
||||
describe('Indexing Technique Variations', () => {
|
||||
// Tests for different indexing techniques
|
||||
const indexingTechniques = ['high_quality', 'economy']
|
||||
|
||||
it.each(indexingTechniques)('should handle %s indexing technique', (technique) => {
|
||||
// Arrange
|
||||
mockDataset = {
|
||||
id: 'dataset-123',
|
||||
indexing_technique: technique,
|
||||
@ -789,10 +668,8 @@ describe('Processing', () => {
|
||||
documents: createMockDocuments(1),
|
||||
}
|
||||
|
||||
// Act
|
||||
render(<Processing {...props} />)
|
||||
|
||||
// Assert
|
||||
expect(embeddingProcessProps.indexingType).toBe(technique)
|
||||
})
|
||||
})
|
||||
@ -7,13 +7,8 @@ import { Plan } from '@/app/components/billing/type'
|
||||
import { IndexingType } from '@/app/components/datasets/create/step-two'
|
||||
import { DatasourceType } from '@/models/pipeline'
|
||||
import { RETRIEVE_METHOD } from '@/types/app'
|
||||
import EmbeddingProcess from './index'
|
||||
import EmbeddingProcess from '../index'
|
||||
|
||||
// ==========================================
|
||||
// Mock External Dependencies
|
||||
// ==========================================
|
||||
|
||||
// Mock next/navigation
|
||||
const mockPush = vi.fn()
|
||||
vi.mock('next/navigation', () => ({
|
||||
useRouter: () => ({
|
||||
@ -64,9 +59,7 @@ vi.mock('@/hooks/use-api-access-url', () => ({
|
||||
useDatasetApiAccessUrl: () => 'https://docs.dify.ai/api-reference/datasets',
|
||||
}))
|
||||
|
||||
// ==========================================
|
||||
// Test Data Factory Functions
|
||||
// ==========================================
|
||||
|
||||
/**
|
||||
* Creates a mock InitialDocumentDetail for testing
|
||||
@ -122,10 +115,6 @@ const createDefaultProps = (overrides: Partial<{
|
||||
...overrides,
|
||||
})
|
||||
|
||||
// ==========================================
|
||||
// Test Suite
|
||||
// ==========================================
|
||||
|
||||
describe('EmbeddingProcess', () => {
|
||||
beforeEach(() => {
|
||||
vi.clearAllMocks()
|
||||
@ -151,30 +140,22 @@ describe('EmbeddingProcess', () => {
|
||||
vi.useRealTimers()
|
||||
})
|
||||
|
||||
// ==========================================
|
||||
// Rendering Tests
|
||||
// ==========================================
|
||||
describe('Rendering', () => {
|
||||
// Tests basic rendering functionality
|
||||
it('should render without crashing', () => {
|
||||
// Arrange
|
||||
const props = createDefaultProps()
|
||||
|
||||
// Act
|
||||
render(<EmbeddingProcess {...props} />)
|
||||
|
||||
// Assert
|
||||
expect(screen.getByTestId('rule-detail')).toBeInTheDocument()
|
||||
})
|
||||
|
||||
it('should render RuleDetail component with correct props', () => {
|
||||
// Arrange
|
||||
const props = createDefaultProps({
|
||||
indexingType: IndexingType.ECONOMICAL,
|
||||
retrievalMethod: RETRIEVE_METHOD.fullText,
|
||||
})
|
||||
|
||||
// Act
|
||||
render(<EmbeddingProcess {...props} />)
|
||||
|
||||
// Assert - RuleDetail renders FieldInfo components with translated text
|
||||
@ -183,13 +164,10 @@ describe('EmbeddingProcess', () => {
|
||||
})
|
||||
|
||||
it('should render API reference link with correct URL', () => {
|
||||
// Arrange
|
||||
const props = createDefaultProps()
|
||||
|
||||
// Act
|
||||
render(<EmbeddingProcess {...props} />)
|
||||
|
||||
// Assert
|
||||
const apiLink = screen.getByRole('link', { name: /access the api/i })
|
||||
expect(apiLink).toHaveAttribute('href', 'https://docs.dify.ai/api-reference/datasets')
|
||||
expect(apiLink).toHaveAttribute('target', '_blank')
|
||||
@ -197,231 +175,185 @@ describe('EmbeddingProcess', () => {
|
||||
})
|
||||
|
||||
it('should render navigation button', () => {
|
||||
// Arrange
|
||||
const props = createDefaultProps()
|
||||
|
||||
// Act
|
||||
render(<EmbeddingProcess {...props} />)
|
||||
|
||||
// Assert
|
||||
expect(screen.getByText('datasetCreation.stepThree.navTo')).toBeInTheDocument()
|
||||
})
|
||||
})
|
||||
|
||||
// ==========================================
|
||||
// Billing/Upgrade Banner Tests
|
||||
// ==========================================
|
||||
describe('Billing and Upgrade Banner', () => {
|
||||
// Tests for billing-related UI
|
||||
it('should not show upgrade banner when billing is disabled', () => {
|
||||
// Arrange
|
||||
mockEnableBilling = false
|
||||
const props = createDefaultProps()
|
||||
|
||||
// Act
|
||||
render(<EmbeddingProcess {...props} />)
|
||||
|
||||
// Assert
|
||||
expect(screen.queryByText('billing.plansCommon.documentProcessingPriorityUpgrade')).not.toBeInTheDocument()
|
||||
})
|
||||
|
||||
it('should show upgrade banner when billing is enabled and plan is not team', () => {
|
||||
// Arrange
|
||||
mockEnableBilling = true
|
||||
mockPlanType = Plan.sandbox
|
||||
const props = createDefaultProps()
|
||||
|
||||
// Act
|
||||
render(<EmbeddingProcess {...props} />)
|
||||
|
||||
// Assert
|
||||
expect(screen.getByText('billing.plansCommon.documentProcessingPriorityUpgrade')).toBeInTheDocument()
|
||||
})
|
||||
|
||||
it('should not show upgrade banner when plan is team', () => {
|
||||
// Arrange
|
||||
mockEnableBilling = true
|
||||
mockPlanType = Plan.team
|
||||
const props = createDefaultProps()
|
||||
|
||||
// Act
|
||||
render(<EmbeddingProcess {...props} />)
|
||||
|
||||
// Assert
|
||||
expect(screen.queryByText('billing.plansCommon.documentProcessingPriorityUpgrade')).not.toBeInTheDocument()
|
||||
})
|
||||
|
||||
it('should show upgrade banner for professional plan', () => {
|
||||
// Arrange
|
||||
mockEnableBilling = true
|
||||
mockPlanType = Plan.professional
|
||||
const props = createDefaultProps()
|
||||
|
||||
// Act
|
||||
render(<EmbeddingProcess {...props} />)
|
||||
|
||||
// Assert
|
||||
expect(screen.getByText('billing.plansCommon.documentProcessingPriorityUpgrade')).toBeInTheDocument()
|
||||
})
|
||||
})
|
||||
|
||||
// ==========================================
|
||||
// Status Display Tests
|
||||
// ==========================================
|
||||
describe('Status Display', () => {
|
||||
// Tests for embedding status display
|
||||
it('should show waiting status when all documents are waiting', async () => {
|
||||
// Arrange
|
||||
const doc1 = createMockDocument({ id: 'doc-1' })
|
||||
mockIndexingStatusData = [
|
||||
createMockIndexingStatus({ id: 'doc-1', indexing_status: 'waiting' }),
|
||||
]
|
||||
const props = createDefaultProps({ documents: [doc1] })
|
||||
|
||||
// Act
|
||||
render(<EmbeddingProcess {...props} />)
|
||||
await waitFor(() => {
|
||||
expect(mockFetchIndexingStatus).toHaveBeenCalled()
|
||||
})
|
||||
|
||||
// Assert
|
||||
expect(screen.getByText('datasetDocuments.embedding.waiting')).toBeInTheDocument()
|
||||
})
|
||||
|
||||
it('should show processing status when any document is indexing', async () => {
|
||||
// Arrange
|
||||
const doc1 = createMockDocument({ id: 'doc-1' })
|
||||
mockIndexingStatusData = [
|
||||
createMockIndexingStatus({ id: 'doc-1', indexing_status: 'indexing' }),
|
||||
]
|
||||
const props = createDefaultProps({ documents: [doc1] })
|
||||
|
||||
// Act
|
||||
render(<EmbeddingProcess {...props} />)
|
||||
await waitFor(() => {
|
||||
expect(mockFetchIndexingStatus).toHaveBeenCalled()
|
||||
})
|
||||
|
||||
// Assert
|
||||
expect(screen.getByText('datasetDocuments.embedding.processing')).toBeInTheDocument()
|
||||
})
|
||||
|
||||
it('should show processing status when any document is splitting', async () => {
|
||||
// Arrange
|
||||
const doc1 = createMockDocument({ id: 'doc-1' })
|
||||
mockIndexingStatusData = [
|
||||
createMockIndexingStatus({ id: 'doc-1', indexing_status: 'splitting' }),
|
||||
]
|
||||
const props = createDefaultProps({ documents: [doc1] })
|
||||
|
||||
// Act
|
||||
render(<EmbeddingProcess {...props} />)
|
||||
await waitFor(() => {
|
||||
expect(mockFetchIndexingStatus).toHaveBeenCalled()
|
||||
})
|
||||
|
||||
// Assert
|
||||
expect(screen.getByText('datasetDocuments.embedding.processing')).toBeInTheDocument()
|
||||
})
|
||||
|
||||
it('should show processing status when any document is parsing', async () => {
|
||||
// Arrange
|
||||
const doc1 = createMockDocument({ id: 'doc-1' })
|
||||
mockIndexingStatusData = [
|
||||
createMockIndexingStatus({ id: 'doc-1', indexing_status: 'parsing' }),
|
||||
]
|
||||
const props = createDefaultProps({ documents: [doc1] })
|
||||
|
||||
// Act
|
||||
render(<EmbeddingProcess {...props} />)
|
||||
await waitFor(() => {
|
||||
expect(mockFetchIndexingStatus).toHaveBeenCalled()
|
||||
})
|
||||
|
||||
// Assert
|
||||
expect(screen.getByText('datasetDocuments.embedding.processing')).toBeInTheDocument()
|
||||
})
|
||||
|
||||
it('should show processing status when any document is cleaning', async () => {
|
||||
// Arrange
|
||||
const doc1 = createMockDocument({ id: 'doc-1' })
|
||||
mockIndexingStatusData = [
|
||||
createMockIndexingStatus({ id: 'doc-1', indexing_status: 'cleaning' }),
|
||||
]
|
||||
const props = createDefaultProps({ documents: [doc1] })
|
||||
|
||||
// Act
|
||||
render(<EmbeddingProcess {...props} />)
|
||||
await waitFor(() => {
|
||||
expect(mockFetchIndexingStatus).toHaveBeenCalled()
|
||||
})
|
||||
|
||||
// Assert
|
||||
expect(screen.getByText('datasetDocuments.embedding.processing')).toBeInTheDocument()
|
||||
})
|
||||
|
||||
it('should show completed status when all documents are completed', async () => {
|
||||
// Arrange
|
||||
const doc1 = createMockDocument({ id: 'doc-1' })
|
||||
mockIndexingStatusData = [
|
||||
createMockIndexingStatus({ id: 'doc-1', indexing_status: 'completed' }),
|
||||
]
|
||||
const props = createDefaultProps({ documents: [doc1] })
|
||||
|
||||
// Act
|
||||
render(<EmbeddingProcess {...props} />)
|
||||
await waitFor(() => {
|
||||
expect(mockFetchIndexingStatus).toHaveBeenCalled()
|
||||
})
|
||||
|
||||
// Assert
|
||||
expect(screen.getByText('datasetDocuments.embedding.completed')).toBeInTheDocument()
|
||||
})
|
||||
|
||||
it('should show completed status when all documents have error status', async () => {
|
||||
// Arrange
|
||||
const doc1 = createMockDocument({ id: 'doc-1' })
|
||||
mockIndexingStatusData = [
|
||||
createMockIndexingStatus({ id: 'doc-1', indexing_status: 'error', error: 'Processing failed' }),
|
||||
]
|
||||
const props = createDefaultProps({ documents: [doc1] })
|
||||
|
||||
// Act
|
||||
render(<EmbeddingProcess {...props} />)
|
||||
await waitFor(() => {
|
||||
expect(mockFetchIndexingStatus).toHaveBeenCalled()
|
||||
})
|
||||
|
||||
// Assert
|
||||
expect(screen.getByText('datasetDocuments.embedding.completed')).toBeInTheDocument()
|
||||
})
|
||||
|
||||
it('should show completed status when all documents are paused', async () => {
|
||||
// Arrange
|
||||
const doc1 = createMockDocument({ id: 'doc-1' })
|
||||
mockIndexingStatusData = [
|
||||
createMockIndexingStatus({ id: 'doc-1', indexing_status: 'paused' }),
|
||||
]
|
||||
const props = createDefaultProps({ documents: [doc1] })
|
||||
|
||||
// Act
|
||||
render(<EmbeddingProcess {...props} />)
|
||||
await waitFor(() => {
|
||||
expect(mockFetchIndexingStatus).toHaveBeenCalled()
|
||||
})
|
||||
|
||||
// Assert
|
||||
expect(screen.getByText('datasetDocuments.embedding.completed')).toBeInTheDocument()
|
||||
})
|
||||
})
|
||||
|
||||
// ==========================================
|
||||
// Progress Bar Tests
|
||||
// ==========================================
|
||||
describe('Progress Display', () => {
|
||||
// Tests for progress bar rendering
|
||||
it('should show progress percentage for embedding documents', async () => {
|
||||
// Arrange
|
||||
const doc1 = createMockDocument({ id: 'doc-1' })
|
||||
mockIndexingStatusData = [
|
||||
createMockIndexingStatus({
|
||||
@ -433,18 +365,15 @@ describe('EmbeddingProcess', () => {
|
||||
]
|
||||
const props = createDefaultProps({ documents: [doc1] })
|
||||
|
||||
// Act
|
||||
render(<EmbeddingProcess {...props} />)
|
||||
await waitFor(() => {
|
||||
expect(mockFetchIndexingStatus).toHaveBeenCalled()
|
||||
})
|
||||
|
||||
// Assert
|
||||
expect(screen.getByText('50%')).toBeInTheDocument()
|
||||
})
|
||||
|
||||
it('should cap progress at 100%', async () => {
|
||||
// Arrange
|
||||
const doc1 = createMockDocument({ id: 'doc-1' })
|
||||
mockIndexingStatusData = [
|
||||
createMockIndexingStatus({
|
||||
@ -456,18 +385,15 @@ describe('EmbeddingProcess', () => {
|
||||
]
|
||||
const props = createDefaultProps({ documents: [doc1] })
|
||||
|
||||
// Act
|
||||
render(<EmbeddingProcess {...props} />)
|
||||
await waitFor(() => {
|
||||
expect(mockFetchIndexingStatus).toHaveBeenCalled()
|
||||
})
|
||||
|
||||
// Assert
|
||||
expect(screen.getByText('100%')).toBeInTheDocument()
|
||||
})
|
||||
|
||||
it('should show 0% when total_segments is 0', async () => {
|
||||
// Arrange
|
||||
const doc1 = createMockDocument({ id: 'doc-1' })
|
||||
mockIndexingStatusData = [
|
||||
createMockIndexingStatus({
|
||||
@ -479,18 +405,15 @@ describe('EmbeddingProcess', () => {
|
||||
]
|
||||
const props = createDefaultProps({ documents: [doc1] })
|
||||
|
||||
// Act
|
||||
render(<EmbeddingProcess {...props} />)
|
||||
await waitFor(() => {
|
||||
expect(mockFetchIndexingStatus).toHaveBeenCalled()
|
||||
})
|
||||
|
||||
// Assert
|
||||
expect(screen.getByText('0%')).toBeInTheDocument()
|
||||
})
|
||||
|
||||
it('should not show progress for completed documents', async () => {
|
||||
// Arrange
|
||||
const doc1 = createMockDocument({ id: 'doc-1' })
|
||||
mockIndexingStatusData = [
|
||||
createMockIndexingStatus({
|
||||
@ -502,27 +425,21 @@ describe('EmbeddingProcess', () => {
|
||||
]
|
||||
const props = createDefaultProps({ documents: [doc1] })
|
||||
|
||||
// Act
|
||||
render(<EmbeddingProcess {...props} />)
|
||||
await waitFor(() => {
|
||||
expect(mockFetchIndexingStatus).toHaveBeenCalled()
|
||||
})
|
||||
|
||||
// Assert
|
||||
expect(screen.queryByText('100%')).not.toBeInTheDocument()
|
||||
})
|
||||
})
|
||||
|
||||
// ==========================================
|
||||
// Polling Logic Tests
|
||||
// ==========================================
|
||||
describe('Polling Logic', () => {
|
||||
// Tests for API polling behavior
|
||||
it('should start polling on mount', async () => {
|
||||
// Arrange
|
||||
const props = createDefaultProps()
|
||||
|
||||
// Act
|
||||
render(<EmbeddingProcess {...props} />)
|
||||
|
||||
// Assert - verify fetch was called at least once
|
||||
@ -532,7 +449,6 @@ describe('EmbeddingProcess', () => {
|
||||
})
|
||||
|
||||
it('should continue polling while documents are processing', async () => {
|
||||
// Arrange
|
||||
const doc1 = createMockDocument({ id: 'doc-1' })
|
||||
mockIndexingStatusData = [
|
||||
createMockIndexingStatus({ id: 'doc-1', indexing_status: 'indexing' }),
|
||||
@ -540,7 +456,6 @@ describe('EmbeddingProcess', () => {
|
||||
const props = createDefaultProps({ documents: [doc1] })
|
||||
const initialCallCount = mockFetchIndexingStatus.mock.calls.length
|
||||
|
||||
// Act
|
||||
render(<EmbeddingProcess {...props} />)
|
||||
|
||||
// Wait for initial fetch
|
||||
@ -560,14 +475,12 @@ describe('EmbeddingProcess', () => {
|
||||
})
|
||||
|
||||
it('should stop polling when all documents are completed', async () => {
|
||||
// Arrange
|
||||
const doc1 = createMockDocument({ id: 'doc-1' })
|
||||
mockIndexingStatusData = [
|
||||
createMockIndexingStatus({ id: 'doc-1', indexing_status: 'completed' }),
|
||||
]
|
||||
const props = createDefaultProps({ documents: [doc1] })
|
||||
|
||||
// Act
|
||||
render(<EmbeddingProcess {...props} />)
|
||||
|
||||
// Wait for initial fetch and state update
|
||||
@ -586,14 +499,12 @@ describe('EmbeddingProcess', () => {
|
||||
})
|
||||
|
||||
it('should stop polling when all documents have errors', async () => {
|
||||
// Arrange
|
||||
const doc1 = createMockDocument({ id: 'doc-1' })
|
||||
mockIndexingStatusData = [
|
||||
createMockIndexingStatus({ id: 'doc-1', indexing_status: 'error' }),
|
||||
]
|
||||
const props = createDefaultProps({ documents: [doc1] })
|
||||
|
||||
// Act
|
||||
render(<EmbeddingProcess {...props} />)
|
||||
|
||||
// Wait for initial fetch
|
||||
@ -611,14 +522,12 @@ describe('EmbeddingProcess', () => {
|
||||
})
|
||||
|
||||
it('should stop polling when all documents are paused', async () => {
|
||||
// Arrange
|
||||
const doc1 = createMockDocument({ id: 'doc-1' })
|
||||
mockIndexingStatusData = [
|
||||
createMockIndexingStatus({ id: 'doc-1', indexing_status: 'paused' }),
|
||||
]
|
||||
const props = createDefaultProps({ documents: [doc1] })
|
||||
|
||||
// Act
|
||||
render(<EmbeddingProcess {...props} />)
|
||||
|
||||
// Wait for initial fetch
|
||||
@ -636,14 +545,12 @@ describe('EmbeddingProcess', () => {
|
||||
})
|
||||
|
||||
it('should cleanup timeout on unmount', async () => {
|
||||
// Arrange
|
||||
const doc1 = createMockDocument({ id: 'doc-1' })
|
||||
mockIndexingStatusData = [
|
||||
createMockIndexingStatus({ id: 'doc-1', indexing_status: 'indexing' }),
|
||||
]
|
||||
const props = createDefaultProps({ documents: [doc1] })
|
||||
|
||||
// Act
|
||||
const { unmount } = render(<EmbeddingProcess {...props} />)
|
||||
|
||||
// Wait for initial fetch
|
||||
@ -664,67 +571,52 @@ describe('EmbeddingProcess', () => {
|
||||
})
|
||||
})
|
||||
|
||||
// ==========================================
|
||||
// User Interactions Tests
|
||||
// ==========================================
|
||||
describe('User Interactions', () => {
|
||||
// Tests for button clicks and navigation
|
||||
it('should navigate to document list when nav button is clicked', async () => {
|
||||
// Arrange
|
||||
const props = createDefaultProps({ datasetId: 'my-dataset-123' })
|
||||
|
||||
// Act
|
||||
render(<EmbeddingProcess {...props} />)
|
||||
const navButton = screen.getByText('datasetCreation.stepThree.navTo')
|
||||
fireEvent.click(navButton)
|
||||
|
||||
// Assert
|
||||
expect(mockInvalidDocumentList).toHaveBeenCalled()
|
||||
expect(mockPush).toHaveBeenCalledWith('/datasets/my-dataset-123/documents')
|
||||
})
|
||||
|
||||
it('should call invalidDocumentList before navigation', () => {
|
||||
// Arrange
|
||||
const props = createDefaultProps()
|
||||
const callOrder: string[] = []
|
||||
mockInvalidDocumentList.mockImplementation(() => callOrder.push('invalidate'))
|
||||
mockPush.mockImplementation(() => callOrder.push('push'))
|
||||
|
||||
// Act
|
||||
render(<EmbeddingProcess {...props} />)
|
||||
const navButton = screen.getByText('datasetCreation.stepThree.navTo')
|
||||
fireEvent.click(navButton)
|
||||
|
||||
// Assert
|
||||
expect(callOrder).toEqual(['invalidate', 'push'])
|
||||
})
|
||||
})
|
||||
|
||||
// ==========================================
|
||||
// Document Display Tests
|
||||
// ==========================================
|
||||
describe('Document Display', () => {
|
||||
// Tests for document list rendering
|
||||
it('should display document names', async () => {
|
||||
// Arrange
|
||||
const doc1 = createMockDocument({ id: 'doc-1', name: 'my-report.pdf' })
|
||||
mockIndexingStatusData = [
|
||||
createMockIndexingStatus({ id: 'doc-1', indexing_status: 'indexing' }),
|
||||
]
|
||||
const props = createDefaultProps({ documents: [doc1] })
|
||||
|
||||
// Act
|
||||
render(<EmbeddingProcess {...props} />)
|
||||
await waitFor(() => {
|
||||
expect(mockFetchIndexingStatus).toHaveBeenCalled()
|
||||
})
|
||||
|
||||
// Assert
|
||||
expect(screen.getByText('my-report.pdf')).toBeInTheDocument()
|
||||
})
|
||||
|
||||
it('should display multiple documents', async () => {
|
||||
// Arrange
|
||||
const doc1 = createMockDocument({ id: 'doc-1', name: 'file1.txt' })
|
||||
const doc2 = createMockDocument({ id: 'doc-2', name: 'file2.pdf' })
|
||||
mockIndexingStatusData = [
|
||||
@ -733,43 +625,35 @@ describe('EmbeddingProcess', () => {
|
||||
]
|
||||
const props = createDefaultProps({ documents: [doc1, doc2] })
|
||||
|
||||
// Act
|
||||
render(<EmbeddingProcess {...props} />)
|
||||
await waitFor(() => {
|
||||
expect(mockFetchIndexingStatus).toHaveBeenCalled()
|
||||
})
|
||||
|
||||
// Assert
|
||||
expect(screen.getByText('file1.txt')).toBeInTheDocument()
|
||||
expect(screen.getByText('file2.pdf')).toBeInTheDocument()
|
||||
})
|
||||
|
||||
it('should handle documents with special characters in names', async () => {
|
||||
// Arrange
|
||||
const doc1 = createMockDocument({ id: 'doc-1', name: 'report_2024 (final) - copy.pdf' })
|
||||
mockIndexingStatusData = [
|
||||
createMockIndexingStatus({ id: 'doc-1', indexing_status: 'indexing' }),
|
||||
]
|
||||
const props = createDefaultProps({ documents: [doc1] })
|
||||
|
||||
// Act
|
||||
render(<EmbeddingProcess {...props} />)
|
||||
await waitFor(() => {
|
||||
expect(mockFetchIndexingStatus).toHaveBeenCalled()
|
||||
})
|
||||
|
||||
// Assert
|
||||
expect(screen.getByText('report_2024 (final) - copy.pdf')).toBeInTheDocument()
|
||||
})
|
||||
})
|
||||
|
||||
// ==========================================
|
||||
// Data Source Type Tests
|
||||
// ==========================================
|
||||
describe('Data Source Types', () => {
|
||||
// Tests for different data source type displays
|
||||
it('should handle local file data source', async () => {
|
||||
// Arrange
|
||||
const doc1 = createMockDocument({
|
||||
id: 'doc-1',
|
||||
name: 'local-file.pdf',
|
||||
@ -780,18 +664,15 @@ describe('EmbeddingProcess', () => {
|
||||
]
|
||||
const props = createDefaultProps({ documents: [doc1] })
|
||||
|
||||
// Act
|
||||
render(<EmbeddingProcess {...props} />)
|
||||
await waitFor(() => {
|
||||
expect(mockFetchIndexingStatus).toHaveBeenCalled()
|
||||
})
|
||||
|
||||
// Assert
|
||||
expect(screen.getByText('local-file.pdf')).toBeInTheDocument()
|
||||
})
|
||||
|
||||
it('should handle online document data source', async () => {
|
||||
// Arrange
|
||||
const doc1 = createMockDocument({
|
||||
id: 'doc-1',
|
||||
name: 'Notion Page',
|
||||
@ -803,18 +684,15 @@ describe('EmbeddingProcess', () => {
|
||||
]
|
||||
const props = createDefaultProps({ documents: [doc1] })
|
||||
|
||||
// Act
|
||||
render(<EmbeddingProcess {...props} />)
|
||||
await waitFor(() => {
|
||||
expect(mockFetchIndexingStatus).toHaveBeenCalled()
|
||||
})
|
||||
|
||||
// Assert
|
||||
expect(screen.getByText('Notion Page')).toBeInTheDocument()
|
||||
})
|
||||
|
||||
it('should handle website crawl data source', async () => {
|
||||
// Arrange
|
||||
const doc1 = createMockDocument({
|
||||
id: 'doc-1',
|
||||
name: 'https://example.com/page',
|
||||
@ -825,18 +703,15 @@ describe('EmbeddingProcess', () => {
|
||||
]
|
||||
const props = createDefaultProps({ documents: [doc1] })
|
||||
|
||||
// Act
|
||||
render(<EmbeddingProcess {...props} />)
|
||||
await waitFor(() => {
|
||||
expect(mockFetchIndexingStatus).toHaveBeenCalled()
|
||||
})
|
||||
|
||||
// Assert
|
||||
expect(screen.getByText('https://example.com/page')).toBeInTheDocument()
|
||||
})
|
||||
|
||||
it('should handle online drive data source', async () => {
|
||||
// Arrange
|
||||
const doc1 = createMockDocument({
|
||||
id: 'doc-1',
|
||||
name: 'Google Drive Document',
|
||||
@ -847,24 +722,19 @@ describe('EmbeddingProcess', () => {
|
||||
]
|
||||
const props = createDefaultProps({ documents: [doc1] })
|
||||
|
||||
// Act
|
||||
render(<EmbeddingProcess {...props} />)
|
||||
await waitFor(() => {
|
||||
expect(mockFetchIndexingStatus).toHaveBeenCalled()
|
||||
})
|
||||
|
||||
// Assert
|
||||
expect(screen.getByText('Google Drive Document')).toBeInTheDocument()
|
||||
})
|
||||
})
|
||||
|
||||
// ==========================================
|
||||
// Error Handling Tests
|
||||
// ==========================================
|
||||
describe('Error Handling', () => {
|
||||
// Tests for error states and displays
|
||||
it('should display error icon for documents with error status', async () => {
|
||||
// Arrange
|
||||
const doc1 = createMockDocument({ id: 'doc-1' })
|
||||
mockIndexingStatusData = [
|
||||
createMockIndexingStatus({
|
||||
@ -875,7 +745,6 @@ describe('EmbeddingProcess', () => {
|
||||
]
|
||||
const props = createDefaultProps({ documents: [doc1] })
|
||||
|
||||
// Act
|
||||
const { container } = render(<EmbeddingProcess {...props} />)
|
||||
await waitFor(() => {
|
||||
expect(mockFetchIndexingStatus).toHaveBeenCalled()
|
||||
@ -887,7 +756,6 @@ describe('EmbeddingProcess', () => {
|
||||
})
|
||||
|
||||
it('should apply error styling to document row with error', async () => {
|
||||
// Arrange
|
||||
const doc1 = createMockDocument({ id: 'doc-1' })
|
||||
mockIndexingStatusData = [
|
||||
createMockIndexingStatus({
|
||||
@ -898,7 +766,6 @@ describe('EmbeddingProcess', () => {
|
||||
]
|
||||
const props = createDefaultProps({ documents: [doc1] })
|
||||
|
||||
// Act
|
||||
const { container } = render(<EmbeddingProcess {...props} />)
|
||||
await waitFor(() => {
|
||||
expect(mockFetchIndexingStatus).toHaveBeenCalled()
|
||||
@ -910,13 +777,9 @@ describe('EmbeddingProcess', () => {
|
||||
})
|
||||
})
|
||||
|
||||
// ==========================================
|
||||
// Edge Cases
|
||||
// ==========================================
|
||||
describe('Edge Cases', () => {
|
||||
// Tests for boundary conditions
|
||||
it('should throw error when documents array is empty', () => {
|
||||
// Arrange
|
||||
// The component accesses documents[0].id for useProcessRule (line 81-82),
|
||||
// which throws TypeError when documents array is empty.
|
||||
// This test documents this known limitation.
|
||||
@ -934,11 +797,9 @@ describe('EmbeddingProcess', () => {
|
||||
})
|
||||
|
||||
it('should handle empty indexing status response', async () => {
|
||||
// Arrange
|
||||
mockIndexingStatusData = []
|
||||
const props = createDefaultProps()
|
||||
|
||||
// Act
|
||||
render(<EmbeddingProcess {...props} />)
|
||||
await waitFor(() => {
|
||||
expect(mockFetchIndexingStatus).toHaveBeenCalled()
|
||||
@ -951,7 +812,6 @@ describe('EmbeddingProcess', () => {
|
||||
})
|
||||
|
||||
it('should handle document with undefined name', async () => {
|
||||
// Arrange
|
||||
const doc1 = createMockDocument({ id: 'doc-1', name: undefined as unknown as string })
|
||||
mockIndexingStatusData = [
|
||||
createMockIndexingStatus({ id: 'doc-1', indexing_status: 'indexing' }),
|
||||
@ -963,7 +823,6 @@ describe('EmbeddingProcess', () => {
|
||||
})
|
||||
|
||||
it('should handle document not found in indexing status', async () => {
|
||||
// Arrange
|
||||
const doc1 = createMockDocument({ id: 'doc-1' })
|
||||
mockIndexingStatusData = [
|
||||
createMockIndexingStatus({ id: 'other-doc', indexing_status: 'indexing' }),
|
||||
@ -975,7 +834,6 @@ describe('EmbeddingProcess', () => {
|
||||
})
|
||||
|
||||
it('should handle undefined indexing_status', async () => {
|
||||
// Arrange
|
||||
const doc1 = createMockDocument({ id: 'doc-1' })
|
||||
mockIndexingStatusData = [
|
||||
createMockIndexingStatus({
|
||||
@ -990,7 +848,6 @@ describe('EmbeddingProcess', () => {
|
||||
})
|
||||
|
||||
it('should handle mixed status documents', async () => {
|
||||
// Arrange
|
||||
const doc1 = createMockDocument({ id: 'doc-1' })
|
||||
const doc2 = createMockDocument({ id: 'doc-2' })
|
||||
const doc3 = createMockDocument({ id: 'doc-3' })
|
||||
@ -1001,7 +858,6 @@ describe('EmbeddingProcess', () => {
|
||||
]
|
||||
const props = createDefaultProps({ documents: [doc1, doc2, doc3] })
|
||||
|
||||
// Act
|
||||
render(<EmbeddingProcess {...props} />)
|
||||
await waitFor(() => {
|
||||
expect(mockFetchIndexingStatus).toHaveBeenCalled()
|
||||
@ -1012,16 +868,12 @@ describe('EmbeddingProcess', () => {
|
||||
})
|
||||
})
|
||||
|
||||
// ==========================================
|
||||
// Props Variations Tests
|
||||
// ==========================================
|
||||
describe('Props Variations', () => {
|
||||
// Tests for different prop combinations
|
||||
it('should handle undefined indexingType', () => {
|
||||
// Arrange
|
||||
const props = createDefaultProps({ indexingType: undefined })
|
||||
|
||||
// Act
|
||||
render(<EmbeddingProcess {...props} />)
|
||||
|
||||
// Assert - component renders without crashing
|
||||
@ -1029,10 +881,8 @@ describe('EmbeddingProcess', () => {
|
||||
})
|
||||
|
||||
it('should handle undefined retrievalMethod', () => {
|
||||
// Arrange
|
||||
const props = createDefaultProps({ retrievalMethod: undefined })
|
||||
|
||||
// Act
|
||||
render(<EmbeddingProcess {...props} />)
|
||||
|
||||
// Assert - component renders without crashing
|
||||
@ -1040,13 +890,11 @@ describe('EmbeddingProcess', () => {
|
||||
})
|
||||
|
||||
it('should pass different indexingType values', () => {
|
||||
// Arrange
|
||||
const indexingTypes = [IndexingType.QUALIFIED, IndexingType.ECONOMICAL]
|
||||
|
||||
indexingTypes.forEach((indexingType) => {
|
||||
const props = createDefaultProps({ indexingType })
|
||||
|
||||
// Act
|
||||
const { unmount } = render(<EmbeddingProcess {...props} />)
|
||||
|
||||
// Assert - RuleDetail renders and shows appropriate text based on indexingType
|
||||
@ -1057,13 +905,11 @@ describe('EmbeddingProcess', () => {
|
||||
})
|
||||
|
||||
it('should pass different retrievalMethod values', () => {
|
||||
// Arrange
|
||||
const retrievalMethods = [RETRIEVE_METHOD.semantic, RETRIEVE_METHOD.fullText, RETRIEVE_METHOD.hybrid]
|
||||
|
||||
retrievalMethods.forEach((retrievalMethod) => {
|
||||
const props = createDefaultProps({ retrievalMethod })
|
||||
|
||||
// Act
|
||||
const { unmount } = render(<EmbeddingProcess {...props} />)
|
||||
|
||||
// Assert - RuleDetail renders and shows appropriate text based on retrievalMethod
|
||||
@ -1074,9 +920,6 @@ describe('EmbeddingProcess', () => {
|
||||
})
|
||||
})
|
||||
|
||||
// ==========================================
|
||||
// Memoization Tests
|
||||
// ==========================================
|
||||
describe('Memoization Logic', () => {
|
||||
// Tests for useMemo computed values
|
||||
it('should correctly compute isEmbeddingWaiting', async () => {
|
||||
@ -1089,13 +932,11 @@ describe('EmbeddingProcess', () => {
|
||||
]
|
||||
const props = createDefaultProps({ documents: [doc1, doc2] })
|
||||
|
||||
// Act
|
||||
render(<EmbeddingProcess {...props} />)
|
||||
await waitFor(() => {
|
||||
expect(mockFetchIndexingStatus).toHaveBeenCalled()
|
||||
})
|
||||
|
||||
// Assert
|
||||
expect(screen.getByText('datasetDocuments.embedding.waiting')).toBeInTheDocument()
|
||||
})
|
||||
|
||||
@ -1109,13 +950,11 @@ describe('EmbeddingProcess', () => {
|
||||
]
|
||||
const props = createDefaultProps({ documents: [doc1, doc2] })
|
||||
|
||||
// Act
|
||||
render(<EmbeddingProcess {...props} />)
|
||||
await waitFor(() => {
|
||||
expect(mockFetchIndexingStatus).toHaveBeenCalled()
|
||||
})
|
||||
|
||||
// Assert
|
||||
expect(screen.getByText('datasetDocuments.embedding.processing')).toBeInTheDocument()
|
||||
})
|
||||
|
||||
@ -1131,24 +970,19 @@ describe('EmbeddingProcess', () => {
|
||||
]
|
||||
const props = createDefaultProps({ documents: [doc1, doc2, doc3] })
|
||||
|
||||
// Act
|
||||
render(<EmbeddingProcess {...props} />)
|
||||
await waitFor(() => {
|
||||
expect(mockFetchIndexingStatus).toHaveBeenCalled()
|
||||
})
|
||||
|
||||
// Assert
|
||||
expect(screen.getByText('datasetDocuments.embedding.completed')).toBeInTheDocument()
|
||||
})
|
||||
})
|
||||
|
||||
// ==========================================
|
||||
// File Type Detection Tests
|
||||
// ==========================================
|
||||
describe('File Type Detection', () => {
|
||||
// Tests for getFileType helper function
|
||||
it('should extract file extension correctly', async () => {
|
||||
// Arrange
|
||||
const doc1 = createMockDocument({
|
||||
id: 'doc-1',
|
||||
name: 'document.pdf',
|
||||
@ -1159,7 +993,6 @@ describe('EmbeddingProcess', () => {
|
||||
]
|
||||
const props = createDefaultProps({ documents: [doc1] })
|
||||
|
||||
// Act
|
||||
render(<EmbeddingProcess {...props} />)
|
||||
await waitFor(() => {
|
||||
expect(mockFetchIndexingStatus).toHaveBeenCalled()
|
||||
@ -1170,7 +1003,6 @@ describe('EmbeddingProcess', () => {
|
||||
})
|
||||
|
||||
it('should handle files with multiple dots', async () => {
|
||||
// Arrange
|
||||
const doc1 = createMockDocument({
|
||||
id: 'doc-1',
|
||||
name: 'my.report.2024.pdf',
|
||||
@ -1181,18 +1013,15 @@ describe('EmbeddingProcess', () => {
|
||||
]
|
||||
const props = createDefaultProps({ documents: [doc1] })
|
||||
|
||||
// Act
|
||||
render(<EmbeddingProcess {...props} />)
|
||||
await waitFor(() => {
|
||||
expect(mockFetchIndexingStatus).toHaveBeenCalled()
|
||||
})
|
||||
|
||||
// Assert
|
||||
expect(screen.getByText('my.report.2024.pdf')).toBeInTheDocument()
|
||||
})
|
||||
|
||||
it('should handle files without extension', async () => {
|
||||
// Arrange
|
||||
const doc1 = createMockDocument({
|
||||
id: 'doc-1',
|
||||
name: 'README',
|
||||
@ -1203,24 +1032,19 @@ describe('EmbeddingProcess', () => {
|
||||
]
|
||||
const props = createDefaultProps({ documents: [doc1] })
|
||||
|
||||
// Act
|
||||
render(<EmbeddingProcess {...props} />)
|
||||
await waitFor(() => {
|
||||
expect(mockFetchIndexingStatus).toHaveBeenCalled()
|
||||
})
|
||||
|
||||
// Assert
|
||||
expect(screen.getByText('README')).toBeInTheDocument()
|
||||
})
|
||||
})
|
||||
|
||||
// ==========================================
|
||||
// Priority Label Tests
|
||||
// ==========================================
|
||||
describe('Priority Label', () => {
|
||||
// Tests for priority label display
|
||||
it('should show priority label when billing is enabled', async () => {
|
||||
// Arrange
|
||||
mockEnableBilling = true
|
||||
mockPlanType = Plan.sandbox
|
||||
const doc1 = createMockDocument({ id: 'doc-1' })
|
||||
@ -1229,7 +1053,6 @@ describe('EmbeddingProcess', () => {
|
||||
]
|
||||
const props = createDefaultProps({ documents: [doc1] })
|
||||
|
||||
// Act
|
||||
const { container } = render(<EmbeddingProcess {...props} />)
|
||||
await waitFor(() => {
|
||||
expect(mockFetchIndexingStatus).toHaveBeenCalled()
|
||||
@ -1241,7 +1064,6 @@ describe('EmbeddingProcess', () => {
|
||||
})
|
||||
|
||||
it('should not show priority label when billing is disabled', async () => {
|
||||
// Arrange
|
||||
mockEnableBilling = false
|
||||
const doc1 = createMockDocument({ id: 'doc-1' })
|
||||
mockIndexingStatusData = [
|
||||
@ -1249,7 +1071,6 @@ describe('EmbeddingProcess', () => {
|
||||
]
|
||||
const props = createDefaultProps({ documents: [doc1] })
|
||||
|
||||
// Act
|
||||
render(<EmbeddingProcess {...props} />)
|
||||
await waitFor(() => {
|
||||
expect(mockFetchIndexingStatus).toHaveBeenCalled()
|
||||
@ -4,13 +4,9 @@ import * as React from 'react'
|
||||
import { IndexingType } from '@/app/components/datasets/create/step-two'
|
||||
import { ProcessMode } from '@/models/datasets'
|
||||
import { RETRIEVE_METHOD } from '@/types/app'
|
||||
import RuleDetail from './rule-detail'
|
||||
import RuleDetail from '../rule-detail'
|
||||
|
||||
// ==========================================
|
||||
// Mock External Dependencies
|
||||
// ==========================================
|
||||
|
||||
// Mock next/image (using img element for simplicity in tests)
|
||||
// Override global next/image auto-mock: tests assert on data-testid="next-image" and src attributes
|
||||
vi.mock('next/image', () => ({
|
||||
default: function MockImage({ src, alt, className }: { src: string, alt: string, className?: string }) {
|
||||
// eslint-disable-next-line next/no-img-element
|
||||
@ -42,9 +38,7 @@ vi.mock('@/app/components/datasets/create/icons', () => ({
|
||||
},
|
||||
}))
|
||||
|
||||
// ==========================================
|
||||
// Test Data Factory Functions
|
||||
// ==========================================
|
||||
|
||||
/**
|
||||
* Creates a mock ProcessRuleResponse for testing
|
||||
@ -71,33 +65,22 @@ const createMockProcessRule = (overrides: Partial<ProcessRuleResponse> = {}): Pr
|
||||
...overrides,
|
||||
})
|
||||
|
||||
// ==========================================
|
||||
// Test Suite
|
||||
// ==========================================
|
||||
|
||||
describe('RuleDetail', () => {
|
||||
beforeEach(() => {
|
||||
vi.clearAllMocks()
|
||||
})
|
||||
|
||||
// ==========================================
|
||||
// Rendering Tests
|
||||
// ==========================================
|
||||
describe('Rendering', () => {
|
||||
it('should render without crashing', () => {
|
||||
// Arrange & Act
|
||||
render(<RuleDetail />)
|
||||
|
||||
// Assert
|
||||
const fieldInfos = screen.getAllByTestId('field-info')
|
||||
expect(fieldInfos).toHaveLength(3)
|
||||
})
|
||||
|
||||
it('should render three FieldInfo components', () => {
|
||||
// Arrange
|
||||
const sourceData = createMockProcessRule()
|
||||
|
||||
// Act
|
||||
render(
|
||||
<RuleDetail
|
||||
sourceData={sourceData}
|
||||
@ -106,13 +89,11 @@ describe('RuleDetail', () => {
|
||||
/>,
|
||||
)
|
||||
|
||||
// Assert
|
||||
const fieldInfos = screen.getAllByTestId('field-info')
|
||||
expect(fieldInfos).toHaveLength(3)
|
||||
})
|
||||
|
||||
it('should render mode field with correct label', () => {
|
||||
// Arrange & Act
|
||||
render(<RuleDetail />)
|
||||
|
||||
// Assert - first field-info is for mode
|
||||
@ -121,45 +102,34 @@ describe('RuleDetail', () => {
|
||||
})
|
||||
})
|
||||
|
||||
// ==========================================
|
||||
// Mode Value Tests
|
||||
// ==========================================
|
||||
describe('Mode Value', () => {
|
||||
it('should show "-" when sourceData is undefined', () => {
|
||||
// Arrange & Act
|
||||
render(<RuleDetail />)
|
||||
|
||||
// Assert
|
||||
const fieldValues = screen.getAllByTestId('field-value')
|
||||
expect(fieldValues[0]).toHaveTextContent('-')
|
||||
})
|
||||
|
||||
it('should show "-" when sourceData.mode is undefined', () => {
|
||||
// Arrange
|
||||
const sourceData = { ...createMockProcessRule(), mode: undefined as unknown as ProcessMode }
|
||||
|
||||
// Act
|
||||
render(<RuleDetail sourceData={sourceData} />)
|
||||
|
||||
// Assert
|
||||
const fieldValues = screen.getAllByTestId('field-value')
|
||||
expect(fieldValues[0]).toHaveTextContent('-')
|
||||
})
|
||||
|
||||
it('should show custom mode text when mode is general', () => {
|
||||
// Arrange
|
||||
const sourceData = createMockProcessRule({ mode: ProcessMode.general })
|
||||
|
||||
// Act
|
||||
render(<RuleDetail sourceData={sourceData} />)
|
||||
|
||||
// Assert
|
||||
const fieldValues = screen.getAllByTestId('field-value')
|
||||
expect(fieldValues[0]).toHaveTextContent('datasetDocuments.embedding.custom')
|
||||
})
|
||||
|
||||
it('should show hierarchical mode with paragraph parent mode', () => {
|
||||
// Arrange
|
||||
const sourceData = createMockProcessRule({
|
||||
mode: ProcessMode.parentChild,
|
||||
rules: {
|
||||
@ -170,16 +140,13 @@ describe('RuleDetail', () => {
|
||||
},
|
||||
})
|
||||
|
||||
// Act
|
||||
render(<RuleDetail sourceData={sourceData} />)
|
||||
|
||||
// Assert
|
||||
const fieldValues = screen.getAllByTestId('field-value')
|
||||
expect(fieldValues[0]).toHaveTextContent('datasetDocuments.embedding.hierarchical · dataset.parentMode.paragraph')
|
||||
})
|
||||
|
||||
it('should show hierarchical mode with full-doc parent mode', () => {
|
||||
// Arrange
|
||||
const sourceData = createMockProcessRule({
|
||||
mode: ProcessMode.parentChild,
|
||||
rules: {
|
||||
@ -190,24 +157,18 @@ describe('RuleDetail', () => {
|
||||
},
|
||||
})
|
||||
|
||||
// Act
|
||||
render(<RuleDetail sourceData={sourceData} />)
|
||||
|
||||
// Assert
|
||||
const fieldValues = screen.getAllByTestId('field-value')
|
||||
expect(fieldValues[0]).toHaveTextContent('datasetDocuments.embedding.hierarchical · dataset.parentMode.fullDoc')
|
||||
})
|
||||
})
|
||||
|
||||
// ==========================================
|
||||
// Indexing Type Tests
|
||||
// ==========================================
|
||||
describe('Indexing Type', () => {
|
||||
it('should show qualified indexing type', () => {
|
||||
// Arrange & Act
|
||||
render(<RuleDetail indexingType={IndexingType.QUALIFIED} />)
|
||||
|
||||
// Assert
|
||||
const fieldInfos = screen.getAllByTestId('field-info')
|
||||
expect(fieldInfos[1]).toHaveAttribute('data-label', 'datasetCreation.stepTwo.indexMode')
|
||||
|
||||
@ -216,48 +177,37 @@ describe('RuleDetail', () => {
|
||||
})
|
||||
|
||||
it('should show economical indexing type', () => {
|
||||
// Arrange & Act
|
||||
render(<RuleDetail indexingType={IndexingType.ECONOMICAL} />)
|
||||
|
||||
// Assert
|
||||
const fieldValues = screen.getAllByTestId('field-value')
|
||||
expect(fieldValues[1]).toHaveTextContent('datasetCreation.stepTwo.economical')
|
||||
})
|
||||
|
||||
it('should show high_quality icon for qualified indexing', () => {
|
||||
// Arrange & Act
|
||||
render(<RuleDetail indexingType={IndexingType.QUALIFIED} />)
|
||||
|
||||
// Assert
|
||||
const images = screen.getAllByTestId('next-image')
|
||||
expect(images[0]).toHaveAttribute('src', '/icons/high_quality.svg')
|
||||
})
|
||||
|
||||
it('should show economical icon for economical indexing', () => {
|
||||
// Arrange & Act
|
||||
render(<RuleDetail indexingType={IndexingType.ECONOMICAL} />)
|
||||
|
||||
// Assert
|
||||
const images = screen.getAllByTestId('next-image')
|
||||
expect(images[0]).toHaveAttribute('src', '/icons/economical.svg')
|
||||
})
|
||||
})
|
||||
|
||||
// ==========================================
|
||||
// Retrieval Method Tests
|
||||
// ==========================================
|
||||
describe('Retrieval Method', () => {
|
||||
it('should show retrieval setting label', () => {
|
||||
// Arrange & Act
|
||||
render(<RuleDetail retrievalMethod={RETRIEVE_METHOD.semantic} />)
|
||||
|
||||
// Assert
|
||||
const fieldInfos = screen.getAllByTestId('field-info')
|
||||
expect(fieldInfos[2]).toHaveAttribute('data-label', 'datasetSettings.form.retrievalSetting.title')
|
||||
})
|
||||
|
||||
it('should show semantic search title for qualified indexing with semantic method', () => {
|
||||
// Arrange & Act
|
||||
render(
|
||||
<RuleDetail
|
||||
indexingType={IndexingType.QUALIFIED}
|
||||
@ -265,13 +215,11 @@ describe('RuleDetail', () => {
|
||||
/>,
|
||||
)
|
||||
|
||||
// Assert
|
||||
const fieldValues = screen.getAllByTestId('field-value')
|
||||
expect(fieldValues[2]).toHaveTextContent('dataset.retrieval.semantic_search.title')
|
||||
})
|
||||
|
||||
it('should show full text search title for fullText method', () => {
|
||||
// Arrange & Act
|
||||
render(
|
||||
<RuleDetail
|
||||
indexingType={IndexingType.QUALIFIED}
|
||||
@ -279,13 +227,11 @@ describe('RuleDetail', () => {
|
||||
/>,
|
||||
)
|
||||
|
||||
// Assert
|
||||
const fieldValues = screen.getAllByTestId('field-value')
|
||||
expect(fieldValues[2]).toHaveTextContent('dataset.retrieval.full_text_search.title')
|
||||
})
|
||||
|
||||
it('should show hybrid search title for hybrid method', () => {
|
||||
// Arrange & Act
|
||||
render(
|
||||
<RuleDetail
|
||||
indexingType={IndexingType.QUALIFIED}
|
||||
@ -293,13 +239,11 @@ describe('RuleDetail', () => {
|
||||
/>,
|
||||
)
|
||||
|
||||
// Assert
|
||||
const fieldValues = screen.getAllByTestId('field-value')
|
||||
expect(fieldValues[2]).toHaveTextContent('dataset.retrieval.hybrid_search.title')
|
||||
})
|
||||
|
||||
it('should force keyword_search for economical indexing type', () => {
|
||||
// Arrange & Act
|
||||
render(
|
||||
<RuleDetail
|
||||
indexingType={IndexingType.ECONOMICAL}
|
||||
@ -307,13 +251,11 @@ describe('RuleDetail', () => {
|
||||
/>,
|
||||
)
|
||||
|
||||
// Assert
|
||||
const fieldValues = screen.getAllByTestId('field-value')
|
||||
expect(fieldValues[2]).toHaveTextContent('dataset.retrieval.keyword_search.title')
|
||||
})
|
||||
|
||||
it('should show vector icon for semantic search', () => {
|
||||
// Arrange & Act
|
||||
render(
|
||||
<RuleDetail
|
||||
indexingType={IndexingType.QUALIFIED}
|
||||
@ -321,13 +263,11 @@ describe('RuleDetail', () => {
|
||||
/>,
|
||||
)
|
||||
|
||||
// Assert
|
||||
const images = screen.getAllByTestId('next-image')
|
||||
expect(images[1]).toHaveAttribute('src', '/icons/vector.svg')
|
||||
})
|
||||
|
||||
it('should show fullText icon for full text search', () => {
|
||||
// Arrange & Act
|
||||
render(
|
||||
<RuleDetail
|
||||
indexingType={IndexingType.QUALIFIED}
|
||||
@ -335,13 +275,11 @@ describe('RuleDetail', () => {
|
||||
/>,
|
||||
)
|
||||
|
||||
// Assert
|
||||
const images = screen.getAllByTestId('next-image')
|
||||
expect(images[1]).toHaveAttribute('src', '/icons/fullText.svg')
|
||||
})
|
||||
|
||||
it('should show hybrid icon for hybrid search', () => {
|
||||
// Arrange & Act
|
||||
render(
|
||||
<RuleDetail
|
||||
indexingType={IndexingType.QUALIFIED}
|
||||
@ -349,46 +287,35 @@ describe('RuleDetail', () => {
|
||||
/>,
|
||||
)
|
||||
|
||||
// Assert
|
||||
const images = screen.getAllByTestId('next-image')
|
||||
expect(images[1]).toHaveAttribute('src', '/icons/hybrid.svg')
|
||||
})
|
||||
})
|
||||
|
||||
// ==========================================
|
||||
// Edge Cases
|
||||
// ==========================================
|
||||
describe('Edge Cases', () => {
|
||||
it('should handle all props undefined', () => {
|
||||
// Arrange & Act
|
||||
render(<RuleDetail />)
|
||||
|
||||
// Assert
|
||||
expect(screen.getAllByTestId('field-info')).toHaveLength(3)
|
||||
})
|
||||
|
||||
it('should handle undefined indexingType with defined retrievalMethod', () => {
|
||||
// Arrange & Act
|
||||
render(<RuleDetail retrievalMethod={RETRIEVE_METHOD.hybrid} />)
|
||||
|
||||
// Assert
|
||||
const fieldValues = screen.getAllByTestId('field-value')
|
||||
// When indexingType is undefined, it's treated as qualified
|
||||
expect(fieldValues[1]).toHaveTextContent('datasetCreation.stepTwo.qualified')
|
||||
})
|
||||
|
||||
it('should handle undefined retrievalMethod with defined indexingType', () => {
|
||||
// Arrange & Act
|
||||
render(<RuleDetail indexingType={IndexingType.QUALIFIED} />)
|
||||
|
||||
// Assert
|
||||
const images = screen.getAllByTestId('next-image')
|
||||
// When retrievalMethod is undefined, vector icon is used as default
|
||||
expect(images[1]).toHaveAttribute('src', '/icons/vector.svg')
|
||||
})
|
||||
|
||||
it('should handle sourceData with null rules', () => {
|
||||
// Arrange
|
||||
const sourceData = {
|
||||
...createMockProcessRule(),
|
||||
mode: ProcessMode.parentChild,
|
||||
@ -401,15 +328,11 @@ describe('RuleDetail', () => {
|
||||
})
|
||||
})
|
||||
|
||||
// ==========================================
|
||||
// Props Variations Tests
|
||||
// ==========================================
|
||||
describe('Props Variations', () => {
|
||||
it('should render correctly with all props provided', () => {
|
||||
// Arrange
|
||||
const sourceData = createMockProcessRule({ mode: ProcessMode.general })
|
||||
|
||||
// Act
|
||||
render(
|
||||
<RuleDetail
|
||||
sourceData={sourceData}
|
||||
@ -418,7 +341,6 @@ describe('RuleDetail', () => {
|
||||
/>,
|
||||
)
|
||||
|
||||
// Assert
|
||||
const fieldValues = screen.getAllByTestId('field-value')
|
||||
expect(fieldValues[0]).toHaveTextContent('datasetDocuments.embedding.custom')
|
||||
expect(fieldValues[1]).toHaveTextContent('datasetCreation.stepTwo.qualified')
|
||||
@ -426,10 +348,8 @@ describe('RuleDetail', () => {
|
||||
})
|
||||
|
||||
it('should render correctly for economical mode with full settings', () => {
|
||||
// Arrange
|
||||
const sourceData = createMockProcessRule({ mode: ProcessMode.parentChild })
|
||||
|
||||
// Act
|
||||
render(
|
||||
<RuleDetail
|
||||
sourceData={sourceData}
|
||||
@ -438,7 +358,6 @@ describe('RuleDetail', () => {
|
||||
/>,
|
||||
)
|
||||
|
||||
// Assert
|
||||
const fieldValues = screen.getAllByTestId('field-value')
|
||||
expect(fieldValues[1]).toHaveTextContent('datasetCreation.stepTwo.economical')
|
||||
// Economical always uses keyword_search regardless of retrievalMethod
|
||||
@ -446,9 +365,6 @@ describe('RuleDetail', () => {
|
||||
})
|
||||
})
|
||||
|
||||
// ==========================================
|
||||
// Memoization Tests
|
||||
// ==========================================
|
||||
describe('Memoization', () => {
|
||||
it('should be wrapped in React.memo', () => {
|
||||
// Assert - RuleDetail should be a memoized component
|
||||
@ -456,7 +372,6 @@ describe('RuleDetail', () => {
|
||||
})
|
||||
|
||||
it('should not re-render with same props', () => {
|
||||
// Arrange
|
||||
const sourceData = createMockProcessRule()
|
||||
const props = {
|
||||
sourceData,
|
||||
@ -464,7 +379,6 @@ describe('RuleDetail', () => {
|
||||
retrievalMethod: RETRIEVE_METHOD.semantic,
|
||||
}
|
||||
|
||||
// Act
|
||||
const { rerender } = render(<RuleDetail {...props} />)
|
||||
rerender(<RuleDetail {...props} />)
|
||||
|
||||
Reference in New Issue
Block a user