mirror of
https://github.com/firestar5683/StarPilot.git
synced 2026-11-08 13:33:42 +08:00
80fbb4f6db
Register vehicle controls, planner modes, UI actions and Galaxy services after their providers exist. Wire the shared runtime entrypoints and cover their combined behavior. Co-authored-by: Adeeb Shihadeh <adeebshihadeh@gmail.com> Co-authored-by: Daniel Koepping <elkoled@gmail.com> Co-authored-by: Danny <dannyirwin31@yahoo.com> Co-authored-by: DimitriChrysafis <Dimitri.chrysafis@gmail.com> Co-authored-by: Dom <168790843+firestar5683@users.noreply.github.com> Co-authored-by: Harald Schäfer <harald.the.engineer@gmail.com> Co-authored-by: Kacper Rączy <gfw.kra@gmail.com> Co-authored-by: Prabhaav Pillai <prabhaav@msu.edu> Co-authored-by: dirwin31 <83434411+dirwin31@users.noreply.github.com> Co-authored-by: firestarsdog <229254897+firestarsdog@users.noreply.github.com> Co-authored-by: stef <19478336+stefpi@users.noreply.github.com> Co-authored-by: whoisdomi <dcantu83@gmail.com> Co-authored-by: Intelli <contact@intelli.software> Co-authored-by: haraschax <6804392+haraschax@users.noreply.github.com> Co-authored-by: prabhaavp <prabhaav@msu.edu>
90 lines
4.1 KiB
JavaScript
90 lines
4.1 KiB
JavaScript
import assert from 'node:assert/strict'
|
|
import { DeviceState, DeviceStateFeed, validDeviceState } from '../web/js/device-state.js'
|
|
|
|
for (const state of ['parked', 'driving', 'standby', null]) assert.equal(validDeviceState({ state, maxAgeMs: 3000 }), true)
|
|
for (const state of ['unknown', 'constructor', '', false]) assert.equal(validDeviceState({ state, maxAgeMs: 3000 }), false)
|
|
for (const maxAgeMs of [undefined, 0, -1, 3001, Infinity, '3000']) assert.equal(validDeviceState({ state: 'parked', maxAgeMs }), false)
|
|
assert.equal(DeviceState.computed.label.call({ state: null }), 'State unavailable')
|
|
assert.equal(DeviceState.computed.label.call({ state: 'standby' }), 'Standby')
|
|
const flush = async () => { for (let n = 0; n < 8; n++) await Promise.resolve() }
|
|
|
|
function fixture() {
|
|
let now = 0, next = 0, revoked = 0
|
|
const timers = new Map(), requests = [], states = []
|
|
const feed = new DeviceStateFeed({ publish: (update) => states.push(update), clock: () => now,
|
|
unauthorized: () => revoked++,
|
|
later: (fn, ms) => { timers.set(++next, { fn, at: now + ms }); return next }, cancelTimer: (id) => timers.delete(id),
|
|
fetcher: (url, options) => new Promise((resolve) => requests.push({ url, options, resolve })) })
|
|
return { feed, timers, requests, states, get revoked() { return revoked },
|
|
async advance(ms) {
|
|
now += ms
|
|
for (const [key, timer] of [...timers]) if (timer.at <= now && timers.delete(key)) timer.fn()
|
|
await flush()
|
|
},
|
|
async reply(index, state, status = 200) {
|
|
requests[index].resolve({ ok: status === 200, status, json: async () => ({ state, maxAgeMs: 3000 }) })
|
|
await flush()
|
|
} }
|
|
}
|
|
|
|
const live = fixture()
|
|
live.feed.start()
|
|
assert.equal(live.requests[0].url, './api/device/state')
|
|
assert.equal(live.requests[0].options.credentials, 'same-origin')
|
|
await live.reply(0, 'parked')
|
|
assert.deepEqual(live.states.at(-1), { state: 'parked', stale: false })
|
|
const initialUpdates = live.states.length
|
|
await live.advance(1500)
|
|
await live.reply(1, 'parked')
|
|
assert.equal(live.states.length, initialUpdates, 'unchanged healthy polls do not republish presentation')
|
|
await live.advance(1500)
|
|
await live.reply(2, null)
|
|
assert.deepEqual(live.states.at(-1), { state: 'parked', stale: false }, 'one missing source does not erase last state')
|
|
await live.advance(1500)
|
|
assert.deepEqual(live.states.at(-1), { state: 'parked', stale: true }, 'last-known display becomes explicitly stale')
|
|
await live.reply(3, 'driving')
|
|
assert.deepEqual(live.states.at(-1), { state: 'driving', stale: false }, 'real transition is immediate')
|
|
live.feed.stop()
|
|
assert.equal(live.timers.size, 0)
|
|
assert.deepEqual(live.states.at(-1), { state: null, stale: false })
|
|
|
|
const expired = fixture()
|
|
expired.feed.start()
|
|
await expired.reply(0, 'parked')
|
|
await expired.advance(1500)
|
|
await expired.advance(4000)
|
|
assert.equal(expired.requests[1].options.signal.aborted, true)
|
|
assert.deepEqual(expired.states.at(-1), { state: 'parked', stale: true }, 'timeout retains only bounded last-known display')
|
|
await expired.reply(1, 'driving')
|
|
assert.equal(expired.states.at(-1).state, 'parked', 'late response cannot replace current state')
|
|
await expired.advance(2500)
|
|
assert.equal(expired.states.at(-1).state, null, 'repeated failure cannot indefinitely preserve last-known state')
|
|
expired.feed.stop()
|
|
|
|
const auth = fixture()
|
|
auth.feed.start()
|
|
await auth.reply(0, null, 401)
|
|
assert.equal(auth.revoked, 1)
|
|
assert.equal(auth.states.at(-1).state, null)
|
|
assert.equal(auth.timers.size, 0)
|
|
|
|
const previousDocument = globalThis.document
|
|
const listeners = new Map()
|
|
globalThis.document = { hidden: true, addEventListener: (key, fn) => listeners.set(key, fn),
|
|
removeEventListener: (key) => listeners.delete(key) }
|
|
const page = { $data: { state: null }, unauthorized() {} }
|
|
DeviceState.created.call(page)
|
|
let requests = 0
|
|
page.feed.fetcher = () => { requests++; return new Promise(() => {}) }
|
|
DeviceState.mounted.call(page)
|
|
assert.equal(requests, 0)
|
|
document.hidden = false
|
|
listeners.get('visibilitychange')()
|
|
assert.equal(requests, 1)
|
|
document.hidden = true
|
|
listeners.get('visibilitychange')()
|
|
assert.equal(page.$data.state, null)
|
|
DeviceState.beforeUnmount.call(page)
|
|
assert.equal(listeners.size, 0)
|
|
globalThis.document = previousDocument
|