diff --git a/frontend/cypress/e2e/auto-update.cy.ts b/frontend/cypress/e2e/auto-update.cy.ts index 26b9930fa..ab923d033 100644 --- a/frontend/cypress/e2e/auto-update.cy.ts +++ b/frontend/cypress/e2e/auto-update.cy.ts @@ -374,6 +374,17 @@ describe('Auto Update Feature', () => { delay: 2000, }).as('downloadUpdate'); + cy.intercept('GET', '/api/download-update/progress*', { + statusCode: 200, + body: { + state: 'downloading', + bytes_written: 5242880, + total_bytes: 10485760, + percentage: 50, + indeterminate: false, + }, + }).as('downloadProgress'); + cy.visit('/'); cy.wait('@getFeeds'); @@ -389,6 +400,11 @@ describe('Auto Update Feature', () => { // Verify progress bar exists cy.get('[data-testid="update-download-progress"]').should('be.visible'); + cy.wait('@downloadProgress'); + cy.contains('50%').should('be.visible'); + cy.wait('@downloadUpdate') + .its('request.body.request_id') + .should('match', /^[A-Za-z0-9_-]+$/); }); it('should show installing message after download completes', () => { @@ -464,7 +480,7 @@ describe('Auto Update Feature', () => { // Mock download failure cy.intercept('POST', '/api/download-update', { statusCode: 500, - body: { error: 'Download failed' }, + body: { success: false, error_code: 'download_network_error' }, }).as('downloadUpdate'); cy.visit('/'); @@ -482,6 +498,8 @@ describe('Auto Update Feature', () => { // Verify error message is shown (via toast notification) cy.get('.toast-container').should('exist'); + cy.contains(/release page|发布页/i).should('be.visible'); + cy.contains(/network|网络/i).should('be.visible'); }); it('should handle update check failure gracefully', () => { diff --git a/frontend/src/App.vue b/frontend/src/App.vue index 6a7b7b419..dee21dad6 100644 --- a/frontend/src/App.vue +++ b/frontend/src/App.vue @@ -91,6 +91,10 @@ const { downloadingUpdate, installingUpdate, downloadProgress, + downloadProgressKnown, + downloadBytesWritten, + downloadTotalBytes, + downloadErrorCode, } = useAppUpdates(); // Update dialog state @@ -365,6 +369,10 @@ function onFeedUpdated(): void { :downloading-update="downloadingUpdate" :installing-update="installingUpdate" :download-progress="downloadProgress" + :download-progress-known="downloadProgressKnown" + :download-bytes-written="downloadBytesWritten" + :download-total-bytes="downloadTotalBytes" + :download-error-code="downloadErrorCode" @close="showUpdateDialog = false" @update="downloadAndInstallUpdate" /> diff --git a/frontend/src/components/modals/SettingsModal.vue b/frontend/src/components/modals/SettingsModal.vue index 354109ebc..ee019daeb 100644 --- a/frontend/src/components/modals/SettingsModal.vue +++ b/frontend/src/components/modals/SettingsModal.vue @@ -49,6 +49,10 @@ const { downloadingUpdate, installingUpdate, downloadProgress, + downloadProgressKnown, + downloadBytesWritten, + downloadTotalBytes, + downloadErrorCode, checkForUpdates: handleCheckUpdates, downloadAndInstallUpdate: handleDownloadInstallUpdate, } = useAppUpdates(); @@ -270,6 +274,10 @@ function handleDiscoverAll() { :downloading-update="downloadingUpdate" :installing-update="installingUpdate" :download-progress="downloadProgress" + :download-progress-known="downloadProgressKnown" + :download-bytes-written="downloadBytesWritten" + :download-total-bytes="downloadTotalBytes" + :download-error-code="downloadErrorCode" @check-updates="handleCheckUpdates" @download-install-update="handleDownloadInstallUpdate" /> diff --git a/frontend/src/components/modals/settings/about/AboutTab.vue b/frontend/src/components/modals/settings/about/AboutTab.vue index 6d6a46646..8522cd32c 100644 --- a/frontend/src/components/modals/settings/about/AboutTab.vue +++ b/frontend/src/components/modals/settings/about/AboutTab.vue @@ -28,6 +28,10 @@ interface Props { downloadingUpdate?: boolean; installingUpdate?: boolean; downloadProgress?: number; + downloadProgressKnown?: boolean; + downloadBytesWritten?: number; + downloadTotalBytes?: number; + downloadErrorCode?: string; } withDefaults(defineProps(), { @@ -36,6 +40,10 @@ withDefaults(defineProps(), { downloadingUpdate: false, installingUpdate: false, downloadProgress: 0, + downloadProgressKnown: false, + downloadBytesWritten: 0, + downloadTotalBytes: 0, + downloadErrorCode: '', }); const emit = defineEmits<{ @@ -80,6 +88,11 @@ function openGitHubRepo() { function openGitHubRelease() { openInBrowser('https://github.com/DevXDojo/MrRSS/releases/latest'); } + +function formatBytes(bytes: number): string { + if (bytes <= 0) return '0 MB'; + return `${(bytes / 1024 / 1024).toFixed(1)} MB`; +}