mirror of
https://github.com/langgenius/dify.git
synced 2026-04-21 03:07:39 +08:00
Merge remote-tracking branch 'origin/main' into feat/support-agent-sandbox
This commit is contained in:
@ -19,11 +19,13 @@ vi.mock('@/app/components/base/file-uploader/hooks', () => ({
|
||||
useFileSizeLimit: vi.fn(),
|
||||
}))
|
||||
|
||||
vi.mock('@/app/components/base/toast/context', () => ({
|
||||
useToastContext: () => ({
|
||||
notify: vi.fn(),
|
||||
close: vi.fn(),
|
||||
}),
|
||||
vi.mock('@/app/components/base/ui/toast', () => ({
|
||||
toast: {
|
||||
success: vi.fn(),
|
||||
error: vi.fn(),
|
||||
warning: vi.fn(),
|
||||
info: vi.fn(),
|
||||
},
|
||||
}))
|
||||
|
||||
const createPayload = (overrides: Partial<UploadFileSetting> = {}): UploadFileSetting => ({
|
||||
|
||||
@ -10,7 +10,7 @@ import { useEffect, useRef } from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import Button from '@/app/components/base/button'
|
||||
import { getProcessedFiles } from '@/app/components/base/file-uploader/utils'
|
||||
import Toast from '@/app/components/base/toast'
|
||||
import { toast } from '@/app/components/base/ui/toast'
|
||||
import Split from '@/app/components/workflow/nodes/_base/components/split'
|
||||
import SingleRunForm from '@/app/components/workflow/nodes/human-input/components/single-run-form'
|
||||
import { BlockEnum, InputVarType } from '@/app/components/workflow/types'
|
||||
@ -126,10 +126,7 @@ const BeforeRunForm: FC<BeforeRunFormProps> = ({
|
||||
})
|
||||
})
|
||||
if (errMsg) {
|
||||
Toast.notify({
|
||||
message: errMsg,
|
||||
type: 'error',
|
||||
})
|
||||
toast.error(errMsg)
|
||||
return
|
||||
}
|
||||
|
||||
@ -147,10 +144,7 @@ const BeforeRunForm: FC<BeforeRunFormProps> = ({
|
||||
})
|
||||
})
|
||||
if (parseErrorJsonField) {
|
||||
Toast.notify({
|
||||
message: t('errorMsg.invalidJson', { ns: 'workflow', field: parseErrorJsonField }),
|
||||
type: 'error',
|
||||
})
|
||||
toast.error(t('errorMsg.invalidJson', { ns: 'workflow', field: parseErrorJsonField }))
|
||||
return
|
||||
}
|
||||
|
||||
|
||||
@ -6,7 +6,7 @@ import type { CommonNodeType, ValueSelector } from '@/app/components/workflow/ty
|
||||
import { useCallback, useEffect, useState } from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import { useStoreApi } from 'reactflow'
|
||||
import Toast from '@/app/components/base/toast'
|
||||
import { toast } from '@/app/components/base/ui/toast'
|
||||
import {
|
||||
useNodesSyncDraft,
|
||||
} from '@/app/components/workflow/hooks'
|
||||
@ -183,7 +183,7 @@ const useLastRun = <T>({
|
||||
return false
|
||||
|
||||
const message = warningForNode.errorMessages[0] || 'This node has unresolved checklist issues'
|
||||
Toast.notify({ type: 'error', message })
|
||||
toast.error(message)
|
||||
return true
|
||||
}, [warningNodes, currentNodeId])
|
||||
|
||||
@ -304,13 +304,10 @@ const useLastRun = <T>({
|
||||
if (!inspectVarValue) {
|
||||
const nodeLabel = getContextNodeLabel(nodeId)
|
||||
|| t('nodes.llm.contextUnknownNode', { ns: 'workflow' })
|
||||
Toast.notify({
|
||||
type: 'error',
|
||||
message: t('nodes.llm.contextMissing', {
|
||||
ns: 'workflow',
|
||||
nodeName: nodeLabel,
|
||||
}),
|
||||
})
|
||||
toast.error(t('nodes.llm.contextMissing', {
|
||||
ns: 'workflow',
|
||||
nodeName: nodeLabel,
|
||||
}))
|
||||
return false
|
||||
}
|
||||
}
|
||||
@ -328,13 +325,10 @@ const useLastRun = <T>({
|
||||
const dependentVars = singleRunParams?.getDependentVars?.()
|
||||
const nullOutput = getNullDependentOutput(dependentVars)
|
||||
if (nullOutput) {
|
||||
Toast.notify({
|
||||
type: 'error',
|
||||
message: t('singleRun.subgraph.nullOutputError', {
|
||||
ns: 'workflow',
|
||||
output: formatSubgraphOutputLabel(nullOutput),
|
||||
}),
|
||||
})
|
||||
toast.error(t('singleRun.subgraph.nullOutputError', {
|
||||
ns: 'workflow',
|
||||
output: formatSubgraphOutputLabel(nullOutput),
|
||||
}))
|
||||
return
|
||||
}
|
||||
setNodeRunning()
|
||||
@ -442,13 +436,10 @@ const useLastRun = <T>({
|
||||
const dependentVars = singleRunParams?.getDependentVars?.()
|
||||
const nullOutput = getNullDependentOutput(dependentVars)
|
||||
if (nullOutput) {
|
||||
Toast.notify({
|
||||
type: 'error',
|
||||
message: t('singleRun.subgraph.nullOutputError', {
|
||||
ns: 'workflow',
|
||||
output: formatSubgraphOutputLabel(nullOutput),
|
||||
}),
|
||||
})
|
||||
toast.error(t('singleRun.subgraph.nullOutputError', {
|
||||
ns: 'workflow',
|
||||
output: formatSubgraphOutputLabel(nullOutput),
|
||||
}))
|
||||
return
|
||||
}
|
||||
if (blockType === BlockEnum.TriggerWebhook || blockType === BlockEnum.TriggerPlugin || blockType === BlockEnum.TriggerSchedule)
|
||||
|
||||
@ -13,7 +13,7 @@ import {
|
||||
import { useShallow } from 'zustand/react/shallow'
|
||||
import { trackEvent } from '@/app/components/base/amplitude'
|
||||
import { getInputVars as doGetInputVars } from '@/app/components/base/prompt-editor/constants'
|
||||
import Toast from '@/app/components/base/toast'
|
||||
import { toast } from '@/app/components/base/ui/toast'
|
||||
import {
|
||||
useIsChatMode,
|
||||
useNodeDataUpdate,
|
||||
@ -429,14 +429,14 @@ const useOneStepRun = <T>({
|
||||
})
|
||||
|
||||
if (!response) {
|
||||
const message = 'Schedule trigger run failed'
|
||||
Toast.notify({ type: 'error', message })
|
||||
const message = t('common.scheduleTriggerRunFailed', { ns: 'workflow' })
|
||||
toast.error(message)
|
||||
throw new Error(message)
|
||||
}
|
||||
|
||||
if (response?.status === 'error') {
|
||||
const message = response?.message || 'Schedule trigger run failed'
|
||||
Toast.notify({ type: 'error', message })
|
||||
const message = response?.message || t('common.scheduleTriggerRunFailed', { ns: 'workflow' })
|
||||
toast.error(message)
|
||||
throw new Error(message)
|
||||
}
|
||||
|
||||
@ -461,10 +461,10 @@ const useOneStepRun = <T>({
|
||||
_singleRunningStatus: NodeRunningStatus.Failed,
|
||||
},
|
||||
})
|
||||
Toast.notify({ type: 'error', message: 'Schedule trigger run failed' })
|
||||
toast.error(t('common.scheduleTriggerRunFailed', { ns: 'workflow' }))
|
||||
throw error
|
||||
}
|
||||
}, [flowId, id, handleNodeDataUpdate, data])
|
||||
}, [flowId, id, handleNodeDataUpdate, data, t])
|
||||
|
||||
const runWebhookSingleRun = useCallback(async (): Promise<any | null> => {
|
||||
const urlPath = `/apps/${flowId}/workflows/draft/nodes/${id}/trigger/run`
|
||||
@ -486,8 +486,8 @@ const useOneStepRun = <T>({
|
||||
return null
|
||||
|
||||
if (!response) {
|
||||
const message = response?.message || 'Webhook debug failed'
|
||||
Toast.notify({ type: 'error', message })
|
||||
const message = response?.message || t('common.webhookDebugFailed', { ns: 'workflow' })
|
||||
toast.error(message)
|
||||
cancelWebhookSingleRun()
|
||||
throw new Error(message)
|
||||
}
|
||||
@ -514,8 +514,8 @@ const useOneStepRun = <T>({
|
||||
}
|
||||
|
||||
if (response?.status === 'error') {
|
||||
const message = response.message || 'Webhook debug failed'
|
||||
Toast.notify({ type: 'error', message })
|
||||
const message = response.message || t('common.webhookDebugFailed', { ns: 'workflow' })
|
||||
toast.error(message)
|
||||
cancelWebhookSingleRun()
|
||||
throw new Error(message)
|
||||
}
|
||||
@ -538,7 +538,7 @@ const useOneStepRun = <T>({
|
||||
if (controller.signal.aborted)
|
||||
return null
|
||||
|
||||
Toast.notify({ type: 'error', message: 'Webhook debug request failed' })
|
||||
toast.error(t('common.webhookDebugRequestFailed', { ns: 'workflow' }))
|
||||
cancelWebhookSingleRun()
|
||||
if (error instanceof Error)
|
||||
throw error
|
||||
@ -550,7 +550,7 @@ const useOneStepRun = <T>({
|
||||
}
|
||||
|
||||
return null
|
||||
}, [flowId, id, data, handleNodeDataUpdate, cancelWebhookSingleRun])
|
||||
}, [flowId, id, data, handleNodeDataUpdate, cancelWebhookSingleRun, t])
|
||||
|
||||
const runPluginSingleRun = useCallback(async (): Promise<any | null> => {
|
||||
const urlPath = `/apps/${flowId}/workflows/draft/nodes/${id}/trigger/run`
|
||||
@ -585,14 +585,14 @@ const useOneStepRun = <T>({
|
||||
if (controller.signal.aborted)
|
||||
return null
|
||||
|
||||
Toast.notify({ type: 'error', message: requestError.message })
|
||||
toast.error(requestError.message)
|
||||
cancelPluginSingleRun()
|
||||
throw requestError
|
||||
}
|
||||
|
||||
if (!response) {
|
||||
const message = 'Plugin debug failed'
|
||||
Toast.notify({ type: 'error', message })
|
||||
toast.error(message)
|
||||
cancelPluginSingleRun()
|
||||
throw new Error(message)
|
||||
}
|
||||
@ -619,7 +619,7 @@ const useOneStepRun = <T>({
|
||||
|
||||
if (response?.status === 'error') {
|
||||
const message = response.message || 'Plugin debug failed'
|
||||
Toast.notify({ type: 'error', message })
|
||||
toast.error(message)
|
||||
cancelPluginSingleRun()
|
||||
throw new Error(message)
|
||||
}
|
||||
@ -652,10 +652,8 @@ const useOneStepRun = <T>({
|
||||
_isSingleRun: false,
|
||||
},
|
||||
})
|
||||
Toast.notify({
|
||||
type: 'error',
|
||||
message: res.errorMessage || '',
|
||||
})
|
||||
if (res.errorMessage)
|
||||
toast.error(res.errorMessage)
|
||||
}
|
||||
return res
|
||||
}, [checkValid, data, handleNodeDataUpdate, id, t, moreDataForCheckValid])
|
||||
|
||||
@ -1,15 +1,16 @@
|
||||
import { render, screen } from '@testing-library/react'
|
||||
import userEvent from '@testing-library/user-event'
|
||||
import { toast } from '@/app/components/base/ui/toast'
|
||||
import { BodyPayloadValueType, BodyType } from '../../types'
|
||||
import CurlPanel from '../curl-panel'
|
||||
import * as curlParser from '../curl-parser'
|
||||
|
||||
const {
|
||||
mockHandleNodeSelect,
|
||||
mockNotify,
|
||||
mockToastError,
|
||||
} = vi.hoisted(() => ({
|
||||
mockHandleNodeSelect: vi.fn(),
|
||||
mockNotify: vi.fn(),
|
||||
mockToastError: vi.fn(),
|
||||
}))
|
||||
|
||||
vi.mock('@/app/components/workflow/hooks', () => ({
|
||||
@ -18,9 +19,9 @@ vi.mock('@/app/components/workflow/hooks', () => ({
|
||||
}),
|
||||
}))
|
||||
|
||||
vi.mock('@/app/components/base/toast', () => ({
|
||||
default: {
|
||||
notify: mockNotify,
|
||||
vi.mock('@/app/components/base/ui/toast', () => ({
|
||||
toast: {
|
||||
error: mockToastError,
|
||||
},
|
||||
}))
|
||||
|
||||
@ -131,9 +132,7 @@ describe('curl-panel', () => {
|
||||
await user.type(screen.getByRole('textbox'), 'invalid')
|
||||
await user.click(screen.getByRole('button', { name: 'common.operation.save' }))
|
||||
|
||||
expect(mockNotify).toHaveBeenCalledWith(expect.objectContaining({
|
||||
type: 'error',
|
||||
}))
|
||||
expect(vi.mocked(toast.error)).toHaveBeenCalledWith(expect.stringContaining('Invalid cURL command'))
|
||||
})
|
||||
|
||||
it('should keep the panel open when parsing returns no node and no error', async () => {
|
||||
@ -159,7 +158,7 @@ describe('curl-panel', () => {
|
||||
expect(onHide).not.toHaveBeenCalled()
|
||||
expect(handleCurlImport).not.toHaveBeenCalled()
|
||||
expect(mockHandleNodeSelect).not.toHaveBeenCalled()
|
||||
expect(mockNotify).not.toHaveBeenCalled()
|
||||
expect(vi.mocked(toast.error)).not.toHaveBeenCalled()
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
@ -7,7 +7,7 @@ import { useTranslation } from 'react-i18next'
|
||||
import Button from '@/app/components/base/button'
|
||||
import Modal from '@/app/components/base/modal'
|
||||
import Textarea from '@/app/components/base/textarea'
|
||||
import Toast from '@/app/components/base/toast'
|
||||
import { toast } from '@/app/components/base/ui/toast'
|
||||
import { useNodesInteractions } from '@/app/components/workflow/hooks'
|
||||
import { parseCurl } from './curl-parser'
|
||||
|
||||
@ -26,10 +26,7 @@ const CurlPanel: FC<Props> = ({ nodeId, isShow, onHide, handleCurlImport }) => {
|
||||
const handleSave = useCallback(() => {
|
||||
const { node, error } = parseCurl(inputString)
|
||||
if (error) {
|
||||
Toast.notify({
|
||||
type: 'error',
|
||||
message: error,
|
||||
})
|
||||
toast.error(error)
|
||||
return
|
||||
}
|
||||
if (!node)
|
||||
|
||||
@ -12,7 +12,7 @@ import Divider from '@/app/components/base/divider'
|
||||
import Input from '@/app/components/base/input'
|
||||
import Modal from '@/app/components/base/modal'
|
||||
import Switch from '@/app/components/base/switch'
|
||||
import Toast from '@/app/components/base/toast'
|
||||
import { toast } from '@/app/components/base/ui/toast'
|
||||
import { useSelector as useAppContextWithSelector } from '@/context/app-context'
|
||||
import MailBodyInput from './mail-body-input'
|
||||
import Recipient from './recipient'
|
||||
@ -45,31 +45,22 @@ const EmailConfigureModal = ({
|
||||
|
||||
const checkValidConfig = useCallback(() => {
|
||||
if (!subject.trim()) {
|
||||
Toast.notify({
|
||||
type: 'error',
|
||||
message: 'subject is required',
|
||||
})
|
||||
toast.error(t(`${i18nPrefix}.deliveryMethod.emailConfigure.subjectRequired`, { ns: 'workflow' }))
|
||||
return false
|
||||
}
|
||||
if (!body.trim()) {
|
||||
Toast.notify({
|
||||
type: 'error',
|
||||
message: 'body is required',
|
||||
})
|
||||
toast.error(t(`${i18nPrefix}.deliveryMethod.emailConfigure.bodyRequired`, { ns: 'workflow' }))
|
||||
return false
|
||||
}
|
||||
if (!/\{\{#url#\}\}/.test(body.trim())) {
|
||||
Toast.notify({
|
||||
type: 'error',
|
||||
message: `body must contain one ${t('promptEditor.requestURL.item.title', { ns: 'common' })}`,
|
||||
})
|
||||
toast.error(t(`${i18nPrefix}.deliveryMethod.emailConfigure.bodyMustContainRequestURL`, {
|
||||
ns: 'workflow',
|
||||
field: t('promptEditor.requestURL.item.title', { ns: 'common' }),
|
||||
}))
|
||||
return false
|
||||
}
|
||||
if (!recipients || (recipients.items.length === 0 && !recipients.whole_workspace)) {
|
||||
Toast.notify({
|
||||
type: 'error',
|
||||
message: 'recipients is required',
|
||||
})
|
||||
toast.error(t(`${i18nPrefix}.deliveryMethod.emailConfigure.recipientsRequired`, { ns: 'workflow' }))
|
||||
return false
|
||||
}
|
||||
return true
|
||||
|
||||
@ -7,7 +7,7 @@ import * as React from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import Button from '@/app/components/base/button'
|
||||
import Input from '@/app/components/base/input'
|
||||
import Toast from '@/app/components/base/toast'
|
||||
import { toast } from '@/app/components/base/ui/toast'
|
||||
import ButtonStyleDropdown from './button-style-dropdown'
|
||||
|
||||
const i18nPrefix = 'nodes.humanInput'
|
||||
@ -47,14 +47,14 @@ const UserActionItem: FC<UserActionItemProps> = ({
|
||||
.join('')
|
||||
|
||||
if (sanitized !== withUnderscores) {
|
||||
Toast.notify({ type: 'error', message: t(`${i18nPrefix}.userActions.actionIdFormatTip`, { ns: 'workflow' }) })
|
||||
toast.error(t(`${i18nPrefix}.userActions.actionIdFormatTip`, { ns: 'workflow' }))
|
||||
return
|
||||
}
|
||||
|
||||
// Limit to 20 characters
|
||||
if (sanitized.length > ACTION_ID_MAX_LENGTH) {
|
||||
sanitized = sanitized.slice(0, ACTION_ID_MAX_LENGTH)
|
||||
Toast.notify({ type: 'error', message: t(`${i18nPrefix}.userActions.actionIdTooLong`, { ns: 'workflow', maxLength: ACTION_ID_MAX_LENGTH }) })
|
||||
toast.error(t(`${i18nPrefix}.userActions.actionIdTooLong`, { ns: 'workflow', maxLength: ACTION_ID_MAX_LENGTH }))
|
||||
}
|
||||
|
||||
if (sanitized)
|
||||
@ -65,7 +65,7 @@ const UserActionItem: FC<UserActionItemProps> = ({
|
||||
let value = e.target.value
|
||||
if (value.length > BUTTON_TEXT_MAX_LENGTH) {
|
||||
value = value.slice(0, BUTTON_TEXT_MAX_LENGTH)
|
||||
Toast.notify({ type: 'error', message: t(`${i18nPrefix}.userActions.buttonTextTooLong`, { ns: 'workflow', maxLength: BUTTON_TEXT_MAX_LENGTH }) })
|
||||
toast.error(t(`${i18nPrefix}.userActions.buttonTextTooLong`, { ns: 'workflow', maxLength: BUTTON_TEXT_MAX_LENGTH }))
|
||||
}
|
||||
onChange({ ...data, title: value })
|
||||
}
|
||||
|
||||
@ -16,8 +16,8 @@ import { useTranslation } from 'react-i18next'
|
||||
import ActionButton from '@/app/components/base/action-button'
|
||||
import Button from '@/app/components/base/button'
|
||||
import Divider from '@/app/components/base/divider'
|
||||
import Toast from '@/app/components/base/toast'
|
||||
import Tooltip from '@/app/components/base/tooltip'
|
||||
import { toast } from '@/app/components/base/ui/toast'
|
||||
import OutputVars, { VarItem } from '@/app/components/workflow/nodes/_base/components/output-vars'
|
||||
import Split from '@/app/components/workflow/nodes/_base/components/split'
|
||||
import useAvailableVarList from '@/app/components/workflow/nodes/_base/hooks/use-available-var-list'
|
||||
@ -132,7 +132,7 @@ const Panel: FC<NodePanelProps<HumanInputNodeType>> = ({
|
||||
className="flex size-6 cursor-pointer items-center justify-center rounded-md hover:bg-components-button-ghost-bg-hover"
|
||||
onClick={() => {
|
||||
copy(inputs.form_content)
|
||||
Toast.notify({ type: 'success', message: t('actionMsg.copySuccessfully', { ns: 'common' }) })
|
||||
toast.success(t('actionMsg.copySuccessfully', { ns: 'common' }))
|
||||
}}
|
||||
>
|
||||
<RiClipboardLine className="h-4 w-4 text-text-secondary" />
|
||||
|
||||
@ -3,7 +3,7 @@ import type { IterationNodeType } from '../types'
|
||||
import type { PanelProps } from '@/types/workflow'
|
||||
import { fireEvent, render, screen } from '@testing-library/react'
|
||||
import userEvent from '@testing-library/user-event'
|
||||
import Toast from '@/app/components/base/toast'
|
||||
import { toast } from '@/app/components/base/ui/toast'
|
||||
import { ErrorHandleMode } from '@/app/components/workflow/types'
|
||||
import { BlockEnum, VarType } from '../../../types'
|
||||
import AddBlock from '../add-block'
|
||||
@ -15,6 +15,15 @@ const mockHandleNodeAdd = vi.fn()
|
||||
const mockHandleNodeIterationRerender = vi.fn()
|
||||
let mockNodesReadOnly = false
|
||||
|
||||
vi.mock('@/app/components/base/ui/toast', () => ({
|
||||
toast: {
|
||||
success: vi.fn(),
|
||||
error: vi.fn(),
|
||||
warning: vi.fn(),
|
||||
info: vi.fn(),
|
||||
},
|
||||
}))
|
||||
|
||||
vi.mock('reactflow', async () => {
|
||||
const actual = await vi.importActual<typeof import('reactflow')>('reactflow')
|
||||
return {
|
||||
@ -102,7 +111,7 @@ vi.mock('../use-config', () => ({
|
||||
}))
|
||||
|
||||
const mockUseConfig = vi.mocked(useConfig)
|
||||
const mockToastNotify = vi.spyOn(Toast, 'notify').mockImplementation(() => ({}))
|
||||
const mockToastWarning = vi.mocked(toast.warning)
|
||||
|
||||
const createData = (overrides: Partial<IterationNodeType> = {}): IterationNodeType => ({
|
||||
title: 'Iteration',
|
||||
@ -191,11 +200,7 @@ describe('iteration path', () => {
|
||||
expect(screen.getByRole('button', { name: 'select-block' })).toBeInTheDocument()
|
||||
expect(screen.getByTestId('iteration-background-iteration-node')).toBeInTheDocument()
|
||||
expect(mockHandleNodeIterationRerender).toHaveBeenCalledWith('iteration-node')
|
||||
expect(mockToastNotify).toHaveBeenCalledWith({
|
||||
type: 'warning',
|
||||
message: 'workflow.nodes.iteration.answerNodeWarningDesc',
|
||||
duration: 5000,
|
||||
})
|
||||
expect(mockToastWarning).toHaveBeenCalledWith('workflow.nodes.iteration.answerNodeWarningDesc')
|
||||
})
|
||||
|
||||
it('should wire panel input, output, parallel, numeric, error mode, and flatten actions', async () => {
|
||||
|
||||
@ -12,7 +12,7 @@ import {
|
||||
useNodesInitialized,
|
||||
useViewport,
|
||||
} from 'reactflow'
|
||||
import Toast from '@/app/components/base/toast'
|
||||
import { toast } from '@/app/components/base/ui/toast'
|
||||
import { cn } from '@/utils/classnames'
|
||||
import { IterationStartNodeDumb } from '../iteration-start'
|
||||
import AddBlock from './add-block'
|
||||
@ -34,11 +34,7 @@ const Node: FC<NodeProps<IterationNodeType>> = ({
|
||||
if (nodesInitialized)
|
||||
handleNodeIterationRerender(id)
|
||||
if (data.is_parallel && showTips) {
|
||||
Toast.notify({
|
||||
type: 'warning',
|
||||
message: t(`${i18nPrefix}.answerNodeWarningDesc`, { ns: 'workflow' }),
|
||||
duration: 5000,
|
||||
})
|
||||
toast.warning(t(`${i18nPrefix}.answerNodeWarningDesc`, { ns: 'workflow' }))
|
||||
setShowTips(false)
|
||||
}
|
||||
}, [nodesInitialized, id, handleNodeIterationRerender, data.is_parallel, showTips, t])
|
||||
|
||||
@ -4,7 +4,7 @@ import { useCallback, useState } from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import Button from '@/app/components/base/button'
|
||||
import Divider from '@/app/components/base/divider'
|
||||
import Toast from '@/app/components/base/toast'
|
||||
import { toast } from '@/app/components/base/ui/toast'
|
||||
import { JSON_SCHEMA_MAX_DEPTH } from '@/config'
|
||||
import { cn } from '@/utils/classnames'
|
||||
import { SegmentedControl } from '../../../../../base/segmented-control'
|
||||
@ -196,10 +196,7 @@ const JsonSchemaConfig: FC<JsonSchemaConfigProps> = ({
|
||||
}
|
||||
else if (currentTab === SchemaView.VisualEditor) {
|
||||
if (advancedEditing || isAddingNewField) {
|
||||
Toast.notify({
|
||||
type: 'warning',
|
||||
message: t('nodes.llm.jsonSchema.warningTips.saveSchema', { ns: 'workflow' }),
|
||||
})
|
||||
toast.warning(t('nodes.llm.jsonSchema.warningTips.saveSchema', { ns: 'workflow' }))
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
@ -9,7 +9,7 @@ import {
|
||||
PortalToFollowElemContent,
|
||||
PortalToFollowElemTrigger,
|
||||
} from '@/app/components/base/portal-to-follow-elem'
|
||||
import Toast from '@/app/components/base/toast'
|
||||
import { toast } from '@/app/components/base/ui/toast'
|
||||
import { ModelTypeEnum } from '@/app/components/header/account-setting/model-provider-page/declarations'
|
||||
import { useModelListAndDefaultModelAndCurrentProviderAndModel } from '@/app/components/header/account-setting/model-provider-page/hooks'
|
||||
import { STORAGE_KEYS } from '@/config/storage-keys'
|
||||
@ -110,10 +110,7 @@ const JsonSchemaGenerator: FC<JsonSchemaGeneratorProps> = ({
|
||||
const generateSchema = useCallback(async () => {
|
||||
const { output, error } = await generateStructuredOutputRules({ instruction, model_config: model! })
|
||||
if (error) {
|
||||
Toast.notify({
|
||||
type: 'error',
|
||||
message: error,
|
||||
})
|
||||
toast.error(error)
|
||||
setSchema(null)
|
||||
setView(GeneratorView.promptEditor)
|
||||
return
|
||||
|
||||
@ -3,7 +3,8 @@ import type { Field } from '../../../types'
|
||||
import type { EditData } from './edit-card'
|
||||
import { noop } from 'es-toolkit/function'
|
||||
import { produce } from 'immer'
|
||||
import Toast from '@/app/components/base/toast'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import { toast } from '@/app/components/base/ui/toast'
|
||||
import { ArrayType, FILE_REF_FORMAT, Type } from '../../../types'
|
||||
import { findPropertyWithPath } from '../../../utils'
|
||||
import { useMittContext } from './context'
|
||||
@ -22,6 +23,7 @@ type AddEventParams = {
|
||||
|
||||
export const useSchemaNodeOperations = (props: VisualEditorProps) => {
|
||||
const { schema: jsonSchema, onChange: doOnChange } = props
|
||||
const { t } = useTranslation()
|
||||
const onChange = doOnChange || noop
|
||||
const backupSchema = useVisualEditorStore(state => state.backupSchema)
|
||||
const setBackupSchema = useVisualEditorStore(state => state.setBackupSchema)
|
||||
@ -65,10 +67,7 @@ export const useSchemaNodeOperations = (props: VisualEditorProps) => {
|
||||
if (schema.type === Type.object) {
|
||||
const properties = schema.properties || {}
|
||||
if (properties[newName]) {
|
||||
Toast.notify({
|
||||
type: 'error',
|
||||
message: 'Property name already exists',
|
||||
})
|
||||
toast.error(t('nodes.llm.jsonSchema.fieldNameAlreadyExists', { ns: 'workflow' }))
|
||||
emit('restorePropertyName')
|
||||
return
|
||||
}
|
||||
@ -92,10 +91,7 @@ export const useSchemaNodeOperations = (props: VisualEditorProps) => {
|
||||
if (schema.type === Type.array && schema.items && schema.items.type === Type.object) {
|
||||
const properties = schema.items.properties || {}
|
||||
if (properties[newName]) {
|
||||
Toast.notify({
|
||||
type: 'error',
|
||||
message: 'Property name already exists',
|
||||
})
|
||||
toast.error(t('nodes.llm.jsonSchema.fieldNameAlreadyExists', { ns: 'workflow' }))
|
||||
emit('restorePropertyName')
|
||||
return
|
||||
}
|
||||
@ -279,10 +275,7 @@ export const useSchemaNodeOperations = (props: VisualEditorProps) => {
|
||||
if (oldName !== newName) {
|
||||
const properties = parentSchema.properties
|
||||
if (properties[newName]) {
|
||||
Toast.notify({
|
||||
type: 'error',
|
||||
message: 'Property name already exists',
|
||||
})
|
||||
toast.error(t('nodes.llm.jsonSchema.fieldNameAlreadyExists', { ns: 'workflow' }))
|
||||
samePropertyNameError = true
|
||||
}
|
||||
|
||||
@ -382,10 +375,7 @@ export const useSchemaNodeOperations = (props: VisualEditorProps) => {
|
||||
if (oldName !== newName) {
|
||||
const properties = parentSchema.items.properties || {}
|
||||
if (properties[newName]) {
|
||||
Toast.notify({
|
||||
type: 'error',
|
||||
message: 'Property name already exists',
|
||||
})
|
||||
toast.error(t('nodes.llm.jsonSchema.fieldNameAlreadyExists', { ns: 'workflow' }))
|
||||
samePropertyNameError = true
|
||||
}
|
||||
|
||||
|
||||
@ -8,8 +8,8 @@ import { useCallback } from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import AddButton2 from '@/app/components/base/button/add-button'
|
||||
import Switch from '@/app/components/base/switch'
|
||||
import Toast from '@/app/components/base/toast'
|
||||
import Tooltip from '@/app/components/base/tooltip'
|
||||
import { toast } from '@/app/components/base/ui/toast'
|
||||
import ModelParameterModal from '@/app/components/header/account-setting/model-provider-page/model-parameter-modal'
|
||||
import { FieldCollapse } from '@/app/components/workflow/nodes/_base/components/collapse'
|
||||
import Field from '@/app/components/workflow/nodes/_base/components/field'
|
||||
@ -151,11 +151,11 @@ const Panel: FC<NodePanelProps<LLMNodeType>> = ({
|
||||
)
|
||||
const keys = Object.keys(removedDetails)
|
||||
if (keys.length)
|
||||
Toast.notify({ type: 'warning', message: `${t('modelProvider.parametersInvalidRemoved', { ns: 'common' })}: ${keys.map(k => `${k} (${removedDetails[k]})`).join(', ')}` })
|
||||
toast.warning(`${t('modelProvider.parametersInvalidRemoved', { ns: 'common' })}: ${keys.map(k => `${k} (${removedDetails[k]})`).join(', ')}`)
|
||||
handleCompletionParamsChange(filtered)
|
||||
}
|
||||
catch {
|
||||
Toast.notify({ type: 'error', message: t('error', { ns: 'common' }) })
|
||||
toast.error(t('error', { ns: 'common' }))
|
||||
handleCompletionParamsChange({})
|
||||
}
|
||||
finally {
|
||||
|
||||
@ -181,10 +181,12 @@ vi.mock('@/app/components/workflow/nodes/_base/components/editor/code-editor', (
|
||||
),
|
||||
}))
|
||||
|
||||
vi.mock('@/app/components/base/toast', () => ({
|
||||
__esModule: true,
|
||||
default: {
|
||||
notify: (payload: unknown) => mockToastNotify(payload),
|
||||
vi.mock('@/app/components/base/ui/toast', () => ({
|
||||
toast: {
|
||||
success: (message: string) => mockToastNotify({ type: 'success', message }),
|
||||
error: (message: string) => mockToastNotify({ type: 'error', message }),
|
||||
warning: (message: string) => mockToastNotify({ type: 'warning', message }),
|
||||
info: (message: string) => mockToastNotify({ type: 'info', message }),
|
||||
},
|
||||
}))
|
||||
|
||||
|
||||
@ -7,7 +7,7 @@ import { useCallback } from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import ActionButton from '@/app/components/base/action-button'
|
||||
import Input from '@/app/components/base/input'
|
||||
import Toast from '@/app/components/base/toast'
|
||||
import { toast } from '@/app/components/base/ui/toast'
|
||||
import { ValueType, VarType } from '@/app/components/workflow/types'
|
||||
import { checkKeys, replaceSpaceWithUnderscoreInVarNameInput } from '@/utils/var'
|
||||
import FormItem from './form-item'
|
||||
@ -28,10 +28,7 @@ const Item = ({
|
||||
const checkVariableName = (value: string) => {
|
||||
const { isValid, errorMessageKey } = checkKeys([value], false)
|
||||
if (!isValid) {
|
||||
Toast.notify({
|
||||
type: 'error',
|
||||
message: t(`varKeyError.${errorMessageKey}`, { ns: 'appDebug', key: t('env.modal.name', { ns: 'workflow' }) }),
|
||||
})
|
||||
toast.error(t(`varKeyError.${errorMessageKey}`, { ns: 'appDebug', key: t('env.modal.name', { ns: 'workflow' }) }))
|
||||
return false
|
||||
}
|
||||
return true
|
||||
|
||||
@ -6,7 +6,7 @@ import type { ToolDefaultValue } from '@/app/components/workflow/block-selector/
|
||||
import type { PanelProps } from '@/types/workflow'
|
||||
import { fireEvent, render, screen } from '@testing-library/react'
|
||||
import userEvent from '@testing-library/user-event'
|
||||
import Toast from '@/app/components/base/toast'
|
||||
import { toast } from '@/app/components/base/ui/toast'
|
||||
import {
|
||||
useTextGenerationCurrentProviderAndModelAndModelList,
|
||||
} from '@/app/components/header/account-setting/model-provider-page/hooks'
|
||||
@ -36,6 +36,15 @@ let mockWorkflowTools: MockToolCollection[] = []
|
||||
let mockSelectedToolInfo: ToolDefaultValue | undefined
|
||||
let mockBlockSelectorOpen = false
|
||||
|
||||
vi.mock('@/app/components/base/ui/toast', () => ({
|
||||
toast: {
|
||||
success: vi.fn(),
|
||||
error: vi.fn(),
|
||||
warning: vi.fn(),
|
||||
info: vi.fn(),
|
||||
},
|
||||
}))
|
||||
|
||||
vi.mock('@/app/components/workflow/block-selector', () => ({
|
||||
__esModule: true,
|
||||
default: ({
|
||||
@ -254,7 +263,7 @@ vi.mock('../use-config', () => ({
|
||||
|
||||
const mockUseTextGeneration = vi.mocked(useTextGenerationCurrentProviderAndModelAndModelList)
|
||||
const mockUseConfig = vi.mocked(useConfig)
|
||||
const mockToastNotify = vi.spyOn(Toast, 'notify').mockImplementation(() => ({}))
|
||||
const mockToastError = vi.mocked(toast.error)
|
||||
|
||||
const createToolParameter = (overrides: Partial<ToolParameter> = {}): ToolParameter => ({
|
||||
name: 'city',
|
||||
@ -356,7 +365,7 @@ const panelProps: PanelProps = {
|
||||
describe('parameter-extractor path', () => {
|
||||
beforeEach(() => {
|
||||
vi.clearAllMocks()
|
||||
mockToastNotify.mockClear()
|
||||
mockToastError.mockClear()
|
||||
mockBuiltInTools = []
|
||||
mockCustomTools = []
|
||||
mockWorkflowTools = []
|
||||
@ -582,7 +591,7 @@ describe('parameter-extractor path', () => {
|
||||
await user.click(screen.getByRole('button', { name: 'common.operation.save' }))
|
||||
|
||||
expect(onSave).not.toHaveBeenCalled()
|
||||
expect(mockToastNotify).toHaveBeenCalled()
|
||||
expect(mockToastError).toHaveBeenCalled()
|
||||
})
|
||||
|
||||
it('should render the add trigger for new parameters', () => {
|
||||
@ -614,7 +623,7 @@ describe('parameter-extractor path', () => {
|
||||
const descriptionInput = screen.getByPlaceholderText('workflow.nodes.parameterExtractor.addExtractParameterContent.descriptionPlaceholder')
|
||||
|
||||
fireEvent.change(nameInput, { target: { value: '1bad' } })
|
||||
expect(mockToastNotify).toHaveBeenCalled()
|
||||
expect(mockToastError).toHaveBeenCalled()
|
||||
expect(nameInput).toHaveValue('')
|
||||
|
||||
fireEvent.change(nameInput, { target: { value: 'temporary_name' } })
|
||||
@ -649,7 +658,7 @@ describe('parameter-extractor path', () => {
|
||||
await user.click(screen.getByRole('button', { name: 'common.operation.save' }))
|
||||
|
||||
expect(onSave).not.toHaveBeenCalled()
|
||||
expect(mockToastNotify).toHaveBeenCalled()
|
||||
expect(mockToastError).toHaveBeenCalled()
|
||||
})
|
||||
|
||||
it('should keep rename metadata and updated options when editing a select parameter', async () => {
|
||||
|
||||
@ -15,7 +15,7 @@ import Modal from '@/app/components/base/modal'
|
||||
import Select from '@/app/components/base/select'
|
||||
import Switch from '@/app/components/base/switch'
|
||||
import Textarea from '@/app/components/base/textarea'
|
||||
import Toast from '@/app/components/base/toast'
|
||||
import { toast } from '@/app/components/base/ui/toast'
|
||||
import { ChangeType } from '@/app/components/workflow/types'
|
||||
import { checkKeys } from '@/utils/var'
|
||||
import { ParamType } from '../../types'
|
||||
@ -54,10 +54,7 @@ const AddExtractParameter: FC<Props> = ({
|
||||
if (key === 'name') {
|
||||
const { isValid, errorKey, errorMessageKey } = checkKeys([value], true)
|
||||
if (!isValid) {
|
||||
Toast.notify({
|
||||
type: 'error',
|
||||
message: t(`varKeyError.${errorMessageKey}`, { ns: 'appDebug', key: errorKey }),
|
||||
})
|
||||
toast.error(t(`varKeyError.${errorMessageKey}`, { ns: 'appDebug', key: errorKey }))
|
||||
return
|
||||
}
|
||||
}
|
||||
@ -106,10 +103,7 @@ const AddExtractParameter: FC<Props> = ({
|
||||
errMessage = t(`${errorI18nPrefix}.fieldRequired`, { ns: 'workflow', field: t(`${i18nPrefix}.addExtractParameterContent.description`, { ns: 'workflow' }) })
|
||||
|
||||
if (errMessage) {
|
||||
Toast.notify({
|
||||
type: 'error',
|
||||
message: errMessage,
|
||||
})
|
||||
toast.error(errMessage)
|
||||
return false
|
||||
}
|
||||
return true
|
||||
|
||||
@ -7,7 +7,7 @@ import * as React from 'react'
|
||||
import { useCallback, useMemo } from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import { ReactSortable } from 'react-sortablejs'
|
||||
import Toast from '@/app/components/base/toast'
|
||||
import { toast } from '@/app/components/base/ui/toast'
|
||||
import { ChangeType } from '@/app/components/workflow/types'
|
||||
import { cn } from '@/utils/classnames'
|
||||
import { hasDuplicateStr } from '@/utils/var'
|
||||
@ -43,10 +43,7 @@ const VarList: FC<Props> = ({
|
||||
}
|
||||
|
||||
if (errorMsgKey && typeName) {
|
||||
Toast.notify({
|
||||
type: 'error',
|
||||
message: t(errorMsgKey, { ns: 'appDebug', key: t(typeName, { ns: 'appDebug' }) }),
|
||||
})
|
||||
toast.error(t(errorMsgKey, { ns: 'appDebug', key: t(typeName, { ns: 'appDebug' }) }))
|
||||
return false
|
||||
}
|
||||
onChange(newList, moreInfo ? { index, payload: moreInfo } : undefined)
|
||||
|
||||
@ -4,7 +4,7 @@ import { useBoolean } from 'ahooks'
|
||||
import { produce } from 'immer'
|
||||
import { useCallback, useState } from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import Toast from '@/app/components/base/toast'
|
||||
import { toast } from '@/app/components/base/ui/toast'
|
||||
import {
|
||||
useIsChatMode,
|
||||
useNodesReadOnly,
|
||||
@ -97,10 +97,7 @@ const useConfig = (id: string, payload: StartNodeType) => {
|
||||
}
|
||||
|
||||
if (errorMsgKey && typeName) {
|
||||
Toast.notify({
|
||||
type: 'error',
|
||||
message: t(errorMsgKey, { ns: 'appDebug', key: t(typeName, { ns: 'appDebug' }) }),
|
||||
})
|
||||
toast.error(t(errorMsgKey, { ns: 'appDebug', key: t(typeName, { ns: 'appDebug' }) }))
|
||||
return false
|
||||
}
|
||||
setInputs(newInputs)
|
||||
|
||||
@ -5,7 +5,7 @@ import { capitalize } from 'es-toolkit/string'
|
||||
import { produce } from 'immer'
|
||||
import { useCallback, useEffect, useMemo, useState } from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import Toast from '@/app/components/base/toast'
|
||||
import { toast } from '@/app/components/base/ui/toast'
|
||||
import { useLanguage } from '@/app/components/header/account-setting/model-provider-page/hooks'
|
||||
import { CollectionType } from '@/app/components/tools/types'
|
||||
import {
|
||||
@ -66,10 +66,7 @@ const useConfig = (id: string, payload: ToolNodeType) => {
|
||||
async (value: any) => {
|
||||
await updateBuiltInToolCredential(currCollection?.name as string, value)
|
||||
|
||||
Toast.notify({
|
||||
type: 'success',
|
||||
message: t('api.actionSuccess', { ns: 'common' }),
|
||||
})
|
||||
toast.success(t('api.actionSuccess', { ns: 'common' }))
|
||||
invalidToolsByType()
|
||||
hideSetAuthModal()
|
||||
},
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
import type { WebhookTriggerNodeType } from '../types'
|
||||
import { renderHook } from '@testing-library/react'
|
||||
import { useStore as useAppStore } from '@/app/components/app/store'
|
||||
import Toast from '@/app/components/base/toast'
|
||||
import { toast } from '@/app/components/base/ui/toast'
|
||||
import { BlockEnum, VarType } from '@/app/components/workflow/types'
|
||||
import { fetchWebhookUrl } from '@/service/apps'
|
||||
import { createNodeCrudModuleMock } from '../../__tests__/use-config-test-utils'
|
||||
@ -18,10 +18,10 @@ vi.mock('react-i18next', () => ({
|
||||
}),
|
||||
}))
|
||||
|
||||
vi.mock('@/app/components/base/toast', () => ({
|
||||
vi.mock('@/app/components/base/ui/toast', () => ({
|
||||
__esModule: true,
|
||||
default: {
|
||||
notify: vi.fn(),
|
||||
toast: {
|
||||
error: vi.fn(),
|
||||
},
|
||||
}))
|
||||
|
||||
@ -42,7 +42,7 @@ vi.mock('@/service/apps', () => ({
|
||||
}))
|
||||
|
||||
const mockedFetchWebhookUrl = vi.mocked(fetchWebhookUrl)
|
||||
const mockedToastNotify = vi.mocked(Toast.notify)
|
||||
const mockedToastError = vi.mocked(toast.error)
|
||||
|
||||
const createPayload = (overrides: Partial<WebhookTriggerNodeType> = {}): WebhookTriggerNodeType => ({
|
||||
title: 'Webhook',
|
||||
@ -148,7 +148,7 @@ describe('useConfig', () => {
|
||||
}),
|
||||
]),
|
||||
}))
|
||||
expect(mockedToastNotify).toHaveBeenCalledTimes(1)
|
||||
expect(mockedToastError).toHaveBeenCalledTimes(1)
|
||||
})
|
||||
|
||||
it('should generate webhook urls once and fall back to empty url on request failure', async () => {
|
||||
|
||||
@ -8,7 +8,6 @@ import { useEffect, useRef, useState } from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import InputWithCopy from '@/app/components/base/input-with-copy'
|
||||
import { SimpleSelect } from '@/app/components/base/select'
|
||||
import Toast from '@/app/components/base/toast'
|
||||
import Tooltip from '@/app/components/base/tooltip'
|
||||
import {
|
||||
NumberField,
|
||||
@ -18,6 +17,7 @@ import {
|
||||
NumberFieldIncrement,
|
||||
NumberFieldInput,
|
||||
} from '@/app/components/base/ui/number-field'
|
||||
import { toast } from '@/app/components/base/ui/toast'
|
||||
import Field from '@/app/components/workflow/nodes/_base/components/field'
|
||||
import OutputVars from '@/app/components/workflow/nodes/_base/components/output-vars'
|
||||
import Split from '@/app/components/workflow/nodes/_base/components/split'
|
||||
@ -103,10 +103,7 @@ const Panel: FC<NodePanelProps<WebhookTriggerNodeType>> = ({
|
||||
placeholder={t(`${i18nPrefix}.webhookUrlPlaceholder`, { ns: 'workflow' })}
|
||||
readOnly
|
||||
onCopy={() => {
|
||||
Toast.notify({
|
||||
type: 'success',
|
||||
message: t(`${i18nPrefix}.urlCopied`, { ns: 'workflow' }),
|
||||
})
|
||||
toast.success(t(`${i18nPrefix}.urlCopied`, { ns: 'workflow' }))
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
|
||||
@ -2,7 +2,7 @@ import type { HttpMethod, WebhookHeader, WebhookParameter, WebhookTriggerNodeTyp
|
||||
import { useCallback } from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import { useStore as useAppStore } from '@/app/components/app/store'
|
||||
import Toast from '@/app/components/base/toast'
|
||||
import { toast } from '@/app/components/base/ui/toast'
|
||||
import { useNodesReadOnly, useWorkflow } from '@/app/components/workflow/hooks'
|
||||
import useNodeCrud from '@/app/components/workflow/nodes/_base/hooks/use-node-crud'
|
||||
import { fetchWebhookUrl } from '@/service/apps'
|
||||
@ -33,10 +33,7 @@ export const useConfig = (id: string, payload: WebhookTriggerNodeType) => {
|
||||
? t(key as never, { ns: 'appDebug', key: fieldLabel })
|
||||
: t('varKeyError.keyAlreadyExists', { ns: 'appDebug', key: fieldLabel })
|
||||
|
||||
Toast.notify({
|
||||
type: 'error',
|
||||
message,
|
||||
})
|
||||
toast.error(message)
|
||||
}, [t])
|
||||
|
||||
const handleMethodChange = useCallback((method: HttpMethod) => {
|
||||
|
||||
@ -3,7 +3,7 @@ import type { VariableAssignerNodeType } from '../types'
|
||||
import type { PanelProps } from '@/types/workflow'
|
||||
import { fireEvent, render, screen } from '@testing-library/react'
|
||||
import userEvent from '@testing-library/user-event'
|
||||
import Toast from '@/app/components/base/toast'
|
||||
import { toast } from '@/app/components/base/ui/toast'
|
||||
import { renderWorkflowFlowComponent } from '@/app/components/workflow/__tests__/workflow-test-env'
|
||||
import { BlockEnum, VarType } from '@/app/components/workflow/types'
|
||||
import AddVariable from '../components/add-variable'
|
||||
@ -19,6 +19,15 @@ const mockHandleGroupItemMouseEnter = vi.fn()
|
||||
const mockHandleGroupItemMouseLeave = vi.fn()
|
||||
const mockGetAvailableVars = vi.fn()
|
||||
|
||||
vi.mock('@/app/components/base/ui/toast', () => ({
|
||||
toast: {
|
||||
success: vi.fn(),
|
||||
error: vi.fn(),
|
||||
warning: vi.fn(),
|
||||
info: vi.fn(),
|
||||
},
|
||||
}))
|
||||
|
||||
vi.mock('@/app/components/workflow/nodes/_base/components/add-variable-popup', () => ({
|
||||
default: ({ onSelect }: any) => (
|
||||
<button
|
||||
@ -102,6 +111,7 @@ vi.mock('../use-config', () => ({
|
||||
}))
|
||||
|
||||
const mockUseConfig = vi.mocked(useConfig)
|
||||
const mockToastError = vi.mocked(toast.error)
|
||||
|
||||
const createData = (overrides: Partial<VariableAssignerNodeType> = {}): VariableAssignerNodeType => ({
|
||||
title: 'Variable Assigner',
|
||||
@ -168,7 +178,6 @@ describe('variable-assigner path', () => {
|
||||
},
|
||||
])
|
||||
mockUseConfig.mockReturnValue(createConfigResult())
|
||||
vi.spyOn(Toast, 'notify').mockImplementation(() => ({}))
|
||||
})
|
||||
|
||||
describe('Path Integration', () => {
|
||||
@ -296,7 +305,7 @@ describe('variable-assigner path', () => {
|
||||
|
||||
await user.click(screen.getByText('Group1'))
|
||||
fireEvent.change(screen.getByDisplayValue('Group1'), { target: { value: '1bad' } })
|
||||
expect(Toast.notify).toHaveBeenCalled()
|
||||
expect(mockToastError).toHaveBeenCalled()
|
||||
|
||||
fireEvent.change(screen.getByDisplayValue('Group1'), { target: { value: 'Renamed Group' } })
|
||||
expect(onGroupNameChange).toHaveBeenCalledWith('Renamed_Group')
|
||||
|
||||
@ -11,7 +11,7 @@ import * as React from 'react'
|
||||
import { useCallback } from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import { Folder } from '@/app/components/base/icons/src/vender/line/files'
|
||||
import Toast from '@/app/components/base/toast'
|
||||
import { toast } from '@/app/components/base/ui/toast'
|
||||
import Field from '@/app/components/workflow/nodes/_base/components/field'
|
||||
import { VarType as VarKindType } from '@/app/components/workflow/nodes/tool/types'
|
||||
import { VarType } from '@/app/components/workflow/types'
|
||||
@ -94,10 +94,7 @@ const VarGroupItem: FC<Props> = ({
|
||||
const value = e.target.value
|
||||
const { isValid, errorKey, errorMessageKey } = checkKeys([value], false)
|
||||
if (!isValid) {
|
||||
Toast.notify({
|
||||
type: 'error',
|
||||
message: t(`varKeyError.${errorMessageKey}`, { ns: 'appDebug', key: errorKey }),
|
||||
})
|
||||
toast.error(t(`varKeyError.${errorMessageKey}`, { ns: 'appDebug', key: errorKey }))
|
||||
return
|
||||
}
|
||||
onGroupNameChange?.(value)
|
||||
|
||||
Reference in New Issue
Block a user