落地管理员 RBAC/封禁/推送任务 stub,logout 解绑 device 并统一各页 ensureAccount,同时收口 P2 生日生成与状态文档。 Co-authored-by: Cursor <cursoragent@cursor.com>
110 lines
3.0 KiB
TypeScript
110 lines
3.0 KiB
TypeScript
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('探索结果')
|
|
})
|
|
})
|