Coverage for catalog/tests/test_views.py: 100.00%
222 statements
« prev ^ index » next coverage.py v7.17.0, created at 2026-10-29 10:34 -0700
« prev ^ index » next coverage.py v7.17.0, created at 2026-10-29 10:34 -0700
1import datetime 1a
3from django.contrib.auth import get_user_model 1a
4from django.contrib.auth.models import Permission 1a
5from django.test import TestCase 1a
6from django.urls import resolve, reverse 1a
7from django.utils import timezone 1a
9from ..models import Author, Book, BookInstance, Genre, Language 1a
10from ..views import index 1a
13class AuthorListViewTest(TestCase): 1a
14 def setUp(self): 1a
15 url = reverse("authors") 1a
16 self.response = self.client.get(url) 1a
18 @classmethod 1a
19 def setUpTestData(cls): 1a
20 # Create authors for pagination tests
21 number_of_authors = 13 1a
22 for author_id in range(number_of_authors): 1a
23 Author.objects.create( 1a
24 first_name=f"Django {author_id}",
25 last_name=f"Wilkins {author_id}",
26 )
28 def test_view_url_exists_at_desired_location(self): 1a
29 response = self.client.get("/catalog/authors/") 1a
30 self.assertEqual(response.status_code, 200) 1a
32 def test_view_url_accessible_by_name(self): 1a
33 self.assertEqual(self.response.status_code, 200) 1a
35 def test_view_uses_correct_template(self): 1a
36 self.assertEqual(self.response.status_code, 200) 1a
37 self.assertTemplateUsed(self.response, "catalog/author_list.html") 1a
39 def test_pagination_is_ten(self): 1a
40 self.assertEqual(self.response.status_code, 200) 1a
41 self.assertTrue("is_paginated" in self.response.context) 1a
42 self.assertTrue(self.response.context["is_paginated"] is True) 1a
43 self.assertEqual(len(self.response.context["author_list"]), 10) 1a
45 def test_lists_all_authors(self): 1a
46 # Get second page and confirm it has (exactly) the remaining 3 items
47 response = self.client.get(reverse("authors") + "?page=2") 1a
48 self.assertEqual(response.status_code, 200) 1a
49 self.assertTrue("is_paginated" in response.context) 1a
50 self.assertTrue(response.context["is_paginated"] is True) 1a
51 self.assertEqual(len(response.context["author_list"]), 3) 1a
54class LoanedBookInstancesByUserListViewTest(TestCase): 1a
55 def setUp(self): 1a
56 # Create two users
57 test_user1 = get_user_model().objects.create_user( 1a
58 username="testuser1", password="1X<ISRUkw+tuK"
59 )
60 test_user2 = get_user_model().objects.create_user( 1a
61 username="testuser2", password="2HJ1vRV0Z&3iD"
62 )
64 test_user1.save() 1a
65 test_user2.save() 1a
67 # Create a book
68 test_author = Author.objects.create(first_name="John", last_name="Smith") 1a
69 # test_genre = Genre.objects.create(name="Fantasy")
70 Genre.objects.create(name="Fantasy") 1a
71 test_language = Language.objects.create(name="English") 1a
72 test_book = Book.objects.create( 1a
73 title="Book Title",
74 summary="My book summary",
75 isbn="ABCDEFG",
76 author=test_author,
77 language=test_language,
78 )
79 # Create genre as a post-step
80 genre_objects_for_book = Genre.objects.all() 1a
81 test_book.genre.set(genre_objects_for_book) 1a
82 test_book.save() 1a
84 # Create 30 BookInstance objects
85 number_of_book_copies = 30 1a
86 for book_copy in range(number_of_book_copies): 1a
87 return_date = timezone.now() + datetime.timedelta(days=book_copy % 5) 1a
88 if book_copy % 2: 1a
89 the_borrower = test_user1 1a
90 else:
91 the_borrower = test_user2 1a
92 status = "m" 1a
93 BookInstance.objects.create( 1a
94 book=test_book,
95 imprint="Unlikely Imprint, 2016",
96 due_back=return_date,
97 borrower=the_borrower,
98 status=status,
99 )
101 def test_redirect_if_not_logged_in(self): 1a
102 response = self.client.get(reverse("my-borrowed")) 1a
103 self.assertRedirects(response, "/accounts/login/?next=/catalog/mybooks/") 1a
105 def test_logged_in_uses_correct_template(self): 1a
106 login = self.client.login( # noqa:F841 1a
107 username="testuser1", password="1X<ISRUkw+tuK"
108 )
109 response = self.client.get(reverse("my-borrowed")) 1a
111 # Check our user is logged in
112 self.assertEqual(str(response.context["user"]), "testuser1") 1a
113 # Check that we got a response "success"
114 self.assertEqual(response.status_code, 200) 1a
116 # Check we used correct template
117 self.assertTemplateUsed( 1a
118 response, "catalog/bookinstance_list_borrowed_user.html"
119 )
121 def test_only_borrowed_books_in_list(self): 1a
122 login = self.client.login( # noqa:F841 1a
123 username="testuser1", password="1X<ISRUkw+tuK"
124 )
125 response = self.client.get(reverse("my-borrowed")) 1a
127 # Check our user is logged in
128 self.assertEqual(str(response.context["user"]), "testuser1") 1a
129 # Check that we got a response "success"
130 self.assertEqual(response.status_code, 200) 1a
132 # Check that initially we don't have any books in list (none on loan)
133 self.assertTrue("bookinstance_list" in response.context) 1a
134 self.assertEqual(len(response.context["bookinstance_list"]), 0) 1a
136 # Now change all books to be on loan
137 get_ten_books = BookInstance.objects.all()[:10] 1a
139 for copy in get_ten_books: 1a
140 copy.status = "o" 1a
141 copy.save() 1a
143 # Check that now we have borrowed books in the list
144 response = self.client.get(reverse("my-borrowed")) 1a
145 # Check our user is logged in
146 self.assertEqual(str(response.context["user"]), "testuser1") 1a
147 # Check that we got a response "success"
148 self.assertEqual(response.status_code, 200) 1a
150 self.assertTrue("bookinstance_list" in response.context) 1a
152 # Confirm all books belong to testuser1 and are on loan
153 for bookitem in response.context["bookinstance_list"]: 1a
154 self.assertEqual(response.context["user"], bookitem.borrower) 1a
155 self.assertEqual(bookitem.status, "o") 1a
157 def test_pages_paginated_to_ten(self): 1a
158 # Change all books to be on loan.
159 # This should make 15 test user ones.
160 for copy in BookInstance.objects.all(): 1a
161 copy.status = "o" 1a
162 copy.save() 1a
164 login = self.client.login( # noqa:F841 1a
165 username="testuser1", password="1X<ISRUkw+tuK"
166 )
167 response = self.client.get(reverse("my-borrowed")) 1a
169 # Check our user is logged in
170 self.assertEqual(str(response.context["user"]), "testuser1") 1a
171 # Check that we got a response "success"
172 self.assertEqual(response.status_code, 200) 1a
174 # Confirm that only 10 items are displayed due to pagination
175 # (if pagination not enabled, there would be 15 returned)
176 self.assertEqual(len(response.context["bookinstance_list"]), 10) 1a
178 def test_pages_ordered_by_due_date(self): 1a
179 # Change all books to be on loan
180 for copy in BookInstance.objects.all(): 1a
181 copy.status = "o" 1a
182 copy.save() 1a
184 login = self.client.login( # noqa:F841 1a
185 username="testuser1", password="1X<ISRUkw+tuK"
186 )
187 response = self.client.get(reverse("my-borrowed")) 1a
189 # Check our user is logged in
190 self.assertEqual(str(response.context["user"]), "testuser1") 1a
191 # Check that we got a response "success"
192 self.assertEqual(response.status_code, 200) 1a
194 # Confirm that of the items, only 10 are displayed due to pagination.
195 self.assertEqual(len(response.context["bookinstance_list"]), 10) 1a
197 last_date = 0 1a
198 for copy in response.context["bookinstance_list"]: 1a
199 if last_date == 0: 1a
200 last_date = copy.due_back 1a
201 else:
202 self.assertTrue(last_date <= copy.due_back) 1a
205class RenewBookInstancesViewTest(TestCase): 1a
206 def setUp(self): 1a
207 # Create a user
208 test_user1 = get_user_model().objects.create_user( 1a
209 username="testuser1", password="1X<ISRUkw+tuK"
210 )
211 test_user1.save() 1a
213 test_user2 = get_user_model().objects.create_user( 1a
214 username="testuser2", password="2HJ1vRV0Z&3iD"
215 )
216 test_user2.save() 1a
217 permission = Permission.objects.get(name="Set book as returned") 1a
218 test_user2.user_permissions.add(permission) 1a
219 test_user2.save() 1a
221 # Create a book
222 test_author = Author.objects.create(first_name="John", last_name="Smith") 1a
223 test_genre = Genre.objects.create(name="Fantasy") # noqa:F841 1a
224 test_language = Language.objects.create(name="English") 1a
225 test_book = Book.objects.create( 1a
226 title="Book Title",
227 summary="My book summary",
228 isbn="ABCDEFG",
229 author=test_author,
230 language=test_language,
231 )
232 # Create genre as a post-step
233 genre_objects_for_book = Genre.objects.all() 1a
234 test_book.genre.set(genre_objects_for_book) 1a
235 test_book.save() 1a
237 # Create a BookInstance object for test_user1
238 return_date = datetime.date.today() + datetime.timedelta(days=5) 1a
239 self.test_bookinstance1 = BookInstance.objects.create( 1a
240 book=test_book,
241 imprint="Unlikely Imprint, 2016",
242 due_back=return_date,
243 borrower=test_user1,
244 status="o",
245 )
247 # Create a BookInstance object for test_user2
248 return_date = datetime.date.today() + datetime.timedelta(days=5) 1a
249 self.test_bookinstance2 = BookInstance.objects.create( 1a
250 book=test_book,
251 imprint="Unlikely Imprint, 2016",
252 due_back=return_date,
253 borrower=test_user2,
254 status="o",
255 )
257 def test_redirect_if_not_logged_in(self): 1a
258 response = self.client.get( 1a
259 reverse(
260 "renew-book-librarian",
261 kwargs={"pk": self.test_bookinstance1.pk},
262 )
263 )
264 # Manually check redirect (Can't use assertRedirect,
265 # because the redirect URL is unpredictable)
266 self.assertEqual(response.status_code, 302) 1a
267 self.assertTrue(response.url.startswith("/accounts/login/")) 1a
269 def test_forbidden_if_logged_in_but_not_correct_permission(self): 1a
270 login = self.client.login( # noqa:F841 1a
271 username="testuser1", password="1X<ISRUkw+tuK"
272 )
273 response = self.client.get( 1a
274 reverse(
275 "renew-book-librarian",
276 kwargs={"pk": self.test_bookinstance1.pk},
277 )
278 )
279 self.assertEqual(response.status_code, 403) 1a
281 def test_logged_in_with_permission_borrowed_book(self): 1a
282 login = self.client.login( # noqa:F841 1a
283 username="testuser2", password="2HJ1vRV0Z&3iD"
284 )
285 response = self.client.get( 1a
286 reverse(
287 "renew-book-librarian",
288 kwargs={"pk": self.test_bookinstance2.pk},
289 )
290 )
292 # Check that it lets us login - this is our book and we have
293 # the right permissions.
294 self.assertEqual(response.status_code, 200) 1a
296 def test_logged_in_with_permission_another_users_borrowed_book(self): 1a
297 login = self.client.login( # noqa:F841 1a
298 username="testuser2", password="2HJ1vRV0Z&3iD"
299 )
300 response = self.client.get( 1a
301 reverse(
302 "renew-book-librarian",
303 kwargs={"pk": self.test_bookinstance1.pk},
304 )
305 )
307 # Check that it lets us login. We're a librarian, so we can
308 # view any users book
309 self.assertEqual(response.status_code, 200) 1a
311 def test_uses_correct_template(self): 1a
312 login = self.client.login( # noqa:F841 1a
313 username="testuser2", password="2HJ1vRV0Z&3iD"
314 )
315 response = self.client.get( 1a
316 reverse(
317 "renew-book-librarian",
318 kwargs={"pk": self.test_bookinstance1.pk},
319 )
320 )
321 self.assertEqual(response.status_code, 200) 1a
323 # Check we used correct template
324 self.assertTemplateUsed(response, "catalog/book_renew_librarian.html") 1a
326 def test_form_renewal_date_initially_has_date_three_weeks_in_future(self): 1a
327 login = self.client.login( # noqa:F841 1a
328 username="testuser2", password="2HJ1vRV0Z&3iD"
329 )
330 response = self.client.get( 1a
331 reverse(
332 "renew-book-librarian",
333 kwargs={"pk": self.test_bookinstance1.pk},
334 )
335 )
336 self.assertEqual(response.status_code, 200) 1a
338 date_3_weeks_in_future = datetime.date.today() + datetime.timedelta(weeks=3) 1a
339 self.assertEqual( 1a
340 response.context["form"].initial["renewal_date"],
341 date_3_weeks_in_future,
342 )
344 """ 1a
345 def test_form_invalid_renewal_date_past(self):
346 login = self.client.login( # noqa:F841
347 username="testuser2", password="2HJ1vRV0Z&3iD"
348 )
350 date_in_past = datetime.date.today() - datetime.timedelta(weeks=1)
351 response = self.client.post(
352 reverse(
353 "renew-book-librarian",
354 kwargs={"pk": self.test_bookinstance1.pk},
355 ),
356 {"renewal_date": date_in_past},
357 )
358 self.assertEqual(response.status_code, 200)
359 self.assertFormError(
360 response, "form", "renewal_date", "Invalid date - renewal in past"
361 )
363 def test_form_invalid_renewal_date_future(self):
364 login = self.client.login( # noqa:F841
365 username="testuser2", password="2HJ1vRV0Z&3iD"
366 )
368 invalid_date_in_future = datetime.date.today() + datetime.timedelta(weeks=5)
369 response = self.client.post(
370 reverse(
371 "renew-book-librarian",
372 kwargs={"pk": self.test_bookinstance1.pk},
373 ),
374 {"renewal_date": invalid_date_in_future},
375 )
376 self.assertEqual(response.status_code, 200)
377 self.assertFormError(
378 response,
379 "form",
380 "renewal_date",
381 "Invalid date - renewal more than 4 weeks ahead",
382 )
383 """
385 def test_redirects_to_all_borrowed_book_list_on_success(self): 1a
386 login = self.client.login( # noqa:F841 1a
387 username="testuser2", password="2HJ1vRV0Z&3iD"
388 )
389 valid_date_in_future = datetime.date.today() + datetime.timedelta(weeks=2) 1a
390 response = self.client.post( 1a
391 reverse(
392 "renew-book-librarian",
393 kwargs={"pk": self.test_bookinstance1.pk},
394 ),
395 {"renewal_date": valid_date_in_future},
396 )
397 self.assertRedirects(response, reverse("all-borrowed")) 1a
399 def test_HTTP404_for_invalid_book_if_logged_in(self): 1a
400 import uuid 1a
402 test_uid = uuid.uuid4() # unlikely UID to match our bookinstance! 1a
403 login = self.client.login( # noqa:F841 1a
404 username="testuser2", password="2HJ1vRV0Z&3iD"
405 )
406 response = self.client.get( 1a
407 reverse("renew-book-librarian", kwargs={"pk": test_uid})
408 )
409 self.assertEqual(response.status_code, 404) 1a
412class AuthorCreateViewTest(TestCase): 1a
413 """Test case for the AuthorCreate view."""
415 def setUp(self): 1a
416 # Create a user
417 test_user1 = get_user_model().objects.create_user( 1a
418 username="testuser1", password="1X<ISRUkw+tuK"
419 )
420 test_user2 = get_user_model().objects.create_user( 1a
421 username="testuser2", password="2HJ1vRV0Z&3iD"
422 )
424 test_user1.save() 1a
425 test_user2.save() 1a
427 permission = Permission.objects.get(name="Set book as returned") 1a
428 test_user2.user_permissions.add(permission) 1a
429 test_user2.save() 1a
431 # Create an author
432 test_author = Author.objects.create( # noqa:F841 1a
433 first_name="John", last_name="Smith"
434 )
436 def test_redirect_if_not_logged_in(self): 1a
437 response = self.client.get(reverse("author-create")) 1a
438 self.assertRedirects(response, "/accounts/login/?next=/catalog/author/create/") 1a
440 def test_forbidden_if_logged_in_but_not_correct_permission(self): 1a
441 login = self.client.login( # noqa:F841 1a
442 username="testuser1", password="1X<ISRUkw+tuK"
443 )
444 response = self.client.get(reverse("author-create")) 1a
445 self.assertEqual(response.status_code, 403) 1a
447 def test_logged_in_with_permission(self): 1a
448 login = self.client.login( # noqa:F841 1a
449 username="testuser2", password="2HJ1vRV0Z&3iD"
450 )
451 response = self.client.get(reverse("author-create")) 1a
452 self.assertEqual(response.status_code, 200) 1a
454 def test_uses_correct_template(self): 1a
455 login = self.client.login( # noqa:F841 1a
456 username="testuser2", password="2HJ1vRV0Z&3iD"
457 )
458 response = self.client.get(reverse("author-create")) 1a
459 self.assertEqual(response.status_code, 200) 1a
460 self.assertTemplateUsed(response, "catalog/author_create.html") 1a
462 def test_form_date_of_birth_initially_set_to_expected_date(self): 1a
463 login = self.client.login( # noqa:F841 1a
464 username="testuser2", password="2HJ1vRV0Z&3iD"
465 )
466 response = self.client.get(reverse("author-create")) 1a
467 self.assertEqual(response.status_code, 200) 1a
469 expected_initial_date = datetime.date(1882, 2, 2) 1a
470 response_date = response.context["form"].initial["date_of_birth"] 1a
471 response_date = datetime.datetime.strptime(response_date, "%d/%m/%Y").date() 1a
472 self.assertEqual(response_date, expected_initial_date) 1a
474 def test_redirects_to_detail_view_on_success(self): 1a
475 login = self.client.login( # noqa:F841 1a
476 username="testuser2", password="2HJ1vRV0Z&3iD"
477 )
478 response = self.client.post( 1a
479 reverse("author-create"),
480 {"first_name": "Christian Name", "last_name": "Surname"},
481 )
482 # Manually check redirect because we don't know what author was created
483 self.assertEqual(response.status_code, 302) 1a
484 self.assertTrue(response.url.startswith("/catalog/author/")) 1a
487class IndexTests(TestCase): 1a
488 def setUp(self): 1a
489 url = reverse("index") 1a
490 self.response = self.client.get(url) 1a
492 def test_index_status_code(self): 1a
493 self.assertEqual(self.response.status_code, 200) 1a
495 def test_index_url_name(self): 1a
496 self.assertEqual(self.response.status_code, 200) 1a
498 def test_index_contains_correct_html(self): 1a
499 self.assertContains(self.response, "Catalog contents") 1a
501 def test_index_does_not_contain_incorrect_html(self): 1a
502 self.assertNotContains(self.response, "About Page") 1a
504 def test_index_template(self): 1a
505 self.assertTemplateUsed(self.response, "index.html") 1a
507 def test_index_page_url_resolves_index(self): 1a
508 view = resolve("/catalog/") 1a
509 self.assertEqual(view.func.__name__, index.__name__) 1a