147
tests/unit/GuideAutoSwitchStateMachine.spec.ts
Normal file
147
tests/unit/GuideAutoSwitchStateMachine.spec.ts
Normal 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'])
|
||||
}
|
||||
)
|
||||
})
|
||||
Reference in New Issue
Block a user