Files
frontend-miniapp/tests/unit/GuideAutoSwitchStateMachine.spec.ts
lyf 9f642ca6ed
Some checks failed
CI / verify (push) Has been cancelled
优化三维导览建筑内外自动切换
2026-07-13 18:54:55 +08:00

179 lines
5.4 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.
import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest'
import {
GuideAutoSwitchStateMachine,
type GuideAutoSwitchDirection,
type GuideAutoSwitchInputSource
} from '@/components/map/guideAutoSwitchStateMachine'
const createMachine = () => {
const requests: GuideAutoSwitchDirection[] = []
const machine = new GuideAutoSwitchStateMachine({
onSwitchRequested: ({ direction }) => requests.push(direction)
})
return { machine, requests }
}
beforeEach(() => {
vi.useFakeTimers()
vi.setSystemTime(0)
})
afterEach(() => {
vi.useRealTimers()
})
describe('建筑外观与馆内楼层自动切换状态机', () => {
it('连续放大 14.9% 不进入,达到 15% 后进入', () => {
const { machine, requests } = createMachine()
machine.beginInput(100, 'gesture')
machine.updateDistance(85.1, { source: 'gesture' })
vi.advanceTimersByTime(400)
expect(requests).toEqual([])
machine.updateDistance(85, { source: 'gesture' })
vi.advanceTimersByTime(120)
expect(requests).toEqual(['enter-floor'])
})
it('进入条件必须连续保持 120ms', () => {
const { machine, requests } = createMachine()
machine.beginInput(100, 'wheel')
machine.updateDistance(85, { source: 'wheel' })
vi.advanceTimersByTime(119)
expect(requests).toEqual([])
vi.advanceTimersByTime(1)
expect(requests).toEqual(['enter-floor'])
})
it('两次滚轮事件累计不足 15% 时不进入', () => {
const { machine, requests } = createMachine()
machine.beginInput(100, 'wheel')
machine.updateDistance(95, { source: 'wheel' })
machine.beginInput(95, 'wheel')
machine.updateDistance(90, { source: 'wheel' })
vi.advanceTimersByTime(400)
expect(requests).toEqual([])
})
it('相对楼层初始距离拉远 19.9% 不退出,达到 20% 后退出', () => {
const { machine, requests } = createMachine()
machine.setView('floor')
machine.setFloorInitialDistance(100)
machine.updateDistance(119.9)
vi.advanceTimersByTime(500)
expect(requests).toEqual([])
machine.updateDistance(120)
vi.advanceTimersByTime(400)
expect(requests).toEqual(['exit-overview'])
})
it('退出条件必须连续保持 400ms', () => {
const { machine, requests } = createMachine()
machine.setView('floor')
machine.setFloorInitialDistance(100)
machine.updateDistance(120)
vi.advanceTimersByTime(399)
expect(requests).toEqual([])
vi.advanceTimersByTime(1)
expect(requests).toEqual(['exit-overview'])
})
it('0.8% 内的触控反向抖动不重置进入基准,也不取消候选状态', () => {
const { machine, requests } = createMachine()
machine.beginInput(100, 'touch', { resetBaseline: true })
machine.updateDistance(85, { source: 'touch' })
vi.advanceTimersByTime(60)
machine.updateDistance(85.6, { source: 'touch' })
vi.advanceTimersByTime(60)
expect(requests).toEqual(['enter-floor'])
})
it('明确反向缩放超过 0.8% 后取消候选并重置进入基准', () => {
const { machine, requests } = createMachine()
machine.beginInput(100, 'touch', { resetBaseline: true })
machine.updateDistance(85, { source: 'touch' })
vi.advanceTimersByTime(60)
machine.updateDistance(86, { source: 'touch' })
vi.advanceTimersByTime(120)
expect(requests).toEqual([])
machine.updateDistance(73, { source: 'touch' })
vi.advanceTimersByTime(120)
expect(requests).toEqual(['enter-floor'])
})
it('退出候选明确反向超过 0.8% 后会取消防抖任务', () => {
const { machine, requests } = createMachine()
machine.setView('floor')
machine.setFloorInitialDistance(100)
machine.updateDistance(120)
vi.advanceTimersByTime(200)
machine.updateDistance(118.9)
vi.advanceTimersByTime(400)
expect(requests).toEqual([])
})
it('进入意图超时后使用新的连续缩放距离重新计算基准', () => {
const { machine, requests } = createMachine()
machine.beginInput(100, 'wheel')
machine.updateDistance(90, { source: 'wheel' })
vi.advanceTimersByTime(2001)
machine.updateDistance(80, { previousDistance: 90, source: 'wheel' })
vi.advanceTimersByTime(120)
expect(requests).toEqual([])
machine.updateDistance(76.5, { source: 'wheel' })
vi.advanceTimersByTime(120)
expect(requests).toEqual(['enter-floor'])
})
it('切换成功后 1499ms 内不能反向切换1500ms 后可以', () => {
const { machine, requests } = createMachine()
machine.beginInput(100, 'wheel')
machine.updateDistance(85, { source: 'wheel' })
vi.advanceTimersByTime(120)
expect(requests).toEqual(['enter-floor'])
machine.markTransitionSucceeded()
machine.setView('floor')
machine.setFloorInitialDistance(100)
machine.updateDistance(120)
vi.advanceTimersByTime(1499)
expect(requests).toEqual(['enter-floor'])
vi.advanceTimersByTime(1)
expect(requests).toEqual(['enter-floor', 'exit-overview'])
})
it.each<GuideAutoSwitchInputSource>(['wheel', 'button', 'touch'])(
'%s 路径使用同一套 15% 进入判断',
(source) => {
const { machine, requests } = createMachine()
machine.beginInput(100, source, { resetBaseline: source === 'touch' })
machine.updateDistance(85.1, { source })
vi.advanceTimersByTime(400)
expect(requests).toEqual([])
machine.updateDistance(85, { source })
vi.advanceTimersByTime(120)
expect(requests).toEqual(['enter-floor'])
}
)
})