Files
everything-is-suitable/everything-is-suitable-uniapp/src/pages/push-subscription/__tests__/index.test.ts
T
zhangxiang f4c1bd957c feat(miniapp): 实现订阅管理页面与运势页订阅入口
- 新增订阅管理页面:订阅开关、推送时间设置、模板管理
- 运势主页添加订阅入口区域
- 更新页面路由配置
- 补充运势页相关测试
2026-08-13 08:06:19 +08:00

193 lines
5.7 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import { describe, it, expect, vi, beforeEach, afterEach } from 'vitest'
import { mount } from '@vue/test-utils'
import { createI18n } from 'vue-i18n'
import { triggerOnShow } from '../../../__mocks__/dcloudio/uni-app'
import SubscriptionPage from '../index.vue'
const i18n = createI18n({
legacy: false,
locale: 'zh-CN',
messages: {},
})
// Mock wx 全局对象
const mockWx = {
cloud: {
callFunction: vi.fn(),
},
}
function mountPage() {
return mount(SubscriptionPage, {
global: {
plugins: [i18n],
stubs: {
picker: { template: '<div><slot /></div>' },
},
},
})
}
describe('PushSubscriptionPage', () => {
beforeEach(() => {
vi.stubGlobal('wx', mockWx)
vi.clearAllMocks()
// 默认设置订阅状态
const store = (globalThis as any).__uniStorage__ ?? {}
store['eis_push_subscription'] = JSON.stringify({
pushTime: '07:00',
pushEnabled: true,
subscribedAt: '2026-08-13T00:00:00.000Z',
})
;(globalThis as any).__uniStorage__ = store
})
afterEach(() => {
vi.useRealTimers()
})
it('应显示订阅状态为"已开启"', async () => {
const wrapper = mountPage()
triggerOnShow()
await wrapper.vm.$nextTick()
expect(wrapper.find('.status-value').exists()).toBe(true)
expect(wrapper.find('.status-value').text()).toContain('已开启')
})
it('应显示当前推送时间', async () => {
const wrapper = mountPage()
triggerOnShow()
await wrapper.vm.$nextTick()
expect(wrapper.find('.time-value').exists()).toBe(true)
expect(wrapper.find('.time-value').text()).toBe('07:00')
})
it('点击"取消订阅"应弹出确认对话框', async () => {
const wrapper = mountPage()
triggerOnShow()
await wrapper.vm.$nextTick()
wrapper.find('.unsubscribe-btn').trigger('tap')
expect(uni.showModal).toHaveBeenCalled()
const callArgs = (uni.showModal as any).mock.calls[0][0]
expect(callArgs.title).toContain('确认取消')
expect(callArgs.content).toContain('取消后将不再收到每日运势推送')
})
it('确认取消订阅后应调用云函数并清除缓存', async () => {
// 模拟 wx.cloud.callFunction 返回成功
mockWx.cloud.callFunction.mockResolvedValue({
result: { success: true },
})
const wrapper = mountPage()
triggerOnShow()
await wrapper.vm.$nextTick()
// 触发取消订阅
wrapper.find('.unsubscribe-btn').trigger('tap')
// 模拟确认对话框
const modalCall = (uni.showModal as any).mock.calls[0][0]
modalCall.success({ confirm: true })
// 等待异步操作完成(包括 setTimeout 1500ms)
await new Promise((r) => setTimeout(r, 2000))
await wrapper.vm.$nextTick()
// 验证云函数被调用
expect(mockWx.cloud.callFunction).toHaveBeenCalledWith({ name: 'unsubscribe' })
// 验证本地缓存被清除
expect(uni.removeStorageSync).toHaveBeenCalledWith('eis_push_subscription')
// 验证提示
expect(uni.showToast).toHaveBeenCalledWith({ title: '已取消订阅', icon: 'success' })
// 验证返回上一页
expect(uni.navigateBack).toHaveBeenCalled()
})
it('取消订阅失败时应提示"取消失败"', async () => {
// 模拟云函数返回失败
mockWx.cloud.callFunction.mockResolvedValue({
result: { success: false, error: '未找到订阅记录' },
})
const wrapper = mountPage()
triggerOnShow()
await wrapper.vm.$nextTick()
wrapper.find('.unsubscribe-btn').trigger('tap')
const modalCall = (uni.showModal as any).mock.calls[0][0]
modalCall.success({ confirm: true })
await new Promise((r) => setTimeout(r, 50))
await wrapper.vm.$nextTick()
expect(uni.showToast).toHaveBeenCalledWith({ title: '取消失败,请重试', icon: 'none' })
})
it('保存推送时间应调用云函数并更新本地缓存', async () => {
mockWx.cloud.callFunction.mockResolvedValue({
result: { success: true },
})
const wrapper = mountPage()
triggerOnShow()
await wrapper.vm.$nextTick()
// 修改时间
await wrapper.vm.onTimeChange({ detail: { value: '08:00' } })
await wrapper.vm.$nextTick()
// 保存
wrapper.find('.save-btn').trigger('tap')
await new Promise((r) => setTimeout(r, 50))
await wrapper.vm.$nextTick()
// 验证云函数被调用
expect(mockWx.cloud.callFunction).toHaveBeenCalledWith({
name: 'updatePushTime',
data: { pushTime: '08:00' },
})
// 验证提示
expect(uni.showToast).toHaveBeenCalledWith({ title: '保存成功', icon: 'success' })
})
it('未订阅时,应使用默认时间 07:00', async () => {
// 清空存储
;(globalThis as any).__uniStorage__ = {}
const wrapper = mountPage()
triggerOnShow()
await wrapper.vm.$nextTick()
expect(wrapper.vm.selectedTime).toBe('07:00')
})
it('时间选择应四舍五入到 30 分钟步长', async () => {
const wrapper = mountPage()
triggerOnShow()
await wrapper.vm.$nextTick()
// 07:08 → 07:00
wrapper.vm.onTimeChange({ detail: { value: '07:08' } })
expect(wrapper.vm.selectedTime).toBe('07:00')
// 07:15 → 07:30
wrapper.vm.onTimeChange({ detail: { value: '07:15' } })
expect(wrapper.vm.selectedTime).toBe('07:30')
// 07:45 → 08:00
wrapper.vm.onTimeChange({ detail: { value: '07:45' } })
expect(wrapper.vm.selectedTime).toBe('08:00')
// 22:45 → 22:00(上限 22:00)
wrapper.vm.onTimeChange({ detail: { value: '22:45' } })
expect(wrapper.vm.selectedTime).toBe('22:00')
// 05:30 → 06:30(下限 06:00,分钟 30 保留)
wrapper.vm.onTimeChange({ detail: { value: '05:30' } })
expect(wrapper.vm.selectedTime).toBe('06:30')
})
})