test: cover electron boundary modules
This commit is contained in:
196
tests/unit/update-service.test.ts
Normal file
196
tests/unit/update-service.test.ts
Normal file
@@ -0,0 +1,196 @@
|
||||
import { beforeEach, describe, expect, it, vi } from 'vitest'
|
||||
import type { UpdateConfig } from '../../src/main/types/config.schema'
|
||||
import type { UpdateCatalog, UpdateRelease, UpdateStatus } from '../../src/main/types/update.types'
|
||||
|
||||
const mockPublishUpdateStatus = vi.fn()
|
||||
const mockReadText = vi.fn()
|
||||
const mockDownloadToFile = vi.fn()
|
||||
const mockLoadCatalog = vi.fn()
|
||||
const mockGetDialogCatalog = vi.fn()
|
||||
const mockResolveUserStatus = vi.fn()
|
||||
const mockResolveAdminStatus = vi.fn()
|
||||
const mockGetDownloadPath = vi.fn()
|
||||
const mockCalculateSha256 = vi.fn()
|
||||
const mockInstallDownloadedRelease = vi.fn()
|
||||
const mockGetValidDownloadedRelease = vi.fn()
|
||||
|
||||
let currentUpdateConfig: UpdateConfig = {
|
||||
enabled: true,
|
||||
allowDevMode: true,
|
||||
endpoint: 'http://localhost:9000',
|
||||
accessKey: 'key',
|
||||
secretKey: 'secret',
|
||||
bucket: 'bucket',
|
||||
region: 'us-east-1',
|
||||
basePrefix: 'updates/win-portable',
|
||||
checkIntervalMinutes: 30,
|
||||
maxAdminHistoryPerChannel: 10
|
||||
}
|
||||
|
||||
function createRelease(version: string, channel: 'stable' | 'preview' = 'stable'): UpdateRelease {
|
||||
return {
|
||||
version,
|
||||
channel,
|
||||
artifactKey: `${channel}/${version}.exe`,
|
||||
sha256: `${channel}-${version}-sha`,
|
||||
size: 1,
|
||||
publishedAt: '2026-03-21T10:00:00Z',
|
||||
changelogKey: `${channel}/${version}.md`
|
||||
}
|
||||
}
|
||||
|
||||
vi.mock('../../src/main/services/config/config-manager', () => ({
|
||||
ConfigManager: {
|
||||
getInstance: vi.fn(() => ({
|
||||
getConfig: () => ({ update: currentUpdateConfig })
|
||||
}))
|
||||
}
|
||||
}))
|
||||
|
||||
vi.mock('../../src/main/services/logger', () => ({
|
||||
createLogger: vi.fn(() => ({
|
||||
info: vi.fn(),
|
||||
warn: vi.fn(),
|
||||
error: vi.fn(),
|
||||
debug: vi.fn()
|
||||
}))
|
||||
}))
|
||||
|
||||
vi.mock('../../src/main/services/update/update-status-publisher', () => ({
|
||||
publishUpdateStatus: mockPublishUpdateStatus
|
||||
}))
|
||||
|
||||
vi.mock('../../src/main/services/update/update-storage-client', () => ({
|
||||
UpdateStorageClient: class {
|
||||
readText = mockReadText
|
||||
downloadToFile = mockDownloadToFile
|
||||
}
|
||||
}))
|
||||
|
||||
vi.mock('../../src/main/services/update/update-catalog-service', () => ({
|
||||
UpdateCatalogService: class {
|
||||
loadCatalog = mockLoadCatalog
|
||||
getDialogCatalog = mockGetDialogCatalog
|
||||
resolveUserStatus = mockResolveUserStatus
|
||||
resolveAdminStatus = mockResolveAdminStatus
|
||||
}
|
||||
}))
|
||||
|
||||
vi.mock('../../src/main/services/update/update-installer', () => ({
|
||||
UpdateInstaller: class {
|
||||
getDownloadPath = mockGetDownloadPath
|
||||
calculateSha256 = mockCalculateSha256
|
||||
installDownloadedRelease = mockInstallDownloadedRelease
|
||||
getValidDownloadedRelease = mockGetValidDownloadedRelease
|
||||
}
|
||||
}))
|
||||
|
||||
describe('UpdateService', () => {
|
||||
beforeEach(() => {
|
||||
vi.clearAllMocks()
|
||||
currentUpdateConfig = {
|
||||
enabled: true,
|
||||
allowDevMode: true,
|
||||
endpoint: 'http://localhost:9000',
|
||||
accessKey: 'key',
|
||||
secretKey: 'secret',
|
||||
bucket: 'bucket',
|
||||
region: 'us-east-1',
|
||||
basePrefix: 'updates/win-portable',
|
||||
checkIntervalMinutes: 30,
|
||||
maxAdminHistoryPerChannel: 10
|
||||
}
|
||||
mockReadText.mockReset()
|
||||
mockDownloadToFile.mockReset()
|
||||
mockLoadCatalog.mockReset()
|
||||
mockGetDialogCatalog.mockReset()
|
||||
mockResolveUserStatus.mockReset()
|
||||
mockResolveAdminStatus.mockReset()
|
||||
mockGetDownloadPath.mockReset()
|
||||
mockCalculateSha256.mockReset()
|
||||
mockInstallDownloadedRelease.mockReset()
|
||||
mockGetValidDownloadedRelease.mockReset()
|
||||
})
|
||||
|
||||
async function loadService() {
|
||||
vi.resetModules()
|
||||
const module = await import('../../src/main/services/update/update-service')
|
||||
;(module.UpdateService as unknown as { instance: unknown }).instance = null
|
||||
return module.UpdateService.getInstance()
|
||||
}
|
||||
|
||||
it('initializes enabled update status from config', async () => {
|
||||
const service = await loadService()
|
||||
|
||||
service.initialize()
|
||||
|
||||
expect(service.getStatus()).toMatchObject({
|
||||
enabled: true,
|
||||
supported: true
|
||||
})
|
||||
})
|
||||
|
||||
it('clears update state when user context becomes guest-like', async () => {
|
||||
const service = await loadService()
|
||||
|
||||
await service.setUserContext(null)
|
||||
|
||||
expect(service.getStatus()).toMatchObject({
|
||||
currentUserType: null,
|
||||
phase: 'idle',
|
||||
recommendedRelease: undefined,
|
||||
downloadedRelease: undefined
|
||||
})
|
||||
expect(mockPublishUpdateStatus).toHaveBeenCalled()
|
||||
})
|
||||
|
||||
it('checks updates for user and auto-downloads available recommendation', async () => {
|
||||
const recommended = createRelease('1.1.0')
|
||||
const catalog: UpdateCatalog = {
|
||||
stable: [recommended],
|
||||
preview: []
|
||||
}
|
||||
const userStatus: Partial<UpdateStatus> = {
|
||||
phase: 'available',
|
||||
recommendedRelease: recommended,
|
||||
latestVersion: recommended.version,
|
||||
latestChannel: recommended.channel,
|
||||
message: `发现稳定版 ${recommended.version}`
|
||||
}
|
||||
|
||||
mockLoadCatalog.mockResolvedValue(catalog)
|
||||
mockResolveUserStatus.mockResolvedValue(userStatus)
|
||||
mockGetDownloadPath.mockReturnValue('D:/downloads/stable-1.1.0.exe')
|
||||
mockCalculateSha256.mockResolvedValue(recommended.sha256)
|
||||
|
||||
const service = await loadService()
|
||||
await service.setUserContext('User')
|
||||
|
||||
expect(mockLoadCatalog).toHaveBeenCalledWith('User')
|
||||
expect(mockResolveUserStatus).toHaveBeenCalled()
|
||||
expect(mockDownloadToFile).toHaveBeenCalledWith(
|
||||
recommended.artifactKey,
|
||||
'D:/downloads/stable-1.1.0.exe'
|
||||
)
|
||||
expect(service.getStatus()).toMatchObject({
|
||||
phase: 'downloaded',
|
||||
latestVersion: '1.1.0',
|
||||
latestChannel: 'stable'
|
||||
})
|
||||
})
|
||||
|
||||
it('returns disabled catalog when update services are unavailable', async () => {
|
||||
currentUpdateConfig = {
|
||||
...currentUpdateConfig,
|
||||
enabled: false,
|
||||
allowDevMode: false
|
||||
}
|
||||
const service = await loadService()
|
||||
service.initialize()
|
||||
|
||||
const result = service.getCatalog()
|
||||
|
||||
expect(result).toEqual({ mode: 'disabled' })
|
||||
expect(mockGetDialogCatalog).not.toHaveBeenCalled()
|
||||
})
|
||||
})
|
||||
Reference in New Issue
Block a user