test: trim redundant test coverage

This commit is contained in:
wonfen
2026-08-19 10:24:37 +08:00
parent 807f9a206d
commit e15ddab542
38 changed files with 194 additions and 4259 deletions
-98
View File
@@ -1,98 +0,0 @@
// @vitest-environment jsdom
import { renderHook } from '@testing-library/react'
import { beforeEach, describe, expect, it, vi } from 'vitest'
import { useForgetSelection, useRecordSelection } from './use-record-selection'
const recordSelectedNode = vi.hoisted(() => vi.fn(() => Promise.resolve()))
const forgetSelectedNode = vi.hoisted(() => vi.fn(() => Promise.resolve()))
vi.mock('@/services/cmds', () => ({ forgetSelectedNode, recordSelectedNode }))
const record = (groupName: string, proxyName: string) => {
const { result } = renderHook(() => useRecordSelection())
result.current(groupName, proxyName)
}
beforeEach(() => {
recordSelectedNode.mockClear()
forgetSelectedNode.mockClear()
})
describe('useForgetSelection', () => {
it('sends only the group name', () => {
const { result } = renderHook(() => useForgetSelection())
result.current('Proxy')
expect(forgetSelectedNode).toHaveBeenCalledWith('Proxy')
})
it('resolves after the clear request finishes', async () => {
let resolveForget!: () => void
forgetSelectedNode.mockImplementationOnce(
() => new Promise<void>((resolve) => (resolveForget = resolve)),
)
const { result } = renderHook(() => useForgetSelection())
const forget = result.current('Proxy')
let settled = false
forget.then(() => {
settled = true
})
await Promise.resolve()
expect(settled).toBe(false)
resolveForget()
await forget
expect(settled).toBe(true)
})
it('reports a failed clear without throwing at the caller', async () => {
const consoleError = vi.spyOn(console, 'error').mockImplementation(() => {})
forgetSelectedNode.mockRejectedValueOnce(new Error('no profile'))
const { result } = renderHook(() => useForgetSelection())
expect(() => result.current('Proxy')).not.toThrow()
await vi.waitFor(() => expect(consoleError).toHaveBeenCalled())
consoleError.mockRestore()
})
})
describe('useRecordSelection', () => {
it('sends only the group and the node', () => {
record('Proxy', 'Node A')
expect(recordSelectedNode).toHaveBeenCalledWith('Proxy', 'Node A')
})
it('does not derive anything from a rendered selection list', () => {
// Pair-wise writes let the backend merge concurrent choices against fresh state.
record('Proxy', 'Node A')
record('Fallback', 'Node C')
expect(recordSelectedNode).toHaveBeenNthCalledWith(1, 'Proxy', 'Node A')
expect(recordSelectedNode).toHaveBeenNthCalledWith(2, 'Fallback', 'Node C')
})
it('is stable across renders, so callers may hold it in a dependency array', () => {
const { result, rerender } = renderHook(() => useRecordSelection())
const first = result.current
rerender()
expect(result.current).toBe(first)
})
it('reports a failed write without throwing at the caller', async () => {
// Persistence failure cannot roll back a core selection that already succeeded.
const consoleError = vi.spyOn(console, 'error').mockImplementation(() => {})
recordSelectedNode.mockRejectedValueOnce(new Error('no profile'))
expect(() => record('Proxy', 'Node A')).not.toThrow()
await vi.waitFor(() => expect(consoleError).toHaveBeenCalled())
})
})
-147
View File
@@ -1,147 +0,0 @@
// @vitest-environment jsdom
import { act, cleanup, renderHook } from '@testing-library/react'
import { afterEach, beforeEach, expect, it, vi } from 'vitest'
import { useSystemProxyState } from './use-system-proxy-state'
const patchVergeConfig = vi.hoisted(() => vi.fn())
const mutateVerge = vi.hoisted(() => vi.fn())
const getCacheData = vi.hoisted(() => vi.fn())
const revalidateQueries = vi.hoisted(() => vi.fn())
const CACHED: IVergeConfig = { enable_system_proxy: false } as IVergeConfig
vi.mock('@/hooks/use-verge', () => ({
useVerge: () => ({ verge: CACHED, mutateVerge }),
}))
vi.mock('@/hooks/use-displayed-mixed-port', () => ({
useDisplayedMixedPort: () => 7897,
}))
vi.mock('@/providers/app-data-context', () => ({
useSystemData: () => ({ sysproxy: undefined }),
}))
vi.mock('@/services/cmds', () => ({
getAutotemProxy: vi.fn(),
getEmbeddedServerPort: vi.fn(),
patchVergeConfig,
}))
vi.mock('tauri-plugin-mihomo-api', () => ({
closeAllConnections: vi.fn(() => Promise.resolve()),
}))
vi.mock('@/services/query-client', () => ({
useQuery: () => ({ data: undefined }),
getCacheData,
revalidateQueries,
}))
beforeEach(() => {
patchVergeConfig.mockReset()
mutateVerge.mockReset()
getCacheData.mockReset()
getCacheData.mockReturnValue(CACHED)
revalidateQueries.mockReset()
revalidateQueries.mockResolvedValue([])
})
afterEach(() => {
cleanup()
})
const lastWrite = () => {
const call = mutateVerge.mock.calls[mutateVerge.mock.calls.length - 1]?.[0]
return typeof call === 'function' ? call(CACHED) : call
}
it('puts the cache back when the toggle fails', async () => {
patchVergeConfig.mockRejectedValue({
code: 'SYSPROXY_PRIVILEGE_REQUIRED',
detail: 'refused',
})
const { result } = renderHook(() => useSystemProxyState())
await act(async () => {
await expect(result.current.toggleSystemProxy(true)).rejects.toBeTruthy()
})
expect(lastWrite()).toMatchObject({ enable_system_proxy: false })
})
it('falls back to what the last successful click reached, not to where the run began', async () => {
patchVergeConfig.mockResolvedValueOnce(undefined).mockRejectedValueOnce({
code: 'SYSPROXY_PRIVILEGE_REQUIRED',
detail: 'refused',
})
getCacheData.mockReturnValue({ enable_system_proxy: true } as IVergeConfig)
const { result } = renderHook(() => useSystemProxyState())
await act(async () => {
const inFlight = result.current.toggleSystemProxy(false)
void result.current.toggleSystemProxy(true)
await expect(inFlight).rejects.toBeTruthy()
})
expect(lastWrite()).toMatchObject({ enable_system_proxy: false })
})
it('lets a revalidation failure surface when the toggle itself worked', async () => {
patchVergeConfig.mockResolvedValue(undefined)
revalidateQueries.mockRejectedValue(new Error('network gone'))
const { result } = renderHook(() => useSystemProxyState())
await act(async () => {
await expect(result.current.toggleSystemProxy(true)).rejects.toThrow(
'network gone',
)
})
})
it('reports the failure the backend classified, not a revalidation that failed after it', async () => {
patchVergeConfig.mockRejectedValue({
code: 'SYSPROXY_PRIVILEGE_REQUIRED',
detail: 'refused',
})
revalidateQueries.mockRejectedValue(new Error('network gone'))
const { result } = renderHook(() => useSystemProxyState())
await act(async () => {
await expect(result.current.toggleSystemProxy(true)).rejects.toMatchObject({
code: 'SYSPROXY_PRIVILEGE_REQUIRED',
})
})
})
it('revalidates the config it wrote to, not only the two proxy reads', async () => {
patchVergeConfig.mockResolvedValue(undefined)
const { result } = renderHook(() => useSystemProxyState())
await act(async () => {
await result.current.toggleSystemProxy(true)
})
expect(revalidateQueries).toHaveBeenCalledWith([
['getVergeConfig'],
['getSystemProxy'],
['getAutotemProxy'],
])
})
it('drops a click queued behind one that failed', async () => {
let rejectFirst: ((reason: unknown) => void) | undefined
patchVergeConfig.mockImplementationOnce(
() =>
new Promise((_resolve, reject) => {
rejectFirst = reject
}),
)
const { result } = renderHook(() => useSystemProxyState())
let inFlight: Promise<unknown> = Promise.resolve()
await act(async () => {
inFlight = result.current.toggleSystemProxy(true)
void result.current.toggleSystemProxy(false)
rejectFirst?.({ code: 'SYSPROXY_PRIVILEGE_REQUIRED', detail: 'refused' })
await expect(inFlight).rejects.toBeTruthy()
})
expect(patchVergeConfig).toHaveBeenCalledTimes(1)
})
-32
View File
@@ -1,32 +0,0 @@
// @vitest-environment jsdom
import { act, renderHook, waitFor } from '@testing-library/react'
import { beforeEach, expect, test, vi } from 'vitest'
import { setPreloadConfig } from '@/services/preload'
import { useUpdate } from './use-update'
const check = vi.hoisted(() => vi.fn())
vi.mock('@tauri-apps/plugin-updater', () => ({ check }))
beforeEach(() => {
localStorage.clear()
setPreloadConfig({ auto_check_update: false } as IVergeConfig)
check.mockReset()
})
test('manual update check works when automatic checks are disabled', async () => {
const availableUpdate = { version: '9.9.9' }
check.mockResolvedValueOnce(availableUpdate)
const { result } = renderHook(() => useUpdate())
let checked
await act(async () => {
checked = await result.current.checkUpdate()
})
expect(check).toHaveBeenCalledOnce()
expect(checked).toEqual({ data: availableUpdate })
await waitFor(() => expect(result.current.lastCheckUpdate).not.toBeNull())
})