dify/web/features/agent-v2/roster/components/__tests__/edit-agent-dialog.spec.tsx
盐粒 Yanli 3f2d22ec0f
feat(agent-v2): sync nightly updates to main (#37599)
Co-authored-by: Jingyi-Dify <jingyi.qi@dify.ai>
Co-authored-by: yyh <yuanyouhuilyz@gmail.com>
Co-authored-by: Joel <iamjoel007@gmail.com>
Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
Co-authored-by: hjlarry <hjlarry@163.com>
Co-authored-by: Bond Zhu <783504079@qq.com>
Co-authored-by: Yansong Zhang <916125788@qq.com>
Co-authored-by: yyh <92089059+lyzno1@users.noreply.github.com>
2026-06-18 05:03:34 +00:00

222 lines
7.1 KiB
TypeScript

import type { AgentAppPartial } from '@dify/contracts/api/console/agent/types.gen'
import { render, screen, within } from '@testing-library/react'
import userEvent from '@testing-library/user-event'
import { EditAgentDialog } from '../edit-agent-dialog'
const mutationMock = vi.hoisted(() => ({
isPending: false,
mutate: vi.fn(),
}))
const toastMock = vi.hoisted(() => ({
error: vi.fn(),
success: vi.fn(),
}))
vi.mock('@tanstack/react-query', () => ({
useMutation: () => ({
isPending: mutationMock.isPending,
mutate: mutationMock.mutate,
}),
}))
vi.mock('@langgenius/dify-ui/toast', () => ({
toast: toastMock,
}))
vi.mock('@/app/components/base/app-icon-picker', () => ({
__esModule: true,
default: ({
onSelect,
open,
}: {
onSelect: (payload: { type: 'emoji', icon: string, background: string }) => void
open: boolean
}) => open
? (
<button
type="button"
onClick={() => onSelect({ type: 'emoji', icon: '🧠', background: '#E0F2FE' })}
>
Select brain icon
</button>
)
: null,
}))
vi.mock('@/service/client', () => ({
consoleQuery: {
agent: {
byAgentId: {
put: {
mutationOptions: vi.fn(() => ({})),
},
},
},
},
}))
const createAgent = (overrides: Partial<AgentAppPartial> = {}): AgentAppPartial => ({
description: 'Find and summarize market materials.',
icon: '🧸',
icon_background: '#F5F3FF',
icon_type: 'emoji',
id: 'agent-1',
icon_url: null,
mode: 'agent',
name: 'Research Agent',
role: 'Research Assistant',
...overrides,
})
const renderDialog = (agent = createAgent()) => {
const onOpenChange = vi.fn()
render(
<EditAgentDialog
agent={agent}
open
onOpenChange={onOpenChange}
/>,
)
return { onOpenChange }
}
describe('EditAgentDialog', () => {
beforeEach(() => {
vi.clearAllMocks()
mutationMock.isPending = false
})
it('submits the full agent payload when only the name changes', async () => {
const user = userEvent.setup()
renderDialog()
const dialog = screen.getByRole('dialog', { name: 'agentV2.roster.editDialog.title' })
await user.clear(within(dialog).getByRole('textbox', { name: 'agentV2.roster.createForm.nameLabel' }))
await user.type(within(dialog).getByRole('textbox', { name: 'agentV2.roster.createForm.nameLabel' }), ' Market Agent ')
await user.click(within(dialog).getByRole('button', { name: 'common.operation.save' }))
expect(mutationMock.mutate).toHaveBeenCalledWith({
params: {
agent_id: 'agent-1',
},
body: {
name: 'Market Agent',
description: 'Find and summarize market materials.',
role: 'Research Assistant',
icon_type: 'emoji',
icon: '🧸',
icon_background: '#F5F3FF',
},
}, expect.objectContaining({
onError: expect.any(Function),
onSuccess: expect.any(Function),
}))
})
it('submits the full agent payload when only the role changes', async () => {
const user = userEvent.setup()
renderDialog()
const dialog = screen.getByRole('dialog', { name: 'agentV2.roster.editDialog.title' })
await user.clear(within(dialog).getByRole('textbox', { name: 'agentV2.roster.createForm.roleLabel' }))
await user.type(within(dialog).getByRole('textbox', { name: 'agentV2.roster.createForm.roleLabel' }), ' Market Analyst ')
await user.click(within(dialog).getByRole('button', { name: 'common.operation.save' }))
expect(mutationMock.mutate).toHaveBeenCalledWith({
params: {
agent_id: 'agent-1',
},
body: {
name: 'Research Agent',
description: 'Find and summarize market materials.',
role: 'Market Analyst',
icon_type: 'emoji',
icon: '🧸',
icon_background: '#F5F3FF',
},
}, expect.objectContaining({
onError: expect.any(Function),
onSuccess: expect.any(Function),
}))
})
it('submits selected icon fields when the roster icon changes', async () => {
const user = userEvent.setup()
renderDialog()
const dialog = screen.getByRole('dialog', { name: 'agentV2.roster.editDialog.title' })
await user.click(within(dialog).getByRole('button', { name: /agentV2\.roster\.editAgent/ }))
await user.click(screen.getByRole('button', { hidden: true, name: 'Select brain icon' }))
await user.click(within(dialog).getByRole('button', { name: 'common.operation.save' }))
expect(mutationMock.mutate).toHaveBeenCalledWith({
params: {
agent_id: 'agent-1',
},
body: {
name: 'Research Agent',
description: 'Find and summarize market materials.',
role: 'Research Assistant',
icon_type: 'emoji',
icon: '🧠',
icon_background: '#E0F2FE',
},
}, expect.objectContaining({
onError: expect.any(Function),
onSuccess: expect.any(Function),
}))
})
it('shows a field error when saving with an empty name', async () => {
const user = userEvent.setup()
renderDialog()
const dialog = screen.getByRole('dialog', { name: 'agentV2.roster.editDialog.title' })
await user.clear(within(dialog).getByRole('textbox', { name: 'agentV2.roster.createForm.nameLabel' }))
const saveButton = within(dialog).getByRole('button', { name: 'common.operation.save' })
expect(saveButton).not.toBeDisabled()
await user.click(saveButton)
expect(await within(dialog).findByText('agentV2.roster.createForm.nameRequired')).toBeInTheDocument()
expect(toastMock.error).not.toHaveBeenCalled()
expect(mutationMock.mutate).not.toHaveBeenCalled()
})
it('shows a field error when saving with an empty role', async () => {
const user = userEvent.setup()
renderDialog()
const dialog = screen.getByRole('dialog', { name: 'agentV2.roster.editDialog.title' })
await user.clear(within(dialog).getByRole('textbox', { name: 'agentV2.roster.createForm.roleLabel' }))
const saveButton = within(dialog).getByRole('button', { name: 'common.operation.save' })
expect(saveButton).not.toBeDisabled()
await user.click(saveButton)
expect(await within(dialog).findByText('agentV2.roster.createForm.roleRequired')).toBeInTheDocument()
expect(toastMock.error).not.toHaveBeenCalled()
expect(mutationMock.mutate).not.toHaveBeenCalled()
})
it('shows a field error when saving with a blank role', async () => {
const user = userEvent.setup()
renderDialog()
const dialog = screen.getByRole('dialog', { name: 'agentV2.roster.editDialog.title' })
await user.clear(within(dialog).getByRole('textbox', { name: 'agentV2.roster.createForm.roleLabel' }))
await user.type(within(dialog).getByRole('textbox', { name: 'agentV2.roster.createForm.roleLabel' }), ' ')
const saveButton = within(dialog).getByRole('button', { name: 'common.operation.save' })
expect(saveButton).not.toBeDisabled()
await user.click(saveButton)
expect(await within(dialog).findByText('agentV2.roster.createForm.roleRequired')).toBeInTheDocument()
expect(toastMock.error).not.toHaveBeenCalled()
expect(mutationMock.mutate).not.toHaveBeenCalled()
})
})