feat(web-console): rebuild intelligent cockpit sync interface
This commit is contained in:
@@ -47,27 +47,16 @@ class FrontendVehicleStateSyncContractTests(unittest.TestCase):
|
||||
self.extension_source,
|
||||
)
|
||||
|
||||
def test_shared_twin_theme_tracks_demo_role_and_extension_is_always_user(self) -> None:
|
||||
def test_shared_twin_theme_is_fixed_to_user(self) -> None:
|
||||
self.assertIn("function applyTwinSceneTheme(", self.app_source)
|
||||
self.assertIn('canvas.dataset.themeRole = themeRole', self.app_source)
|
||||
self.assertIn('canvas.dataset.themeRole = "user"', self.app_source)
|
||||
self.assertIn(
|
||||
'canvas.dataset.themeAccent = `#${palette.accent.toString(16).padStart(6, "0")}`',
|
||||
self.app_source,
|
||||
)
|
||||
self.assertIn("accent: 0x0e7773", self.app_source)
|
||||
self.assertIn("accent: 0x315eaa", self.app_source)
|
||||
self.assertIn(
|
||||
'if (document.body.dataset.module === "self-extension") return "user"',
|
||||
self.app_source,
|
||||
)
|
||||
self.assertIn(
|
||||
'const themeRole = document.body.dataset.module === "self-extension"',
|
||||
self.app_source,
|
||||
)
|
||||
self.assertIn(
|
||||
'window.addEventListener("cognitive-agent:demo-role-change"',
|
||||
self.app_source,
|
||||
)
|
||||
self.assertNotIn("accent: 0x315eaa", self.app_source)
|
||||
self.assertNotIn("cognitive-agent:demo-role-change", self.app_source)
|
||||
|
||||
def test_shared_twin_ground_uses_theme_radial_alpha_texture(self) -> None:
|
||||
self.assertIn("function createTwinGroundTexture(", self.app_source)
|
||||
|
||||
@@ -10,27 +10,29 @@ def source(name: str) -> str:
|
||||
return (ROOT / "apps" / "web-console" / name).read_text(encoding="utf-8")
|
||||
|
||||
|
||||
def test_calibration_twin_tracks_labels_and_commits_direct_axis_drag() -> None:
|
||||
calibration = source("self-calibration.js")
|
||||
seat3d = source("self-repair-seat3d.js")
|
||||
styles = source("self-calibration.css")
|
||||
def test_frontend_only_exposes_user_orchestration_and_extension() -> None:
|
||||
web_root = ROOT / "apps" / "web-console"
|
||||
html = source("index.html")
|
||||
console = source("console-v2.js")
|
||||
|
||||
assert 'data-seat-axis-label="backrest"' in calibration
|
||||
assert 'data-seat-label-line="legrest"' in calibration
|
||||
assert 'window.addEventListener("calibration-seat-axis-preview"' in calibration
|
||||
assert 'window.addEventListener("calibration-seat-axis-commit"' in calibration
|
||||
assert "function layoutSeatLabels()" in seat3d
|
||||
assert "makePanel(legrestPivot, cushionShape(0.08)" in seat3d
|
||||
assert "function legrestShape(" not in seat3d
|
||||
assert 'enableAxisDrag: true' in seat3d
|
||||
assert 'function startAxisDrag(axis, event, source = "model")' in seat3d
|
||||
assert 'startAxisDrag(item.axis, event, "label")' in seat3d
|
||||
assert "calculateAxisDragVector(axis, value)" in seat3d
|
||||
assert "Math.max(0, Math.min(100," in seat3d
|
||||
assert 'new CustomEvent("calibration-seat-axis-commit"' in seat3d
|
||||
assert ".v2-calibration-label-lines line" in styles
|
||||
assert '.v2-axis-tag[data-control-enabled="true"]' in styles
|
||||
assert "pointer-events: auto;" in styles
|
||||
for removed in (
|
||||
"self-calibration.js",
|
||||
"self-calibration.css",
|
||||
"self-repair.js",
|
||||
"self-repair.css",
|
||||
"self-repair-seat3d.js",
|
||||
"self-evolution.js",
|
||||
"self-evolution.css",
|
||||
):
|
||||
assert not (web_root / removed).exists()
|
||||
assert removed not in html
|
||||
|
||||
assert "511工程-智能座舱" in console
|
||||
assert '["self-orchestration", "self-extension"]' in console
|
||||
assert 'id="vehicleExtensionSync"' in console
|
||||
assert 'getRole: () => "user"' in console
|
||||
assert '"admin"' not in console
|
||||
assert "v2RoleSelect" not in console
|
||||
|
||||
|
||||
def test_extension_pet_and_transient_vehicle_state_restart_contract() -> None:
|
||||
@@ -41,17 +43,63 @@ def test_extension_pet_and_transient_vehicle_state_restart_contract() -> None:
|
||||
assert "function initializeDesktopPet()" in extension
|
||||
assert "saved.vehicleExecutions = {};" in extension
|
||||
assert "saved.lastProtocol = null;" in extension
|
||||
assert 'src="/assets/pets/self-extension-cat.png?v=3"' in extension
|
||||
assert 'class="v2-extension-pet-entrance-canvas"' in extension
|
||||
assert '"/assets/pets/self-extension-cat-entrance.png?v=3"' in extension
|
||||
assert "const ENTRANCE_KEYFRAME_COUNT = 12" in extension
|
||||
assert "const ENTRANCE_DURATION_MS = 2300" in extension
|
||||
assert "const ENTRANCE_WALK_STEPS = 5" in extension
|
||||
assert "const ENTRANCE_SETTLE_START_FRAME = 5" in extension
|
||||
assert "0, 1, 2, 3, 4, 3, 2, 1, 0, 1, 2, 3, 4" in extension
|
||||
assert "const easedStepProgress = 0.5 - (Math.cos(Math.PI * stepProgress) / 2)" in extension
|
||||
assert "function playEntrance()" in extension
|
||||
assert 'pet.dataset.entering = "true"' in extension
|
||||
assert "const drawEntrancePose =" in extension
|
||||
assert "window.requestAnimationFrame(renderEntrance)" in extension
|
||||
assert "function createThemedPetDataUrl(" in extension
|
||||
assert "blueDominance < 24" in extension
|
||||
assert 'window.addEventListener("cognitive-agent:demo-role-change"' not in extension
|
||||
assert 'class="v2-extension-pet-blink"' in extension
|
||||
assert "const scheduleBlink =" in extension
|
||||
assert 'pet.dataset.blinking = "true"' in extension
|
||||
assert 'class="v2-extension-pet-mouth-closed"' in extension
|
||||
assert "const animateMouth = () =>" in extension
|
||||
assert "mouth.animate?.(" in extension
|
||||
assert "{ opacity: 0, offset: 0.09 }" in extension
|
||||
assert "{ opacity: 0, offset: 0.41 }" in extension
|
||||
assert "{ opacity: 0, offset: 0.73 }" in extension
|
||||
assert "{ duration: 1260" in extension
|
||||
assert 'class="v2-extension-pet-tail-canvas"' in extension
|
||||
assert "const runTailWave =" in extension
|
||||
assert "const requestTailWave =" in extension
|
||||
assert 'prefers-reduced-motion: reduce' not in extension
|
||||
assert "tailWaveQueued = true" in extension
|
||||
assert "window.setTimeout(() => runTailWave(true), 180)" in extension
|
||||
assert "scheduleTailWave" not in extension
|
||||
assert 'pet.dataset.tailWaving = "true"' in extension
|
||||
assert "const tailMotionFrames = [" in extension
|
||||
assert "const sampleTailOffset =" in extension
|
||||
assert "sampleTailOffset(tailPose, distanceFromBase)" in extension
|
||||
assert "clampToSegment = false" in extension
|
||||
assert "Math.max(Math.min(start, end)" in extension
|
||||
assert "const sampleTravelingTailOffset =" not in extension
|
||||
assert 'document.visibilityState !== "visible"' in extension
|
||||
assert ".v2-extension-pet-body" in styles
|
||||
assert "@keyframes extension-pet-blink" in styles
|
||||
assert ".v2-extension-pet-entrance-canvas" in styles
|
||||
assert '.v2-extension-pet[data-entering="true"] .v2-extension-pet-image' in styles
|
||||
assert '.v2-extension-pet[data-blinking="true"] .v2-extension-pet-blink' in styles
|
||||
assert ".v2-extension-pet-mouth-closed" in styles
|
||||
assert "width: 176px;" in styles
|
||||
assert "font-size: 13px;" in styles
|
||||
assert '.v2-extension-pet[data-tail-waving="true"] .v2-extension-pet-tail-canvas' in styles
|
||||
assert '.v2-extension-pet[data-tail-waving="true"] .v2-extension-pet-image' in styles
|
||||
assert "position: fixed;" in styles
|
||||
assert "extension-pet-float" not in styles
|
||||
assert '[data-module="self-extension"][data-demo-role="admin"] .v2-sidebar' not in styles
|
||||
assert '[data-module="self-extension"][data-demo-role="admin"] .v2-avatar' not in styles
|
||||
|
||||
|
||||
def test_virtual_modules_reset_but_physical_sessions_remain_authoritative() -> None:
|
||||
def test_orchestration_session_reset_remains_available() -> None:
|
||||
orchestration = source("app.js")
|
||||
calibration = source("self-calibration.js")
|
||||
repair = source("self-repair.js")
|
||||
|
||||
assert 'sessionStorage.removeItem("cognitive-agent.conversation-id")' in orchestration
|
||||
assert 'api("/session/reset")' in calibration
|
||||
assert 'if (state.transport?.mode === "simulation")' in calibration
|
||||
assert 'if (backendMode === "bench")' in repair
|
||||
assert 'await apiPost("/runtime/reset-statistics")' in repair
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
from __future__ import annotations
|
||||
|
||||
import json
|
||||
import tempfile
|
||||
import time
|
||||
from pathlib import Path
|
||||
@@ -10,6 +11,41 @@ from cognitive_agent.application.calibration import protocol
|
||||
from cognitive_agent.application.calibration.service import ApiError, CalibrationService
|
||||
|
||||
|
||||
def test_video_settings_use_webrtc_and_migrate_legacy_rtsp() -> None:
|
||||
with tempfile.TemporaryDirectory() as directory:
|
||||
root = Path(directory)
|
||||
data_dir = root / "data"
|
||||
data_dir.mkdir()
|
||||
(data_dir / "settings.json").write_text(
|
||||
json.dumps(
|
||||
{
|
||||
"mqtt": {"host": "172.20.10.12", "port": 1883, "topic": "zed/seatpose"},
|
||||
"video": {
|
||||
"scheme": "http",
|
||||
"host": "172.20.10.12",
|
||||
"port": 8554,
|
||||
"path": "zed",
|
||||
"transport": "webrtc",
|
||||
},
|
||||
}
|
||||
),
|
||||
encoding="utf-8",
|
||||
)
|
||||
|
||||
service = CalibrationService(root)
|
||||
settings = service.snapshot()["settings"]
|
||||
|
||||
assert settings["mqtt"]["host"] == "172.20.10.6"
|
||||
assert settings["video"] == {
|
||||
"scheme": "http",
|
||||
"host": "172.20.10.6",
|
||||
"port": 8889,
|
||||
"path": "zed",
|
||||
"transport": "webrtc",
|
||||
}
|
||||
assert service.start_video()["video"]["state"] == "ready"
|
||||
|
||||
|
||||
def test_protocol_matches_android_golden_vectors() -> None:
|
||||
assert protocol.crc8(b"123456789") == 0x4B
|
||||
vectors = (
|
||||
|
||||
Reference in New Issue
Block a user