mirror of
https://github.com/clash-verge-rev/clash-verge-rev.git
synced 2026-11-02 21:12:13 +08:00
fix(service): fall back after installation verification rejects cores
This commit is contained in:
@@ -1,7 +1,13 @@
|
||||
import { useState } from 'react'
|
||||
import { beforeEach, expect, it, vi } from 'vitest'
|
||||
|
||||
import type { RunState } from '@/services/cmds'
|
||||
import {
|
||||
getRuntimeState,
|
||||
installService,
|
||||
restartCore,
|
||||
type RunState,
|
||||
} from '@/services/cmds'
|
||||
import { showNotice } from '@/services/notice-service'
|
||||
import { useQuery } from '@/services/query-client'
|
||||
|
||||
import { ServiceMigrationDialog } from './service-migration-dialog'
|
||||
@@ -14,8 +20,14 @@ vi.mock('@mui/material', () => ({ Alert: 'div' }))
|
||||
vi.mock('@/components/base', () => ({ BaseDialog: 'dialog' }))
|
||||
vi.mock('@/hooks/use-visibility', () => ({ useVisibility: () => true }))
|
||||
vi.mock('@/hooks/use-system-state', () => ({ runStateQueryKey: ['state'] }))
|
||||
vi.mock('@/services/cmds', () => ({ getRuntimeState: vi.fn() }))
|
||||
vi.mock('@/services/notice-service', () => ({ showNotice: {} }))
|
||||
vi.mock('@/services/cmds', () => ({
|
||||
getRuntimeState: vi.fn(),
|
||||
installService: vi.fn(),
|
||||
restartCore: vi.fn(),
|
||||
}))
|
||||
vi.mock('@/services/notice-service', () => ({
|
||||
showNotice: { warning: vi.fn(), error: vi.fn(), success: vi.fn() },
|
||||
}))
|
||||
vi.mock('@/services/query-client', () => ({
|
||||
useQuery: vi.fn(),
|
||||
setCacheData: vi.fn(),
|
||||
@@ -47,6 +59,36 @@ it.each([
|
||||
},
|
||||
)
|
||||
|
||||
it('reports the permission refusal and finishes after installation falls back to Sidecar', async () => {
|
||||
vi.mocked(useQuery).mockReturnValue({
|
||||
data: { service: 'notInstalled', mode: 'NotRunning' },
|
||||
} as ReturnType<typeof useQuery>)
|
||||
const reason = 'core path C:\\ is writable by Everyone'
|
||||
vi.mocked(installService).mockResolvedValue({ status: 'sidecar', reason })
|
||||
vi.mocked(getRuntimeState).mockResolvedValue({
|
||||
service: 'unavailable',
|
||||
mode: 'Sidecar',
|
||||
sidecarAllowed: true,
|
||||
serviceNeedsAttention: false,
|
||||
} as RunState)
|
||||
|
||||
const dialog = ServiceMigrationDialog()
|
||||
dialog.props.onOk()
|
||||
await vi.waitFor(() => {
|
||||
expect(showNotice.warning).toHaveBeenCalledWith(
|
||||
'settings.feedback.notifications.clashService.permissionFallback',
|
||||
{ reason },
|
||||
)
|
||||
})
|
||||
|
||||
expect(restartCore).not.toHaveBeenCalled()
|
||||
expect(showNotice.error).not.toHaveBeenCalled()
|
||||
expect(showNotice.success).not.toHaveBeenCalled()
|
||||
expect(vi.mocked(useState).mock.results[2].value[1]).toHaveBeenLastCalledWith(
|
||||
false,
|
||||
)
|
||||
})
|
||||
|
||||
it.each([
|
||||
{ service: 'notInstalled', mode: 'NotRunning' },
|
||||
{ service: 'versionMismatch', mode: 'NotRunning' },
|
||||
|
||||
@@ -13,6 +13,7 @@ import {
|
||||
repairService,
|
||||
restartCore,
|
||||
type RunState,
|
||||
type ServiceInstallOutcome,
|
||||
} from '@/services/cmds'
|
||||
import { showNotice } from '@/services/notice-service'
|
||||
import { setCacheData, useQuery } from '@/services/query-client'
|
||||
@@ -79,16 +80,15 @@ export const ServiceMigrationDialog = () => {
|
||||
const handleServiceAction = async () => {
|
||||
setLoading(true)
|
||||
setWorkflowIncomplete(true)
|
||||
let actionSucceeded = false
|
||||
let outcome: ServiceInstallOutcome | undefined
|
||||
try {
|
||||
if (remedy === 'install') {
|
||||
await installService()
|
||||
outcome = await installService()
|
||||
} else if (remedy === 'repair') {
|
||||
await repairService()
|
||||
outcome = await repairService()
|
||||
} else {
|
||||
await reinstallService()
|
||||
outcome = await reinstallService()
|
||||
}
|
||||
actionSucceeded = true
|
||||
} catch (error) {
|
||||
showNotice.error(
|
||||
'layout.components.serviceMigration.errors.actionFailed',
|
||||
@@ -106,10 +106,19 @@ export const ServiceMigrationDialog = () => {
|
||||
error,
|
||||
)
|
||||
}
|
||||
if (!actionSucceeded || !initialRefreshSucceeded) {
|
||||
if (!outcome || !initialRefreshSucceeded) {
|
||||
setLoading(false)
|
||||
return
|
||||
}
|
||||
if (outcome.status === 'sidecar') {
|
||||
setWorkflowIncomplete(false)
|
||||
setLoading(false)
|
||||
showNotice.warning(
|
||||
'settings.feedback.notifications.clashService.permissionFallback',
|
||||
{ reason: outcome.reason },
|
||||
)
|
||||
return
|
||||
}
|
||||
|
||||
let restartSucceeded = false
|
||||
try {
|
||||
|
||||
@@ -12,6 +12,7 @@ import {
|
||||
restartCore,
|
||||
type FailedOperation,
|
||||
type PendingFailure,
|
||||
type ServiceInstallOutcome,
|
||||
} from '@/services/cmds'
|
||||
import { showNotice } from '@/services/notice-service'
|
||||
import {
|
||||
@@ -99,12 +100,21 @@ export const SysproxyPrivilegeDialog = () => {
|
||||
|
||||
const handleFix = async () => {
|
||||
try {
|
||||
let outcome: ServiceInstallOutcome | undefined
|
||||
if (remedy === 'reinstallAndRestart') {
|
||||
setStep('installing')
|
||||
await reinstallService()
|
||||
outcome = await reinstallService()
|
||||
} else if (remedy === 'installAndRestart') {
|
||||
setStep('installing')
|
||||
await installService()
|
||||
outcome = await installService()
|
||||
}
|
||||
if (outcome?.status === 'sidecar') {
|
||||
showNotice.warning(
|
||||
'settings.feedback.notifications.clashService.permissionFallback',
|
||||
{ reason: outcome.reason },
|
||||
)
|
||||
close()
|
||||
return
|
||||
}
|
||||
setStep('restarting')
|
||||
await restartCore()
|
||||
|
||||
Reference in New Issue
Block a user