Files
StarPilot/sunnypilot/sunnylink/tests/test_params_metadata.py
DevTekVE a4454721ea sunnylink: dynamic param metadata (#1522)
* feat(params): add support for parameter metadata retrieval

- Introduced `getKeyMetadata` method for accessing metadata associated with params.
- Enhanced `getParamsAllKeysV1` to include metadata parsing and optional dynamic enum generation.
- Extended unit tests to verify metadata parsing, enum mapping, and edge cases.

* Revert "feat(params): add support for parameter metadata retrieval"

This reverts commit 865b695ff966bfab7dab4d211fb2d91f06fe92db.

* update: integrate params metadata management and unit tests

- Added `update_params_metadata.py` to manage and update parameters metadata.
- Enhanced `getParamsAllKeysV1` to include metadata for params.
- Created comprehensive tests (`test_params_metadata.py`, `test_params_sync.py`) to validate metadata integrity and params consistency.

* update: improve params metadata readability and enhance enums

- Renamed params titles for clarity and consistency.
- Added enum options and mappings to selected params for better usability.

* update: enhance params metadata with improved enum structures

- Replaced plain enum lists with detailed objects (`value`, `label`) for clarity.
- Standardized parameter options for consistency across metadata.

* update: add validation constraints to params metadata

- Introduced `min`, `max`, and `step` attributes for improved parameter range validation.
- Enhances user input handling and ensures consistency in metadata.

* lint

* more lint stuff and permissions

* does this suffice?

* more lint

* update: refine params type hinting and remove unused shebang

- Adjusted type annotation in `params_dict` for better compatibility.
- Removed unnecessary shebang from `test_params_metadata.py`.

* update: expand test coverage for params metadata validation

- Added detailed test cases to ensure metadata consistency (`options`, `constraints`, `titles`).
- Validates API response alignment with `params_metadata.json`.

* the finals

* names

---------

Co-authored-by: Jason Wen <haibin.wen3@gmail.com>
2025-11-29 03:52:01 -05:00

87 lines
3.4 KiB
Python

"""
Copyright (c) 2021-, Haibin Wen, sunnypilot, and a number of other contributors.
This file is part of sunnypilot and is licensed under the MIT License.
See the LICENSE.md file in the root directory for more details.
"""
import json
from openpilot.sunnypilot.sunnylink.athena.sunnylinkd import getParamsAllKeysV1, METADATA_PATH
def test_get_params_all_keys_v1():
"""
Test the getParamsAllKeysV1 API endpoint.
Why:
This endpoint is used by the UI (and potentially external tools) to fetch the list of
available parameters along with their metadata (titles, descriptions, options, constraints).
We need to ensure it returns the correct structure and that the metadata from
params_metadata.json is correctly merged into the response.
Expected:
- The response should contain a "keys" field which is a JSON string of a list of parameters.
- Each parameter object should have "key", "type", "default_value", and optionally "_extra".
- The "_extra" field should contain the rich metadata (title, options, min/max, etc.) matching
the source of truth (params_metadata.json).
"""
response = getParamsAllKeysV1()
assert "keys" in response
keys_json = response["keys"]
params_list = json.loads(keys_json)
assert isinstance(params_list, list)
assert len(params_list) > 0
# Check structure of first item
first_param = params_list[0]
assert "key" in first_param
assert "type" in first_param
assert "default_value" in first_param
if "_extra" in first_param:
assert isinstance(first_param["_extra"], dict)
assert "default" not in first_param["_extra"]
assert "type" not in first_param["_extra"]
# Load the source of truth
with open(METADATA_PATH) as f:
metadata = json.load(f)
# Verify that the API response matches the metadata file for a few sample keys
# This ensures the plumbing is working without being brittle to content changes
# 1. Check a key that should have metadata
keys_with_metadata = [k for k in params_list if k["key"] in metadata]
assert len(keys_with_metadata) > 0, "No parameters found that match metadata keys"
for param in keys_with_metadata[:5]: # Check first 5 matches
key = param["key"]
expected_meta = metadata[key]
assert "_extra" in param, f"Parameter {key} should have _extra field"
actual_meta = param["_extra"]
# Verify all fields in JSON are present in the API response
for meta_key, meta_val in expected_meta.items():
assert meta_key in actual_meta, f"Missing {meta_key} in API response for {key}"
assert actual_meta[meta_key] == meta_val, f"Mismatch for {key}.{meta_key}: expected {meta_val}, got {actual_meta[meta_key]}"
# 2. Check that we are correctly serving options if they exist
params_with_options = [k for k in keys_with_metadata if "options" in k.get("_extra", {})]
if params_with_options:
param = params_with_options[0]
key = param["key"]
assert isinstance(param["_extra"]["options"], list), f"Options for {key} should be a list"
assert param["_extra"]["options"] == metadata[key]["options"]
# 3. Check that we are correctly serving numeric constraints if they exist
params_with_constraints = [k for k in keys_with_metadata if "min" in k.get("_extra", {})]
if params_with_constraints:
param = params_with_constraints[0]
key = param["key"]
assert param["_extra"]["min"] == metadata[key]["min"]
assert param["_extra"]["max"] == metadata[key]["max"]
assert param["_extra"]["step"] == metadata[key]["step"]