Files
frontend-miniapp/tests/unit/ExplainListNavigation.spec.ts
2026-07-14 10:58:41 +08:00

130 lines
4.2 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
// @vitest-environment happy-dom
import { defineComponent } from 'vue'
import { flushPromises, mount } from '@vue/test-utils'
import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest'
import ExplainListPage from '@/pages/explain/list.vue'
const hostEnvironmentMocks = vi.hoisted(() => ({
embeddedInWechatMiniProgram: false
}))
const testState = vi.hoisted(() => ({
onLoadHandler: null as null | (() => void)
}))
vi.mock('@dcloudio/uni-app', () => ({
onLoad: (handler: () => void) => {
testState.onLoadHandler = handler
}
}))
vi.mock('@/utils/hostEnvironment', () => ({
isEmbeddedInWechatMiniProgram: () => hostEnvironmentMocks.embeddedInWechatMiniProgram
}))
vi.mock('@/usecases/explainUseCase', () => ({
explainUseCase: {
loadExplainHalls: async () => [],
loadExplainHallSummaries: async () => ({})
}
}))
const GuidePageFrameStub = defineComponent({
name: 'GuidePageFrame',
template: '<main><slot /></main>'
})
const ExplainHallSelectStub = defineComponent({
name: 'ExplainHallSelect',
emits: ['back'],
template: '<button data-testid="explain-list-back" @click="$emit(\'back\')">返回</button>'
})
const mountExplainList = () => mount(ExplainListPage, {
global: {
stubs: {
GuidePageFrame: GuidePageFrameStub,
ExplainHallSelect: ExplainHallSelectStub
}
}
})
beforeEach(() => {
hostEnvironmentMocks.embeddedInWechatMiniProgram = false
testState.onLoadHandler = null
window.location.hash = '#/pages/explain/list'
window.history.replaceState({}, '', window.location.href)
vi.stubGlobal('uni', {
navigateBack: vi.fn(),
redirectTo: vi.fn(),
reLaunch: vi.fn()
})
})
afterEach(() => {
vi.restoreAllMocks()
vi.unstubAllGlobals()
})
describe('讲解展厅列表返回', () => {
it('微信内嵌时不调用 navigateBack并保留宿主标识返回首页讲解 Tab', async () => {
hostEnvironmentMocks.embeddedInWechatMiniProgram = true
window.location.hash = '#/pages/explain/list?embedded=wechat-mini-program&weapp=1&mini-program=1'
window.history.replaceState({}, '', window.location.href)
const wrapper = mountExplainList()
const pushState = vi.spyOn(window.history, 'pushState')
testState.onLoadHandler?.()
await flushPromises()
await wrapper.get('[data-testid="explain-list-back"]').trigger('click')
expect(pushState).toHaveBeenCalledWith(
expect.objectContaining({ museumGuidePage: 'explain-list' }),
'',
window.location.href
)
expect(uni.navigateBack).not.toHaveBeenCalled()
expect(uni.reLaunch).toHaveBeenCalledTimes(1)
const url = vi.mocked(uni.reLaunch).mock.calls[0]?.[0]?.url || ''
const query = new URLSearchParams(url.split('?')[1])
expect(url.split('?')[0]).toBe('/pages/index/index')
expect(query.get('tab')).toBe('explain')
expect(query.get('embedded')).toBe('wechat-mini-program')
expect(query.get('weapp')).toBe('1')
expect(query.get('mini-program')).toBe('1')
wrapper.unmount()
})
it('微信内嵌浏览器返回时回到首页讲解 Tab', async () => {
hostEnvironmentMocks.embeddedInWechatMiniProgram = true
window.location.hash = '#/pages/explain/list?embedded=wechat-mini-program&weapp=1'
window.history.replaceState({}, '', window.location.href)
const wrapper = mountExplainList()
testState.onLoadHandler?.()
await flushPromises()
window.dispatchEvent(new PopStateEvent('popstate', { state: {} }))
await flushPromises()
expect(uni.navigateBack).not.toHaveBeenCalled()
const url = vi.mocked(uni.reLaunch).mock.calls[0]?.[0]?.url || ''
const query = new URLSearchParams(url.split('?')[1])
expect(url.split('?')[0]).toBe('/pages/index/index')
expect(query.get('tab')).toBe('explain')
expect(query.get('embedded')).toBe('wechat-mini-program')
expect(query.get('weapp')).toBe('1')
wrapper.unmount()
})
it('普通 H5 保持原有 navigateBack 行为', async () => {
const wrapper = mountExplainList()
await wrapper.get('[data-testid="explain-list-back"]').trigger('click')
expect(uni.navigateBack).toHaveBeenCalledWith(expect.objectContaining({ delta: 1 }))
expect(uni.reLaunch).not.toHaveBeenCalled()
wrapper.unmount()
})
})