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

1import datetime 

2 

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 

8 

9from ..models import Author, Book, BookInstance, Genre, Language 

10from ..views import index 

11 

12 

13class AuthorListViewTest(TestCase): 

14 def setUp(self): 

15 url = reverse("authors") 

16 self.response = self.client.get(url) 

17 

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 ) 

27 

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

31 

32 def test_view_url_accessible_by_name(self): 

33 self.assertEqual(self.response.status_code, 200) 1z

34 

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

38 

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

44 

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

52 

53 

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 ) 

63 

64 test_user1.save() 

65 test_user2.save() 

66 

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() 

82 

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 ) 

99 

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

103 

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

109 

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

114 

115 # Check we used correct template 

116 self.assertTemplateUsed( 1g

117 response, "catalog/bookinstance_list_borrowed_user.html" 

118 ) 

119 

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

125 

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

130 

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

134 

135 # Now change all books to be on loan 

136 get_ten_books = BookInstance.objects.all()[:10] 1b

137 

138 for copy in get_ten_books: 1b

139 copy.status = "o" 1b

140 copy.save() 1b

141 

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

148 

149 self.assertTrue("bookinstance_list" in response.context) 1b

150 

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

155 

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

162 

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

167 

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

172 

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

176 

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

182 

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

187 

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

192 

193 # Confirm that of the items, only 10 are displayed due to pagination. 

194 self.assertEqual(len(response.context["bookinstance_list"]), 10) 1c

195 

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

202 

203 

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() 

211 

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() 

219 

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() 

235 

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 ) 

245 

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 ) 

255 

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

267 

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

279 

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 ) 

290 

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

294 

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 ) 

305 

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

309 

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

321 

322 # Check we used correct template 

323 self.assertTemplateUsed(response, "catalog/book_renew_librarian.html") 1k

324 

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

336 

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 ) 

342 

343 """ 

344 def test_form_invalid_renewal_date_past(self): 

345 login = self.client.login( # noqa:F841 

346 username="testuser2", password="2HJ1vRV0Z&3iD" 

347 ) 

348 

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 ) 

361 

362 def test_form_invalid_renewal_date_future(self): 

363 login = self.client.login( # noqa:F841 

364 username="testuser2", password="2HJ1vRV0Z&3iD" 

365 ) 

366 

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 """ 

383 

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

397 

398 def test_HTTP404_for_invalid_book_if_logged_in(self): 

399 import uuid 1i

400 

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

409 

410 

411class AuthorCreateViewTest(TestCase): 

412 """Test case for the AuthorCreate view.""" 

413 

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 ) 

422 

423 test_user1.save() 

424 test_user2.save() 

425 

426 permission = Permission.objects.get(name="Set book as returned") 

427 test_user2.user_permissions.add(permission) 

428 test_user2.save() 

429 

430 # Create an author 

431 test_author = Author.objects.create( # noqa:F841 

432 first_name="John", last_name="Smith" 

433 ) 

434 

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

438 

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

445 

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

452 

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

460 

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

467 

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

472 

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

484 

485 

486class IndexTests(TestCase): 

487 def setUp(self): 

488 url = reverse("index") 

489 self.response = self.client.get(url) 

490 

491 def test_index_status_code(self): 

492 self.assertEqual(self.response.status_code, 200) 1A

493 

494 def test_index_url_name(self): 

495 self.assertEqual(self.response.status_code, 200) 1B

496 

497 def test_index_contains_correct_html(self): 

498 self.assertContains(self.response, "Catalog contents") 1C

499 

500 def test_index_does_not_contain_incorrect_html(self): 

501 self.assertNotContains(self.response, "About Page") 1D

502 

503 def test_index_template(self): 

504 self.assertTemplateUsed(self.response, "index.html") 1E

505 

506 def test_index_page_url_resolves_index(self): 

507 view = resolve("/catalog/") 1y

508 self.assertEqual(view.func.__name__, index.__name__) 1y