Extended search functionality
This commit is contained in:
@@ -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."""
|
||||
|
||||
Reference in New Issue
Block a user