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"]) self.assertEqual(self.titles("q=e_D"), ["100% Pure"]) self.assertEqual(self.titles("q=k_s"), []) self.assertEqual(self.titles("q=k%5Cs"), ["1000 Pages"]) 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(), [] )