优化建筑内外自动切换状态机
Some checks failed
CI / verify (push) Has been cancelled

This commit is contained in:
lyf
2026-07-13 16:16:24 +08:00
parent e473b6a2a5
commit 9c003c16dc
5 changed files with 502 additions and 363 deletions

View File

@@ -0,0 +1,147 @@
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'])
}
)
})