Formatting

This commit is contained in:
2025-12-07 03:33:51 +01:00
parent a923a760ef
commit 4eae1d6d58
24 changed files with 1003 additions and 833 deletions

View File

@@ -21,24 +21,30 @@ def create_mock_response(status_code, json_data=None, text=None):
class TestFindMediaImdbId:
"""Tests for find_media_imdb_id tool."""
@patch('infrastructure.api.tmdb.client.requests.get')
@patch("infrastructure.api.tmdb.client.requests.get")
def test_success(self, mock_get, memory):
"""Should return movie info on success."""
# Mock HTTP responses
def mock_get_side_effect(url, **kwargs):
if "search" in url:
return create_mock_response(200, json_data={
"results": [{
"id": 27205,
"title": "Inception",
"release_date": "2010-07-16",
"overview": "A thief...",
"media_type": "movie"
}]
})
return create_mock_response(
200,
json_data={
"results": [
{
"id": 27205,
"title": "Inception",
"release_date": "2010-07-16",
"overview": "A thief...",
"media_type": "movie",
}
]
},
)
elif "external_ids" in url:
return create_mock_response(200, json_data={"imdb_id": "tt1375666"})
mock_get.side_effect = mock_get_side_effect
result = api_tools.find_media_imdb_id("Inception")
@@ -46,26 +52,32 @@ class TestFindMediaImdbId:
assert result["status"] == "ok"
assert result["imdb_id"] == "tt1375666"
assert result["title"] == "Inception"
# Verify HTTP calls
assert mock_get.call_count == 2
@patch('infrastructure.api.tmdb.client.requests.get')
@patch("infrastructure.api.tmdb.client.requests.get")
def test_stores_in_stm(self, mock_get, memory):
"""Should store result in STM on success."""
def mock_get_side_effect(url, **kwargs):
if "search" in url:
return create_mock_response(200, json_data={
"results": [{
"id": 27205,
"title": "Inception",
"release_date": "2010-07-16",
"media_type": "movie"
}]
})
return create_mock_response(
200,
json_data={
"results": [
{
"id": 27205,
"title": "Inception",
"release_date": "2010-07-16",
"media_type": "movie",
}
]
},
)
elif "external_ids" in url:
return create_mock_response(200, json_data={"imdb_id": "tt1375666"})
mock_get.side_effect = mock_get_side_effect
api_tools.find_media_imdb_id("Inception")
@@ -76,7 +88,7 @@ class TestFindMediaImdbId:
assert entity["title"] == "Inception"
assert mem.stm.current_topic == "searching_media"
@patch('infrastructure.api.tmdb.client.requests.get')
@patch("infrastructure.api.tmdb.client.requests.get")
def test_not_found(self, mock_get, memory):
"""Should return error when not found."""
mock_get.return_value = create_mock_response(200, json_data={"results": []})
@@ -86,7 +98,7 @@ class TestFindMediaImdbId:
assert result["status"] == "error"
assert result["error"] == "not_found"
@patch('infrastructure.api.tmdb.client.requests.get')
@patch("infrastructure.api.tmdb.client.requests.get")
def test_does_not_store_on_error(self, mock_get, memory):
"""Should not store in STM on error."""
mock_get.return_value = create_mock_response(200, json_data={"results": []})
@@ -100,49 +112,57 @@ class TestFindMediaImdbId:
class TestFindTorrent:
"""Tests for find_torrent tool."""
@patch('infrastructure.api.knaben.client.requests.post')
@patch("infrastructure.api.knaben.client.requests.post")
def test_success(self, mock_post, memory):
"""Should return torrents on success."""
mock_post.return_value = create_mock_response(200, json_data={
"hits": [
{
"title": "Torrent 1",
"seeders": 100,
"leechers": 10,
"magnetUrl": "magnet:?xt=...",
"size": "2.5 GB"
},
{
"title": "Torrent 2",
"seeders": 50,
"leechers": 5,
"magnetUrl": "magnet:?xt=...",
"size": "1.8 GB"
}
]
})
mock_post.return_value = create_mock_response(
200,
json_data={
"hits": [
{
"title": "Torrent 1",
"seeders": 100,
"leechers": 10,
"magnetUrl": "magnet:?xt=...",
"size": "2.5 GB",
},
{
"title": "Torrent 2",
"seeders": 50,
"leechers": 5,
"magnetUrl": "magnet:?xt=...",
"size": "1.8 GB",
},
]
},
)
result = api_tools.find_torrent("Inception 1080p")
assert result["status"] == "ok"
assert len(result["torrents"]) == 2
# Verify HTTP payload
payload = mock_post.call_args[1]['json']
assert payload['query'] == "Inception 1080p"
@patch('infrastructure.api.knaben.client.requests.post')
# Verify HTTP payload
payload = mock_post.call_args[1]["json"]
assert payload["query"] == "Inception 1080p"
@patch("infrastructure.api.knaben.client.requests.post")
def test_stores_in_episodic(self, mock_post, memory):
"""Should store results in episodic memory."""
mock_post.return_value = create_mock_response(200, json_data={
"hits": [{
"title": "Torrent 1",
"seeders": 100,
"leechers": 10,
"magnetUrl": "magnet:?xt=...",
"size": "2.5 GB"
}]
})
mock_post.return_value = create_mock_response(
200,
json_data={
"hits": [
{
"title": "Torrent 1",
"seeders": 100,
"leechers": 10,
"magnetUrl": "magnet:?xt=...",
"size": "2.5 GB",
}
]
},
)
api_tools.find_torrent("Inception")
@@ -151,16 +171,37 @@ class TestFindTorrent:
assert mem.episodic.last_search_results["query"] == "Inception"
assert mem.stm.current_topic == "selecting_torrent"
@patch('infrastructure.api.knaben.client.requests.post')
@patch("infrastructure.api.knaben.client.requests.post")
def test_results_have_indexes(self, mock_post, memory):
"""Should add indexes to results."""
mock_post.return_value = create_mock_response(200, json_data={
"hits": [
{"title": "Torrent 1", "seeders": 100, "leechers": 10, "magnetUrl": "magnet:?xt=1", "size": "1GB"},
{"title": "Torrent 2", "seeders": 50, "leechers": 5, "magnetUrl": "magnet:?xt=2", "size": "2GB"},
{"title": "Torrent 3", "seeders": 25, "leechers": 2, "magnetUrl": "magnet:?xt=3", "size": "3GB"}
]
})
mock_post.return_value = create_mock_response(
200,
json_data={
"hits": [
{
"title": "Torrent 1",
"seeders": 100,
"leechers": 10,
"magnetUrl": "magnet:?xt=1",
"size": "1GB",
},
{
"title": "Torrent 2",
"seeders": 50,
"leechers": 5,
"magnetUrl": "magnet:?xt=2",
"size": "2GB",
},
{
"title": "Torrent 3",
"seeders": 25,
"leechers": 2,
"magnetUrl": "magnet:?xt=3",
"size": "3GB",
},
]
},
)
api_tools.find_torrent("Test")
@@ -170,7 +211,7 @@ class TestFindTorrent:
assert results[1]["index"] == 2
assert results[2]["index"] == 3
@patch('infrastructure.api.knaben.client.requests.post')
@patch("infrastructure.api.knaben.client.requests.post")
def test_not_found(self, mock_post, memory):
"""Should return error when no torrents found."""
mock_post.return_value = create_mock_response(200, json_data={"hits": []})
@@ -236,16 +277,16 @@ class TestGetTorrentByIndex:
class TestAddTorrentToQbittorrent:
"""Tests for add_torrent_to_qbittorrent tool.
Note: These tests mock the qBittorrent client because:
1. The client requires authentication/session management
2. We want to test the tool's logic (memory updates, workflow management)
3. The client itself is tested separately in infrastructure tests
This is acceptable mocking because we're testing the TOOL logic, not the client.
"""
@patch('agent.tools.api.qbittorrent_client')
@patch("agent.tools.api.qbittorrent_client")
def test_success(self, mock_client, memory):
"""Should add torrent successfully and update memory."""
mock_client.add_torrent.return_value = True
@@ -257,7 +298,7 @@ class TestAddTorrentToQbittorrent:
# Verify client was called correctly
mock_client.add_torrent.assert_called_once_with("magnet:?xt=urn:btih:abc123")
@patch('agent.tools.api.qbittorrent_client')
@patch("agent.tools.api.qbittorrent_client")
def test_adds_to_active_downloads(self, mock_client, memory_with_search_results):
"""Should add to active downloads on success."""
mock_client.add_torrent.return_value = True
@@ -267,9 +308,12 @@ class TestAddTorrentToQbittorrent:
# Test memory update logic
mem = get_memory()
assert len(mem.episodic.active_downloads) == 1
assert mem.episodic.active_downloads[0]["name"] == "Inception.2010.1080p.BluRay.x264"
assert (
mem.episodic.active_downloads[0]["name"]
== "Inception.2010.1080p.BluRay.x264"
)
@patch('agent.tools.api.qbittorrent_client')
@patch("agent.tools.api.qbittorrent_client")
def test_sets_topic_and_ends_workflow(self, mock_client, memory):
"""Should set topic and end workflow."""
mock_client.add_torrent.return_value = True
@@ -282,10 +326,11 @@ class TestAddTorrentToQbittorrent:
assert mem.stm.current_topic == "downloading"
assert mem.stm.current_workflow is None
@patch('agent.tools.api.qbittorrent_client')
@patch("agent.tools.api.qbittorrent_client")
def test_error_handling(self, mock_client, memory):
"""Should handle client errors correctly."""
from infrastructure.api.qbittorrent.exceptions import QBittorrentAPIError
mock_client.add_torrent.side_effect = QBittorrentAPIError("Connection failed")
result = api_tools.add_torrent_to_qbittorrent("magnet:?xt=...")
@@ -296,7 +341,7 @@ class TestAddTorrentToQbittorrent:
class TestAddTorrentByIndex:
"""Tests for add_torrent_by_index tool.
These tests verify the tool's logic:
- Getting torrent from memory by index
- Extracting magnet link
@@ -304,7 +349,7 @@ class TestAddTorrentByIndex:
- Error handling for edge cases
"""
@patch('agent.tools.api.qbittorrent_client')
@patch("agent.tools.api.qbittorrent_client")
def test_success(self, mock_client, memory_with_search_results):
"""Should get torrent by index and add it."""
mock_client.add_torrent.return_value = True
@@ -317,7 +362,7 @@ class TestAddTorrentByIndex:
# Verify correct magnet was extracted and used
mock_client.add_torrent.assert_called_once_with("magnet:?xt=urn:btih:abc123")
@patch('agent.tools.api.qbittorrent_client')
@patch("agent.tools.api.qbittorrent_client")
def test_uses_correct_magnet(self, mock_client, memory_with_search_results):
"""Should extract correct magnet from index."""
mock_client.add_torrent.return_value = True