refactor(web): migrate plugin toast usage to new UI toast API and update tests (#34001)

Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
This commit is contained in:
yyh
2026-03-24 14:02:52 +08:00
committed by GitHub
parent 8b634a9bee
commit b0920ecd17
41 changed files with 390 additions and 339 deletions

View File

@ -122,10 +122,16 @@ vi.mock('@/utils/urlValidation', () => ({
}))
const mockToastNotify = vi.fn()
vi.mock('@/app/components/base/toast', () => ({
default: {
notify: (params: unknown) => mockToastNotify(params),
},
vi.mock('@/app/components/base/ui/toast', () => ({
toast: Object.assign((params: unknown) => mockToastNotify(params), {
success: (message: unknown) => mockToastNotify({ type: 'success', message }),
error: (message: unknown) => mockToastNotify({ type: 'error', message }),
warning: (message: unknown) => mockToastNotify({ type: 'warning', message }),
info: (message: unknown) => mockToastNotify({ type: 'info', message }),
dismiss: vi.fn(),
update: vi.fn(),
promise: vi.fn(),
}),
}))
vi.mock('@/app/components/base/modal/modal', () => ({

View File

@ -2,6 +2,7 @@ import type { SimpleDetail } from '../../../store'
import type { TriggerOAuthConfig, TriggerProviderApiEntity, TriggerSubscription, TriggerSubscriptionBuilder } from '@/app/components/workflow/block-selector/types'
import { fireEvent, render, screen, waitFor } from '@testing-library/react'
import { beforeEach, describe, expect, it, vi } from 'vitest'
import { toast } from '@/app/components/base/ui/toast'
import { SupportedCreationMethods } from '@/app/components/plugins/types'
import { TriggerCredentialTypeEnum } from '@/app/components/workflow/block-selector/types'
import { CreateButtonType, CreateSubscriptionButton, DEFAULT_METHOD } from '../index'
@ -33,10 +34,16 @@ vi.mock('@/app/components/base/portal-to-follow-elem', () => ({
},
}))
vi.mock('@/app/components/base/toast', () => ({
default: {
notify: vi.fn(),
},
vi.mock('@/app/components/base/ui/toast', () => ({
toast: Object.assign(vi.fn(), {
success: vi.fn(),
error: vi.fn(),
warning: vi.fn(),
info: vi.fn(),
dismiss: vi.fn(),
update: vi.fn(),
promise: vi.fn(),
}),
}))
let mockStoreDetail: SimpleDetail | undefined
@ -908,8 +915,6 @@ describe('CreateSubscriptionButton', () => {
it('should handle OAuth initiation error', async () => {
// Arrange
const Toast = await import('@/app/components/base/toast')
mockInitiateOAuth.mockImplementation((_provider: string, callbacks: { onError: () => void }) => {
callbacks.onError()
})
@ -932,9 +937,7 @@ describe('CreateSubscriptionButton', () => {
// Assert
await waitFor(() => {
expect(Toast.default.notify).toHaveBeenCalledWith(
expect.objectContaining({ type: 'error' }),
)
expect(toast.error).toHaveBeenCalled()
})
})
})

View File

@ -86,10 +86,19 @@ vi.mock('@/hooks/use-oauth', () => ({
}))
const mockToastNotify = vi.fn()
vi.mock('@/app/components/base/toast', () => ({
default: {
notify: (params: unknown) => mockToastNotify(params),
},
vi.mock('@/app/components/base/ui/toast', () => ({
toast: Object.assign(
(message: string, options?: { type?: string }) => mockToastNotify({ type: options?.type, message }),
{
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 }),
dismiss: vi.fn(),
update: vi.fn(),
promise: vi.fn(),
},
),
}))
const mockClipboardWriteText = vi.fn()

View File

@ -77,10 +77,19 @@ vi.mock('@/hooks/use-oauth', () => ({
}))
const mockToastNotify = vi.fn()
vi.mock('@/app/components/base/toast', () => ({
default: {
notify: (params: unknown) => mockToastNotify(params),
},
vi.mock('@/app/components/base/ui/toast', () => ({
toast: Object.assign(
(message: string, options?: { type?: string }) => mockToastNotify({ type: options?.type, message }),
{
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 }),
dismiss: vi.fn(),
update: vi.fn(),
promise: vi.fn(),
},
),
}))
// ============================================================================

View File

@ -7,7 +7,7 @@ import type { BuildTriggerSubscriptionPayload } from '@/service/use-triggers'
import { debounce } from 'es-toolkit/compat'
import { useCallback, useEffect, useMemo, useRef, useState } from 'react'
import { useTranslation } from 'react-i18next'
import Toast from '@/app/components/base/toast'
import { toast } from '@/app/components/base/ui/toast'
import { SupportedCreationMethods } from '@/app/components/plugins/types'
import { TriggerCredentialTypeEnum } from '@/app/components/workflow/block-selector/types'
import {
@ -154,10 +154,7 @@ export const useCommonModalState = ({
onError: async (error: unknown) => {
const errorMessage = await parsePluginErrorMessage(error) || t('modal.errors.updateFailed', { ns: 'pluginTrigger' })
console.error('Failed to update subscription builder:', error)
Toast.notify({
type: 'error',
message: errorMessage,
})
toast.error(errorMessage)
},
},
)
@ -178,10 +175,7 @@ export const useCommonModalState = ({
}
catch (error) {
console.error('createBuilder error:', error)
Toast.notify({
type: 'error',
message: t('modal.errors.createFailed', { ns: 'pluginTrigger' }),
})
toast.error(t('modal.errors.createFailed', { ns: 'pluginTrigger' }))
}
}
if (!isInitializedRef.current && !subscriptionBuilder && detail?.provider)
@ -239,10 +233,7 @@ export const useCommonModalState = ({
const handleVerify = useCallback(() => {
// Guard against uninitialized state
if (!detail?.provider || !subscriptionBuilder?.id) {
Toast.notify({
type: 'error',
message: 'Subscription builder not initialized',
})
toast.error('Subscription builder not initialized')
return
}
@ -250,10 +241,7 @@ export const useCommonModalState = ({
const credentials = apiKeyCredentialsFormValues.values
if (!Object.keys(credentials).length) {
Toast.notify({
type: 'error',
message: 'Please fill in all required credentials',
})
toast.error('Please fill in all required credentials')
return
}
@ -270,10 +258,7 @@ export const useCommonModalState = ({
},
{
onSuccess: () => {
Toast.notify({
type: 'success',
message: t('modal.apiKey.verify.success', { ns: 'pluginTrigger' }),
})
toast.success(t('modal.apiKey.verify.success', { ns: 'pluginTrigger' }))
setCurrentStep(ApiKeyStep.Configuration)
},
onError: async (error: unknown) => {
@ -290,10 +275,7 @@ export const useCommonModalState = ({
// Handle create
const handleCreate = useCallback(() => {
if (!subscriptionBuilder) {
Toast.notify({
type: 'error',
message: 'Subscription builder not found',
})
toast.error('Subscription builder not found')
return
}
@ -327,19 +309,13 @@ export const useCommonModalState = ({
params,
{
onSuccess: () => {
Toast.notify({
type: 'success',
message: t('subscription.createSuccess', { ns: 'pluginTrigger' }),
})
toast.success(t('subscription.createSuccess', { ns: 'pluginTrigger' }))
onClose()
refetch?.()
},
onError: async (error: unknown) => {
const errorMessage = await parsePluginErrorMessage(error) || t('subscription.createFailed', { ns: 'pluginTrigger' })
Toast.notify({
type: 'error',
message: errorMessage,
})
toast.error(errorMessage)
},
},
)

View File

@ -4,7 +4,7 @@ import type { TriggerOAuthClientParams, TriggerOAuthConfig, TriggerSubscriptionB
import type { ConfigureTriggerOAuthPayload } from '@/service/use-triggers'
import { useCallback, useEffect, useMemo, useRef, useState } from 'react'
import { useTranslation } from 'react-i18next'
import Toast from '@/app/components/base/toast'
import { toast } from '@/app/components/base/ui/toast'
import { openOAuthPopup } from '@/hooks/use-oauth'
import {
useConfigureTriggerOAuth,
@ -118,20 +118,14 @@ export const useOAuthClientState = ({
openOAuthPopup(response.authorization_url, (callbackData) => {
if (!callbackData)
return
Toast.notify({
type: 'success',
message: t('modal.oauth.authorization.authSuccess', { ns: 'pluginTrigger' }),
})
toast.success(t('modal.oauth.authorization.authSuccess', { ns: 'pluginTrigger' }))
onClose()
showOAuthCreateModal(response.subscription_builder)
})
},
onError: () => {
setAuthorizationStatus(AuthorizationStatusEnum.Failed)
Toast.notify({
type: 'error',
message: t('modal.oauth.authorization.authFailed', { ns: 'pluginTrigger' }),
})
toast.error(t('modal.oauth.authorization.authFailed', { ns: 'pluginTrigger' }))
},
})
}, [providerName, initiateOAuth, onClose, showOAuthCreateModal, t])
@ -141,16 +135,10 @@ export const useOAuthClientState = ({
deleteOAuth(providerName, {
onSuccess: () => {
onClose()
Toast.notify({
type: 'success',
message: t('modal.oauth.remove.success', { ns: 'pluginTrigger' }),
})
toast.success(t('modal.oauth.remove.success', { ns: 'pluginTrigger' }))
},
onError: (error: unknown) => {
Toast.notify({
type: 'error',
message: getErrorMessage(error, t('modal.oauth.remove.failed', { ns: 'pluginTrigger' })),
})
toast.error(getErrorMessage(error, t('modal.oauth.remove.failed', { ns: 'pluginTrigger' })))
},
})
}, [providerName, deleteOAuth, onClose, t])
@ -187,10 +175,7 @@ export const useOAuthClientState = ({
return
}
onClose()
Toast.notify({
type: 'success',
message: t('modal.oauth.save.success', { ns: 'pluginTrigger' }),
})
toast.success(t('modal.oauth.save.success', { ns: 'pluginTrigger' }))
},
})
}, [clientType, providerName, oauthClientSchema, oauthConfig?.params, configureOAuth, handleAuthorization, onClose, t])

View File

@ -8,8 +8,8 @@ import { ActionButton, ActionButtonState } from '@/app/components/base/action-bu
import Badge from '@/app/components/base/badge'
import { Button } from '@/app/components/base/button'
import CustomSelect from '@/app/components/base/select/custom'
import Toast from '@/app/components/base/toast'
import Tooltip from '@/app/components/base/tooltip'
import { toast } from '@/app/components/base/ui/toast'
import { openOAuthPopup } from '@/hooks/use-oauth'
import { useInitiateTriggerOAuth, useTriggerOAuthConfig, useTriggerProviderInfo } from '@/service/use-triggers'
import { cn } from '@/utils/classnames'
@ -107,19 +107,13 @@ export const CreateSubscriptionButton = ({ buttonType = CreateButtonType.FULL_BU
onSuccess: (response) => {
openOAuthPopup(response.authorization_url, (callbackData) => {
if (callbackData) {
Toast.notify({
type: 'success',
message: t('modal.oauth.authorization.authSuccess', { ns: 'pluginTrigger' }),
})
toast.success(t('modal.oauth.authorization.authSuccess', { ns: 'pluginTrigger' }))
setSelectedCreateInfo({ type: SupportedCreationMethods.OAUTH, builder: response.subscription_builder })
}
})
},
onError: () => {
Toast.notify({
type: 'error',
message: t('modal.oauth.authorization.authFailed', { ns: 'pluginTrigger' }),
})
toast.error(t('modal.oauth.authorization.authFailed', { ns: 'pluginTrigger' }))
},
})
}

View File

@ -8,7 +8,7 @@ import { useTranslation } from 'react-i18next'
import Button from '@/app/components/base/button'
import { BaseForm } from '@/app/components/base/form/components/base'
import Modal from '@/app/components/base/modal/modal'
import Toast from '@/app/components/base/toast'
import { toast } from '@/app/components/base/ui/toast'
import OptionCard from '@/app/components/workflow/nodes/_base/components/option-card'
import { usePluginStore } from '../../store'
import { ClientTypeEnum, useOAuthClientState } from './hooks/use-oauth-client-state'
@ -48,10 +48,7 @@ export const OAuthClientSettingsModal = ({ oauthConfig, onClose, showOAuthCreate
const handleCopyRedirectUri = () => {
navigator.clipboard.writeText(oauthConfig?.redirect_uri || '')
Toast.notify({
type: 'success',
message: t('actionMsg.copySuccessfully', { ns: 'common' }),
})
toast.success(t('actionMsg.copySuccessfully', { ns: 'common' }))
}
return (