148 lines
4.5 KiB
TypeScript
148 lines
4.5 KiB
TypeScript
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'])
|
||
}
|
||
)
|
||
})
|