M5: roll Energy chart window for live auto-refresh (English label); render boolean config fields as switches
This commit is contained in:
@@ -557,3 +557,102 @@ def test_put_config_invalid_mqtt_port_returns_422_and_does_not_write(
|
||||
conn.close()
|
||||
|
||||
assert rows.get("MQTT_BROKER_PORT") != "not-a-number"
|
||||
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# M5-polish2 Area B: bool fields have input_type="checkbox"
|
||||
# ---------------------------------------------------------------------------
|
||||
|
||||
EXPECTED_CHECKBOX_FIELDS = {
|
||||
"APP_DEBUG",
|
||||
"SMTP_ENABLED",
|
||||
"SMTP_USE_STARTTLS",
|
||||
"AUTH_LOGIN_THROTTLE_ENABLED",
|
||||
"MQTT_ENABLED",
|
||||
"MQTT_TLS_ENABLED",
|
||||
"HA_DISCOVERY_ENABLED",
|
||||
"MODBUS_POLLING_ENABLED",
|
||||
}
|
||||
|
||||
|
||||
def test_bool_fields_have_checkbox_input_type(client: TestClient) -> None:
|
||||
"""All pure-bool config fields must return input_type='checkbox' from GET /api/config."""
|
||||
_login(client)
|
||||
|
||||
response = client.get("/api/config")
|
||||
assert response.status_code == 200
|
||||
body = response.json()
|
||||
|
||||
all_fields = {
|
||||
field["env_name"]: field
|
||||
for section in body["sections"]
|
||||
for field in section["fields"]
|
||||
}
|
||||
|
||||
for env_name in EXPECTED_CHECKBOX_FIELDS:
|
||||
assert env_name in all_fields, f"{env_name} not found in config response"
|
||||
actual_type = all_fields[env_name]["input_type"]
|
||||
assert actual_type == "checkbox", (
|
||||
f"{env_name}: expected input_type='checkbox', got {actual_type!r}"
|
||||
)
|
||||
|
||||
|
||||
def test_auth_cookie_secure_override_is_not_checkbox(client: TestClient) -> None:
|
||||
"""AUTH_COOKIE_SECURE_OVERRIDE is bool|None (three-state) and must NOT be checkbox."""
|
||||
_login(client)
|
||||
|
||||
response = client.get("/api/config")
|
||||
assert response.status_code == 200
|
||||
body = response.json()
|
||||
|
||||
all_fields = {
|
||||
field["env_name"]: field
|
||||
for section in body["sections"]
|
||||
for field in section["fields"]
|
||||
}
|
||||
|
||||
# This field is present in CONFIG_FIELDS; its type is bool|None so it stays text.
|
||||
if "AUTH_COOKIE_SECURE_OVERRIDE" in all_fields:
|
||||
actual_type = all_fields["AUTH_COOKIE_SECURE_OVERRIDE"]["input_type"]
|
||||
assert actual_type != "checkbox", (
|
||||
f"AUTH_COOKIE_SECURE_OVERRIDE should not be checkbox (it is bool|None); got {actual_type!r}"
|
||||
)
|
||||
|
||||
|
||||
def test_put_config_bool_field_roundtrip_true_false(
|
||||
client: TestClient, test_database_urls
|
||||
) -> None:
|
||||
"""Saving 'true'/'false' string for a bool checkbox field roundtrips correctly."""
|
||||
_login(client)
|
||||
|
||||
# Set MQTT_ENABLED to 'true' via config PUT
|
||||
payload_true = _full_config_payload({"MQTT_ENABLED": "true"})
|
||||
resp_true = client.put(
|
||||
"/api/config",
|
||||
json={"updates": payload_true},
|
||||
headers={"X-CSRF-Token": "token"},
|
||||
)
|
||||
assert resp_true.status_code == 200
|
||||
|
||||
conn = sqlite3.connect(test_database_urls["app_path"])
|
||||
try:
|
||||
rows = dict(conn.execute("SELECT key, value FROM app_config").fetchall())
|
||||
finally:
|
||||
conn.close()
|
||||
assert rows.get("MQTT_ENABLED") == "true"
|
||||
|
||||
# Now set to 'false'
|
||||
payload_false = _full_config_payload({"MQTT_ENABLED": "false"})
|
||||
resp_false = client.put(
|
||||
"/api/config",
|
||||
json={"updates": payload_false},
|
||||
headers={"X-CSRF-Token": "token"},
|
||||
)
|
||||
assert resp_false.status_code == 200
|
||||
|
||||
conn = sqlite3.connect(test_database_urls["app_path"])
|
||||
try:
|
||||
rows = dict(conn.execute("SELECT key, value FROM app_config").fetchall())
|
||||
finally:
|
||||
conn.close()
|
||||
assert rows.get("MQTT_ENABLED") == "false"
|
||||
|
||||
Reference in New Issue
Block a user