refactor(ECR-004): Synastry 再拆、Scale 测、Membership 守卫、OpenAPI 与 CI
压合盘贴线文件;补选答单测与 nil 守卫;对齐关键 OpenAPI schemas;加 GitHub Actions 门禁。 Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -0,0 +1,106 @@
|
||||
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: {
|
||||
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' } }),
|
||||
}))
|
||||
|
||||
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.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('探索结果')
|
||||
})
|
||||
})
|
||||
Reference in New Issue
Block a user