Files
frontend-miniapp/tests/unit/WechatMiniProgramBridgeService.spec.ts
lyf d199b4602f
Some checks failed
CI / verify (push) Has been cancelled
完善馆内点位展示与微信地图桥接
2026-07-19 16:01:32 +08:00

88 lines
4.6 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 { afterEach, beforeEach, describe, expect, it, vi } from 'vitest'
const target = { latitude: 22.604321, longitude: 114.058765, name: '停车场 A&B', address: '龙华区 #1' }
const setEmbeddedRuntime = () => Object.assign(window, { __wxjs_environment: 'miniprogram' })
const loadService = async () => {
vi.resetModules()
return import('@/services/WechatMiniProgramBridgeService')
}
beforeEach(() => {
vi.useFakeTimers()
vi.stubGlobal('uni', { showToast: vi.fn() })
delete (window as Window & { wx?: unknown }).wx
delete (window as Window & { __wxjs_environment?: string }).__wxjs_environment
window.history.replaceState({}, '', '/')
})
afterEach(() => {
vi.useRealTimers()
vi.unstubAllGlobals()
document.querySelectorAll('script[data-wechat-js-sdk="true"]').forEach((node) => node.remove())
})
describe('微信小程序 web-view 桥接', () => {
it('普通浏览器立即返回 not-embedded不加载 SDK', async () => {
const { openWechatMiniProgramLocation } = await loadService()
await expect(openWechatMiniProgramLocation(target)).resolves.toEqual({ status: 'not-embedded' })
expect(document.querySelector('[data-wechat-js-sdk="true"]')).toBeNull()
})
it('等待延迟注入的 bridge 后导航到编码后的宿主页', async () => {
setEmbeddedRuntime()
const { openWechatMiniProgramLocation } = await loadService()
const result = openWechatMiniProgramLocation(target)
await vi.advanceTimersByTimeAsync(100)
const navigateTo = vi.fn(({ success }) => success())
Object.assign(window, { wx: { miniProgram: { getEnv: (done: (value: { miniprogram: boolean }) => void) => done({ miniprogram: true }), navigateTo } } })
await vi.advanceTimersByTimeAsync(100)
await expect(result).resolves.toEqual({ status: 'opened' })
expect(navigateTo).toHaveBeenCalledWith(expect.objectContaining({
url: expect.stringContaining('/pages/open-location/index?latitude=22.604321&longitude=114.058765&name=%E5%81%9C%E8%BD%A6%E5%9C%BA%20A%26B')
}))
})
it('handles getEnv false, navigate fail, page not found, and callback timeout', async () => {
setEmbeddedRuntime()
const { openWechatMiniProgramLocation } = await loadService()
Object.assign(window, { wx: { miniProgram: { getEnv: (done: (value: { miniprogram: boolean }) => void) => done({ miniprogram: false }), navigateTo: vi.fn() } } })
await expect(openWechatMiniProgramLocation(target)).resolves.toEqual({ status: 'failed', reason: 'not-in-mini-program' })
Object.assign(window, { wx: { miniProgram: { getEnv: (done: (value: { miniprogram: boolean }) => void) => done({ miniprogram: true }) } } })
await expect(openWechatMiniProgramLocation(target)).resolves.toEqual({ status: 'failed', reason: 'bridge-unavailable' })
Object.assign(window, { wx: { miniProgram: { getEnv: (done: (value: { miniprogram: boolean }) => void) => done({ miniprogram: true }), navigateTo: vi.fn(({ fail }) => fail({ errMsg: 'navigateTo:fail permission denied' })) } } })
await expect(openWechatMiniProgramLocation(target)).resolves.toEqual({ status: 'failed', reason: 'navigation-failed' })
const navigateTo = vi.fn(({ fail }) => fail({ errMsg: 'navigateTo:fail page not found' }))
Object.assign(window, { wx: { miniProgram: { getEnv: (done: (value: { miniprogram: boolean }) => void) => done({ miniprogram: true }), navigateTo } } })
await expect(openWechatMiniProgramLocation(target)).resolves.toEqual({ status: 'failed', reason: 'page-not-found' })
Object.assign(window, { wx: { miniProgram: { getEnv: (done: (value: { miniprogram: boolean }) => void) => done({ miniprogram: true }), navigateTo: vi.fn() } } })
const timeoutResult = openWechatMiniProgramLocation(target)
await vi.advanceTimersByTimeAsync(3001)
await expect(timeoutResult).resolves.toEqual({ status: 'failed', reason: 'timeout' })
})
it('deduplicates rapid calls while navigation is in flight', async () => {
setEmbeddedRuntime()
const { openWechatMiniProgramLocation } = await loadService()
let succeed: (() => void) | undefined
const navigateTo = vi.fn(({ success }) => { succeed = success })
Object.assign(window, { wx: { miniProgram: { getEnv: (done: (value: { miniprogram: boolean }) => void) => done({ miniprogram: true }), navigateTo } } })
const first = openWechatMiniProgramLocation(target)
expect(openWechatMiniProgramLocation(target)).toBe(first)
await Promise.resolve()
await Promise.resolve()
await Promise.resolve()
expect(navigateTo).toHaveBeenCalledTimes(1)
succeed?.()
await expect(first).resolves.toEqual({ status: 'opened' })
expect(navigateTo).toHaveBeenCalledTimes(1)
})
})