feat: update button (download, verify, stage)

This commit is contained in:
fsylvain committed 2026-10-01 18:13:45 +02:00
1 parent 834493a4f5
commit 70460e4170
41 files changed
+5345 -97

No files matched your search

+60 -9
View File
@@ -208,6 +208,44 @@ function updateAvailable() {
})
}
const updateBoardNotes = {
version: updateLatestTag,
released_at: updateReleasedAt,
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.',
],
}
const updateBoardTotalBytes = 27262976
const updateBoardDoneBytes = 11534336
const updateJobStartedAt = '2026-09-30T09:51:00Z'
function updateStartable(overrides: Record<string, unknown> = {}) {
return updateStatusBody({
latest: updateLatestTag,
available: true,
notes: updateBoardNotes,
can_apply: true,
...overrides,
})
}
function updateJob(state: string, overrides: Record<string, unknown> = {}) {
return updateStartable({ state, started_at: updateJobStartedAt, ...overrides })
}
function updateDownloading() {
return updateJob('downloading', {
progress: {
percent: 42,
downloaded_bytes: updateBoardDoneBytes,
total_bytes: updateBoardTotalBytes,
},
})
}
const updateCheckHangs: ApiMock = { status: 200, hang: true }
function updateApi(
@@ -2046,19 +2084,25 @@ export const visualStates: Record<string, Record<string, VisualState>> = {
api: updateApi('owner', updateNeverChecked(), updateCheckHangs),
},
'Check failed': { path: '/settings', skip: 'clock-sensitive' },
'Update available': { path: '/settings', skip: 'pending' },
'Update available, notes open': { path: '/settings', skip: 'pending' },
Downloading: { path: '/settings', skip: 'pending' },
Verifying: { path: '/settings', skip: 'pending' },
'Ready to install': { path: '/settings', skip: 'pending' },
'Update available': { path: '/settings', skip: 'clock-sensitive' },
'Update available, notes open': { path: '/settings', skip: 'clock-sensitive' },
Downloading: { path: '/settings', api: updateApi('owner', updateDownloading()) },
Verifying: { path: '/settings', api: updateApi('owner', updateJob('verifying')) },
'Ready to install': { path: '/settings', api: updateApi('owner', updateJob('ready')) },
'Restart: confirm': { path: '/settings', skip: 'pending' },
'Restart: request failed': { path: '/settings', skip: 'pending' },
'Restarting to install': { path: '/settings', skip: 'pending' },
'Restarting, taking longer': { path: '/settings', skip: 'pending' },
'Update done': { path: '/settings', skip: 'pending' },
'Update failed, rolled back': { path: '/settings', skip: 'pending' },
'Download failed': { path: '/settings', skip: 'pending' },
'Verification failed': { path: '/settings', skip: 'pending' },
'Download failed': {
path: '/settings',
api: updateApi('owner', updateJob('failed', { error: 'download' })),
},
'Verification failed': {
path: '/settings',
api: updateApi('owner', updateJob('failed', { error: 'verification' })),
},
'Too many requests (429)': {
path: '/settings',
api: updateApi('owner', updateNeverChecked(), {
@@ -2104,7 +2148,7 @@ export const visualStates: Record<string, Record<string, VisualState>> = {
},
},
},
'Update already running (409)': { path: '/settings', skip: 'pending' },
'Update already running (409)': { path: '/settings', skip: 'clock-sensitive' },
},
integration: {
Default: {
@@ -2378,7 +2422,14 @@ export const visualStates: Record<string, Record<string, VisualState>> = {
'GET /v1/system/update': { status: 200, body: updateAvailable() },
},
},
'Update ready to install (owner)': { path: '/home', skip: 'pending' },
'Update ready to install (owner)': {
path: '/home',
api: {
'GET /v1/auth/me': verifiedSession,
'GET /v1/article/': { status: 200, body: sixArticlesFixture },
'GET /v1/system/update': { status: 200, body: updateJob('ready') },
},
},
},
'log-in': {
Default: { path: '/login', api: { 'GET /v1/auth/registration': registrationClosed } },