import { describe, it, expect, vi, beforeEach } from 'vitest' import { mount, flushPromises } from '@vue/test-utils' import ScalePage from './ScalePage.vue' const { api } = vi.hoisted(() => ({ api: { authMe: vi.fn(), getScale: vi.fn(), listProfiles: vi.fn(), submitScale: vi.fn(), }, })) vi.mock('../api/client', () => ({ api })) vi.mock('../lib/scaleDraft', () => ({ loadScaleDraft: () => null, saveScaleDraft: vi.fn(), clearScaleDraft: vi.fn(), })) vi.mock('vue-router', () => ({ useRoute: () => ({ params: { slug: 'mbti-lite' }, fullPath: '/scales/mbti-lite' }), useRouter: () => ({ replace: vi.fn() }), })) const scaleDetail = { slug: 'mbti-lite', title: 'MBTI 轻测', description: '探索向', questions: [ { id: 'q1', sort: 1, body: { prompt: '第一题?', options: [ { key: 'a', text: '选项A' }, { key: 'b', text: '选项B' }, ], }, }, { id: 'q2', sort: 2, body: { prompt: '第二题?', options: [ { key: 'a', text: '选项A' }, { key: 'b', text: '选项B' }, ], }, }, ], } describe('ScalePage', () => { beforeEach(() => { vi.clearAllMocks() api.authMe.mockResolvedValue({ id: 'u1' }) api.getScale.mockResolvedValue(scaleDetail) api.listProfiles.mockResolvedValue({ items: [{ id: 'p1', relation: 'self', display_name: '我', birth_date: '1990-01-01' }], }) api.submitScale.mockResolvedValue({ id: 'res1', result: { label: '探索结果', share_line: '分享一句', summary: '摘要' }, }) }) it('selects answers via emit then submits on last next', async () => { const w = mount(ScalePage, { global: { stubs: { RouterLink: true, ShareSheet: true, HomeToolIcon: true, BackButton: true } }, }) await flushPromises() expect(w.text()).toContain('MBTI 轻测') await w.find('button.intro-start').trigger('click') await flushPromises() expect(w.text()).toContain('第一题?') const radios = w.findAll('input[type="radio"]') expect(radios.length).toBeGreaterThan(0) await radios[0].setValue() await radios[0].trigger('change') await flushPromises() const next = w.findAll('button').find((b) => b.text().includes('下一题')) expect(next).toBeTruthy() await next!.trigger('click') await flushPromises() expect(w.text()).toContain('第二题?') const radios2 = w.findAll('input[type="radio"]') await radios2[0].setValue() await radios2[0].trigger('change') await flushPromises() const submitBtn = w.findAll('button').find((b) => b.text().includes('查看探索结果')) expect(submitBtn).toBeTruthy() await submitBtn!.trigger('click') await flushPromises() expect(api.submitScale).toHaveBeenCalledWith( 'mbti-lite', 'p1', expect.objectContaining({ q1: 'a', q2: 'a' }), ) expect(w.text()).toContain('探索结果') }) })