Skip to content

add route tests for canvas endpoints - #2209

Open
jaylfc wants to merge 1 commit into
devfrom
exec/tsk-6pf7bz
Open

add route tests for canvas endpoints#2209
jaylfc wants to merge 1 commit into
devfrom
exec/tsk-6pf7bz

Conversation

@jaylfc

@jaylfc jaylfc commented Jul 29, 2026

Copy link
Copy Markdown
Owner

Autonomous build of board card tsk-6pf7bz.

Files:
tests/test_routes_canvas.py | 285 ++++++++++++++++++++++++--------------------
1 file changed, 156 insertions(+), 129 deletions(-)

Summary by CodeRabbit

  • Tests
    • Expanded coverage for canvas creation, retrieval, updates, deletion, and listing.
    • Added validation for canvas field persistence and edit-token handling.
    • Added authorization checks for protected canvas operations.
    • Added coverage for missing canvases and unauthenticated WebSocket connections.
    • Verified authenticated WebSocket connections remain active after joining.

@coderabbitai

coderabbitai Bot commented Jul 29, 2026

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Walkthrough

Canvas route tests now run against a configured FastAPI app with seeded authentication. Coverage verifies canvas creation, persistence, retrieval, updates, authorization failures, deletion, listing, and WebSocket authentication.

Changes

Canvas route tests

Layer / File(s) Summary
Configured application and authentication fixtures
tests/test_routes_canvas.py
Builds a temporary configured app and provides authenticated and unauthenticated clients.
Canvas HTTP lifecycle and persistence
tests/test_routes_canvas.py
Tests creation, stored fields, data retrieval, updates, edit-token checks, and deletion behavior.
Canvas listing and WebSocket access
tests/test_routes_canvas.py
Validates empty and populated listings and authenticated versus unauthenticated WebSocket connections.

Estimated code review effort: 3 (Moderate) | ~20 minutes

Possibly related PRs

  • jaylfc/taOS#1118: Both changes expand HTTP canvas route coverage, with this change also adding configured authentication and WebSocket assertions.
🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately summarizes the main change: adding route tests for canvas endpoints.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches 💡 1
📝 Generate docstrings 💡
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch exec/tsk-6pf7bz

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@gitar-bot

gitar-bot Bot commented Jul 29, 2026

Copy link
Copy Markdown

Important

You are using the Gitar free plan. Upgrade to unlock code review, CI analysis, auto-apply, custom automations, and more.

Gitar

@qodo-code-review

Copy link
Copy Markdown

PR Summary by Qodo

Add route tests for canvas HTTP + WebSocket endpoints

🧪 Tests 🕐 20-40 Minutes

Grey Divider

AI Description

• Expand coverage for canvas create/read/update/delete/list HTTP routes.
• Assert persisted canvas fields plus 404/403 error cases.
• Add /ws/canvas WebSocket auth tests using FastAPI TestClient.
Diagram

graph TD
T["tests/test_routes_canvas.py"] --> AC["Async HTTP client"] --> R["Canvas HTTP routes"] --> S["CanvasStore"] --> H["ChatHub"]
T --> TC["TestClient (WS)"] --> WSR["Canvas WS route"] --> AM["AuthManager"] --> H
Loading
High-Level Assessment

The following are alternative approaches to this PR:

1. Factor shared WS app/client fixtures into conftest.py
  • ➕ Avoids duplicating _make_app/_make_client patterns across ws-related test modules
  • ➕ Keeps auth-cookie/session setup consistent in one place
  • ➖ Introduces shared test infrastructure that may be less explicit per-test-file
  • ➖ May require touching multiple test files to migrate
2. Rely on existing tests/test_ws_auth.py for /ws/canvas coverage
  • ➕ Prevents overlapping WebSocket auth coverage across test suites
  • ➕ Keeps route tests focused on HTTP semantics
  • ➖ Canvas route suite becomes less self-contained
  • ➖ Harder to discover WS expectations when working only on canvas routes

Recommendation: Current approach (using FastAPI TestClient for WebSocket coverage) is appropriate because the async HTTP client fixture can’t open WS connections. Consider extracting the duplicated app/auth TestClient setup into a shared fixture if more endpoint test files add WS coverage, to reduce repetition and keep session-cookie semantics consistent.

Files changed (1) +156 / -129

Tests (1) +156 / -129
test_routes_canvas.pyRework canvas route tests and add WebSocket auth coverage +156/-129

Rework canvas route tests and add WebSocket auth coverage

• Refactors and expands REST endpoint tests for canvas generate/data/update/delete/list with clearer assertions around persistence and error codes. Adds FastAPI TestClient-based fixtures to test /ws/canvas authentication behavior (1008 on missing cookie, connection accepted with valid session). Removes prior hub.broadcast mocking in favor of end-to-end route behavior checks.

tests/test_routes_canvas.py

@jaylfc

jaylfc commented Jul 29, 2026

Copy link
Copy Markdown
Owner Author

nemotron-super review

VERDICT: Blocking issues found.

  • tests/test_routes_canvas.py:69

Automated first-pass review by the nemotron-super lane. The lead still reviews before merge.

@jaylfc

jaylfc commented Jul 29, 2026

Copy link
Copy Markdown
Owner Author

nemotron-ultra-orB review

VERDICT: Test refactor improves structure and adds WebSocket auth tests, but one test makes unverified assumptions about response fields.

  • tests/test_routes_canvas.py:119 test_get_canvas_data_returns_fields asserts keys content, style, format, created_by exist on a canvas created with only {"title": "T"} — these fields may be absent or null depending on API defaults, making the test fragile.
  • tests/test_routes_canvas.py:183 test_ws_canvas_authenticated_accepted connects to a non-existent canvas ID (test-canvas-id) and only verifies the connection stays open — doesn't validate hub join logic or canvas existence checks.
  • tests/test_routes_canvas.py:96 test_create_canvas_stores_values uses format: "html" — should confirm this is a valid enum value accepted by the API (vs. only markdown).
  • Removed patch.object(hub, "broadcast") from update tests — if the endpoint still calls hub.broadcast, tests may fail or produce noise; verify the broadcast call was removed from the route handler or add the mock back.

Automated first-pass review by the nemotron-ultra-orB lane. The lead still reviews before merge.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@tests/test_routes_canvas.py`:
- Line 19: Update the “server” host value in the test configuration to use the
loopback address 127.0.0.1 instead of the wildcard address 0.0.0.0, while
preserving the existing port.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: 7c7d0e5c-e672-4cb8-88fc-90257176849c

📥 Commits

Reviewing files that changed from the base of the PR and between 6dda472 and 42b4566.

📒 Files selected for processing (1)
  • tests/test_routes_canvas.py

from tinyagentos.app import create_app

config = {
"server": {"host": "0.0.0.0", "port": 6969},

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔒 Security & Privacy | 🟡 Minor | ⚡ Quick win

Use a loopback address in the test config.

0.0.0.0 triggers Ruff S104. TestClient does not need a wildcard listener; use 127.0.0.1 instead.

Proposed fix
-        "server": {"host": "0.0.0.0", "port": 6969},
+        "server": {"host": "127.0.0.1", "port": 6969},
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
"server": {"host": "0.0.0.0", "port": 6969},
"server": {"host": "127.0.0.1", "port": 6969},
🧰 Tools
🪛 Ruff (0.16.0)

[error] 19-19: Possible binding to all interfaces

(S104)

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@tests/test_routes_canvas.py` at line 19, Update the “server” host value in
the test configuration to use the loopback address 127.0.0.1 instead of the
wildcard address 0.0.0.0, while preserving the existing port.

Source: Linters/SAST tools

@jaylfc

jaylfc commented Jul 29, 2026

Copy link
Copy Markdown
Owner Author

nemotron-ultra-kilo review

VERDICT: Significant test coverage improvements but introduces test isolation issues and potential flakiness.

  • tests/test_routes_canvas.py:13-35 - _make_client creates a fresh app per test but uses module-level imports inside the function (from tinyagentos.app import create_app, import yaml). This is fine for isolation but unconventional; consider moving imports to module top.

  • tests/test_routes_canvas.py:37-52 - ws_app, unauthed_client, authed_client fixtures create new app instances per test via tmp_path. Good isolation, but authed_client calls ws_app.state.auth.setup_user("admin", "Admin", "", "adminpass") on every test run — this mutates shared state if fixtures are session-scoped (they're function-scoped here, so OK).

  • tests/test_routes_canvas.py:58 - test_create_canvas_returns_200 now only sends {"title": "Test"} vs original full payload. If the endpoint requires other fields, this test may pass incorrectly. Original test validated full request shape.

  • tests/test_routes_canvas.py:73-83 - test_create_canvas_stores_values asserts stored["edit_token"] == edit_token but the GET /data endpoint may not return edit_token (security: edit tokens should not be readable via GET). This could be a test bug or an API leak.

  • tests/test_routes_canvas.py:103-106 - test_get_canvas_data_returns_fields checks for "created_by" key but the original test didn't include this. If the field doesn't exist, test fails — need to verify API contract.

  • tests/test_routes_canvas.py:145-146 - test_delete_canvas_happy_path adds follow_up = await client.get(...) asserting 404. Good — verifies actual deletion.

  • tests/test_routes_canvas.py:157-163 - test_list_canvases_empty_by_default assumes empty list. If tests run in parallel or fixture cleanup fails, this becomes flaky. Should create/cleanup explicitly or use unique prefixes.

  • tests/test_routes_canvas.py:165-173 - test_list_canvases_returns_created creates a canvas but doesn't clean it up. Subsequent tests may see it, breaking test_list_canvases_empty_by_default if run after.

  • tests/test_routes_canvas.py:178-192 - WebSocket tests use unauthed_client/authed_client fixtures which create full apps. test_ws_canvas_unauthenticated_rejected expects WebSocketDisconnect with code 1008 but catches it via pytest.raises around the context manager — this won't work because websocket_connect returns a context manager, the exception is raised inside the with block, not at construction. The test will hang or fail incorrectly.

  • tests/test_routes_canvas.py:194-198 - test_ws_canvas_authenticated_accepted sends "ping" but doesn't verify any response or behavior. Weak assertion — connection staying open is not a strong test.

  • Missing tests: No test for WebSocket message broadcasting, concurrent updates, edit token rotation, or authorization boundaries (e.g., user A cannot update user B's canvas).

  • Style: Inconsistent naming — some tests use client fixture (async), others use unauthed_client/authed_client (sync TestClient). This mixes async/sync test patterns confusingly.
    VERDICT: Significant test coverage improvements but introduces test isolation issues and potential flakiness.

  • tests/test_routes_canvas.py:13-35 - _make_client creates a fresh app per test but uses module-level imports inside the function (from tinyagentos.app import create_app, import yaml). This is fine for isolation but unconventional; consider moving imports to module top.

  • tests/test_routes_canvas.py:37-52 - ws_app, unauthed_client, authed_client fixtures create new app instances per test via tmp_path. Good isolation, but authed_client calls ws_app.state.auth.setup_user("admin", "Admin", "", "adminpass") on every test run — this mutates shared state if fixtures are session-scoped (they're function-scoped here, so OK).

  • tests/test_routes_canvas.py:58 - test_create_canvas_returns_200 now only sends {"title": "Test"} vs original full payload. If the endpoint requires other fields, this test may pass incorrectly. Original test validated full request shape.

  • tests/test_routes_canvas.py:73-83 - test_create_canvas_stores_values asserts stored["edit_token"] == edit_token but the GET /data endpoint may not return edit_token (security: edit tokens should not be readable via GET). This could be a test bug or an API leak.

  • tests/test_routes_canvas.py:103-106 - test_get_canvas_data_returns_fields checks for "created_by" key but the original test didn't include this. If the field doesn't exist, test fails — need to verify API contract.

  • tests/test_routes_canvas.py:145-146 - test_delete_canvas_happy_path adds follow_up = await client.get(...) asserting 404. Good — verifies actual deletion.

  • tests/test_routes_canvas.py:157-163 - test_list_canvases_empty_by_default assumes empty list. If tests run in parallel or fixture cleanup fails, this becomes flaky. Should create/cleanup explicitly or use unique prefixes.

  • tests/test_routes_canvas.py:165-173 - test_list_canvases_returns_created creates a canvas but doesn't clean it up. Subsequent tests may see it, breaking test_list_canvases_empty_by_default if run after.

  • tests/test_routes_canvas.py:178-192 - WebSocket tests use unauthed_client/authed_client fixtures which create full apps. test_ws_canvas_unauthenticated_rejected expects WebSocketDisconnect with code 1008 but catches it via pytest.raises around the context manager — this won't work because websocket_connect returns a context manager, the exception is raised inside the with block, not at construction. The test will hang or fail incorrectly.

  • tests/test_routes_canvas.py:194-198 - test_ws_canvas_authenticated_accepted sends "ping" but doesn't verify any response or behavior. Weak assertion — connection staying open is not a strong test.

  • Missing tests: No test for WebSocket message broadcasting, concurrent updates, edit token rotation, or authorization boundaries (e.g., user A cannot update user B's canvas).

  • Style: Inconsistent naming — some tests use client fixture (async), others use unauthed_client/authed_client (sync TestClient). This mixes async/sync test patterns confusingly.

Automated first-pass review by the nemotron-ultra-kilo lane. The lead still reviews before merge.

@qodo-code-review

Copy link
Copy Markdown

Code Review by Qodo

🐞 Bugs (2) 📘 Rule violations (0) 📜 Skill insights (1)

Context used
✅ Compliance rules (platform): 35 rules

Grey Divider


Action required

1. Hardcoded adminpass test password 📜 Skill insight ⛨ Security
Description
The test helper hardcodes a password value (adminpass) in source code. This violates the
requirement to avoid storing credentials in code/config and increases the risk of accidental reuse
or leakage.
Code

tests/test_routes_canvas.py[R29-31]

+    app = create_app(data_dir=tmp_path)
+    app.state.auth.setup_user("admin", "Admin", "", "adminpass")
+    return app
Relevance

●● Moderate

No clear precedent banning literal test passwords; only related S106 suppression discussion (PR
#300).

PR-#300

ⓘ Recommendations generated based on similar findings in past PRs

Evidence
PR Compliance ID 2185205 prohibits hardcoded credentials in source files. The added test helper
calls setup_user(...) with a literal password string (adminpass).

tests/test_routes_canvas.py[29-31]
Skill: taos-development-skill

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
`tests/test_routes_canvas.py` hardcodes a password (`adminpass`) when creating the test admin user.

## Issue Context
Compliance requires that credentials (passwords/tokens/keys) are not hardcoded in source files; even in tests, use a generated ephemeral value or a secrets-store-backed value.

## Fix Focus Areas
- tests/test_routes_canvas.py[29-31]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools



Remediation recommended

2. WS fixtures run full lifespan 🐞 Bug ➹ Performance
Description
The new ws_app/authed_client/unauthed_client fixtures build a full create_app() and wrap it in
TestClient, which runs the full FastAPI lifespan (initializing many stores and starting background
services). This makes these canvas tests significantly heavier than the existing async client
fixture pattern that bypasses lifespan, increasing test runtime and the risk of lifecycle-related
flakes.
Code

tests/test_routes_canvas.py[R15-51]

+def _make_client(tmp_path):
+    from tinyagentos.app import create_app
+
+    config = {
+        "server": {"host": "0.0.0.0", "port": 6969},
+        "backends": [],
+        "qmd": {"url": "http://localhost:7832"},
+        "agents": [],
+        "metrics": {"poll_interval": 30, "retention_days": 30},
+    }
+    import yaml
+
+    (tmp_path / "config.yaml").write_text(yaml.dump(config))
+    (tmp_path / ".setup_complete").touch()
+    app = create_app(data_dir=tmp_path)
+    app.state.auth.setup_user("admin", "Admin", "", "adminpass")
+    return app
+
+
+@pytest.fixture()
+def ws_app(tmp_path):
+    return _make_client(tmp_path)
+
+
+@pytest.fixture()
+def unauthed_client(ws_app):
+    with TestClient(ws_app, raise_server_exceptions=False) as c:
+        yield c
+
+
+@pytest.fixture()
+def authed_client(ws_app):
+    record = ws_app.state.auth.find_user("admin")
+    token = ws_app.state.auth.create_session(user_id=record["id"], long_lived=True)
+    with TestClient(ws_app, raise_server_exceptions=False) as c:
+        c.cookies.set("taos_session", token)
+        yield c
Relevance

●●● Strong

Team routinely optimizes/unflakes tests; fixture/lifespan fixes landed (PR #708, #388, #263).

PR-#708
PR-#388
PR-#263

ⓘ Recommendations generated based on similar findings in past PRs

Evidence
The PR fixtures explicitly create an app via create_app() and then enter a TestClient context,
which runs the app lifespan. The app lifespan performs extensive initialization and starts
background services; the core async test client fixture in tests bypasses lifespan and sets
_startup_complete manually, highlighting that full lifespan is intentionally avoided elsewhere for
test efficiency/stability.

tests/test_routes_canvas.py[15-51]
tinyagentos/app.py[503-520]
tinyagentos/app.py[960-1016]
tests/conftest.py[279-466]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
WebSocket tests in `tests/test_routes_canvas.py` create a full application via `create_app()` and run it under `TestClient`, triggering the full app lifespan (large init + background services). This is disproportionate for validating the `/ws/canvas/{canvas_id}` auth gate.

## Issue Context
`tinyagentos.app.create_app()` defines a lifespan that initializes many stores and starts background services (cluster manager, backend catalog, provider refresher, etc.). The main async `client` fixture in `tests/conftest.py` explicitly bypasses lifespan and manually initializes only what’s needed.

## Fix Focus Areas
- tests/test_routes_canvas.py[15-51]
- tinyagentos/app.py[503-520]
- tinyagentos/app.py[960-1016]
- tests/conftest.py[279-466]

## Implementation notes
Choose one:
1) Remove these WS tests (preferred if redundant with `tests/test_ws_auth.py`).
2) If you keep WS tests here, avoid full `create_app()`:
  - Build a minimal `FastAPI()` instance.
  - Attach `app.state.auth = AuthManager(tmp_path)` and `app.state.chat_hub = ChatHub()`.
  - Include only `tinyagentos.routes.canvas.router`.
  - Then use `TestClient(minimal_app)` for websocket_connect.
This keeps the test scoped to the endpoint under test and avoids the expensive global lifespan.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


3. Duplicate canvas WS auth tests 🐞 Bug ⚙ Maintainability
Description
tests/test_routes_canvas.py adds /ws/canvas unauthenticated/authenticated tests that already exist
in tests/test_ws_auth.py, creating redundant coverage and two places to update expected close
codes/behavior. This increases suite runtime and maintenance burden with no additional assertions
beyond what’s already covered.
Code

tests/test_routes_canvas.py[R213-223]

+def test_ws_canvas_unauthenticated_rejected(unauthed_client):
+    with pytest.raises(WebSocketDisconnect) as exc_info:
+        with unauthed_client.websocket_connect("/ws/canvas/test-canvas-id") as ws:
+            ws.receive_text()
+    assert exc_info.value.code == 1008


-# WebSocket endpoint (/ws/canvas/{canvas_id}) requires a live WebSocket
-# connection and real-time hub interaction; skipped as it needs an external
-# transport not available through the async HTTP client fixture.
+def test_ws_canvas_authenticated_accepted(authed_client):
+    with authed_client.websocket_connect("/ws/canvas/test-canvas-id") as ws:
+        ws.send_text("ping")
+        # Connection staying open means auth passed and hub.join succeeded.
Relevance

●● Moderate

No historical evidence found about removing redundant tests; no similar accepted/rejected findings
located.

ⓘ Recommendations generated based on similar findings in past PRs

Evidence
The PR adds two WS auth tests in test_routes_canvas.py, but an existing test module already
exercises the same endpoint/auth outcomes (1008 on unauthenticated, authenticated connect succeeds).

tests/test_routes_canvas.py[213-223]
tests/test_ws_auth.py[127-149]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
`tests/test_routes_canvas.py` adds WebSocket auth tests for `/ws/canvas/{canvas_id}` that duplicate existing coverage in `tests/test_ws_auth.py`, increasing runtime and maintenance burden.

## Issue Context
There is already a dedicated WebSocket auth test module that covers unauthenticated, invalid-session, and authenticated connects for `/ws/canvas/test-canvas-id`.

## Fix Focus Areas
- tests/test_routes_canvas.py[213-223]
- tests/test_ws_auth.py[127-149]

## Implementation notes
- Prefer removing the redundant `test_ws_canvas_*` tests from `tests/test_routes_canvas.py`.
- If the intent is canvas-specific WS behavior (not just auth), replace the duplicated auth checks with a distinct assertion (e.g., connect, trigger an update broadcast, and assert the WS receives a `canvas_update` event).

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


Grey Divider

To customize comments, go to the Qodo configuration screen, or learn more in the docs.

Qodo Logo

Comment on lines +29 to +31
app = create_app(data_dir=tmp_path)
app.state.auth.setup_user("admin", "Admin", "", "adminpass")
return app

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Action required

1. Hardcoded adminpass test password 📜 Skill insight ⛨ Security

The test helper hardcodes a password value (adminpass) in source code. This violates the
requirement to avoid storing credentials in code/config and increases the risk of accidental reuse
or leakage.
Agent Prompt
## Issue description
`tests/test_routes_canvas.py` hardcodes a password (`adminpass`) when creating the test admin user.

## Issue Context
Compliance requires that credentials (passwords/tokens/keys) are not hardcoded in source files; even in tests, use a generated ephemeral value or a secrets-store-backed value.

## Fix Focus Areas
- tests/test_routes_canvas.py[29-31]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools

Comment on lines +213 to +223
def test_ws_canvas_unauthenticated_rejected(unauthed_client):
with pytest.raises(WebSocketDisconnect) as exc_info:
with unauthed_client.websocket_connect("/ws/canvas/test-canvas-id") as ws:
ws.receive_text()
assert exc_info.value.code == 1008


# WebSocket endpoint (/ws/canvas/{canvas_id}) requires a live WebSocket
# connection and real-time hub interaction; skipped as it needs an external
# transport not available through the async HTTP client fixture.
def test_ws_canvas_authenticated_accepted(authed_client):
with authed_client.websocket_connect("/ws/canvas/test-canvas-id") as ws:
ws.send_text("ping")
# Connection staying open means auth passed and hub.join succeeded.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Remediation recommended

2. Duplicate canvas ws auth tests 🐞 Bug ⚙ Maintainability

tests/test_routes_canvas.py adds /ws/canvas unauthenticated/authenticated tests that already exist
in tests/test_ws_auth.py, creating redundant coverage and two places to update expected close
codes/behavior. This increases suite runtime and maintenance burden with no additional assertions
beyond what’s already covered.
Agent Prompt
## Issue description
`tests/test_routes_canvas.py` adds WebSocket auth tests for `/ws/canvas/{canvas_id}` that duplicate existing coverage in `tests/test_ws_auth.py`, increasing runtime and maintenance burden.

## Issue Context
There is already a dedicated WebSocket auth test module that covers unauthenticated, invalid-session, and authenticated connects for `/ws/canvas/test-canvas-id`.

## Fix Focus Areas
- tests/test_routes_canvas.py[213-223]
- tests/test_ws_auth.py[127-149]

## Implementation notes
- Prefer removing the redundant `test_ws_canvas_*` tests from `tests/test_routes_canvas.py`.
- If the intent is canvas-specific WS behavior (not just auth), replace the duplicated auth checks with a distinct assertion (e.g., connect, trigger an update broadcast, and assert the WS receives a `canvas_update` event).

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools

Comment on lines +15 to +51
def _make_client(tmp_path):
from tinyagentos.app import create_app

config = {
"server": {"host": "0.0.0.0", "port": 6969},
"backends": [],
"qmd": {"url": "http://localhost:7832"},
"agents": [],
"metrics": {"poll_interval": 30, "retention_days": 30},
}
import yaml

(tmp_path / "config.yaml").write_text(yaml.dump(config))
(tmp_path / ".setup_complete").touch()
app = create_app(data_dir=tmp_path)
app.state.auth.setup_user("admin", "Admin", "", "adminpass")
return app


@pytest.fixture()
def ws_app(tmp_path):
return _make_client(tmp_path)


@pytest.fixture()
def unauthed_client(ws_app):
with TestClient(ws_app, raise_server_exceptions=False) as c:
yield c


@pytest.fixture()
def authed_client(ws_app):
record = ws_app.state.auth.find_user("admin")
token = ws_app.state.auth.create_session(user_id=record["id"], long_lived=True)
with TestClient(ws_app, raise_server_exceptions=False) as c:
c.cookies.set("taos_session", token)
yield c

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Remediation recommended

3. Ws fixtures run full lifespan 🐞 Bug ➹ Performance

The new ws_app/authed_client/unauthed_client fixtures build a full create_app() and wrap it in
TestClient, which runs the full FastAPI lifespan (initializing many stores and starting background
services). This makes these canvas tests significantly heavier than the existing async client
fixture pattern that bypasses lifespan, increasing test runtime and the risk of lifecycle-related
flakes.
Agent Prompt
## Issue description
WebSocket tests in `tests/test_routes_canvas.py` create a full application via `create_app()` and run it under `TestClient`, triggering the full app lifespan (large init + background services). This is disproportionate for validating the `/ws/canvas/{canvas_id}` auth gate.

## Issue Context
`tinyagentos.app.create_app()` defines a lifespan that initializes many stores and starts background services (cluster manager, backend catalog, provider refresher, etc.). The main async `client` fixture in `tests/conftest.py` explicitly bypasses lifespan and manually initializes only what’s needed.

## Fix Focus Areas
- tests/test_routes_canvas.py[15-51]
- tinyagentos/app.py[503-520]
- tinyagentos/app.py[960-1016]
- tests/conftest.py[279-466]

## Implementation notes
Choose one:
1) Remove these WS tests (preferred if redundant with `tests/test_ws_auth.py`).
2) If you keep WS tests here, avoid full `create_app()`:
   - Build a minimal `FastAPI()` instance.
   - Attach `app.state.auth = AuthManager(tmp_path)` and `app.state.chat_hub = ChatHub()`.
   - Include only `tinyagentos.routes.canvas.router`.
   - Then use `TestClient(minimal_app)` for websocket_connect.
This keeps the test scoped to the endpoint under test and avoids the expensive global lifespan.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools

@kilo-code-bot

kilo-code-bot Bot commented Jul 29, 2026

Copy link
Copy Markdown

Code Review Summary

Status: No Issues Found | Recommendation: Merge

Files Reviewed (1 files)
  • tests/test_routes_canvas.py

Reviewed by step-3.7-flash · Input: 202.6K · Output: 20.5K · Cached: 1.2M

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant