refactor(web): migrate plugin toast calls to overlay ui toast

This commit is contained in:
yyh 2026-03-24 12:07:30 +08:00
parent 27c4faad4f
commit 501f3cb26c
40 changed files with 85 additions and 63 deletions

View File

@ -3,7 +3,7 @@ import { beforeEach, describe, expect, it, vi } from 'vitest'
import { useGitHubReleases, useGitHubUpload } from '../hooks'
const mockNotify = vi.fn()
vi.mock('@/app/components/base/toast', () => ({
vi.mock('@/app/components/plugins/utils/toast', () => ({
default: { notify: (...args: unknown[]) => mockNotify(...args) },
}))

View File

@ -1,6 +1,6 @@
import type { GitHubRepoReleaseResponse } from '../types'
import type { IToastProps } from '@/app/components/base/toast'
import Toast from '@/app/components/base/toast'
import type { LegacyToastOptions } from '@/app/components/plugins/utils/toast'
import Toast from '@/app/components/plugins/utils/toast'
import { GITHUB_ACCESS_TOKEN } from '@/config'
import { uploadGitHub } from '@/service/plugins'
import { compareVersion, getLatestVersion } from '@/utils/semver'
@ -54,7 +54,7 @@ export const useGitHubReleases = () => {
const checkForUpdates = (fetchedReleases: GitHubRepoReleaseResponse[], currentVersion: string) => {
let needUpdate = false
const toastProps: IToastProps = {
const toastProps: LegacyToastOptions = {
type: 'info',
message: 'No new version available',
}

View File

@ -57,7 +57,7 @@ const createUpdatePayload = (overrides: Partial<UpdateFromGitHubPayload> = {}):
// Mock external dependencies
const mockNotify = vi.fn()
vi.mock('@/app/components/base/toast', () => ({
vi.mock('@/app/components/plugins/utils/toast', () => ({
default: {
notify: (props: { type: string, message: string }) => mockNotify(props),
},

View File

@ -7,8 +7,8 @@ import * as React from 'react'
import { useCallback, useState } from 'react'
import { useTranslation } from 'react-i18next'
import Modal from '@/app/components/base/modal'
import Toast from '@/app/components/base/toast'
import useGetIcon from '@/app/components/plugins/install-plugin/base/use-get-icon'
import Toast from '@/app/components/plugins/utils/toast'
import { cn } from '@/utils/classnames'
import { InstallStepFromGitHub } from '../../types'
import Installed from '../base/installed'

View File

@ -2,7 +2,7 @@ import type { PluginDetail } from '../../types'
import { fireEvent, render, screen, waitFor } from '@testing-library/react'
import { beforeEach, describe, expect, it, vi } from 'vitest'
import * as amplitude from '@/app/components/base/amplitude'
import Toast from '@/app/components/base/toast'
import Toast from '@/app/components/plugins/utils/toast'
import { PluginSource } from '../../types'
import DetailHeader from '../detail-header'

View File

@ -1,7 +1,7 @@
import type { EndpointListItem, PluginDetail } from '../../types'
import { act, fireEvent, render, screen } from '@testing-library/react'
import { beforeEach, describe, expect, it, vi } from 'vitest'
import Toast from '@/app/components/base/toast'
import Toast from '@/app/components/plugins/utils/toast'
import EndpointCard from '../endpoint-card'
const mockHandleChange = vi.fn()
@ -127,7 +127,7 @@ describe('EndpointCard', () => {
failureFlags.disable = false
failureFlags.delete = false
failureFlags.update = false
// Mock Toast.notify to prevent toast elements from accumulating in DOM
// Mock notifyToast to prevent toast elements from accumulating in DOM
vi.spyOn(Toast, 'notify').mockImplementation(() => ({ clear: vi.fn() }))
// Polyfill document.execCommand for copy-to-clipboard in jsdom
if (typeof document.execCommand !== 'function') {

View File

@ -2,7 +2,7 @@ import type { FormSchema } from '../../../base/form/types'
import type { PluginDetail } from '../../types'
import { fireEvent, render, screen } from '@testing-library/react'
import { beforeEach, describe, expect, it, vi } from 'vitest'
import Toast from '@/app/components/base/toast'
import Toast from '@/app/components/plugins/utils/toast'
import EndpointModal from '../endpoint-modal'
vi.mock('@/hooks/use-i18n', () => ({

View File

@ -3,7 +3,7 @@ import type { ModalStates, VersionTarget } from '../use-detail-header-state'
import { act, renderHook } from '@testing-library/react'
import { beforeEach, describe, expect, it, vi } from 'vitest'
import * as amplitude from '@/app/components/base/amplitude'
import Toast from '@/app/components/base/toast'
import Toast from '@/app/components/plugins/utils/toast'
import { PluginSource } from '../../../../types'
import { usePluginOperations } from '../use-plugin-operations'
@ -233,7 +233,7 @@ describe('usePluginOperations', () => {
})
expect(mockCheckForUpdates).toHaveBeenCalled()
expect(Toast.notify).toHaveBeenCalled()
expect(notifyToast).toHaveBeenCalled()
})
it('should show update plugin modal when update is needed', async () => {

View File

@ -5,7 +5,8 @@ import type { ModalStates, VersionTarget } from './use-detail-header-state'
import { useCallback } from 'react'
import { useTranslation } from 'react-i18next'
import { trackEvent } from '@/app/components/base/amplitude'
import Toast from '@/app/components/base/toast'
import { toast } from '@/app/components/base/ui/toast'
import Toast from '@/app/components/plugins/utils/toast'
import { useModalContext } from '@/context/modal-context'
import { useProviderContext } from '@/context/provider-context'
import { uninstallPlugin } from '@/service/plugins'
@ -74,7 +75,7 @@ export const usePluginOperations = ({
return
const { needUpdate, toastProps } = checkForUpdates(fetchedReleases, meta.version)
Toast.notify(toastProps)
toast(toastProps)
if (needUpdate) {
setShowUpdatePluginModal({

View File

@ -9,9 +9,9 @@ import ActionButton from '@/app/components/base/action-button'
import Confirm from '@/app/components/base/confirm'
import { CopyCheck } from '@/app/components/base/icons/src/vender/line/files'
import Switch from '@/app/components/base/switch'
import Toast from '@/app/components/base/toast'
import Tooltip from '@/app/components/base/tooltip'
import Indicator from '@/app/components/header/indicator'
import Toast from '@/app/components/plugins/utils/toast'
import { addDefaultValue, toolCredentialToFormSchemas } from '@/app/components/tools/utils/to-form-schema'
import {
useDeleteEndpoint,

View File

@ -9,8 +9,8 @@ import * as React from 'react'
import { useMemo } from 'react'
import { useTranslation } from 'react-i18next'
import ActionButton from '@/app/components/base/action-button'
import Toast from '@/app/components/base/toast'
import Tooltip from '@/app/components/base/tooltip'
import Toast from '@/app/components/plugins/utils/toast'
import { toolCredentialToFormSchemas } from '@/app/components/tools/utils/to-form-schema'
import { useDocLink } from '@/context/i18n'
import {

View File

@ -8,8 +8,8 @@ import { useTranslation } from 'react-i18next'
import ActionButton from '@/app/components/base/action-button'
import Button from '@/app/components/base/button'
import Drawer from '@/app/components/base/drawer'
import Toast from '@/app/components/base/toast'
import Form from '@/app/components/header/account-setting/model-provider-page/model-modal/Form'
import Toast from '@/app/components/plugins/utils/toast'
import { useRenderI18nObject } from '@/hooks/use-i18n'
import { cn } from '@/utils/classnames'
import { ReadmeEntrance } from '../readme-panel/entrance'

View File

@ -1,10 +1,10 @@
import type { Model, ModelItem } from '@/app/components/header/account-setting/model-provider-page/declarations'
import { fireEvent, render, screen, waitFor } from '@testing-library/react'
import { beforeEach, describe, expect, it, vi } from 'vitest'
// Import component after mocks
import Toast from '@/app/components/base/toast'
import { ConfigurationMethodEnum, ModelStatusEnum, ModelTypeEnum } from '@/app/components/header/account-setting/model-provider-page/declarations'
// Import component after mocks
import Toast from '@/app/components/plugins/utils/toast'
import ModelParameterModal from '../index'
// ==================== Mock Setup ====================
@ -865,7 +865,7 @@ describe('ModelParameterModal', () => {
// Assert
await waitFor(() => {
expect(Toast.notify).toHaveBeenCalledWith(
expect(notifyToast).toHaveBeenCalledWith(
expect.objectContaining({ type: 'warning' }),
)
})
@ -892,7 +892,7 @@ describe('ModelParameterModal', () => {
// Assert
await waitFor(() => {
expect(Toast.notify).toHaveBeenCalledWith(
expect(notifyToast).toHaveBeenCalledWith(
expect.objectContaining({ type: 'error' }),
)
})

View File

@ -10,7 +10,6 @@ import type {
import type { TriggerProps } from '@/app/components/header/account-setting/model-provider-page/model-parameter-modal/trigger'
import { useMemo, useState } from 'react'
import { useTranslation } from 'react-i18next'
import Toast from '@/app/components/base/toast'
import {
Popover,
PopoverContent,
@ -23,6 +22,7 @@ import {
import AgentModelTrigger from '@/app/components/header/account-setting/model-provider-page/model-parameter-modal/agent-model-trigger'
import Trigger from '@/app/components/header/account-setting/model-provider-page/model-parameter-modal/trigger'
import ModelSelector from '@/app/components/header/account-setting/model-provider-page/model-selector'
import Toast from '@/app/components/plugins/utils/toast'
import { useProviderContext } from '@/context/provider-context'
import { cn } from '@/utils/classnames'
import { fetchAndMergeValidCompletionParams } from '@/utils/completion-params'

View File

@ -1,7 +1,7 @@
import type { TriggerLogEntity } from '@/app/components/workflow/block-selector/types'
import { cleanup, fireEvent, render, screen } from '@testing-library/react'
import { beforeEach, describe, expect, it, vi } from 'vitest'
import Toast from '@/app/components/base/toast'
import Toast from '@/app/components/plugins/utils/toast'
import LogViewer from '../log-viewer'
const mockToastNotify = vi.fn()

View File

@ -26,7 +26,7 @@ vi.mock('@/service/use-triggers', () => ({
useDeleteTriggerSubscription: () => ({ mutate: vi.fn(), isPending: false }),
}))
vi.mock('@/app/components/base/toast', () => ({
vi.mock('@/app/components/plugins/utils/toast', () => ({
default: {
notify: vi.fn(),
},

View File

@ -1,7 +1,7 @@
import type { TriggerSubscription } from '@/app/components/workflow/block-selector/types'
import { fireEvent, render, screen } from '@testing-library/react'
import { beforeEach, describe, expect, it, vi } from 'vitest'
import Toast from '@/app/components/base/toast'
import Toast from '@/app/components/plugins/utils/toast'
import { TriggerCredentialTypeEnum } from '@/app/components/workflow/block-selector/types'
import { SubscriptionSelectorView } from '../selector-view'

View File

@ -1,7 +1,7 @@
import type { TriggerSubscription } from '@/app/components/workflow/block-selector/types'
import { fireEvent, render, screen } from '@testing-library/react'
import { beforeEach, describe, expect, it, vi } from 'vitest'
import Toast from '@/app/components/base/toast'
import Toast from '@/app/components/plugins/utils/toast'
import { TriggerCredentialTypeEnum } from '@/app/components/workflow/block-selector/types'
import SubscriptionCard from '../subscription-card'

View File

@ -122,7 +122,7 @@ vi.mock('@/utils/urlValidation', () => ({
}))
const mockToastNotify = vi.fn()
vi.mock('@/app/components/base/toast', () => ({
vi.mock('@/app/components/plugins/utils/toast', () => ({
default: {
notify: (params: unknown) => mockToastNotify(params),
},

View File

@ -3,6 +3,7 @@ import type { TriggerOAuthConfig, TriggerProviderApiEntity, TriggerSubscription,
import { fireEvent, render, screen, waitFor } from '@testing-library/react'
import { beforeEach, describe, expect, it, vi } from 'vitest'
import { SupportedCreationMethods } from '@/app/components/plugins/types'
import Toast from '@/app/components/plugins/utils/toast'
import { TriggerCredentialTypeEnum } from '@/app/components/workflow/block-selector/types'
import { CreateButtonType, CreateSubscriptionButton, DEFAULT_METHOD } from '../index'
@ -33,7 +34,7 @@ vi.mock('@/app/components/base/portal-to-follow-elem', () => ({
},
}))
vi.mock('@/app/components/base/toast', () => ({
vi.mock('@/app/components/plugins/utils/toast', () => ({
default: {
notify: vi.fn(),
},
@ -908,8 +909,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,7 +931,7 @@ describe('CreateSubscriptionButton', () => {
// Assert
await waitFor(() => {
expect(Toast.default.notify).toHaveBeenCalledWith(
expect(Toast.notify).toHaveBeenCalledWith(
expect.objectContaining({ type: 'error' }),
)
})

View File

@ -86,7 +86,7 @@ vi.mock('@/hooks/use-oauth', () => ({
}))
const mockToastNotify = vi.fn()
vi.mock('@/app/components/base/toast', () => ({
vi.mock('@/app/components/plugins/utils/toast', () => ({
default: {
notify: (params: unknown) => mockToastNotify(params),
},

View File

@ -77,7 +77,7 @@ vi.mock('@/hooks/use-oauth', () => ({
}))
const mockToastNotify = vi.fn()
vi.mock('@/app/components/base/toast', () => ({
vi.mock('@/app/components/plugins/utils/toast', () => ({
default: {
notify: (params: unknown) => mockToastNotify(params),
},

View File

@ -7,8 +7,8 @@ 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 { SupportedCreationMethods } from '@/app/components/plugins/types'
import Toast from '@/app/components/plugins/utils/toast'
import { TriggerCredentialTypeEnum } from '@/app/components/workflow/block-selector/types'
import {
useBuildTriggerSubscription,

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/plugins/utils/toast'
import { openOAuthPopup } from '@/hooks/use-oauth'
import {
useConfigureTriggerOAuth,

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/plugins/utils/toast'
import { openOAuthPopup } from '@/hooks/use-oauth'
import { useInitiateTriggerOAuth, useTriggerOAuthConfig, useTriggerProviderInfo } from '@/service/use-triggers'
import { cn } from '@/utils/classnames'

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/plugins/utils/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'

View File

@ -47,8 +47,8 @@ vi.mock('@/service/use-triggers', () => ({
useTriggerPluginDynamicOptions: () => ({ data: [], isLoading: false }),
}))
vi.mock('@/app/components/base/toast', async (importOriginal) => {
const actual = await importOriginal<typeof import('@/app/components/base/toast')>()
vi.mock('@/app/components/plugins/utils/toast', async (importOriginal) => {
const actual = await importOriginal<typeof import('@/app/components/plugins/utils/toast')>()
return {
...actual,
default: {
@ -57,7 +57,7 @@ vi.mock('@/app/components/base/toast', async (importOriginal) => {
}
})
vi.mock('@/app/components/base/toast/context', () => ({
vi.mock('@/app/components/plugins/utils/toast/context', () => ({
useToastContext: () => ({
notify: (args: { type: string, message: string }) => mockToast(args),
close: vi.fn(),

View File

@ -13,7 +13,7 @@ import { OAuthEditModal } from '../oauth-edit-modal'
// ==================== Mock Setup ====================
const mockToastNotify = vi.fn()
vi.mock('@/app/components/base/toast', () => ({
vi.mock('@/app/components/plugins/utils/toast', () => ({
default: { notify: (params: unknown) => mockToastNotify(params) },
}))

View File

@ -30,8 +30,8 @@ vi.mock('@/service/use-triggers', () => ({
useTriggerPluginDynamicOptions: () => ({ data: [], isLoading: false }),
}))
vi.mock('@/app/components/base/toast', async (importOriginal) => {
const actual = await importOriginal<typeof import('@/app/components/base/toast')>()
vi.mock('@/app/components/plugins/utils/toast', async (importOriginal) => {
const actual = await importOriginal<typeof import('@/app/components/plugins/utils/toast')>()
return {
...actual,
default: {
@ -40,7 +40,7 @@ vi.mock('@/app/components/base/toast', async (importOriginal) => {
}
})
vi.mock('@/app/components/base/toast/context', () => ({
vi.mock('@/app/components/plugins/utils/toast/context', () => ({
useToastContext: () => ({
notify: (args: { type: string, message: string }) => mockToast(args),
close: vi.fn(),

View File

@ -30,8 +30,8 @@ vi.mock('@/service/use-triggers', () => ({
useTriggerPluginDynamicOptions: () => ({ data: [], isLoading: false }),
}))
vi.mock('@/app/components/base/toast', async (importOriginal) => {
const actual = await importOriginal<typeof import('@/app/components/base/toast')>()
vi.mock('@/app/components/plugins/utils/toast', async (importOriginal) => {
const actual = await importOriginal<typeof import('@/app/components/plugins/utils/toast')>()
return {
...actual,
default: {
@ -40,7 +40,7 @@ vi.mock('@/app/components/base/toast', async (importOriginal) => {
}
})
vi.mock('@/app/components/base/toast/context', () => ({
vi.mock('@/app/components/plugins/utils/toast/context', () => ({
useToastContext: () => ({
notify: (args: { type: string, message: string }) => mockToast(args),
close: vi.fn(),

View File

@ -9,8 +9,8 @@ import { EncryptedBottom } from '@/app/components/base/encrypted-bottom'
import { BaseForm } from '@/app/components/base/form/components/base'
import { FormTypeEnum } from '@/app/components/base/form/types'
import Modal from '@/app/components/base/modal/modal'
import Toast from '@/app/components/base/toast'
import { ReadmeEntrance } from '@/app/components/plugins/readme-panel/entrance'
import Toast from '@/app/components/plugins/utils/toast'
import { useUpdateTriggerSubscription, useVerifyTriggerSubscription } from '@/service/use-triggers'
import { parsePluginErrorMessage } from '@/utils/error-parser'
import { ReadmeShowType } from '../../../readme-panel/store'

View File

@ -8,8 +8,8 @@ import { useTranslation } from 'react-i18next'
import { BaseForm } from '@/app/components/base/form/components/base'
import { FormTypeEnum } from '@/app/components/base/form/types'
import Modal from '@/app/components/base/modal/modal'
import Toast from '@/app/components/base/toast'
import { ReadmeEntrance } from '@/app/components/plugins/readme-panel/entrance'
import Toast from '@/app/components/plugins/utils/toast'
import { useUpdateTriggerSubscription } from '@/service/use-triggers'
import { ReadmeShowType } from '../../../readme-panel/store'
import { usePluginStore } from '../../store'

View File

@ -8,8 +8,8 @@ import { useTranslation } from 'react-i18next'
import { BaseForm } from '@/app/components/base/form/components/base'
import { FormTypeEnum } from '@/app/components/base/form/types'
import Modal from '@/app/components/base/modal/modal'
import Toast from '@/app/components/base/toast'
import { ReadmeEntrance } from '@/app/components/plugins/readme-panel/entrance'
import Toast from '@/app/components/plugins/utils/toast'
import { useUpdateTriggerSubscription } from '@/service/use-triggers'
import { ReadmeShowType } from '../../../readme-panel/store'
import { usePluginStore } from '../../store'

View File

@ -11,7 +11,7 @@ import dayjs from 'dayjs'
import * as React from 'react'
import { useState } from 'react'
import { useTranslation } from 'react-i18next'
import Toast from '@/app/components/base/toast'
import Toast from '@/app/components/plugins/utils/toast'
import CodeEditor from '@/app/components/workflow/nodes/_base/components/editor/code-editor'
import { CodeLanguage } from '@/app/components/workflow/nodes/code/types'
import { cn } from '@/utils/classnames'

View File

@ -298,7 +298,7 @@ vi.mock('@/app/components/header/account-setting/model-provider-page/model-modal
// Mock Toast - need to track notify calls for assertions
const mockToastNotify = vi.fn()
vi.mock('@/app/components/base/toast', () => ({
vi.mock('@/app/components/plugins/utils/toast', () => ({
default: { notify: (...args: unknown[]) => mockToastNotify(...args) },
}))
@ -1943,7 +1943,7 @@ describe('ToolCredentialsForm Component', () => {
const saveBtn = screen.getByText(/save/i)
fireEvent.click(saveBtn)
// Toast.notify should have been called with error (lines 49-50)
// notifyToast should have been called with error (lines 49-50)
expect(mockToastNotify).toHaveBeenCalledWith(expect.objectContaining({ type: 'error' }))
// onSaved should not be called because validation fails
expect(onSaved).not.toHaveBeenCalled()

View File

@ -10,11 +10,11 @@ vi.mock('@/utils/classnames', () => ({
cn: (...args: unknown[]) => args.filter(Boolean).join(' '),
}))
vi.mock('@/app/components/base/toast', () => ({
vi.mock('@/app/components/plugins/utils/toast', () => ({
default: { notify: vi.fn() },
}))
vi.mock('@/app/components/base/toast/context', () => ({
vi.mock('@/app/components/plugins/utils/toast/context', () => ({
useToastContext: () => ({ notify: vi.fn() }),
}))

View File

@ -10,8 +10,8 @@ import { useEffect, useState } from 'react'
import { useTranslation } from 'react-i18next'
import Button from '@/app/components/base/button'
import Loading from '@/app/components/base/loading'
import Toast from '@/app/components/base/toast'
import Form from '@/app/components/header/account-setting/model-provider-page/model-modal/Form'
import Toast from '@/app/components/plugins/utils/toast'
import { addDefaultValue, toolCredentialToFormSchemas } from '@/app/components/tools/utils/to-form-schema'
import { useRenderI18nObject } from '@/hooks/use-i18n'
import { fetchBuiltInToolCredential, fetchBuiltInToolCredentialSchema } from '@/service/tools'

View File

@ -1,7 +1,7 @@
import type { MetaData, PluginCategoryEnum } from '../../types'
import { fireEvent, render, screen, waitFor } from '@testing-library/react'
import { beforeEach, describe, expect, it, vi } from 'vitest'
import Toast from '@/app/components/base/toast'
import Toast from '@/app/components/plugins/utils/toast'
// ==================== Imports (after mocks) ====================
@ -140,12 +140,12 @@ const getActionButtons = () => screen.getAllByRole('button')
const queryActionButtons = () => screen.queryAllByRole('button')
describe('Action Component', () => {
// Spy on Toast.notify - real component but we track calls
// Spy on notifyToast - real component but we track calls
let toastNotifySpy: ReturnType<typeof vi.spyOn>
beforeEach(() => {
vi.clearAllMocks()
// Spy on Toast.notify and mock implementation to avoid DOM side effects
// Spy on notifyToast and mock implementation to avoid DOM side effects
toastNotifySpy = vi.spyOn(Toast, 'notify').mockImplementation(() => ({ clear: vi.fn() }))
mockUninstallPlugin.mockResolvedValue({ success: true })
mockFetchReleases.mockResolvedValue([])
@ -563,7 +563,7 @@ describe('Action Component', () => {
render(<Action {...props} />)
fireEvent.click(getActionButtons()[0])
// Assert - Toast.notify is called with the toast props
// Assert - notifyToast is called with the toast props
await waitFor(() => {
expect(toastNotifySpy).toHaveBeenCalledWith({ type: 'success', message: 'Already up to date' })
})

View File

@ -7,7 +7,7 @@ import { useBoolean } from 'ahooks'
import * as React from 'react'
import { useCallback } from 'react'
import { useTranslation } from 'react-i18next'
import Toast from '@/app/components/base/toast'
import { toast } from '@/app/components/base/ui/toast'
import { useModalContext } from '@/context/modal-context'
import { uninstallPlugin } from '@/service/plugins'
import { useInvalidateInstalledPluginList } from '@/service/use-plugins'
@ -65,7 +65,7 @@ const Action: FC<Props> = ({
if (fetchedReleases.length === 0)
return
const { needUpdate, toastProps } = checkForUpdates(fetchedReleases, meta!.version)
Toast.notify(toastProps)
toast(toastProps)
if (needUpdate) {
setShowUpdatePluginModal({
onSaveCallback: () => {

View File

@ -0,0 +1,22 @@
import type { ReactNode } from 'react'
import { toast } from '@/app/components/base/ui/toast'
type ToastType = 'success' | 'error' | 'warning' | 'info'
export type LegacyToastOptions = {
type?: ToastType
message: ReactNode
}
export const notifyToast = ({
type = 'info',
message,
}: LegacyToastOptions) => {
toast[type](message)
}
const Toast = {
notify: notifyToast,
}
export default Toast