mirror of
https://github.com/langgenius/dify.git
synced 2026-05-04 01:18:05 +08:00
Merge remote-tracking branch 'origin/main' into feat/model-plugins-implementing
This commit is contained in:
@ -172,12 +172,8 @@ describe('dataset-config/card-item', () => {
|
||||
const [editButton] = within(card).getAllByRole('button', { hidden: true })
|
||||
await user.click(editButton)
|
||||
|
||||
expect(screen.getByText('Mock settings modal')).toBeInTheDocument()
|
||||
await waitFor(() => {
|
||||
expect(screen.getByRole('dialog')).toBeVisible()
|
||||
})
|
||||
|
||||
fireEvent.click(screen.getByText('Save changes'))
|
||||
expect(await screen.findByText('Mock settings modal')).toBeInTheDocument()
|
||||
fireEvent.click(await screen.findByText('Save changes'))
|
||||
|
||||
await waitFor(() => {
|
||||
expect(onSave).toHaveBeenCalledWith(expect.objectContaining({ name: 'Updated dataset' }))
|
||||
@ -194,7 +190,7 @@ describe('dataset-config/card-item', () => {
|
||||
|
||||
const card = screen.getByText(dataset.name).closest('.group') as HTMLElement
|
||||
const buttons = within(card).getAllByRole('button', { hidden: true })
|
||||
const deleteButton = buttons[buttons.length - 1]
|
||||
const deleteButton = buttons.at(-1)!
|
||||
|
||||
expect(deleteButton.className).not.toContain('action-btn-destructive')
|
||||
|
||||
@ -233,7 +229,7 @@ describe('dataset-config/card-item', () => {
|
||||
await user.click(editButton)
|
||||
expect(screen.getByText('Mock settings modal')).toBeInTheDocument()
|
||||
|
||||
const overlay = Array.from(document.querySelectorAll('[class]'))
|
||||
const overlay = [...document.querySelectorAll('[class]')]
|
||||
.find(element => element.className.toString().includes('bg-black/30'))
|
||||
|
||||
expect(overlay).toBeInTheDocument()
|
||||
|
||||
@ -164,7 +164,7 @@ const VoiceParamConfig = ({
|
||||
</div>
|
||||
<div className="flex items-center gap-1">
|
||||
<Listbox
|
||||
value={voiceItem ?? {}}
|
||||
value={voiceItem}
|
||||
disabled={!languageItem}
|
||||
onChange={(value: Item) => {
|
||||
handleChange({
|
||||
|
||||
@ -1,55 +1,72 @@
|
||||
import type { FormType } from '../../..'
|
||||
import type { CustomActionsProps } from '../actions'
|
||||
import { fireEvent, render, screen } from '@testing-library/react'
|
||||
import { fireEvent, render, screen, waitFor } from '@testing-library/react'
|
||||
import { beforeEach, describe, expect, it, vi } from 'vitest'
|
||||
import { formContext } from '../../..'
|
||||
import Actions from '../actions'
|
||||
|
||||
const renderWithForm = ({
|
||||
canSubmit,
|
||||
isSubmitting,
|
||||
CustomActions,
|
||||
}: {
|
||||
canSubmit: boolean
|
||||
isSubmitting: boolean
|
||||
const mockFormState = vi.hoisted(() => ({
|
||||
canSubmit: true,
|
||||
isSubmitting: false,
|
||||
}))
|
||||
|
||||
vi.mock('@tanstack/react-form', async () => {
|
||||
const actual = await vi.importActual<typeof import('@tanstack/react-form')>('@tanstack/react-form')
|
||||
return {
|
||||
...actual,
|
||||
useStore: (_store: unknown, selector: (state: typeof mockFormState) => unknown) => selector(mockFormState),
|
||||
}
|
||||
})
|
||||
|
||||
type RenderWithFormOptions = {
|
||||
canSubmit?: boolean
|
||||
isSubmitting?: boolean
|
||||
CustomActions?: (props: CustomActionsProps) => React.ReactNode
|
||||
}) => {
|
||||
const submitSpy = vi.fn()
|
||||
const state = {
|
||||
canSubmit,
|
||||
isSubmitting,
|
||||
}
|
||||
onSubmit?: () => void
|
||||
}
|
||||
|
||||
const renderWithForm = ({
|
||||
canSubmit = true,
|
||||
isSubmitting = false,
|
||||
CustomActions,
|
||||
onSubmit = vi.fn(),
|
||||
}: RenderWithFormOptions = {}) => {
|
||||
mockFormState.canSubmit = canSubmit
|
||||
mockFormState.isSubmitting = isSubmitting
|
||||
|
||||
const form = {
|
||||
store: {
|
||||
state,
|
||||
subscribe: () => () => {},
|
||||
},
|
||||
handleSubmit: submitSpy,
|
||||
store: {},
|
||||
handleSubmit: onSubmit,
|
||||
}
|
||||
|
||||
const TestComponent = () => {
|
||||
return (
|
||||
<formContext.Provider value={form as unknown as FormType}>
|
||||
<Actions
|
||||
CustomActions={CustomActions}
|
||||
/>
|
||||
</formContext.Provider>
|
||||
)
|
||||
}
|
||||
render(
|
||||
<formContext.Provider value={form as unknown as FormType}>
|
||||
<Actions CustomActions={CustomActions} />
|
||||
</formContext.Provider>,
|
||||
)
|
||||
|
||||
render(<TestComponent />)
|
||||
return { submitSpy }
|
||||
return { onSubmit }
|
||||
}
|
||||
|
||||
describe('Actions', () => {
|
||||
beforeEach(() => {
|
||||
vi.clearAllMocks()
|
||||
})
|
||||
|
||||
it('should disable submit button when form cannot submit', () => {
|
||||
renderWithForm({ canSubmit: false, isSubmitting: false })
|
||||
renderWithForm({ canSubmit: false })
|
||||
expect(screen.getByRole('button', { name: 'common.operation.submit' })).toBeDisabled()
|
||||
})
|
||||
|
||||
it('should call form submit when users click submit button', () => {
|
||||
const { submitSpy } = renderWithForm({ canSubmit: true, isSubmitting: false })
|
||||
it('should call form submit when users click submit button', async () => {
|
||||
const submitSpy = vi.fn()
|
||||
renderWithForm({ onSubmit: submitSpy })
|
||||
|
||||
fireEvent.click(screen.getByRole('button', { name: 'common.operation.submit' }))
|
||||
expect(submitSpy).toHaveBeenCalledTimes(1)
|
||||
|
||||
await waitFor(() => {
|
||||
expect(submitSpy).toHaveBeenCalledTimes(1)
|
||||
})
|
||||
})
|
||||
|
||||
it('should render custom actions when provided', () => {
|
||||
@ -60,15 +77,14 @@ describe('Actions', () => {
|
||||
))
|
||||
|
||||
renderWithForm({
|
||||
canSubmit: true,
|
||||
isSubmitting: true,
|
||||
CustomActions: customActionsSpy,
|
||||
})
|
||||
|
||||
expect(screen.queryByRole('button', { name: 'common.operation.submit' })).not.toBeInTheDocument()
|
||||
expect(screen.getByText('custom-true-true')).toBeInTheDocument()
|
||||
expect(screen.getByText('custom-false-true')).toBeInTheDocument()
|
||||
expect(customActionsSpy).toHaveBeenCalledWith(expect.objectContaining({
|
||||
isSubmitting: true,
|
||||
form: expect.any(Object),
|
||||
isSubmitting: false,
|
||||
canSubmit: true,
|
||||
}))
|
||||
})
|
||||
|
||||
@ -100,11 +100,11 @@ const Select: FC<ISelectProps> = ({
|
||||
disabled={disabled}
|
||||
value={selectedItem}
|
||||
className={className}
|
||||
onChange={(value: Item) => {
|
||||
onChange={(value) => {
|
||||
if (!disabled) {
|
||||
setSelectedItem(value)
|
||||
setOpen(false)
|
||||
onSelect(value)
|
||||
onSelect(value as Item)
|
||||
}
|
||||
}}
|
||||
>
|
||||
@ -224,10 +224,10 @@ const SimpleSelect: FC<ISelectProps> = ({
|
||||
<Listbox
|
||||
ref={listboxRef}
|
||||
value={selectedItem}
|
||||
onChange={(value: Item) => {
|
||||
onChange={(value) => {
|
||||
if (!disabled) {
|
||||
setSelectedItem(value)
|
||||
onSelect(value)
|
||||
onSelect(value as Item)
|
||||
}
|
||||
}}
|
||||
>
|
||||
|
||||
@ -1,4 +1,5 @@
|
||||
import { act, fireEvent, render, screen, waitFor } from '@testing-library/react'
|
||||
import { act, render, screen, waitFor } from '@testing-library/react'
|
||||
import userEvent from '@testing-library/user-event'
|
||||
import SVGRenderer from '..'
|
||||
|
||||
const mockClick = vi.fn()
|
||||
@ -117,6 +118,7 @@ describe('SVGRenderer', () => {
|
||||
})
|
||||
|
||||
it('closes image preview on cancel', async () => {
|
||||
const user = userEvent.setup()
|
||||
render(<SVGRenderer content={validSvg} />)
|
||||
|
||||
await waitFor(() => {
|
||||
@ -129,9 +131,11 @@ describe('SVGRenderer', () => {
|
||||
|
||||
expect(screen.getByAltText('Preview')).toBeInTheDocument()
|
||||
|
||||
fireEvent.keyDown(document, { key: 'Escape' })
|
||||
await user.click(screen.getByTestId('image-preview-close-button'))
|
||||
|
||||
expect(screen.queryByAltText('Preview')).not.toBeInTheDocument()
|
||||
await waitFor(() => {
|
||||
expect(screen.queryByAltText('Preview')).not.toBeInTheDocument()
|
||||
})
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
@ -1,4 +1,5 @@
|
||||
import { act, cleanup, fireEvent, render, screen, waitFor } from '@testing-library/react'
|
||||
import userEvent from '@testing-library/user-event'
|
||||
import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest'
|
||||
import Operations from '../operations'
|
||||
|
||||
@ -355,16 +356,14 @@ describe('Operations', () => {
|
||||
})
|
||||
|
||||
it('should show rename modal when rename is clicked', async () => {
|
||||
const user = userEvent.setup()
|
||||
render(<Operations {...defaultProps} />)
|
||||
await openPopover()
|
||||
const renameButton = screen.getByText('datasetDocuments.list.table.rename')
|
||||
await act(async () => {
|
||||
fireEvent.click(renameButton)
|
||||
})
|
||||
// Rename modal should be shown
|
||||
await waitFor(() => {
|
||||
expect(screen.getByDisplayValue('Test Document')).toBeInTheDocument()
|
||||
})
|
||||
const renameAction = screen.getByText('datasetDocuments.list.table.rename').parentElement as HTMLElement
|
||||
await user.click(renameAction)
|
||||
|
||||
const renameInput = await screen.findByRole('textbox')
|
||||
expect(renameInput).toHaveValue('Test Document')
|
||||
})
|
||||
|
||||
it('should call sync for notion data source', async () => {
|
||||
|
||||
@ -5,6 +5,7 @@ import { QueryClient, QueryClientProvider } from '@tanstack/react-query'
|
||||
import { render, screen, waitFor } from '@testing-library/react'
|
||||
import userEvent from '@testing-library/user-event'
|
||||
import { beforeEach, describe, expect, it, vi } from 'vitest'
|
||||
import { ToastContext } from '@/app/components/base/toast/context'
|
||||
import { ProcessMode } from '@/models/datasets'
|
||||
import * as datasetsService from '@/service/datasets'
|
||||
import * as useDataset from '@/service/knowledge/use-dataset'
|
||||
@ -13,8 +14,22 @@ import { IndexingType } from '../../../../create/step-two'
|
||||
import { DocumentContext } from '../../context'
|
||||
import EmbeddingDetail from '../index'
|
||||
|
||||
const { mockNotify, mockClose } = vi.hoisted(() => ({
|
||||
mockNotify: vi.fn(),
|
||||
mockClose: vi.fn(),
|
||||
}))
|
||||
|
||||
vi.mock('@/service/datasets')
|
||||
vi.mock('@/service/knowledge/use-dataset')
|
||||
vi.mock('@/app/components/base/toast/context', async () => {
|
||||
const { createContext } = await vi.importActual<typeof import('use-context-selector')>('use-context-selector')
|
||||
return {
|
||||
ToastContext: createContext({
|
||||
notify: mockNotify,
|
||||
close: mockClose,
|
||||
}),
|
||||
}
|
||||
})
|
||||
|
||||
const mockFetchIndexingStatus = vi.mocked(datasetsService.fetchIndexingStatus)
|
||||
const mockPauseDocIndexing = vi.mocked(datasetsService.pauseDocIndexing)
|
||||
@ -32,9 +47,11 @@ const createWrapper = (contextValue: DocumentContextValue = { datasetId: 'ds1',
|
||||
const queryClient = createTestQueryClient()
|
||||
return ({ children }: { children: ReactNode }) => (
|
||||
<QueryClientProvider client={queryClient}>
|
||||
<DocumentContext.Provider value={contextValue}>
|
||||
{children}
|
||||
</DocumentContext.Provider>
|
||||
<ToastContext.Provider value={{ notify: mockNotify, close: vi.fn() }}>
|
||||
<DocumentContext.Provider value={contextValue}>
|
||||
{children}
|
||||
</DocumentContext.Provider>
|
||||
</ToastContext.Provider>
|
||||
</QueryClientProvider>
|
||||
)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user