import { beforeEach, describe, expect, it, vi } from 'vitest' import { mount, flushPromises } from '@vue/test-utils' import { computed, ref } from 'vue' import SystemUpdates from '@/views/settings/SystemUpdates.vue' import type { UpdateStatus } from '@/services/systemUpdates' const state = ref({ configured: true, can_manage: true }) const apply = vi.fn().mockResolvedValue(undefined) const check = vi.fn().mockResolvedValue(undefined) vi.mock('@/composables/useSystemUpdates', () => ({ useSystemUpdates: () => ({ state, busy: computed(() => state.value.update?.status === 'building'), error: ref(''), refresh: vi.fn().mockResolvedValue(undefined), check, apply, }) })) vi.mock('@/layouts/DashboardLayout.vue', () => ({ default: { template: '
' } })) beforeEach(() => { vi.clearAllMocks() state.value = { configured: true, can_manage: true, current: { revision: 'a'.repeat(40), subject: 'current' }, latest: { revision: 'b'.repeat(40), subject: 'new' }, check_interval_minutes: 30, update_available: true, update: { status: 'idle', message: '' } } }) describe('SystemUpdates', () => { it('requires explicit confirmation before starting an update', async () => { const wrapper = mount(SystemUpdates) await flushPromises() const button = wrapper.findAll('button').find(b => b.text() === '更新到此版本')! await button.trigger('click') expect(wrapper.find('[role=dialog]').exists()).toBe(true) expect(apply).not.toHaveBeenCalled() await wrapper.findAll('button').find(b => b.text() === '备份并开始更新')!.trigger('click') await flushPromises() expect(apply).toHaveBeenCalledOnce() wrapper.unmount() }) it('disables installation when there is no newer version or an update is running', async () => { state.value.update_available = false const wrapper = mount(SystemUpdates) await flushPromises() expect(wrapper.find('.update-actions button').attributes('disabled')).toBeDefined() state.value.update_available = true state.value.update = { status: 'building', message: '正在构建' } await flushPromises() expect(wrapper.find('.update-actions button').attributes('disabled')).toBeDefined() expect(wrapper.text()).toContain('正在构建') wrapper.unmount() }) it('shows a failed update and recovery result', async () => { state.value.update = { status: 'rolled_back', message: '已恢复原版本', error: '构建失败' } const wrapper = mount(SystemUpdates) await flushPromises() expect(wrapper.text()).toContain('已恢复原版本') expect(wrapper.text()).toContain('构建失败') wrapper.unmount() }) })