- Replace 4x expect(true).toBe(true) in audit-logger.test.ts with
applyAuditConfig() + app.getVersion call count assertions
- Replace if(!hasCredentials){return} pattern with it.skipIf() in
3 integration test files (cleaner, erp-auth, extractor) so Vitest
correctly reports 12 tests as "skipped" instead of "passed"
- Remove placeholder assertion from skipped update-service test
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
168 lines
4.8 KiB
TypeScript
168 lines
4.8 KiB
TypeScript
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()
|
|
})
|
|
|
|
// Note: This integration scenario is complex to test in unit tests.
|
|
// Moved to integration tests: tests/integration/update-workflow.test.ts
|
|
it.skip('checks updates for user and auto-downloads available recommendation', async () => {
|
|
// Covered by integration tests
|
|
})
|
|
|
|
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()
|
|
})
|
|
})
|