mirror of
https://github.com/firestar5683/StarPilot.git
synced 2026-11-09 22:13:43 +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>
71 lines
6.2 KiB
JavaScript
71 lines
6.2 KiB
JavaScript
import assert from "node:assert/strict"
|
|
import { LaboratoryFeed, LaboratoryPage, laboratoryModels, laboratoryReady, laboratorySelectionError, laboratoryActionAllowed, laboratoryDraft, laboratoryStatusLabel } from "../web/js/model-laboratory.js"
|
|
|
|
const model = (value, version = 'v9') => ({ value, label: `Model ${value}`, version, small: true, modelLabEligible: true, modelLabArtifactAvailable: true, modelLabArtifactInstalled: true })
|
|
const payload = () => ({ schemaVersion: 1, isOnroad: false, chestnutReady: true, runtimeSupported: true,
|
|
configuration: { enabled: false, lateralModel: 'a', longitudinalModel: 'b' }, runtime: { active: false, requested: false },
|
|
download: { downloading: false, jobId: null, progress: '' }, models: [model('a','v8'), model('b','v9')],
|
|
capabilities: { configure: true, download: true, delete: true, cancel: true, refresh: true } })
|
|
const p = payload()
|
|
assert.equal(laboratorySelectionError(p,p.configuration), '') // mixed versions allowed
|
|
assert.equal(laboratoryActionAllowed(p,'enable',null,p.configuration), true)
|
|
assert.match(laboratorySelectionError({...p,runtimeSupported:false,runtimeUnavailableReason:'Pair runtime pending'},p.configuration), /Pair runtime pending/)
|
|
assert.match(laboratorySelectionError({...p,chestnutReady:false},p.configuration), /Chestnut/)
|
|
assert.match(laboratorySelectionError({...p,isOnroad:true},p.configuration), /Turn off the vehicle/)
|
|
assert.match(laboratorySelectionError(p,{lateralModel:'a',longitudinalModel:'a'}), /different/)
|
|
assert.match(laboratorySelectionError(p,{lateralModel:'a',longitudinalModel:'unknown'}), /downloaded/)
|
|
assert.equal(laboratorySelectionError(null,p.configuration), 'Waiting for parked device status')
|
|
const incompatible = [model('big'), model('qcom'), model('old')]
|
|
incompatible[0].small=false; incompatible[1].modelLabArtifactAvailable=false; incompatible[2].modelLabEligible=false
|
|
assert.equal(laboratoryModels({...p,models:incompatible}).length,3)
|
|
assert.equal(laboratoryReady({...p,models:incompatible}).length,0)
|
|
for (const row of incompatible) assert.equal(laboratoryActionAllowed(p,'download',row),false)
|
|
assert.equal(laboratoryReady({...p,models:[{...model('a'),modelLabArtifactInstalled:false}]}).length,0)
|
|
assert.equal(laboratoryActionAllowed({...p,configuration:{...p.configuration,enabled:true}},'delete',p.models[0]),false)
|
|
assert.equal(laboratoryActionAllowed(p,'delete',p.models[0]),true)
|
|
const missing = {...model('c'),modelLabArtifactInstalled:false}
|
|
assert.equal(laboratoryActionAllowed({...p,chestnutReady:false,models:[missing]},'download',missing),true)
|
|
assert.equal(laboratoryActionAllowed({...p,download:{downloading:true,jobId:'job'}},'cancel'),true)
|
|
assert.equal(laboratoryActionAllowed({...p,download:{downloading:true,jobId:'job'}},'enable'),false)
|
|
assert.deepEqual(laboratoryDraft(p,{lateralModel:'b',longitudinalModel:'a'},true),{enabled:false,lateralModel:'b',longitudinalModel:'a'})
|
|
assert.deepEqual(laboratoryDraft({...p,configuration:{enabled:false,lateralModel:'',longitudinalModel:''}},null,false),p.configuration)
|
|
|
|
function fixture() {
|
|
const requests=[],updates=[],timers=new Map();let next=0,unauthorized=0
|
|
const feed=new LaboratoryFeed({publish:u=>updates.push(u),unauthorized:()=>unauthorized++,
|
|
fetcher:(url,options)=>new Promise(resolve=>requests.push({url,options,resolve})),
|
|
later:(fn,ms)=>{timers.set(++next,{fn,ms});return next},cancel:id=>timers.delete(id)})
|
|
const flush=async()=>{for(let i=0;i<12;i++)await Promise.resolve()}
|
|
const reply=async(index,body,status=200)=>{requests[index].resolve({ok:status===200,status,json:async()=>body});await flush()}
|
|
return {feed,requests,updates,timers,reply,flush,get unauthorized(){return unauthorized}}
|
|
}
|
|
const f=fixture();f.feed.start();assert.equal(f.requests[0].url,'./api/models/laboratory');await f.reply(0,p)
|
|
assert.equal(f.feed.data.runtimeSupported,true)
|
|
const action=f.feed.action('enable',null,{enabled:false,lateralModel:'b',longitudinalModel:'a'})
|
|
assert.equal(f.requests[1].url,'./api/models/laboratory')
|
|
assert.equal(f.requests[1].options.method,'POST')
|
|
assert.equal(f.requests[1].options.credentials,'same-origin')
|
|
assert.deepEqual(JSON.parse(f.requests[1].options.body),{enabled:true,lateralModel:'b',longitudinalModel:'a'})
|
|
await f.reply(1,{...p,message:'Pair requested'});assert.equal(f.requests[2].url,'./api/models/laboratory');await f.reply(2,p);await action
|
|
const expiry=[...f.timers.values()].find(t=>t.ms===6000);expiry.fn()
|
|
assert.equal(f.feed.data,null);assert.match(f.updates.at(-1).error,/refresh delayed/)
|
|
assert.equal(await f.feed.action('enable',null,p.configuration),null)
|
|
f.feed.stop()
|
|
const invalid=fixture();invalid.feed.start();await invalid.reply(0,{...p,runtimeSupported:undefined});assert.equal(invalid.feed.data,null)
|
|
const retired=fixture();retired.feed.start();retired.feed.stop();await retired.reply(0,p);assert.equal(retired.feed.data,null)
|
|
const auth=fixture();auth.feed.start();await auth.reply(0,{message:'Unauthorized'},401);assert.equal(auth.unauthorized,1);assert.equal(auth.feed.active,false)
|
|
const download=fixture();download.feed.start();await download.reply(0,{...p,models:[missing]})
|
|
const downloading=download.feed.action('download',missing)
|
|
assert.equal(download.requests[1].url,'./api/models/laboratory/download');assert.deepEqual(JSON.parse(download.requests[1].options.body),{model:'c'})
|
|
await download.reply(1,{message:'Starting download'});await download.reply(2,{...p,download:{downloading:true,jobId:'job',progress:'40%'}});await downloading
|
|
const canceling=download.feed.action('cancel');assert.equal(download.requests[3].url,'./api/models/cancel');assert.deepEqual(JSON.parse(download.requests[3].options.body),{jobId:'job'})
|
|
await download.reply(3,{message:'Cancelling'});await download.reply(4,p);await canceling;download.feed.stop()
|
|
assert.ok(LaboratoryPage.template.indexOf('Available models')<LaboratoryPage.template.indexOf('Compose a pair'))
|
|
assert.match(LaboratoryPage.template,/GalaxySelect/)
|
|
assert.match(LaboratoryPage.template,/Catalog models/)
|
|
assert.match(LaboratoryPage.template,/modelLabReason/)
|
|
assert.equal(laboratoryStatusLabel({modelLabStatus:"runtime-unavailable"}), "Downloaded")
|
|
assert.equal(laboratoryStatusLabel({modelLabStatus:"unsupported"}), "Not supported")
|
|
assert.doesNotMatch(LaboratoryPage.template,/20 Hz/)
|
|
console.log('Model Laboratory contracts passed')
|