fix: restore mode clicks and compose seat-aware assistant scenes
This commit is contained in:
@@ -0,0 +1,177 @@
|
||||
"""Execute the mode preview formatter against actual seat/light parameter shapes."""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import json
|
||||
import shutil
|
||||
import subprocess
|
||||
from pathlib import Path
|
||||
|
||||
import pytest
|
||||
|
||||
ROOT = Path(__file__).resolve().parents[2]
|
||||
|
||||
|
||||
@pytest.fixture(scope="module")
|
||||
def render_rows():
|
||||
node = shutil.which("node")
|
||||
if not node:
|
||||
runtime = (
|
||||
Path.home() / ".cache" / "codex-runtimes" / "codex-primary-runtime"
|
||||
/ "dependencies" / "node" / "bin"
|
||||
)
|
||||
node = next((str(path) for path in (runtime / "node.exe", runtime / "node") if path.is_file()), None)
|
||||
assert node, "Node.js is required to validate rendered mode action text"
|
||||
source = (ROOT / "apps" / "web-console" / "assistant-chat.js").read_text(encoding="utf-8")
|
||||
start = source.index(" function modeDraftRows(")
|
||||
end = source.index("\n function ", start + 1)
|
||||
script = source[start:end] + "\nconst input = JSON.parse(require('node:fs').readFileSync(0, 'utf8'));\n"
|
||||
script += "console.log(JSON.stringify(modeDraftRows(input.draft, input.actions)));"
|
||||
|
||||
def render(actions, instruction=""):
|
||||
completed = subprocess.run(
|
||||
[node, "-e", script],
|
||||
input=json.dumps({"draft": {"instruction": instruction}, "actions": actions}, ensure_ascii=False),
|
||||
capture_output=True,
|
||||
text=True,
|
||||
encoding="utf-8",
|
||||
check=True,
|
||||
)
|
||||
return json.loads(completed.stdout)
|
||||
|
||||
return render
|
||||
|
||||
|
||||
def action(capability, parameters, zone="driver"):
|
||||
return {
|
||||
"domain": capability.split(".")[0],
|
||||
"capability": capability,
|
||||
"target": {"zone": zone},
|
||||
"parameters": parameters,
|
||||
}
|
||||
|
||||
|
||||
@pytest.mark.parametrize("kind", ["ventilation", "heating"])
|
||||
@pytest.mark.parametrize(
|
||||
("parameters", "expected"),
|
||||
[
|
||||
({"state": "on", "level": 1}, "开启 · 高档"),
|
||||
({"state": "on", "level": 2}, "开启 · 低档"),
|
||||
({"state": "on"}, "开启 · 低档"),
|
||||
({"state": "off", "level": 1}, "关闭"),
|
||||
],
|
||||
)
|
||||
def test_driver_native_comfort_uses_its_own_level_scale(render_rows, kind, parameters, expected):
|
||||
rows = render_rows([action(f"seat.set_driver_{kind}_native", parameters, "front_left")])
|
||||
assert rows[0]["label"] == f"主驾座椅{'通风' if kind == 'ventilation' else '加热'}"
|
||||
assert rows[0]["value"] == expected
|
||||
|
||||
|
||||
@pytest.mark.parametrize("kind", ["ventilation", "heating"])
|
||||
@pytest.mark.parametrize("level", [1, 2, 3, 4, 5])
|
||||
def test_passenger_levels_are_not_translated_using_driver_can_codes(render_rows, kind, level):
|
||||
rows = render_rows([action(f"seat.set_{kind}", {"state": "on", "level": level}, "passenger")])
|
||||
assert rows[0]["label"] == f"副驾座椅{'通风' if kind == 'ventilation' else '加热'}"
|
||||
assert rows[0]["value"] == f"开启 · {level}档"
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
("parameters", "expected"),
|
||||
[
|
||||
({"action": "off", "mode": "relax"}, "关闭"),
|
||||
({"action": "mode", "mode": "wave"}, "波浪模式"),
|
||||
({"action": "mode", "mode": "pulse"}, "脉冲模式"),
|
||||
({"action": "mode", "mode": "stretch"}, "舒展模式"),
|
||||
({"action": "mode", "mode": "slack"}, "舒缓模式"),
|
||||
({"action": "mode", "mode": "relax"}, "放松模式"),
|
||||
({"action": "strength", "strength": 1}, "轻柔力度"),
|
||||
({"action": "strength", "strength": 2}, "中等力度"),
|
||||
({"action": "strength", "strength": 3}, "较强力度"),
|
||||
({"action": "mode"}, "按摩模式待确认"),
|
||||
({"action": "strength"}, "按摩力度待确认"),
|
||||
],
|
||||
)
|
||||
def test_massage_preview_distinguishes_operation_mode_and_strength(render_rows, parameters, expected):
|
||||
rows = render_rows([action("seat.set_driver_massage_native", parameters)])
|
||||
assert rows[0]["label"] == "主驾座椅按摩"
|
||||
assert rows[0]["value"] == expected
|
||||
|
||||
|
||||
def test_ambient_native_color_and_brightness_remain_distinct_rows(render_rows):
|
||||
rows = render_rows([
|
||||
action("ambient_light.set_color_index", {"color_index": 127}, "vehicle"),
|
||||
action("ambient_light.set_brightness_level", {"brightness_level": 2}, "vehicle"),
|
||||
])
|
||||
assert [(row["label"], row["value"]) for row in rows] == [
|
||||
("氛围灯颜色", "色号 127"),
|
||||
("氛围灯亮度", "2档"),
|
||||
]
|
||||
|
||||
|
||||
@pytest.mark.parametrize("brightness", [0, 20, 100])
|
||||
def test_rgb_illumination_keeps_exact_color_and_brightness(render_rows, brightness):
|
||||
rows = render_rows([
|
||||
action("ambient_light.set_illumination", {"color_hex": "#FFB347", "brightness_pct": brightness}, "vehicle"),
|
||||
])
|
||||
assert rows[0]["value"] == f"颜色 #FFB347 · 亮度 {brightness}%"
|
||||
|
||||
|
||||
def test_zero_gravity_grouping_keeps_driver_comfort_visible(render_rows):
|
||||
rows = render_rows([
|
||||
action("seat.set_longitudinal_position", {"position_pct": 100}, "passenger"),
|
||||
action("seat.set_backrest_recline", {"position_pct": 81, "angle_deg": 150}, "front_right"),
|
||||
action("seat.set_driver_massage_native", {"action": "mode", "mode": "relax"}),
|
||||
], "副驾零重力模式,并开启主驾放松按摩")
|
||||
assert [(row["label"], row["value"]) for row in rows] == [
|
||||
("副驾座椅", "零重力模式"),
|
||||
("主驾座椅按摩", "放松模式"),
|
||||
]
|
||||
|
||||
|
||||
def test_position_and_power_rows_keep_existing_values(render_rows):
|
||||
rows = render_rows([
|
||||
action("seat.set_backrest_recline", {"position_pct": 81, "angle_deg": 150}, "passenger"),
|
||||
action("ambient_light.set_power", {"state": "off"}, "vehicle"),
|
||||
action("seat.set_ventilation", {"state": "off", "level": 2}, "passenger"),
|
||||
])
|
||||
assert [(row["label"], row["value"]) for row in rows] == [
|
||||
("副驾靠背角度", "81%(150°)"),
|
||||
("氛围灯", "关闭"),
|
||||
("副驾座椅通风", "关闭"),
|
||||
]
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
("capability", "mode", "label", "value"),
|
||||
[
|
||||
("climate.set_control_mode", "auto", "空调控制模式", "自动控制"),
|
||||
("climate.set_control_mode", "manual", "空调控制模式", "手动控制"),
|
||||
("climate.set_cycle_mode", "internal", "空调循环", "内循环"),
|
||||
("climate.set_cycle_mode", "external", "空调循环", "外循环"),
|
||||
("climate.set_outlet_mode", "face", "空调出风模式", "吹面"),
|
||||
("climate.set_outlet_mode", "face_feet", "空调出风模式", "吹面 / 吹脚"),
|
||||
("climate.set_outlet_mode", "feet", "空调出风模式", "吹脚"),
|
||||
("climate.set_outlet_mode", "feet_defrost", "空调出风模式", "吹脚 / 除霜"),
|
||||
("climate.set_outlet_mode", "defrost", "空调出风模式", "除霜"),
|
||||
("climate.set_outlet_mode", "face_feet_defrost", "空调出风模式", "吹面 / 吹脚 / 除霜"),
|
||||
("climate.set_outlet_mode", "face_defrost", "空调出风模式", "吹面 / 除霜"),
|
||||
],
|
||||
)
|
||||
def test_climate_modes_use_capability_specific_labels(render_rows, capability, mode, label, value):
|
||||
rows = render_rows([action(capability, {"mode": mode}, "vehicle")])
|
||||
assert (rows[0]["label"], rows[0]["value"]) == (label, value)
|
||||
|
||||
|
||||
def test_climate_control_circulation_and_outlet_are_not_conflated(render_rows):
|
||||
rows = render_rows([
|
||||
action("climate.set_control_mode", {"mode": "auto"}, "vehicle"),
|
||||
action("climate.set_cycle_mode", {"mode": "internal"}, "vehicle"),
|
||||
action("climate.set_outlet_mode", {"mode": "face_feet"}, "vehicle"),
|
||||
action("climate.set_fan_level", {"level": 2}, "vehicle"),
|
||||
])
|
||||
assert [(row["label"], row["value"]) for row in rows] == [
|
||||
("空调控制模式", "自动控制"),
|
||||
("空调循环", "内循环"),
|
||||
("空调出风模式", "吹面 / 吹脚"),
|
||||
("空调风量", "2档"),
|
||||
]
|
||||
Reference in New Issue
Block a user