139 lines
4.4 KiB
TypeScript
139 lines
4.4 KiB
TypeScript
/**
|
|
* 07-notify — 通知系统
|
|
*
|
|
* 使用 vitest 原汁原味的 vi.fn() + mock 依赖注入模式。
|
|
* 不依赖真实 DOM 渲染,仅测试 Notify 核心逻辑。
|
|
*/
|
|
import { describe, it, expect, beforeEach, beforeAll, vi } from 'vitest'
|
|
import { Notify, setSysForNotify } from '../../src/composables/useNotify'
|
|
|
|
// ---- Mock Sys 依赖 ----
|
|
function createMockSys(overrides: Record<string, any> = {}) {
|
|
return {
|
|
settings: {
|
|
notificationsEnabled: true,
|
|
notifAllow: {} as Record<string, boolean>,
|
|
focus: false,
|
|
...overrides,
|
|
},
|
|
renderDock: vi.fn(),
|
|
}
|
|
}
|
|
|
|
let mockSys = createMockSys()
|
|
setSysForNotify(mockSys)
|
|
|
|
describe('07-notify — 通知系统', () => {
|
|
beforeAll(() => {
|
|
document.body.innerHTML = `
|
|
<div id="notification-center" class="hidden"></div>
|
|
<div id="banner-container"></div>
|
|
<nav id="dock"></nav>
|
|
`
|
|
})
|
|
|
|
beforeEach(() => {
|
|
Notify.list = []
|
|
mockSys = createMockSys()
|
|
setSysForNotify(mockSys)
|
|
})
|
|
|
|
// ==================== 基本发送 ====================
|
|
describe('发送通知', () => {
|
|
it('初始列表为空', () => {
|
|
expect(Notify.list).toHaveLength(0)
|
|
})
|
|
|
|
it('send 添加通知到列表', () => {
|
|
const n = Notify.send({ appId: 'finder', title: '测试', body: '内容', silent: true })
|
|
expect(n).not.toBeNull()
|
|
expect(Notify.list).toHaveLength(1)
|
|
expect(n!.appId).toBe('finder')
|
|
expect(n!.title).toBe('测试')
|
|
})
|
|
|
|
it('返回的通知包含 id 和 ts', () => {
|
|
const n = Notify.send({ appId: 'f', title: 'T', body: 'B', silent: true })
|
|
expect(n!.id).toBeTruthy()
|
|
expect(n!.ts).toBeGreaterThan(0)
|
|
})
|
|
})
|
|
|
|
// ==================== 开关控制 ====================
|
|
describe('开关控制', () => {
|
|
it('总开关关闭时 send 返回 null', () => {
|
|
mockSys.settings.notificationsEnabled = false
|
|
expect(Notify.send({ appId: 'f', title: 'T', body: 'B', silent: true })).toBeNull()
|
|
})
|
|
|
|
it('per-app 关闭时 send 返回 null', () => {
|
|
mockSys.settings.notifAllow['finder'] = false
|
|
expect(Notify.send({ appId: 'finder', title: 'T', body: 'B', silent: true })).toBeNull()
|
|
})
|
|
|
|
it('allowed() 正确判断', () => {
|
|
expect(Notify.allowed('clock')).toBe(true)
|
|
|
|
mockSys.settings.notifAllow['clock'] = false
|
|
expect(Notify.allowed('clock')).toBe(false)
|
|
|
|
mockSys.settings.notifAllow['clock'] = true
|
|
mockSys.settings.notificationsEnabled = false
|
|
expect(Notify.allowed('clock')).toBe(false)
|
|
})
|
|
})
|
|
|
|
// ==================== 已读/未读 ====================
|
|
describe('已读/未读', () => {
|
|
it('新通知默认未读', () => {
|
|
const n = Notify.send({ appId: 'f', title: 'T', body: 'B', silent: true })
|
|
expect(n!.read).toBe(false)
|
|
})
|
|
|
|
it('markRead 标记已读', () => {
|
|
const n = Notify.send({ appId: 'f', title: 'T', body: 'B', silent: true })
|
|
Notify.markRead(n!.id)
|
|
expect(n!.read).toBe(true)
|
|
})
|
|
|
|
it('badgeCount 统计未读数', () => {
|
|
Notify.send({ appId: 'clock', title: 'A', body: '1', silent: true })
|
|
Notify.send({ appId: 'clock', title: 'B', body: '2', silent: true })
|
|
expect(Notify.badgeCount('clock')).toBe(2)
|
|
})
|
|
|
|
it('markRead 减少未读计数', () => {
|
|
const n = Notify.send({ appId: 'clock', title: 'T', body: 'B', silent: true })
|
|
expect(Notify.badgeCount('clock')).toBe(1)
|
|
Notify.markRead(n!.id)
|
|
expect(Notify.badgeCount('clock')).toBe(0)
|
|
})
|
|
})
|
|
|
|
// ==================== 专注模式 ====================
|
|
describe('专注模式', () => {
|
|
it('突破型通知在专注模式下仍发送', () => {
|
|
mockSys.settings.focus = true
|
|
const n = Notify.send({ appId: 'clock', title: '计时器', body: '时间到!', breakthrough: true, silent: true })
|
|
expect(n).not.toBeNull()
|
|
})
|
|
|
|
it('非突破型通知在专注模式下仍记录但不弹横幅', () => {
|
|
mockSys.settings.focus = true
|
|
const n = Notify.send({ appId: 'clock', title: '普通', body: '', silent: true })
|
|
expect(n).not.toBeNull()
|
|
expect(Notify.list).toHaveLength(1)
|
|
})
|
|
})
|
|
|
|
// ==================== 清理 ====================
|
|
describe('清理', () => {
|
|
it('clearAll 清空所有通知', () => {
|
|
Notify.send({ appId: 'f', title: 'T', body: 'B', silent: true })
|
|
expect(Notify.list).toHaveLength(1)
|
|
Notify.clearAll()
|
|
expect(Notify.list).toHaveLength(0)
|
|
})
|
|
})
|
|
})
|