mirror of
https://github.com/Wei-Shaw/sub2api.git
synced 2026-10-14 03:52:26 +08:00
fix(announcements): report failed read confirmations accurately
This commit is contained in:
@@ -373,14 +373,17 @@ function closeDetail() {
|
||||
|
||||
async function markAsRead(id: number) {
|
||||
try {
|
||||
await announcementStore.markAsRead(id)
|
||||
const marked = await announcementStore.markAsRead(id)
|
||||
if (!marked) appStore.showError(t('common.unknownError'))
|
||||
return marked
|
||||
} catch (err: any) {
|
||||
appStore.showError(err?.message || t('common.unknownError'))
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
async function markAsReadAndClose(id: number) {
|
||||
await markAsRead(id)
|
||||
if (!await markAsRead(id)) return
|
||||
appStore.showSuccess(t('announcements.markedAsRead'))
|
||||
closeDetail()
|
||||
}
|
||||
|
||||
@@ -0,0 +1,42 @@
|
||||
import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest'
|
||||
import { enableAutoUnmount, flushPromises, mount } from '@vue/test-utils'
|
||||
import { createPinia, setActivePinia } from 'pinia'
|
||||
import AnnouncementBell from '../AnnouncementBell.vue'
|
||||
import { useAnnouncementStore } from '@/stores/announcements'
|
||||
|
||||
const { markRead, showError, showSuccess } = vi.hoisted(() => ({ markRead: vi.fn(), showError: vi.fn(), showSuccess: vi.fn() }))
|
||||
vi.mock('@/api', () => ({ announcementsAPI: { markRead } }))
|
||||
vi.mock('@/stores/app', () => ({ useAppStore: () => ({ showError, showSuccess }) }))
|
||||
vi.mock('vue-i18n', () => ({ useI18n: () => ({ t: (key: string) => key }) }))
|
||||
vi.mock('@/utils/format', () => ({ formatRelativeTime: () => 'now', formatRelativeWithDateTime: () => 'now' }))
|
||||
enableAutoUnmount(afterEach)
|
||||
beforeEach(() => {
|
||||
setActivePinia(createPinia())
|
||||
vi.clearAllMocks()
|
||||
vi.spyOn(console, 'error').mockImplementation(() => {})
|
||||
useAnnouncementStore().announcements = [{ id: 1, title: 'Notice', content: 'Details', notify_mode: 'silent', created_at: '2026-09-30', updated_at: '2026-09-30' }]
|
||||
})
|
||||
afterEach(() => { vi.restoreAllMocks(); document.body.style.overflow = '' })
|
||||
|
||||
describe('announcement read confirmation', () => {
|
||||
it('keeps a failed read confirmation open and only reports success after retry', async () => {
|
||||
markRead.mockRejectedValue(new Error('offline'))
|
||||
const wrapper = mount(AnnouncementBell, { global: { stubs: { Teleport: true, Transition: true, Icon: true } } })
|
||||
await wrapper.get('button').trigger('click')
|
||||
await wrapper.get('.group.relative').trigger('click')
|
||||
await flushPromises()
|
||||
const confirm = () => wrapper.findAll('button').find(button => button.text() === 'announcements.markRead')!
|
||||
await confirm().trigger('click')
|
||||
await flushPromises()
|
||||
expect(markRead).toHaveBeenCalledTimes(2)
|
||||
expect(showSuccess).not.toHaveBeenCalled()
|
||||
expect(showError).toHaveBeenCalled()
|
||||
expect(wrapper.find('.markdown-body').exists()).toBe(true)
|
||||
markRead.mockResolvedValue(undefined)
|
||||
await confirm().trigger('click')
|
||||
await flushPromises()
|
||||
expect(showSuccess).toHaveBeenCalledWith('announcements.markedAsRead')
|
||||
expect(wrapper.find('.markdown-body').exists()).toBe(false)
|
||||
expect(useAnnouncementStore().unreadCount).toBe(0)
|
||||
})
|
||||
})
|
||||
@@ -96,8 +96,10 @@ export const useAnnouncementStore = defineStore('announcements', () => {
|
||||
if (ann) {
|
||||
ann.read_at = new Date().toISOString()
|
||||
}
|
||||
return true
|
||||
} catch (err: any) {
|
||||
console.error('Failed to mark announcement as read:', err)
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user