218 lines
5.7 KiB
TypeScript
218 lines
5.7 KiB
TypeScript
import { describe, expect, it } from 'vitest'
|
|
import {
|
|
compareVersions,
|
|
normalizeReleases,
|
|
pickLatestRelease,
|
|
resolveAdminDecision,
|
|
resolveUserDecision
|
|
} from '../../src/main/services/update/update-utils'
|
|
import type { UpdateCatalog } from '../../src/main/types/update.types'
|
|
|
|
describe('update-utils', () => {
|
|
it('compares semver-like numeric versions correctly', () => {
|
|
expect(compareVersions('1.3.1', '1.3.1')).toBe(0)
|
|
expect(compareVersions('1.3.2', '1.3.1')).toBe(1)
|
|
expect(compareVersions('1.10.0', '1.9.9')).toBe(1)
|
|
expect(compareVersions('1.2.0', '1.3.0')).toBe(-1)
|
|
})
|
|
|
|
it('pads missing version segments with zero', () => {
|
|
expect(compareVersions('1.3', '1.3.0')).toBe(0)
|
|
expect(compareVersions('1.3.1', '1.3')).toBe(1)
|
|
})
|
|
|
|
it('normalizes channel indexes and drops invalid entries', () => {
|
|
const releases = normalizeReleases(
|
|
{
|
|
releases: [
|
|
{
|
|
version: '1.3.2',
|
|
artifactKey: 'stable/1.3.2.exe',
|
|
sha256: 'abc',
|
|
size: 123,
|
|
publishedAt: '2026-03-20T10:00:00Z',
|
|
changelogKey: 'stable/1.3.2.md'
|
|
},
|
|
{
|
|
version: '1.3.1',
|
|
artifactKey: '',
|
|
sha256: 'missing',
|
|
size: 12,
|
|
publishedAt: '2026-03-19T10:00:00Z',
|
|
changelogKey: 'stable/1.3.1.md'
|
|
}
|
|
]
|
|
},
|
|
'stable'
|
|
)
|
|
|
|
expect(releases).toHaveLength(1)
|
|
expect(releases[0].channel).toBe('stable')
|
|
expect(releases[0].version).toBe('1.3.2')
|
|
})
|
|
|
|
it('keeps higher version newer even if its publishedAt is older', () => {
|
|
const latest = pickLatestRelease([
|
|
{
|
|
version: '1.3.1',
|
|
channel: 'stable',
|
|
artifactKey: 'stable/1.3.1.exe',
|
|
sha256: 'a',
|
|
size: 1,
|
|
publishedAt: '2026-03-20T11:00:00Z',
|
|
changelogKey: 'stable/1.3.1.md'
|
|
},
|
|
{
|
|
version: '1.3.2',
|
|
channel: 'stable',
|
|
artifactKey: 'stable/1.3.2.exe',
|
|
sha256: 'b',
|
|
size: 1,
|
|
publishedAt: '2026-03-20T10:00:00Z',
|
|
changelogKey: 'stable/1.3.2.md'
|
|
}
|
|
])
|
|
|
|
expect(latest?.version).toBe('1.3.2')
|
|
})
|
|
|
|
it('forces User on preview back to latest stable', () => {
|
|
const catalog: UpdateCatalog = {
|
|
stable: [
|
|
{
|
|
version: '1.3.2',
|
|
channel: 'stable',
|
|
artifactKey: 'stable/1.3.2.exe',
|
|
sha256: 'a',
|
|
size: 1,
|
|
publishedAt: '2026-03-20T10:00:00Z',
|
|
changelogKey: 'stable/1.3.2.md'
|
|
}
|
|
],
|
|
preview: [
|
|
{
|
|
version: '1.4.0',
|
|
channel: 'preview',
|
|
artifactKey: 'preview/1.4.0.exe',
|
|
sha256: 'b',
|
|
size: 1,
|
|
publishedAt: '2026-03-20T11:00:00Z',
|
|
changelogKey: 'preview/1.4.0.md'
|
|
}
|
|
]
|
|
}
|
|
|
|
const decision = resolveUserDecision({
|
|
currentVersion: '1.4.0',
|
|
currentChannel: 'preview',
|
|
catalog
|
|
})
|
|
|
|
expect(decision.shouldOffer).toBe(true)
|
|
expect(decision.recommendedRelease?.channel).toBe('stable')
|
|
expect(decision.recommendedRelease?.version).toBe('1.3.2')
|
|
})
|
|
|
|
it('treats stable version mismatch as update for User', () => {
|
|
const catalog: UpdateCatalog = {
|
|
stable: [
|
|
{
|
|
version: '1.3.2',
|
|
channel: 'stable',
|
|
artifactKey: 'stable/1.3.2.exe',
|
|
sha256: 'a',
|
|
size: 1,
|
|
publishedAt: '2026-03-20T10:00:00Z',
|
|
changelogKey: 'stable/1.3.2.md'
|
|
}
|
|
],
|
|
preview: []
|
|
}
|
|
|
|
const decision = resolveUserDecision({
|
|
currentVersion: '1.3.1',
|
|
currentChannel: 'stable',
|
|
catalog
|
|
})
|
|
|
|
expect(decision.shouldOffer).toBe(true)
|
|
expect(decision.recommendedRelease?.version).toBe('1.3.2')
|
|
})
|
|
|
|
it('recommends the highest newer version for Admin', () => {
|
|
const catalog: UpdateCatalog = {
|
|
stable: [
|
|
{
|
|
version: '1.3.2',
|
|
channel: 'stable',
|
|
artifactKey: 'stable/1.3.2.exe',
|
|
sha256: 'a',
|
|
size: 1,
|
|
publishedAt: '2026-03-20T10:00:00Z',
|
|
changelogKey: 'stable/1.3.2.md'
|
|
}
|
|
],
|
|
preview: [
|
|
{
|
|
version: '1.4.0',
|
|
channel: 'preview',
|
|
artifactKey: 'preview/1.4.0.exe',
|
|
sha256: 'b',
|
|
size: 1,
|
|
publishedAt: '2026-03-20T09:00:00Z',
|
|
changelogKey: 'preview/1.4.0.md'
|
|
}
|
|
]
|
|
}
|
|
|
|
const decision = resolveAdminDecision({
|
|
currentVersion: '1.3.1',
|
|
currentChannel: 'stable',
|
|
catalog,
|
|
maxHistoryPerChannel: 10
|
|
})
|
|
|
|
expect(decision.mode).toBe('admin')
|
|
expect(decision.recommendedRelease?.channel).toBe('preview')
|
|
expect(decision.recommendedRelease?.version).toBe('1.4.0')
|
|
expect(decision.channels?.preview).toHaveLength(1)
|
|
})
|
|
|
|
it('still exposes a cross-channel choice for Admin when no newer version exists', () => {
|
|
const catalog: UpdateCatalog = {
|
|
stable: [
|
|
{
|
|
version: '1.4.0',
|
|
channel: 'stable',
|
|
artifactKey: 'stable/1.4.0.exe',
|
|
sha256: 'a',
|
|
size: 1,
|
|
publishedAt: '2026-03-20T10:00:00Z',
|
|
changelogKey: 'stable/1.4.0.md'
|
|
}
|
|
],
|
|
preview: [
|
|
{
|
|
version: '1.4.0',
|
|
channel: 'preview',
|
|
artifactKey: 'preview/1.4.0.exe',
|
|
sha256: 'b',
|
|
size: 1,
|
|
publishedAt: '2026-03-20T09:00:00Z',
|
|
changelogKey: 'preview/1.4.0.md'
|
|
}
|
|
]
|
|
}
|
|
|
|
const decision = resolveAdminDecision({
|
|
currentVersion: '1.4.0',
|
|
currentChannel: 'stable',
|
|
catalog,
|
|
maxHistoryPerChannel: 10
|
|
})
|
|
|
|
expect(decision.recommendedRelease?.channel).toBe('preview')
|
|
expect(decision.recommendedRelease?.version).toBe('1.4.0')
|
|
})
|
|
})
|