feedBack/tests/plugins/tuner/test_config.py
2026-06-16 18:47:13 +02:00

143 lines
6.8 KiB
Python

"""Unit tests for config logic (module-level helpers) and config read/write via HTTP."""
import json
import pytest
import routes
# ── _migrate_custom_tuning ────────────────────────────────────────────────────
class TestMigrateCustomTuning:
def test_old_flat_list_guitar6(self):
result = routes._migrate_custom_tuning("My Tuning", [82.41, 110.00, 146.83, 196.00, 246.94, 329.63])
assert result == {"instrument": "guitar-6", "strings": [82.41, 110.00, 146.83, 196.00, 246.94, 329.63]}
def test_old_flat_list_bass4(self):
result = routes._migrate_custom_tuning("Drop D Bass", [36.71, 55.00, 73.42, 98.00])
assert result["instrument"] == "bass-4"
assert result["strings"] == [36.71, 55.00, 73.42, 98.00]
def test_old_flat_list_bass5(self):
result = routes._migrate_custom_tuning("5-String", [30.87, 41.20, 55.00, 73.42, 98.00])
assert result["instrument"] == "bass-5"
def test_old_flat_list_guitar7(self):
result = routes._migrate_custom_tuning("7-String", [61.74, 82.41, 110.00, 146.83, 196.00, 246.94, 329.63])
assert result["instrument"] == "guitar-7"
def test_old_flat_list_guitar8(self):
strings = [46.25, 61.74, 82.41, 110.00, 146.83, 196.00, 246.94, 329.63]
result = routes._migrate_custom_tuning("8-String", strings)
assert result["instrument"] == "guitar-8"
def test_old_flat_list_unknown_count_defaults_guitar6(self):
result = routes._migrate_custom_tuning("3-String", [100.0, 200.0, 300.0])
assert result["instrument"] == "guitar-6"
def test_new_dict_format_passthrough(self):
value = {"instrument": "bass-4", "strings": [41.20, 55.00, 73.42, 98.00]}
result = routes._migrate_custom_tuning("My Bass", value)
assert result == value
def test_malformed_dict_returns_empty_guitar6(self):
result = routes._migrate_custom_tuning("Bad", {"foo": "bar"})
assert result == {"instrument": "guitar-6", "strings": []}
# ── Config read/write via HTTP ────────────────────────────────────────────────
class TestConfigDefaults:
def test_get_returns_all_default_keys(self, client):
r = client.get("/api/plugins/tuner/config")
assert r.status_code == 200
body = r.json()
assert body["lastTuning"] == "Standard"
assert body["lastInstrument"] == "guitar-6"
assert body["audioInputMode"] == "auto"
assert body["showFloatingButton"] is True
assert body["visualizationMode"] == "default"
assert body["customTunings"] == {}
assert body["disabledTunings"] == []
def test_get_does_not_include_default_tunings(self, client):
# defaultTunings moved to GET /api/tunings (core tuning.read capability).
body = client.get("/api/plugins/tuner/config").json()
assert "defaultTunings" not in body
class TestConfigPersistence:
def test_partial_update_persisted(self, client):
client.post("/api/plugins/tuner/config", json={"lastTuning": "Drop D"})
r = client.get("/api/plugins/tuner/config")
assert r.json()["lastTuning"] == "Drop D"
def test_unmodified_fields_survive_partial_update(self, client):
client.post("/api/plugins/tuner/config", json={"lastTuning": "Drop D"})
client.post("/api/plugins/tuner/config", json={"visualizationMode": "strobe"})
body = client.get("/api/plugins/tuner/config").json()
assert body["lastTuning"] == "Drop D"
assert body["visualizationMode"] == "strobe"
def test_default_tunings_not_written_to_file(self, client, config_dir):
client.post("/api/plugins/tuner/config", json={
"lastTuning": "Open G",
"defaultTunings": {"guitar-6": {"Standard": []}},
})
saved = json.loads((config_dir / "tuner.json").read_text())
assert "defaultTunings" not in saved
def test_invalid_audio_mode_resets_to_auto(self, client):
client.post("/api/plugins/tuner/config", json={"audioInputMode": "invalid"})
body = client.get("/api/plugins/tuner/config").json()
assert body["audioInputMode"] == "auto"
def test_valid_audio_mode_browser_accepted(self, client):
client.post("/api/plugins/tuner/config", json={"audioInputMode": "browser"})
assert client.get("/api/plugins/tuner/config").json()["audioInputMode"] == "browser"
def test_disabled_tunings_strips_entries_without_colon(self, client):
client.post("/api/plugins/tuner/config", json={
"disabledTunings": ["guitar-6:Drop D", "legacy-entry", "bass-4:Standard"]
})
body = client.get("/api/plugins/tuner/config").json()
assert "legacy-entry" not in body["disabledTunings"]
assert "guitar-6:Drop D" in body["disabledTunings"]
assert "bass-4:Standard" in body["disabledTunings"]
def test_custom_tuning_old_format_migrated_on_read(self, client, config_dir):
(config_dir / "tuner.json").write_text(json.dumps({
"customTunings": {"My Tuning": [82.41, 110.0, 146.83, 196.0, 246.94, 329.63]}
}))
body = client.get("/api/plugins/tuner/config").json()
assert body["customTunings"]["My Tuning"]["instrument"] == "guitar-6"
assert isinstance(body["customTunings"]["My Tuning"]["strings"], list)
def test_malformed_config_file_returns_defaults(self, client, config_dir):
(config_dir / "tuner.json").write_text("not json at all {{")
r = client.get("/api/plugins/tuner/config")
assert r.status_code == 200
assert r.json()["lastTuning"] == "Standard"
# ── referencePitch — now a core setting, not a tuner config field ─────────────
# referencePitch moved to GET/POST /api/settings (core tuning.read capability).
# The tuner config must not expose or persist it.
class TestReferencePitchNotInTunerConfig:
def test_not_present_in_default_response(self, client):
body = client.get("/api/plugins/tuner/config").json()
assert "referencePitch" not in body
def test_posting_reference_pitch_is_ignored(self, client):
# POSTing referencePitch must not break the request or leak the field back.
r = client.post("/api/plugins/tuner/config", json={"referencePitch": 432, "lastTuning": "Drop D"})
assert r.status_code == 200
body = client.get("/api/plugins/tuner/config").json()
assert "referencePitch" not in body
assert body["lastTuning"] == "Drop D"
def test_reference_pitch_not_written_to_file(self, client, config_dir):
client.post("/api/plugins/tuner/config", json={"referencePitch": 443})
saved = json.loads((config_dir / "tuner.json").read_text())
assert "referencePitch" not in saved