import { describe, it, expect, vi, beforeEach } from 'vitest' import { mount, flushPromises } from '@vue/test-utils' import MembershipPage from './MembershipPage.vue' const { api } = vi.hoisted(() => ({ api: { getMembership: vi.fn(), createOrder: vi.fn(), payMock: vi.fn(), }, })) vi.mock('../api/client', () => ({ api })) vi.mock('vue-router', () => ({ useRoute: () => ({ query: {} }), useRouter: () => ({ back: vi.fn() }), })) describe('MembershipPage', () => { beforeEach(() => { vi.clearAllMocks() }) it('shows subscribe CTA when inactive', async () => { api.getMembership.mockResolvedValue({ active: false, status: 'none' }) const w = mount(MembershipPage) await flushPromises() expect(w.text()).toContain('尚未开通') expect(w.text()).toContain('开通月卡') }) it('activates membership after mock pay', async () => { api.getMembership .mockResolvedValueOnce({ active: false, status: 'none' }) .mockResolvedValueOnce({ active: true, status: 'active', plan: 'month', expires_at: '2099-01-01T00:00:00Z', ask_quota_left: 100, }) api.createOrder.mockResolvedValue({ order_id: 'om1' }) api.payMock.mockResolvedValue({ paid: true }) const w = mount(MembershipPage) await flushPromises() await w.findAll('button').find((b) => b.text().includes('开通月卡'))!.trigger('click') await flushPromises() expect(api.createOrder).toHaveBeenCalledWith({ kind: 'membership', plan: 'month' }) expect(w.text()).toContain('会员有效') expect(w.text()).toContain('月卡') }) it('shows error with retry', async () => { api.getMembership.mockRejectedValueOnce(new Error('网络错误')) const w = mount(MembershipPage) await flushPromises() expect(w.text()).toContain('网络错误') api.getMembership.mockResolvedValue({ active: false, status: 'none' }) await w.find('button.link').trigger('click') await flushPromises() expect(w.text()).toContain('尚未开通') }) })