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