aboutsummaryrefslogtreecommitdiff
path: root/tools/tests/test_gen_products.py
diff options
context:
space:
mode:
authorcirakg <cirakg@cirakg.xyz>2026-10-18 21:10:37 +0200
committercirakg <cirakg@cirakg.xyz>2026-10-18 21:10:37 +0200
commit2292bf700d28ade39cf2d64b45509e6db21034bc (patch)
treeef455320d39ebe51db236219dbbda2b148dcbe18 /tools/tests/test_gen_products.py
parent85f1ecabd7f58f306b2a042376209ac8cf49ab9b (diff)
test(tools): add screenshot, budget and product checks; enforce file headers
- sim_screenshot.py finds the device drawing in the simulator window, crops the screen and compares it with approved golden images. - check_budgets.py reads key=value DIAG/HARNESS lines (the simulator console escapes quotes, so JSON was dropped). - ciq_test_report.py accepts SDK 9.2.0's real summary line `PASSED (passed=N, failed=N, errors=N)`; a captured log is a fixture. - gen_products.py checks all manifest products are watches with API 5.0+ and at least 512 KB for apps. - lint_project.py rule HDR001: every file carries the Author/Summary header (JSON keys, PNG text chunks; generated package-lock exempt). - make_icon.py --all draws one icon per launcher size in use. - Golden screenshots for fr255s, venusq2, fr70 and fr965. - 44 tests, warnings as errors, ruff and mypy --strict clean. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Diffstat (limited to 'tools/tests/test_gen_products.py')
-rw-r--r--tools/tests/test_gen_products.py63
1 files changed, 63 insertions, 0 deletions
diff --git a/tools/tests/test_gen_products.py b/tools/tests/test_gen_products.py
new file mode 100644
index 0000000..47424d2
--- /dev/null
+++ b/tools/tests/test_gen_products.py
@@ -0,0 +1,63 @@
+# Author: cirakg & claude ai
+# Summary: Tests for tools/gen_products.py (the manifest product rule).
+"""Tests for tools/gen_products.py, with synthetic device definitions."""
+
+from __future__ import annotations
+
+import json
+from pathlib import Path
+
+import gen_products as gp
+
+MANIFEST = """<iq:manifest version="3" xmlns:iq="http://www.garmin.com/xml/connectiq">
+ <iq:application id="x" type="watch-app"><iq:products>{products}</iq:products></iq:application>
+</iq:manifest>"""
+
+
+def add_device(devices: Path, product: str, api: list[str], memory: int, group: str = gp.WATCH_GROUP) -> None:
+ folder = devices / product
+ folder.mkdir(parents=True)
+ compiler = {
+ "displayName": product.upper(),
+ "webDocDeviceGroup": group,
+ "partNumbers": [{"connectIQVersion": v} for v in api],
+ "appTypes": [{"type": "watchApp", "memoryLimit": memory}, {"type": "glance", "memoryLimit": 65536}],
+ }
+ (folder / "compiler.json").write_text(json.dumps(compiler))
+
+
+def write_manifest(tmp_path: Path, products: list[str]) -> Path:
+ path = tmp_path / "manifest.xml"
+ path.write_text(MANIFEST.format(products="".join(f'<iq:product id="{p}"/>' for p in products)))
+ return path
+
+
+def test_qualifying_products_pass(tmp_path: Path) -> None:
+ devices = tmp_path / "Devices"
+ add_device(devices, "fr70", ["6.0.3"], 786432)
+ add_device(devices, "fr255s", ["5.2.0", "5.2.1"], 524288)
+ assert gp.check(write_manifest(tmp_path, ["fr70", "fr255s"]), devices) == gp.EXIT_OK
+
+
+def test_each_rule_is_enforced(tmp_path: Path) -> None:
+ devices = tmp_path / "Devices"
+ add_device(devices, "old", ["4.2.0", "5.0.0"], 786432) # one firmware variant below 5.0
+ add_device(devices, "small", ["6.0.0"], 131072)
+ add_device(devices, "bike", ["5.1.0"], 786432, group="Edge")
+ manifest = write_manifest(tmp_path, ["old", "small", "bike"])
+ assert gp.check(manifest, devices) == gp.EXIT_UNQUALIFIED
+
+
+def test_missing_device_files(tmp_path: Path) -> None:
+ devices = tmp_path / "Devices"
+ devices.mkdir()
+ assert gp.check(write_manifest(tmp_path, ["ghost"]), devices) == gp.EXIT_MISSING
+
+
+def test_problem_messages() -> None:
+ device = gp.Device("x", "X", "Edge", (4, 2, 0), 131072)
+ assert device.problems() == [
+ "group is 'Edge', not 'Watches/Wearables'",
+ "API 4.2.0 is below 5.0.0",
+ "watch apps get 128 KB, below 512 KB",
+ ]