diff --git a/backend/tests/test_search.py b/backend/tests/test_search.py new file mode 100644 index 0000000..b078e0c --- /dev/null +++ b/backend/tests/test_search.py @@ -0,0 +1,46 @@ +from tests.support import ApiTestCase + + +class SearchTests(ApiTestCase): + def setUp(self): + super().setUp() + self.register() + self.scifi = self.genre_id("Science Fiction") + self.fantasy = self.genre_id("Fantasy") + self.create_book(title="Dune", author="Frank Herbert", genre_id=self.scifi) + self.create_book(title="The Hobbit", author="J.R.R. Tolkien", genre_id=self.fantasy) + self.create_book(title="100% Pure", author="Jane_Doe", genre_id=self.fantasy) + self.create_book(title="1000 Pages", author="Back\\slash", genre_id=self.scifi) + + def titles(self, query: str) -> list[str]: + response = self.call("GET", f"/api/books?{query}") + self.assertEqual(response.status_code, 200, response.get_json()) + return sorted(b["title"] for b in response.get_json()) + + def test_matches_title_or_author_case_insensitively(self): + self.assertEqual(self.titles("q=dUnE"), ["Dune"]) + self.assertEqual(self.titles("q=tolkien"), ["The Hobbit"]) + + def test_wildcards_match_literally(self): + self.assertEqual(self.titles("q=100%25"), ["100% Pure"]) # %25 is "%" + self.assertEqual(self.titles("q=e_D"), ["100% Pure"]) # literal "_" in Jane_Doe + self.assertEqual(self.titles("q=k_s"), []) # unescaped "_" would match "Back\\slash" + self.assertEqual(self.titles("q=k%5Cs"), ["1000 Pages"]) # %5C is "\" + + def test_genre_filter_and_combination(self): + self.assertEqual(self.titles(f"genre_id={self.fantasy}"), ["100% Pure", "The Hobbit"]) + self.assertEqual(self.titles(f"q=100&genre_id={self.scifi}"), ["1000 Pages"]) + + def test_blank_query_returns_everything(self): + self.assertEqual(len(self.titles("q=%20%20")), 4) + + def test_invalid_parameters(self): + for query, field in (("genre_id=abc", "genre_id"), ("genre_id=99999", "genre_id"), ("q=a%00b", "q")): + with self.subTest(query=query): + response = self.call("GET", f"/api/books?{query}") + self.assertEqual(response.status_code, 400) + self.assertEqual(response.get_json()["field"], field) + + def test_search_never_returns_other_users_books(self): + bob = self.other_user("bob") + self.assertEqual(self.call("GET", "/api/books?q=dune", client=bob).get_json(), [])