feat: signed releases, release feed, notification (read-only)

This commit is contained in:
fsylvain committed 2026-10-01 15:01:53 +02:00
1 parent a49eec909c
commit 834493a4f5
49 files changed
+4191 -18

No files matched your search

+66
View File
@@ -0,0 +1,66 @@
import { vi } from 'vitest'
import type { UpdateStatus } from '@/composables/useUpdate'
export const RUNNING_VERSION = 'v2.2.0-beta'
export const NEW_TAG = 'v2.3.0-beta'
export const RELEASE_URL = 'https://git.example/fsylvain/RenewCMS/releases/tag/v2.3.0-beta'
export const RELEASED_AT = '2026-09-24T08:00:00Z'
export const NOTE_ITEMS = [
'Images upload faster, and large images no longer stall.',
'Fixed a problem where a draft could show an old title after saving.',
'Small improvements to the Users page.',
]
export const STATUS_PATH = '/v1/system/update'
export const CHECK_PATH = '/v1/system/update/check'
export function hoursAgo(hours: number) {
return new Date(Date.now() - hours * 60 * 60 * 1000).toISOString()
}
export function upToDate(overrides: Partial<UpdateStatus> = {}): UpdateStatus {
return {
current: RUNNING_VERSION,
latest: RUNNING_VERSION,
available: false,
release_url: RELEASE_URL,
notes: { version: RUNNING_VERSION, released_at: RELEASED_AT, items: [] },
checked_at: hoursAgo(1),
can_apply: false,
state: 'idle',
progress: null,
error: null,
started_at: null,
...overrides,
}
}
export function newerAvailable(overrides: Partial<UpdateStatus> = {}): UpdateStatus {
return upToDate({
latest: NEW_TAG,
available: true,
notes: { version: NEW_TAG, released_at: RELEASED_AT, items: NOTE_ITEMS },
...overrides,
})
}
export function stubClipboard() {
const writeText = vi.fn().mockResolvedValue(undefined)
Object.defineProperty(navigator, 'clipboard', {
configurable: true,
value: { writeText },
})
return writeText
}
export function visibleButtonLabels(root: ParentNode = document.body) {
return Array.from(root.querySelectorAll('button'))
.map((button) => button.textContent?.trim() ?? '')
.filter((label) => label !== '')
}
export function findButton(label: string, root: ParentNode = document.body) {
return Array.from(root.querySelectorAll('button')).find(
(button) => button.textContent?.trim() === label,
)
}