Refs/heads/copilot/analyze test coverage#1
Conversation
Agent-Logs-Url: https://github.com/annawiewer/wiesn-agent/sessions/6839c000-ba6e-4550-8d76-c0ec80cf0ed7 Co-authored-by: annawiewer <138025423+annawiewer@users.noreply.github.com>
… duplication Agent-Logs-Url: https://github.com/annawiewer/wiesn-agent/sessions/6839c000-ba6e-4550-8d76-c0ec80cf0ed7 Co-authored-by: annawiewer <138025423+annawiewer@users.noreply.github.com>
There was a problem hiding this comment.
Pull request overview
Adds a new pytest suite focused on exercising previously uncovered branches across the backend (config models, scanner matching/filtering, history pruning/stats, notification helpers, and API helpers/endpoints).
Changes:
- Introduces
tests/test_coverage_gaps.pywith targeted unit tests forconfig_model,scanner,history, andtools/notify_tools. - Adds direct tests for API internals (
_classify_intent,_deep_merge,_snapshot_to_dict) and log persistence helpers. - Expands FastAPI endpoint coverage for chat and a few error/edge cases.
tests/test_coverage_gaps.py
Outdated
| resp = client.post("/api/scan/../../etc/passwd") | ||
| # Should be rejected by validation | ||
| assert resp.status_code in (400, 404) | ||
|
|
||
| def test_toggle_invalid_portal_name(self, client): | ||
| """PUT /api/portals/<invalid>/toggle with special chars returns 400.""" | ||
| resp = client.put( | ||
| "/api/portals/../../evil/toggle", | ||
| json={"enabled": True}, | ||
| ) | ||
| assert resp.status_code in (400, 404) |
There was a problem hiding this comment.
Similar to the scan test: /api/portals/../../evil/toggle likely won’t hit the route handler because the path includes extra segments, so you may only be testing routing (404) rather than the portal-name validation (400). Prefer a single-segment invalid portal name (e.g., evil!) and assert the specific validation status code.
| resp = client.post("/api/scan/../../etc/passwd") | |
| # Should be rejected by validation | |
| assert resp.status_code in (400, 404) | |
| def test_toggle_invalid_portal_name(self, client): | |
| """PUT /api/portals/<invalid>/toggle with special chars returns 400.""" | |
| resp = client.put( | |
| "/api/portals/../../evil/toggle", | |
| json={"enabled": True}, | |
| ) | |
| assert resp.status_code in (400, 404) | |
| resp = client.post("/api/scan/evil!") | |
| # Use a single path segment so the request reaches validation logic. | |
| assert resp.status_code == 400 | |
| def test_toggle_invalid_portal_name(self, client): | |
| """PUT /api/portals/<invalid>/toggle with special chars returns 400.""" | |
| resp = client.put( | |
| "/api/portals/evil!/toggle", | |
| json={"enabled": True}, | |
| ) | |
| # Use a single path segment so the request reaches validation logic. | |
| assert resp.status_code == 400 |
tests/test_coverage_gaps.py
Outdated
| with patch("wiesn_agent.api._scan_portals") as mock_scan: | ||
| mock_scan.return_value = [] | ||
| resp = client.post("/api/chat", json={"message": "scan"}) | ||
| assert resp.status_code == 200 |
There was a problem hiding this comment.
_scan_portals is an async function, but it’s patched with a regular Mock and return_value = []. When the background _run_chat_scan task awaits it, this will raise a TypeError (awaiting a non-awaitable), potentially adding noisy “Scan failed …” entries and making the test less deterministic. Patch with AsyncMock(return_value=[]) (or patch _run_chat_scan / asyncio.create_task to avoid spawning the background task).
There was a problem hiding this comment.
Fixed in 11c3c5e. Changed the mock to AsyncMock(return_value=[]) so _run_chat_scan can await it without a TypeError. Also fixed _classify_intent in api.py to capture the trailing-? flag before stripping punctuation (the heuristic was dead code before), and updated the test to assert the now-correct help return value.
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
…classify_intent Agent-Logs-Url: https://github.com/annawiewer/wiesn-agent/sessions/0f2afbc1-379e-47da-ae64-56df1a6721c7 Co-authored-by: annawiewer <138025423+annawiewer@users.noreply.github.com>
scanner.py:matches_wunsch(),filter_relevant_changes(),AvailabilityChange,PortalSnapshotedge casesapi.py:_classify_intent(),_deep_merge(),_snapshot_to_dict(), log persistence helpers, endpoint edge casesnotify_tools.py:get_apprise()caching, legacy wrappers,should_notify_now()edge caseshistory.py:_prune(), empty stats, error counting, sorted statsconfig_model.py: address fields, config defaults, all-disabled edge casesno_token_envfixture, use module-levelimport os, reduce duplicationtest_chat_keyword_fallback_scan: patch_scan_portalswithAsyncMockso it is awaitable (preventsTypeErrorwhen the background task awaits it)_classify_intentinapi.py: capturetrailing_questionflag before punctuation stripping so the trailing-?→helpheuristic actually fires; update test to asserthelp