Skip to content

Add route tests for torrent - #2249

Merged
jaylfc merged 1 commit into
devfrom
exec/tsk-j7dgjw
Aug 3, 2026
Merged

Add route tests for torrent#2249
jaylfc merged 1 commit into
devfrom
exec/tsk-j7dgjw

Conversation

@jaylfc

@jaylfc jaylfc commented Aug 3, 2026

Copy link
Copy Markdown
Owner

CARD TITLE (intent, not commit subject): Add route tests for torrent

Autonomous build of board card tsk-j7dgjw.

Files:
tests/test_routes_torrent.py | 81 ++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 81 insertions(+)

Summary by CodeRabbit

  • Tests
    • Added coverage for retrieving and updating torrent settings.
    • Added validation checks for response fields and invalid upload limits.
    • Added error handling tests for unavailable settings services.

@gitar-bot

gitar-bot Bot commented Aug 3, 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

@coderabbitai

coderabbitai Bot commented Aug 3, 2026

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Walkthrough

Added asynchronous route tests for torrent settings retrieval and updates. The tests also cover response types, persisted values, unavailable settings storage, and invalid upload limits.

Changes

Torrent settings route coverage

Layer / File(s) Summary
Torrent settings endpoint tests
tests/test_routes_torrent.py
Tests cover successful GET and PUT responses, response fields and types, persisted update values, 503 store errors, and 422 validation errors.

Estimated code review effort: 2 (Simple) | ~10 minutes

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly and concisely describes the added torrent route tests.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
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
📝 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-j7dgjw

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.

@qodo-code-review

Copy link
Copy Markdown

PR Summary by Qodo

Add route tests for torrent settings endpoints

🧪 Tests 🕐 20-40 Minutes

Grey Divider

AI Description

• Add async route tests covering GET/PUT /api/torrent/settings success paths.
• Validate response schema/types and persisted settings echo on save.
• Assert error handling for missing store (503) and invalid payloads (422).
Diagram

graph TD
  T["Pytest async tests"] --> C["Test client"] --> R["/api/torrent/settings"] --> A["App state"] --> ST[("Torrent settings store")]
  R --> E["503/422 errors"]
Loading
High-Level Assessment

The following are alternative approaches to this PR:

1. Provide a dedicated fixture to inject torrent_settings_store
  • ➕ Avoids reaching into private attributes like download_manager._torrent_settings_store
  • ➕ Reduces per-test monkeypatch repetition and tight coupling to app internals
  • ➖ Requires additional test fixture plumbing (possibly in conftest.py)
  • ➖ May need minor refactor of app setup to make injection straightforward
2. Use FastAPI dependency overrides (or equivalent) for the store
  • ➕ More idiomatic route dependency testing; isolates tests from app.state layout
  • ➕ Clearer separation between route wiring and store implementation
  • ➖ Only applicable if the route uses DI patterns; may require refactoring route code
  • ➖ Could diverge from true integration behavior if overrides differ from production wiring
3. Split into route-unit tests plus a smaller integration smoke test
  • ➕ Unit tests can assert edge cases without app wiring complexity
  • ➕ Integration test can focus on just 200/503 coverage
  • ➖ More test files and structure; overhead for a small endpoint
  • ➖ May reduce confidence in end-to-end request validation behavior

Recommendation: Current approach is acceptable as lightweight integration coverage (status codes + schema) and matches how the route resolves its store today. If this endpoint is expected to evolve, consider introducing a small fixture or DI override to inject torrent_settings_store, so tests don’t depend on private app internals (_torrent_settings_store) and remain stable across refactors.

Files changed (1) +81 / -0

Tests (1) +81 / -0
test_routes_torrent.pyAdd async route tests for torrent settings GET/PUT +81/-0

Add async route tests for torrent settings GET/PUT

• Introduces pytest-asyncio tests for /api/torrent/settings covering success responses, response shape/type assertions, and error cases for missing store (503) and invalid payload validation (422). Uses monkeypatch to inject/remove torrent_settings_store on app.state for dependency control.

tests/test_routes_torrent.py

@jaylfc

jaylfc commented Aug 3, 2026

Copy link
Copy Markdown
Owner Author

Reviewed: genuine gap filled - existing torrent tests were store/unit-level only (zero route calls); this adds real-caller route coverage with proper negatives (503 store-missing with exact error, 422 validation). Verified app.py:835 does bind torrent_settings_store in prod, so the fixture graft is compensating for the test app's lifespan, not masking a wiring hole - the grafted object is the same store instance prod binds. Nit only, not blocking: if the client fixture ran the full lifespan the graft would be unnecessary. Merging on green.

@jaylfc
jaylfc enabled auto-merge (squash) August 3, 2026 00:11

@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_torrent.py`:
- Around line 56-62: Extend the test after the existing PUT response assertions
by sending a GET request to the same torrent settings endpoint and asserting a
successful response. Parse the GET payload and verify seed_enabled,
upload_rate_limit_kbps, and max_active_seeds match the values submitted,
confirming persistence through the settings store.
🪄 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: aca1cb96-c229-44e7-98ec-21f1484b2a4c

📥 Commits

Reviewing files that changed from the base of the PR and between 9d9feae and 05b9c81.

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

Comment on lines +56 to +62
resp = await client.put("/api/torrent/settings", json=body)
assert resp.status_code == 200
data = resp.json()
assert data["status"] == "saved"
assert data["seed_enabled"] is False
assert data["upload_rate_limit_kbps"] == 2048
assert data["max_active_seeds"] == 5

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Verify the persisted settings after the PUT request.

The test only checks the PUT response. A route can return these values without writing them to the settings store. Send a GET request after Line 62 and assert the saved values.

Proposed test update
     assert data["seed_enabled"] is False
     assert data["upload_rate_limit_kbps"] == 2048
     assert data["max_active_seeds"] == 5
+
+    persisted = (await client.get("/api/torrent/settings")).json()
+    assert persisted["seed_enabled"] is False
+    assert persisted["upload_rate_limit_kbps"] == 2048
+    assert persisted["max_active_seeds"] == 5
📝 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
resp = await client.put("/api/torrent/settings", json=body)
assert resp.status_code == 200
data = resp.json()
assert data["status"] == "saved"
assert data["seed_enabled"] is False
assert data["upload_rate_limit_kbps"] == 2048
assert data["max_active_seeds"] == 5
resp = await client.put("/api/torrent/settings", json=body)
assert resp.status_code == 200
data = resp.json()
assert data["status"] == "saved"
assert data["seed_enabled"] is False
assert data["upload_rate_limit_kbps"] == 2048
assert data["max_active_seeds"] == 5
persisted = (await client.get("/api/torrent/settings")).json()
assert persisted["seed_enabled"] is False
assert persisted["upload_rate_limit_kbps"] == 2048
assert persisted["max_active_seeds"] == 5
🤖 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_torrent.py` around lines 56 - 62, Extend the test after the
existing PUT response assertions by sending a GET request to the same torrent
settings endpoint and asserting a successful response. Parse the GET payload and
verify seed_enabled, upload_rate_limit_kbps, and max_active_seeds match the
values submitted, confirming persistence through the settings store.

@jaylfc

jaylfc commented Aug 3, 2026

Copy link
Copy Markdown
Owner Author

nemotron-ultra-kilo review

VERDICT: Tests are functional but have significant brittleness and coverage gaps.

  • tests/test_routes_torrent.py:17-19: Direct access to private attributes (_transport, _torrent_settings_store) makes tests fragile to refactoring; should use a proper test fixture or public API

  • tests/test_routes_torrent.py:68-73: test_put_torrent_settings_422_on_invalid_body doesn't monkeypatch store — test may return 503 instead of 422 depending on fixture state, making it flaky

  • tests/test_routes_torrent.py: Missing validation tests for max_active_seeds (negative, zero, non-int), seed_enabled (non-bool), missing required fields, and extra fields in request body

  • tests/test_routes_torrent.py:17-19, 31-33, 44-46, 55-57, 69-71: Repeated store setup boilerplate across 5 tests — should be extracted to a fixture

  • tests/test_routes_torrent.py: Magic numbers (2048, 5, -1) used without constants or explanation
    VERDICT: Tests are functional but have significant brittleness and coverage gaps.

  • tests/test_routes_torrent.py:17-19: Direct access to private attributes (_transport, _torrent_settings_store) makes tests fragile to refactoring; should use a proper test fixture or public API

  • tests/test_routes_torrent.py:68-73: test_put_torrent_settings_422_on_invalid_body doesn't monkeypatch store — test may return 503 instead of 422 depending on fixture state, making it flaky

  • tests/test_routes_torrent.py: Missing validation tests for max_active_seeds (negative, zero, non-int), seed_enabled (non-bool), missing required fields, and extra fields in request body

  • tests/test_routes_torrent.py:17-19, 31-33, 44-46, 55-57, 69-71: Repeated store setup boilerplate across 5 tests — should be extracted to a fixture

  • tests/test_routes_torrent.py: Magic numbers (2048, 5, -1) used without constants or explanation

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

@jaylfc

jaylfc commented Aug 3, 2026

Copy link
Copy Markdown
Owner Author

nemotron-ultra-orB review

VERDICT: Tests cover basic happy/error paths but have fragile setup, missing validation cases, and potential state leakage.

  • tests/test_routes_torrent.py:13-14 — Fragile test setup accessing private attributes (_transport, _torrent_settings_store); breaks if internals change
  • tests/test_routes_torrent.py:13-14,24-25,38-39,50-51 — Repeated monkeypatch boilerplate should be a fixture; raising=False masks missing attribute bugs
  • tests/test_routes_torrent.py:64-71 — Only tests negative upload_rate_limit_kbps for 422; missing: non-boolean seed_enabled, non-integer/negative/zero max_active_seeds, extra fields, missing required fields
  • tests/test_routes_torrent.py:50-51 — No store reset between tests; PUT test mutates store state that subsequent GET tests may depend on (state leakage)
  • tests/test_routes_torrent.py:24-32 — No test for partial PUT body (only some fields provided)
  • tests/test_routes_torrent.py:38-39 — No test for GET when store exists but throws/returns error

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

@qodo-code-review

Copy link
Copy Markdown

Code Review by Qodo

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

Context used
✅ Compliance rules (platform): 35 rules

Grey Divider


Remediation recommended

1. Private test internals 🐞 Bug ⚙ Maintainability
Description
The new tests depend on private implementation details (client._transport.app and
DownloadManager._torrent_settings_store), which makes the test suite fragile to httpx/transport
changes and internal refactors. This can cause CI failures even when the actual torrent settings API
behavior remains correct.
Code

tests/test_routes_torrent.py[R10-13]

+    store = client._transport.app.state.download_manager._torrent_settings_store
+    monkeypatch.setattr(
+        client._transport.app.state, "torrent_settings_store", store, raising=False
+    )
Relevance

●● Moderate

No direct precedent on client._transport/private attrs; team accepts many test robustness
refactors (PR234,449).

PR-#234
PR-#449

ⓘ Recommendations generated based on similar findings in past PRs

Evidence
The test file repeatedly accesses httpx and DownloadManager private attributes; the repo’s client
fixture already exposes app as a fixture (and uses ASGITransport(app=app) internally), so tests
can safely patch app.state without relying on client._transport. DownloadManager stores the
torrent settings store in a private _torrent_settings_store attribute, which tests should not
depend on.

tests/test_routes_torrent.py[8-13]
tests/test_routes_torrent.py[45-50]
tests/conftest.py[273-277]
tests/conftest.py[467-473]
tinyagentos/download_manager.py[28-33]

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_torrent.py` accesses `client._transport.app` (httpx private field) and `download_manager._torrent_settings_store` (DownloadManager private field) to reach `app.state` and the torrent settings store. This creates brittle tests that can break on dependency upgrades or refactors unrelated to route correctness.

### Issue Context
- The route under test reads the store via `getattr(request.app.state, "torrent_settings_store", None)`.
- The `client` fixture constructs an `AsyncClient(transport=ASGITransport(app=app), ...)` but tests should not rely on `AsyncClient._transport` being present or having an `.app` attribute.

### Fix Focus Areas
- tests/test_routes_torrent.py[8-13]
- tests/test_routes_torrent.py[18-24]
- tests/test_routes_torrent.py[35-40]
- tests/test_routes_torrent.py[45-50]
- tests/test_routes_torrent.py[65-70]

### Suggested fix
1. Add the `app` fixture to the tests’ parameters (pytest will provide the *same* `app` instance used by `client`, since `client` depends on `app`).
2. Patch `app.state.torrent_settings_store` directly via `monkeypatch` (no `client._transport` access).
3. Avoid `download_manager._torrent_settings_store` by creating a store explicitly:

```py
from tinyagentos.torrent_settings import TorrentSettingsStore

store = TorrentSettingsStore(app.state.data_dir / "torrent_settings.json")
monkeypatch.setattr(app.state, "torrent_settings_store", store, raising=False)
```

This keeps the tests aligned to the public contract: routes read the store from `app.state.torrent_settings_store`.

ⓘ 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 +10 to +13
store = client._transport.app.state.download_manager._torrent_settings_store
monkeypatch.setattr(
client._transport.app.state, "torrent_settings_store", store, raising=False
)

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

1. Private test internals 🐞 Bug ⚙ Maintainability

The new tests depend on private implementation details (client._transport.app and
DownloadManager._torrent_settings_store), which makes the test suite fragile to httpx/transport
changes and internal refactors. This can cause CI failures even when the actual torrent settings API
behavior remains correct.
Agent Prompt
### Issue description
`tests/test_routes_torrent.py` accesses `client._transport.app` (httpx private field) and `download_manager._torrent_settings_store` (DownloadManager private field) to reach `app.state` and the torrent settings store. This creates brittle tests that can break on dependency upgrades or refactors unrelated to route correctness.

### Issue Context
- The route under test reads the store via `getattr(request.app.state, "torrent_settings_store", None)`.
- The `client` fixture constructs an `AsyncClient(transport=ASGITransport(app=app), ...)` but tests should not rely on `AsyncClient._transport` being present or having an `.app` attribute.

### Fix Focus Areas
- tests/test_routes_torrent.py[8-13]
- tests/test_routes_torrent.py[18-24]
- tests/test_routes_torrent.py[35-40]
- tests/test_routes_torrent.py[45-50]
- tests/test_routes_torrent.py[65-70]

### Suggested fix
1. Add the `app` fixture to the tests’ parameters (pytest will provide the *same* `app` instance used by `client`, since `client` depends on `app`).
2. Patch `app.state.torrent_settings_store` directly via `monkeypatch` (no `client._transport` access).
3. Avoid `download_manager._torrent_settings_store` by creating a store explicitly:

```py
from tinyagentos.torrent_settings import TorrentSettingsStore

store = TorrentSettingsStore(app.state.data_dir / "torrent_settings.json")
monkeypatch.setattr(app.state, "torrent_settings_store", store, raising=False)
```

This keeps the tests aligned to the public contract: routes read the store from `app.state.torrent_settings_store`.

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


@pytest.mark.asyncio
async def test_get_torrent_settings_returns_200(client, monkeypatch):
store = client._transport.app.state.download_manager._torrent_settings_store

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

CRITICAL: Unchecked chained attribute access on download_manager._torrent_settings_store

If download_manager is ever None or lacks _torrent_settings_store, the test setup raises AttributeError before the endpoint is called, masking actual endpoint failures. Use getattr with a fallback.


Reply with @kilocode-bot fix it to have Kilo Code address this issue.


@pytest.mark.asyncio
async def test_get_torrent_settings_response_shape(client, monkeypatch):
store = client._transport.app.state.download_manager._torrent_settings_store

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

CRITICAL: Unchecked chained attribute access on download_manager._torrent_settings_store

If download_manager is ever None or lacks _torrent_settings_store, the test setup raises AttributeError before the endpoint is called, masking actual endpoint failures. Use getattr with a fallback.


Reply with @kilocode-bot fix it to have Kilo Code address this issue.


@pytest.mark.asyncio
async def test_put_torrent_settings_happy_path(client, monkeypatch):
store = client._transport.app.state.download_manager._torrent_settings_store

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

CRITICAL: Unchecked chained attribute access on download_manager._torrent_settings_store

If download_manager is ever None or lacks _torrent_settings_store, the test setup raises AttributeError before the endpoint is called, masking actual endpoint failures. Use getattr with a fallback.


Reply with @kilocode-bot fix it to have Kilo Code address this issue.

resp = await client.put("/api/torrent/settings", json=body)
assert resp.status_code == 200
data = resp.json()
assert data["status"] == "saved"

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

WARNING: Test doesn't verify store.save() was called

The test checks the response says "saved" but doesn't verify that store.save() was actually invoked. A buggy implementation that skips save() would still pass this test.


Reply with @kilocode-bot fix it to have Kilo Code address this issue.

"/api/torrent/settings",
json={"upload_rate_limit_kbps": -1},
)
assert resp.status_code == 422

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

WARNING: 422 test doesn't verify response body

The test only checks resp.status_code == 422 without asserting the response body contains validation error details. A 422 could be returned for reasons other than Pydantic validation failure.


Reply with @kilocode-bot fix it to have Kilo Code address this issue.

@kilo-code-bot

kilo-code-bot Bot commented Aug 3, 2026

Copy link
Copy Markdown

Code Review Summary

Status: 5 Issues Found | Recommendation: Address before merge

Overview

Severity Count
CRITICAL 3
WARNING 2
Issue Details (click to expand)

CRITICAL

File Line Issue
tests/test_routes_torrent.py 10 Unchecked chained attribute access on download_manager._torrent_settings_store
tests/test_routes_torrent.py 20 Unchecked chained attribute access on download_manager._torrent_settings_store
tests/test_routes_torrent.py 47 Unchecked chained attribute access on download_manager._torrent_settings_store

WARNING

File Line Issue
tests/test_routes_torrent.py 59 Test doesn't verify store.save() was called
tests/test_routes_torrent.py 81 422 test doesn't verify response body
Files Reviewed (1 files)
  • tests/test_routes_torrent.py - 5 issues

Fix these issues in Kilo Cloud


Reviewed by step-3.7-flash · Input: 89.7K · Output: 22.4K · Cached: 716.7K

@jaylfc

jaylfc commented Aug 3, 2026

Copy link
Copy Markdown
Owner Author

nemotron-super review

VERDICT: No blocking issues found.

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

@jaylfc
jaylfc merged commit 0703152 into dev Aug 3, 2026
21 checks passed
jaylfc added a commit that referenced this pull request Aug 3, 2026
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