test(plugins): cover stop all plugin tasks

This commit is contained in:
sawyer-shi 2026-05-05 15:58:55 +08:00
parent 225219895e
commit a4c68ee1fa
5 changed files with 71 additions and 38 deletions

View File

@ -3,7 +3,7 @@ import { fireEvent, render, screen, waitFor } from '@testing-library/react'
import { beforeEach, describe, expect, it, vi } from 'vitest'
import { PluginSource, TaskStatus } from '@/app/components/plugins/types'
// Import mocked modules
import { useMutationClearTaskPlugin, usePluginTaskList } from '@/service/use-plugins'
import { useMutationClearTaskPlugin, useMutationStopAllTaskPlugins, usePluginTaskList } from '@/service/use-plugins'
import PluginTaskList from '../components/plugin-task-list'
import TaskStatusIndicator from '../components/task-status-indicator'
import { usePluginTaskStatus } from '../hooks'
@ -14,6 +14,7 @@ import PluginTasks from '../index'
vi.mock('@/service/use-plugins', () => ({
usePluginTaskList: vi.fn(),
useMutationClearTaskPlugin: vi.fn(),
useMutationStopAllTaskPlugins: vi.fn(),
}))
vi.mock('@/app/components/plugins/install-plugin/base/use-get-icon', () => ({
@ -45,6 +46,7 @@ const createMockPlugin = (overrides: Partial<PluginStatus> = {}): PluginStatus =
// Helper to setup mock hook returns
const setupMocks = (plugins: PluginStatus[] = []) => {
const mockMutateAsync = vi.fn().mockResolvedValue({})
const mockStopAllMutateAsync = vi.fn().mockResolvedValue({})
const mockHandleRefetch = vi.fn()
vi.mocked(usePluginTaskList).mockReturnValue({
@ -58,7 +60,11 @@ const setupMocks = (plugins: PluginStatus[] = []) => {
mutateAsync: mockMutateAsync,
} as unknown as ReturnType<typeof useMutationClearTaskPlugin>)
return { mockMutateAsync, mockHandleRefetch }
vi.mocked(useMutationStopAllTaskPlugins).mockReturnValue({
mutateAsync: mockStopAllMutateAsync,
} as unknown as ReturnType<typeof useMutationStopAllTaskPlugins>)
return { mockMutateAsync, mockStopAllMutateAsync, mockHandleRefetch }
}
const getTaskMenuTrigger = () =>
@ -273,6 +279,31 @@ describe('usePluginTaskStatus Hook', () => {
})
})
})
describe('handleStopAllPlugins', () => {
it('should call stop all mutateAsync and handleRefetch', async () => {
const { mockStopAllMutateAsync, mockHandleRefetch } = setupMocks([
createMockPlugin({ status: TaskStatus.running }),
])
const TestComponent = () => {
const { handleStopAllPlugins } = usePluginTaskStatus()
return (
<button onClick={handleStopAllPlugins}>
Stop all
</button>
)
}
render(<TestComponent />)
fireEvent.click(screen.getByRole('button'))
await waitFor(() => {
expect(mockStopAllMutateAsync).toHaveBeenCalledWith()
expect(mockHandleRefetch).toHaveBeenCalled()
})
})
})
})
// ============================================================================
@ -424,6 +455,7 @@ describe('PluginTaskList Component', () => {
onClearAll: vi.fn(),
onClearErrors: vi.fn(),
onClearSingle: vi.fn(),
onStopAll: vi.fn(),
}
beforeEach(() => {
@ -495,6 +527,23 @@ describe('PluginTaskList Component', () => {
expect(handleClearAll).toHaveBeenCalledTimes(1)
})
it('should call onStopAll when stop all button is clicked in running section', () => {
const handleStopAll = vi.fn()
const runningPlugins = [createMockPlugin({ status: TaskStatus.running })]
render(
<PluginTaskList
{...defaultProps}
runningPlugins={runningPlugins}
onStopAll={handleStopAll}
/>,
)
fireEvent.click(screen.getByRole('button', { name: /task\.stopAll/i }))
expect(handleStopAll).toHaveBeenCalledTimes(1)
})
it('should call onClearErrors when clear all button is clicked in error section', () => {
const handleClearErrors = vi.fn()
const errorPlugins = [createMockPlugin({ status: TaskStatus.failed })]

View File

@ -57,6 +57,7 @@ describe('PluginTaskList', () => {
onClearAll: vi.fn(),
onClearErrors: vi.fn(),
onClearSingle: vi.fn(),
onStopAll: vi.fn(),
}
beforeEach(() => {
@ -180,44 +181,28 @@ describe('PluginTaskList', () => {
})
describe('Running section', () => {
it('should not render clear buttons for running plugins', () => {
it('should render stop all button for running plugins', () => {
render(<PluginTaskList {...defaultProps} runningPlugins={runningPlugins} />)
// Running section has no headerAction and no onClearSingle
// Running section has no headerAction and no onClearSingle
// Running section has no headerAction and no onClearSingle
// Running section has no headerAction and no onClearSingle
// Running section has no headerAction and no onClearSingle
// Running section has no headerAction and no onClearSingle
// Running section has no headerAction and no onClearSingle
// Running section has no headerAction and no onClearSingle
// Running section has no headerAction and no onClearSingle
// Running section has no headerAction and no onClearSingle
// Running section has no headerAction and no onClearSingle
// Running section has no headerAction and no onClearSingle
// Running section has no headerAction and no onClearSingle
// Running section has no headerAction and no onClearSingle
// Running section has no headerAction and no onClearSingle
// Running section has no headerAction and no onClearSingle
// Running section has no headerAction and no onClearSingle
// Running section has no headerAction and no onClearSingle
// Running section has no headerAction and no onClearSingle
// Running section has no headerAction and no onClearSingle
// Running section has no headerAction and no onClearSingle
// Running section has no headerAction and no onClearSingle
// Running section has no headerAction and no onClearSingle
// Running section has no headerAction and no onClearSingle
// Running section has no headerAction and no onClearSingle
// Running section has no headerAction and no onClearSingle
// Running section has no headerAction and no onClearSingle
// Running section has no headerAction and no onClearSingle
// Running section has no headerAction and no onClearSingle
// Running section has no headerAction and no onClearSingle
// Running section has no headerAction and no onClearSingle
// Running section has no headerAction and no onClearSingle
expect(screen.getByRole('button', { name: /plugin\.task\.stopAll/ })).toBeInTheDocument()
expect(screen.queryByText(/plugin\.task\.clearAll/)).not.toBeInTheDocument()
})
it('should call onStopAll when stop all button is clicked', () => {
const onStopAll = vi.fn()
render(
<PluginTaskList
{...defaultProps}
runningPlugins={runningPlugins}
onStopAll={onStopAll}
/>,
)
fireEvent.click(screen.getByRole('button', { name: /plugin\.task\.stopAll/ }))
expect(onStopAll).toHaveBeenCalledTimes(1)
})
it('should show installing hint as status text', () => {
render(<PluginTaskList {...defaultProps} runningPlugins={runningPlugins} />)

View File

@ -42,7 +42,7 @@ export const usePluginTaskStatus = () => {
})
handleRefetch()
}, [mutateAsync, handleRefetch])
const handleStopAllPlugins = useCallback(async () => {
await mutateStopAllAsync()
handleRefetch()

View File

@ -82,7 +82,6 @@ const PluginTasks = () => {
[clearPluginsAndClose, errorPlugins],
)
const handleStopAll = useCallback(async () => {
await handleStopAllPlugins()
setOpen(false)

View File

@ -257,4 +257,4 @@
"upgrade.upgrade": "Install",
"upgrade.upgrading": "Installing...",
"upgrade.usedInApps": "Used in {{num}} apps"
}
}