mirror of
https://github.com/langgenius/dify.git
synced 2025-12-19 17:27:16 -05:00
chore: tests for webapp run batch (#29767)
This commit is contained in:
@@ -0,0 +1,49 @@
|
|||||||
|
import React from 'react'
|
||||||
|
import { render, screen } from '@testing-library/react'
|
||||||
|
import CSVDownload from './index'
|
||||||
|
|
||||||
|
const mockType = { Link: 'mock-link' }
|
||||||
|
let capturedProps: Record<string, unknown> | undefined
|
||||||
|
|
||||||
|
jest.mock('react-papaparse', () => ({
|
||||||
|
useCSVDownloader: () => {
|
||||||
|
const CSVDownloader = ({ children, ...props }: React.PropsWithChildren<Record<string, unknown>>) => {
|
||||||
|
capturedProps = props
|
||||||
|
return <div data-testid="csv-downloader" className={props.className as string}>{children}</div>
|
||||||
|
}
|
||||||
|
return {
|
||||||
|
CSVDownloader,
|
||||||
|
Type: mockType,
|
||||||
|
}
|
||||||
|
},
|
||||||
|
}))
|
||||||
|
|
||||||
|
describe('CSVDownload', () => {
|
||||||
|
const vars = [{ name: 'prompt' }, { name: 'context' }]
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
capturedProps = undefined
|
||||||
|
jest.clearAllMocks()
|
||||||
|
})
|
||||||
|
|
||||||
|
test('should render table headers and sample row for each variable', () => {
|
||||||
|
render(<CSVDownload vars={vars} />)
|
||||||
|
|
||||||
|
expect(screen.getByText('share.generation.csvStructureTitle')).toBeInTheDocument()
|
||||||
|
expect(screen.getAllByRole('row')[0].children).toHaveLength(2)
|
||||||
|
expect(screen.getByText('prompt share.generation.field')).toBeInTheDocument()
|
||||||
|
expect(screen.getByText('context share.generation.field')).toBeInTheDocument()
|
||||||
|
})
|
||||||
|
|
||||||
|
test('should configure CSV downloader with template data', () => {
|
||||||
|
render(<CSVDownload vars={vars} />)
|
||||||
|
|
||||||
|
expect(capturedProps?.filename).toBe('template')
|
||||||
|
expect(capturedProps?.type).toBe(mockType.Link)
|
||||||
|
expect(capturedProps?.bom).toBe(true)
|
||||||
|
expect(capturedProps?.data).toEqual([
|
||||||
|
{ prompt: '', context: '' },
|
||||||
|
])
|
||||||
|
expect(screen.getByText('share.generation.downloadTemplate')).toBeInTheDocument()
|
||||||
|
})
|
||||||
|
})
|
||||||
@@ -0,0 +1,70 @@
|
|||||||
|
import React from 'react'
|
||||||
|
import { act, render, screen, waitFor } from '@testing-library/react'
|
||||||
|
import CSVReader from './index'
|
||||||
|
|
||||||
|
let mockAcceptedFile: { name: string } | null = null
|
||||||
|
let capturedHandlers: Record<string, (payload: any) => void> = {}
|
||||||
|
|
||||||
|
jest.mock('react-papaparse', () => ({
|
||||||
|
useCSVReader: () => ({
|
||||||
|
CSVReader: ({ children, ...handlers }: any) => {
|
||||||
|
capturedHandlers = handlers
|
||||||
|
return (
|
||||||
|
<div data-testid="csv-reader-wrapper">
|
||||||
|
{children({
|
||||||
|
getRootProps: () => ({ 'data-testid': 'drop-zone' }),
|
||||||
|
acceptedFile: mockAcceptedFile,
|
||||||
|
})}
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
}))
|
||||||
|
|
||||||
|
describe('CSVReader', () => {
|
||||||
|
beforeEach(() => {
|
||||||
|
mockAcceptedFile = null
|
||||||
|
capturedHandlers = {}
|
||||||
|
jest.clearAllMocks()
|
||||||
|
})
|
||||||
|
|
||||||
|
test('should display upload instructions when no file selected', async () => {
|
||||||
|
const onParsed = jest.fn()
|
||||||
|
render(<CSVReader onParsed={onParsed} />)
|
||||||
|
|
||||||
|
expect(screen.getByText('share.generation.csvUploadTitle')).toBeInTheDocument()
|
||||||
|
expect(screen.getByText('share.generation.browse')).toBeInTheDocument()
|
||||||
|
|
||||||
|
await act(async () => {
|
||||||
|
capturedHandlers.onUploadAccepted?.({ data: [['row1']] })
|
||||||
|
})
|
||||||
|
expect(onParsed).toHaveBeenCalledWith([['row1']])
|
||||||
|
})
|
||||||
|
|
||||||
|
test('should show accepted file name without extension', () => {
|
||||||
|
mockAcceptedFile = { name: 'batch.csv' }
|
||||||
|
render(<CSVReader onParsed={jest.fn()} />)
|
||||||
|
|
||||||
|
expect(screen.getByText('batch')).toBeInTheDocument()
|
||||||
|
expect(screen.getByText('.csv')).toBeInTheDocument()
|
||||||
|
})
|
||||||
|
|
||||||
|
test('should toggle hover styling on drag events', async () => {
|
||||||
|
render(<CSVReader onParsed={jest.fn()} />)
|
||||||
|
const dragEvent = { preventDefault: jest.fn() } as unknown as DragEvent
|
||||||
|
|
||||||
|
await act(async () => {
|
||||||
|
capturedHandlers.onDragOver?.(dragEvent)
|
||||||
|
})
|
||||||
|
await waitFor(() => {
|
||||||
|
expect(screen.getByTestId('drop-zone')).toHaveClass('border-components-dropzone-border-accent')
|
||||||
|
})
|
||||||
|
|
||||||
|
await act(async () => {
|
||||||
|
capturedHandlers.onDragLeave?.(dragEvent)
|
||||||
|
})
|
||||||
|
await waitFor(() => {
|
||||||
|
expect(screen.getByTestId('drop-zone')).not.toHaveClass('border-components-dropzone-border-accent')
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
@@ -0,0 +1,88 @@
|
|||||||
|
import React from 'react'
|
||||||
|
import { act, fireEvent, render, screen, waitFor } from '@testing-library/react'
|
||||||
|
import RunBatch from './index'
|
||||||
|
import useBreakpoints, { MediaType } from '@/hooks/use-breakpoints'
|
||||||
|
|
||||||
|
jest.mock('@/hooks/use-breakpoints', () => {
|
||||||
|
const actual = jest.requireActual('@/hooks/use-breakpoints')
|
||||||
|
return {
|
||||||
|
__esModule: true,
|
||||||
|
default: jest.fn(),
|
||||||
|
MediaType: actual.MediaType,
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
let latestOnParsed: ((data: string[][]) => void) | undefined
|
||||||
|
let receivedCSVDownloadProps: Record<string, unknown> | undefined
|
||||||
|
|
||||||
|
jest.mock('./csv-reader', () => (props: { onParsed: (data: string[][]) => void }) => {
|
||||||
|
latestOnParsed = props.onParsed
|
||||||
|
return <div data-testid="csv-reader" />
|
||||||
|
})
|
||||||
|
|
||||||
|
jest.mock('./csv-download', () => (props: { vars: { name: string }[] }) => {
|
||||||
|
receivedCSVDownloadProps = props
|
||||||
|
return <div data-testid="csv-download" />
|
||||||
|
})
|
||||||
|
|
||||||
|
const mockUseBreakpoints = useBreakpoints as jest.Mock
|
||||||
|
|
||||||
|
describe('RunBatch', () => {
|
||||||
|
const vars = [{ name: 'prompt' }]
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
mockUseBreakpoints.mockReturnValue(MediaType.pc)
|
||||||
|
latestOnParsed = undefined
|
||||||
|
receivedCSVDownloadProps = undefined
|
||||||
|
jest.clearAllMocks()
|
||||||
|
})
|
||||||
|
|
||||||
|
test('should enable run button after CSV parsed and send data', async () => {
|
||||||
|
const onSend = jest.fn()
|
||||||
|
render(
|
||||||
|
<RunBatch
|
||||||
|
vars={vars}
|
||||||
|
onSend={onSend}
|
||||||
|
isAllFinished
|
||||||
|
/>,
|
||||||
|
)
|
||||||
|
|
||||||
|
expect(receivedCSVDownloadProps?.vars).toEqual(vars)
|
||||||
|
await act(async () => {
|
||||||
|
latestOnParsed?.([['row1']])
|
||||||
|
})
|
||||||
|
|
||||||
|
const runButton = screen.getByRole('button', { name: 'share.generation.run' })
|
||||||
|
await waitFor(() => {
|
||||||
|
expect(runButton).not.toBeDisabled()
|
||||||
|
})
|
||||||
|
|
||||||
|
fireEvent.click(runButton)
|
||||||
|
expect(onSend).toHaveBeenCalledWith([['row1']])
|
||||||
|
})
|
||||||
|
|
||||||
|
test('should keep button disabled and show spinner when results still running on mobile', async () => {
|
||||||
|
mockUseBreakpoints.mockReturnValue(MediaType.mobile)
|
||||||
|
const onSend = jest.fn()
|
||||||
|
const { container } = render(
|
||||||
|
<RunBatch
|
||||||
|
vars={vars}
|
||||||
|
onSend={onSend}
|
||||||
|
isAllFinished={false}
|
||||||
|
/>,
|
||||||
|
)
|
||||||
|
|
||||||
|
await act(async () => {
|
||||||
|
latestOnParsed?.([['row']])
|
||||||
|
})
|
||||||
|
|
||||||
|
const runButton = screen.getByRole('button', { name: 'share.generation.run' })
|
||||||
|
await waitFor(() => {
|
||||||
|
expect(runButton).toBeDisabled()
|
||||||
|
})
|
||||||
|
expect(runButton).toHaveClass('grow')
|
||||||
|
const icon = container.querySelector('svg')
|
||||||
|
expect(icon).toHaveClass('animate-spin')
|
||||||
|
expect(onSend).not.toHaveBeenCalled()
|
||||||
|
})
|
||||||
|
})
|
||||||
Reference in New Issue
Block a user