Merge branch 'codex/route-parity-parser-fix'

This commit is contained in:
Clément SAILLANT
2026-02-21 21:28:01 +01:00
4 changed files with 111 additions and 7 deletions
+3
View File
@@ -19,6 +19,9 @@ jobs:
with:
python-version: "3.11"
- name: Test Web Route Parity Parser
run: python3 -m unittest scripts/test_check_web_route_parity.py
- name: Check Web Route Parity
run: python3 scripts/check_web_route_parity.py
+48 -7
View File
@@ -15,10 +15,8 @@ Route = tuple[str, str]
BACKEND_ROUTE_RE = re.compile(
r'server_\.on\(\s*"(?P<path>/api/[^"]+)"\s*,\s*HTTP_(?P<method>[A-Z]+)'
)
FRONTEND_CALL_RE = re.compile(
r'requestJson\(\s*["\'](?P<path>/api/[^"\']+)["\'](?P<args>.*?)\);',
re.DOTALL,
)
FRONTEND_CALL_START_RE = re.compile(r"\brequestJson\(")
FRONTEND_PATH_ARG_RE = re.compile(r'^\s*(["\'])(?P<path>/api/[^"\']+)\1')
METHOD_RE = re.compile(r'method\s*:\s*["\'](?P<method>[A-Z]+)["\']')
@@ -31,11 +29,54 @@ def parse_backend_routes(source: str) -> set[Route]:
return routes
def find_matching_paren(source: str, open_paren_index: int) -> int:
depth = 1
in_string: str | None = None
escaped = False
for index in range(open_paren_index + 1, len(source)):
char = source[index]
if in_string is not None:
if escaped:
escaped = False
continue
if char == "\\":
escaped = True
continue
if char == in_string:
in_string = None
continue
if char in ('"', "'", "`"):
in_string = char
continue
if char == "(":
depth += 1
continue
if char == ")":
depth -= 1
if depth == 0:
return index
return -1
def parse_frontend_routes(source: str) -> set[Route]:
routes: set[Route] = set()
for match in FRONTEND_CALL_RE.finditer(source):
path = match.group("path")
args = match.group("args")
for match in FRONTEND_CALL_START_RE.finditer(source):
open_paren = match.end() - 1
close_paren = find_matching_paren(source, open_paren)
if close_paren < 0:
continue
args = source[open_paren + 1 : close_paren]
path_match = FRONTEND_PATH_ARG_RE.match(args)
if not path_match:
continue
path = path_match.group("path")
method_match = METHOD_RE.search(args)
method = method_match.group("method").upper() if method_match else "GET"
routes.add((method, path))
+57
View File
@@ -0,0 +1,57 @@
#!/usr/bin/env python3
"""Unit tests for check_web_route_parity parser helpers."""
from __future__ import annotations
import unittest
from scripts.check_web_route_parity import parse_frontend_routes
class ParseFrontendRoutesTest(unittest.TestCase):
def test_detects_direct_calls(self) -> None:
source = """
async function refresh() {
await requestJson("/api/status");
await requestJson("/api/control", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ action: "CALL" }),
});
}
"""
routes = parse_frontend_routes(source)
self.assertIn(("GET", "/api/status"), routes)
self.assertIn(("POST", "/api/control"), routes)
def test_detects_calls_inside_promise_all(self) -> None:
source = """
const [wifi, mqtt, espnow, peers] = await Promise.all([
requestJson("/api/network/wifi"),
requestJson("/api/network/mqtt"),
requestJson("/api/network/espnow"),
requestJson("/api/network/espnow/peer"),
]);
"""
routes = parse_frontend_routes(source)
self.assertIn(("GET", "/api/network/wifi"), routes)
self.assertIn(("GET", "/api/network/mqtt"), routes)
self.assertIn(("GET", "/api/network/espnow"), routes)
self.assertIn(("GET", "/api/network/espnow/peer"), routes)
def test_handles_nested_parentheses_in_payload(self) -> None:
source = """
await requestJson("/api/network/mqtt/publish", {
method: "POST",
body: JSON.stringify({
topic: "rtc/test",
payload: JSON.stringify({ ping: true }),
}),
});
"""
routes = parse_frontend_routes(source)
self.assertIn(("POST", "/api/network/mqtt/publish"), routes)
if __name__ == "__main__":
unittest.main()
+3
View File
@@ -12,6 +12,9 @@ mkdir -p .pio/host
c++ -std=c++17 -Wall -Wextra -pedantic -Isrc test/host/test_dtmf_host.cpp src/telephony/DtmfDecoder.cpp -o .pio/host/test_dtmf_host
.pio/host/test_dtmf_host
echo "[test_terminal] run web route parity parser tests"
python3 -m unittest scripts/test_check_web_route_parity.py
echo "[test_terminal] check web route parity"
python3 scripts/check_web_route_parity.py