Files
frontend-miniapp/tests/unit/GuideAutoSwitchStateMachine.spec.ts
lyf 9c003c16dc
Some checks failed
CI / verify (push) Has been cancelled
优化建筑内外自动切换状态机
2026-07-13 16:16:24 +08:00

148 lines
4.5 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% 并保持 500ms 后进入', () => {
const { machine, requests } = createMachine()
machine.beginInput(100, 'gesture')
machine.updateDistance(85.1, { source: 'gesture' })
vi.advanceTimersByTime(500)
expect(requests).toEqual([])
machine.updateDistance(85, { source: 'gesture' })
vi.advanceTimersByTime(499)
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(500)
expect(requests).toEqual([])
})
it('相对楼层初始距离拉远 19.9% 不退出,达到 20% 并保持 500ms 后退出', () => {
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(499)
expect(requests).toEqual([])
vi.advanceTimersByTime(1)
expect(requests).toEqual(['exit-overview'])
})
it('条件满足后反向缩放会取消防抖任务并重置进入基准', () => {
const { machine, requests } = createMachine()
machine.beginInput(100, 'touch', { resetBaseline: true })
machine.updateDistance(85, { source: 'touch' })
vi.advanceTimersByTime(300)
machine.updateDistance(88, { source: 'touch' })
vi.advanceTimersByTime(500)
expect(requests).toEqual([])
machine.updateDistance(74.8, { source: 'touch' })
vi.advanceTimersByTime(500)
expect(requests).toEqual(['enter-floor'])
})
it('退出条件满足后回到 20% 阈值内会取消防抖任务', () => {
const { machine, requests } = createMachine()
machine.setView('floor')
machine.setFloorInitialDistance(100)
machine.updateDistance(120)
vi.advanceTimersByTime(300)
machine.updateDistance(119.9)
vi.advanceTimersByTime(500)
expect(requests).toEqual([])
})
it('进入意图超时后使用新的连续缩放距离重新计算基准', () => {
const { machine, requests } = createMachine()
machine.beginInput(100, 'wheel')
machine.updateDistance(90, { source: 'wheel' })
vi.advanceTimersByTime(1201)
machine.updateDistance(80, { previousDistance: 90, source: 'wheel' })
vi.advanceTimersByTime(500)
expect(requests).toEqual([])
machine.updateDistance(76.5, { source: 'wheel' })
vi.advanceTimersByTime(500)
expect(requests).toEqual(['enter-floor'])
})
it('切换成功后 1499ms 内不能反向切换1500ms 后可以', () => {
const { machine, requests } = createMachine()
machine.beginInput(100, 'wheel')
machine.updateDistance(85, { source: 'wheel' })
vi.advanceTimersByTime(500)
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(500)
expect(requests).toEqual([])
machine.updateDistance(85, { source })
vi.advanceTimersByTime(500)
expect(requests).toEqual(['enter-floor'])
}
)
})