Files
frontend-miniapp/tests/unit/ExplainUseCase.spec.ts
lyf 2edb6bd9f2
Some checks failed
CI / verify (push) Has been cancelled
适配H5讲解统一详情接口
2026-08-05 14:52:36 +08:00

90 lines
4.1 KiB
TypeScript

import { describe, expect, it, vi } from 'vitest'
import type { GuideStopDetail } from '@/data/adapters/guideStopInfoAdapter'
import type { AudioPlayInfoRepository } from '@/repositories/AudioPlayInfoRepository'
import type { ExplainRepository } from '@/repositories/ExplainRepository'
import { ExplainUseCase } from '@/usecases/explainUseCase'
import { dataSourceConfig } from '@/config/dataSource'
const createDetail = (overrides: Partial<GuideStopDetail> = {}): GuideStopDetail => ({
id: 'stop-1',
version: 'standard',
name: 'Guide stop',
galleryUrls: [],
imageStatus: 'MISSING',
linkedExhibits: [{ id: 'exhibit-1', name: 'Linked exhibit', coverImageUrl: '/linked-exhibit.jpg' }],
isSharedStop: false,
textVariants: [
{ version: 'standard', languageCode: 'zh-CN', text: '普通话正文' },
{ version: 'standard', languageCode: 'en-US', text: 'English text' }
],
audioTracks: [
{ channelCode: 'standard.zh-CN.female', version: 'standard', languageCode: 'zh-CN', gender: 'female', playUrl: '/zh-female.mp3' },
{ channelCode: 'standard.yue-HK.female', version: 'standard', languageCode: 'yue-HK', gender: 'female', playUrl: '/yue-female.mp3' }
],
hasText: true,
hasAudio: true,
textVariantCount: 2,
audioTrackCount: 2,
...overrides
})
const createUseCase = (detail: GuideStopDetail) => {
const explain = {
getExhibitById: vi.fn().mockResolvedValue(null),
listExplainExhibits: vi.fn().mockResolvedValue([])
} as unknown as ExplainRepository
const audio = { getStopDetail: vi.fn().mockResolvedValue(detail) } as unknown as AudioPlayInfoRepository
return { useCase: new ExplainUseCase(explain, audio), explain, audio }
}
describe('ExplainUseCase unified stop detail', () => {
it('uses stopId once in remote mode without requesting a catalog fallback', async () => {
const originalMode = dataSourceConfig.explainContentMode
Object.assign(dataSourceConfig, { explainContentMode: 'remote' })
const { useCase, explain, audio } = createUseCase(createDetail())
const result = await useCase.enterExplainDetail({ exhibitId: 'stop-1', stopId: 'stop-1', hallName: '宇宙厅' })
expect(audio.getStopDetail).toHaveBeenCalledWith('stop-1', { version: 'standard' })
expect(explain.getExhibitById).not.toHaveBeenCalled()
expect(result.hallName).toBe('宇宙厅')
Object.assign(dataSourceConfig, { explainContentMode: originalMode })
})
it('does not use linked exhibit images when detail reports MISSING', async () => {
const { useCase } = createUseCase(createDetail())
const result = await useCase.enterExplainDetail({ exhibitId: 'stop-1', stopId: 'stop-1' })
expect(result.image).toBeUndefined()
expect(result.galleryUrls).toEqual([])
expect(result.linkedExhibits?.[0]?.coverImageUrl).toBe('/linked-exhibit.jpg')
})
it('uses local standard text and audio variants, with Chinese text fallback for Cantonese', async () => {
const { useCase, audio } = createUseCase(createDetail())
const result = await useCase.enterExplainDetail({ exhibitId: 'stop-1', stopId: 'stop-1', lang: 'yue-HK' })
const text = await useCase.loadExplainDetailText(result)
const selection = await useCase.selectAudioForExplainDetail(result, { voiceGender: 'male' })
expect(result.guideText).toBe('普通话正文')
expect(text.textInfo.text).toBe('普通话正文')
expect(selection.media?.url).toBe('/yue-female.mp3')
expect(audio.getStopDetail).toHaveBeenCalledTimes(1)
})
it('uses the recommended track for the current detail version by default', async () => {
const { useCase } = createUseCase(createDetail({
recommendedTrackCode: 'standard.zh-CN.female',
audioTracks: [
{ channelCode: 'standard.zh-CN.female', version: 'standard', languageCode: 'zh-CN', gender: 'female', playUrl: '/zh-female.mp3' },
{ channelCode: 'standard.zh-CN.male', version: 'standard', languageCode: 'zh-CN', gender: 'male', playUrl: '/zh-male.mp3' }
]
}))
const result = await useCase.enterExplainDetail({ exhibitId: 'stop-1', stopId: 'stop-1' })
const selection = await useCase.selectAudioForExplainDetail(result)
expect(selection.media?.url).toBe('/zh-female.mp3')
})
})