Extended search functionality

This commit is contained in:
2026-03-16 19:18:11 +01:00
parent d427cec8d5
commit 0083e3d896
5 changed files with 232 additions and 135 deletions

View File

@@ -124,24 +124,6 @@ class TestBookAddCommand:
assert len(book.authors) == 0 # No authors provided
assert len(book.genres) == 0 # No genres provided
def test_book_add_missing_owner_fails(
self, app: Flask, cli_runner: CliRunner
) -> None:
"""Test that book addition fails when owner is not provided."""
result = cli_runner.invoke(
cli,
[
"book",
"add",
"Test Book",
# Missing --owner parameter
],
)
# Should fail with exit code 2 (Click validation error)
assert result.exit_code == 2
assert "Missing option '--owner'" in result.output
class TestBookListCommand:
"""Test the 'hxbooks book list' command."""
@@ -343,46 +325,46 @@ class TestBookSearchCommand:
# Results format depends on BookService.search_books_advanced implementation
@pytest.mark.parametrize(
"query,expected_titles",
"query,username,expected_titles",
[
# String field filters
("title:Hobbit", ["The Hobbit"]),
("author:Tolkien", ["The Hobbit", "The Fellowship"]),
("genre:Fantasy", ["The Hobbit", "The Fellowship"]),
("owner:alice", ["The Hobbit", "The Fellowship", "Dune"]),
("place:home", ["The Hobbit", "Programming Book"]),
("bookshelf:fantasy", ["The Hobbit", "The Fellowship"]),
("title:Hobbit", "", ["The Hobbit"]),
("author:Tolkien", "", ["The Hobbit", "The Fellowship"]),
("genre:Fantasy", "", ["The Hobbit", "The Fellowship"]),
("owner:alice", "", ["The Hobbit", "The Fellowship", "Dune"]),
("place:home", "", ["The Hobbit", "Programming Book"]),
("bookshelf:fantasy", "", ["The Hobbit", "The Fellowship"]),
# Numeric field filters
pytest.param(
"rating>=4",
["The Hobbit", "Programming Book"],
marks=pytest.mark.xfail(reason="Rating filter not implemented yet"),
),
pytest.param(
"rating=3",
["Dune"],
marks=pytest.mark.xfail(reason="Rating filter not implemented yet"),
),
("shelf>1", ["The Fellowship", "Programming Book"]),
(
"year>=1954",
["The Hobbit", "The Fellowship", "Dune", "Programming Book"],
),
("rating>=4", "", ["The Hobbit", "Programming Book"]),
("rating=3", "", ["Dune"]),
("shelf>1", "", ["The Fellowship", "Programming Book"]),
("year>=1954", "", ["The Fellowship", "Dune", "Programming Book"]),
# Date field filters
(
"added>=2026-03-15",
"",
["The Hobbit", "The Fellowship", "Dune", "Programming Book"],
),
("bought<2026-01-01", ["Programming Book"]),
("bought<2026-01-01", "", ["Programming Book"]),
# Negation
("-genre:Fantasy", ["Dune", "Programming Book"]),
("-owner:bob", ["The Hobbit", "The Fellowship", "Dune"]),
("-genre:Fantasy", "", ["Dune", "Programming Book"]),
("-owner:bob", "", ["The Hobbit", "The Fellowship", "Dune"]),
# Complex query with multiple filters
("-genre:Fantasy owner:alice", ["Dune"]),
("-genre:Fantasy owner:alice", "", ["Dune"]),
# User-specific queries
("rating>=4", "alice", ["The Hobbit"]),
("is:reading", "alice", ["The Fellowship"]),
("is:read", "alice", ["The Hobbit", "Dune"]),
("is:wished", "alice", ["Programming Book"]),
],
)
def test_book_search_advanced_queries(
self, app: Flask, cli_runner: CliRunner, query: str, expected_titles: list[str]
self,
app: Flask,
cli_runner: CliRunner,
query: str,
username: str,
expected_titles: list[str],
) -> None:
"""Test advanced search queries with various field filters."""
# Set up comprehensive test data
@@ -390,7 +372,8 @@ class TestBookSearchCommand:
# Execute the search query
result = cli_runner.invoke(
cli, ["book", "search", "--format", "json", "--", query]
cli,
["book", "search", "--format", "json", "--username", username, "--", query],
)
assert result.exit_code == 0, f"Search query '{query}' failed: {result.output}"
@@ -517,6 +500,9 @@ class TestBookSearchCommand:
cli_runner.invoke(cli, ["reading", "start", str(hobbit_id), "--owner", "alice"])
cli_runner.invoke(cli, ["reading", "start", str(dune_id), "--owner", "alice"])
cli_runner.invoke(cli, ["reading", "start", str(prog_id), "--owner", "bob"])
cli_runner.invoke(
cli, ["reading", "start", str(fellowship_id), "--owner", "alice"]
)
with app.app_context():
# Get reading session IDs
@@ -562,6 +548,12 @@ class TestBookSearchCommand:
db.session.commit()
# Add a book to wishlist
cli_runner.invoke(
cli,
["wishlist", "add", str(prog_id), "--owner", "alice"],
)
class TestReadingCommands:
"""Test reading-related CLI commands."""