You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

196 lines
7.2 KiB

  1. from datetime import datetime, timedelta as td
  2. from unittest.mock import patch
  3. from django.utils import timezone
  4. from hc.api.models import Flip, Check, Ping
  5. from hc.test import BaseTestCase
  6. class DetailsTestCase(BaseTestCase):
  7. def setUp(self):
  8. super().setUp()
  9. self.check = Check.objects.create(project=self.project)
  10. ping = Ping.objects.create(owner=self.check)
  11. # Older MySQL versions don't store microseconds. This makes sure
  12. # the ping is older than any notifications we may create later:
  13. ping.created = "2000-01-01T00:00:00+00:00"
  14. ping.save()
  15. self.url = "/checks/%s/details/" % self.check.code
  16. def test_it_works(self):
  17. self.client.login(username="[email protected]", password="password")
  18. r = self.client.get(self.url)
  19. self.assertContains(r, "How To Ping", status_code=200)
  20. self.assertContains(r, "ping-now")
  21. # The page should contain timezone strings
  22. self.assertContains(r, "Europe/Riga")
  23. def test_it_checks_ownership(self):
  24. self.client.login(username="[email protected]", password="password")
  25. r = self.client.get(self.url)
  26. self.assertEqual(r.status_code, 404)
  27. def test_it_shows_cron_expression(self):
  28. self.check.kind = "cron"
  29. self.check.save()
  30. self.client.login(username="[email protected]", password="password")
  31. r = self.client.get(self.url)
  32. self.assertContains(r, "Cron Expression", status_code=200)
  33. def test_it_allows_cross_team_access(self):
  34. self.client.login(username="[email protected]", password="password")
  35. r = self.client.get(self.url)
  36. self.assertEqual(r.status_code, 200)
  37. def test_it_shows_new_check_notice(self):
  38. self.client.login(username="[email protected]", password="password")
  39. r = self.client.get(self.url + "?new")
  40. self.assertContains(r, "Your new check is ready!", status_code=200)
  41. def test_it_hides_actions_from_readonly_users(self):
  42. self.bobs_membership.role = "r"
  43. self.bobs_membership.save()
  44. self.client.login(username="[email protected]", password="password")
  45. r = self.client.get(self.url)
  46. self.assertNotContains(r, "edit-name", status_code=200)
  47. self.assertNotContains(r, "edit-desc")
  48. self.assertNotContains(r, "Filtering Rules")
  49. self.assertNotContains(r, "pause-btn")
  50. self.assertNotContains(r, "Change Schedule")
  51. self.assertNotContains(r, "Create a Copy…")
  52. self.assertNotContains(r, "transfer-btn")
  53. self.assertNotContains(r, "details-remove-check")
  54. def test_it_hides_resume_action_from_readonly_users(self):
  55. self.bobs_membership.role = "r"
  56. self.bobs_membership.save()
  57. self.check.status = "paused"
  58. self.check.manual_resume = True
  59. self.check.save()
  60. self.client.login(username="[email protected]", password="password")
  61. r = self.client.get(self.url)
  62. self.assertNotContains(r, "resume-btn", status_code=200)
  63. def test_crontab_example_guesses_schedules(self):
  64. self.client.login(username="[email protected]", password="password")
  65. pairs = [
  66. (td(minutes=1), "* * * * *"),
  67. (td(minutes=12), "*/12 * * * *"),
  68. (td(hours=1), "0 * * * *"),
  69. (td(hours=6), "0 */6 * * *"),
  70. (td(days=1), "0 0 * * *"),
  71. ]
  72. for timeout, expression in pairs:
  73. self.check.timeout = timeout
  74. self.check.save()
  75. r = self.client.get(self.url)
  76. self.assertContains(r, f"{expression} /your/command.sh")
  77. self.assertNotContains(r, 'FIXME: replace "* * * * *"')
  78. def test_crontab_example_handles_unsupported_timeout_values(self):
  79. self.client.login(username="[email protected]", password="password")
  80. self.check.timeout = td(minutes=13)
  81. self.check.save()
  82. r = self.client.get(self.url)
  83. self.assertContains(r, f"* * * * * /your/command.sh")
  84. self.assertContains(r, 'FIXME: replace "* * * * *"')
  85. @patch("hc.lib.date.timezone.now")
  86. def test_it_calculates_downtime_summary(self, mock_now):
  87. mock_now.return_value = datetime(2020, 2, 1, tzinfo=timezone.utc)
  88. self.check.created = datetime(2019, 1, 1, 0, 0, 0, tzinfo=timezone.utc)
  89. self.check.save()
  90. # going down on Jan 15, at 12:00
  91. f1 = Flip(owner=self.check)
  92. f1.created = datetime(2020, 1, 15, 12, 0, 0, tzinfo=timezone.utc)
  93. f1.old_status = "up"
  94. f1.new_status = "down"
  95. f1.save()
  96. # back up on Jan 15, at 13:00
  97. f2 = Flip(owner=self.check)
  98. f2.created = datetime(2020, 1, 15, 13, 0, 0, tzinfo=timezone.utc)
  99. f2.old_status = "down"
  100. f2.new_status = "up"
  101. f2.save()
  102. self.client.login(username="[email protected]", password="password")
  103. r = self.client.get(self.url)
  104. self.assertContains(r, "Feb. 2020")
  105. self.assertContains(r, "Jan. 2020")
  106. self.assertContains(r, "Dec. 2019")
  107. # The summary for Jan. 2020 should be "1 downtime, 1 hour total"
  108. self.assertContains(r, "1 downtime, 1 hour total", html=True)
  109. @patch("hc.lib.date.timezone.now")
  110. def test_it_handles_months_when_check_did_not_exist(self, mock_now):
  111. mock_now.return_value = datetime(2020, 2, 1, tzinfo=timezone.utc)
  112. self.check.created = datetime(2020, 1, 10, 0, 0, 0, tzinfo=timezone.utc)
  113. self.check.save()
  114. self.client.login(username="[email protected]", password="password")
  115. r = self.client.get(self.url)
  116. self.assertContains(r, "Feb. 2020")
  117. self.assertContains(r, "Jan. 2020")
  118. self.assertContains(r, "Dec. 2019")
  119. # The summary for Dec. 2019 should be "–"
  120. self.assertContains(r, "<td>–</td>", html=True)
  121. def test_it_handles_no_ping_key(self):
  122. self.project.show_slugs = True
  123. self.project.ping_key = None
  124. self.project.save()
  125. self.client.login(username="[email protected]", password="password")
  126. r = self.client.get(self.url)
  127. self.assertContains(r, "Ping Key Required", status_code=200)
  128. self.assertNotContains(r, "ping-now")
  129. def test_it_handles_no_ping_key_for_readonly_user(self):
  130. self.project.show_slugs = True
  131. self.project.ping_key = None
  132. self.project.save()
  133. self.bobs_membership.role = "r"
  134. self.bobs_membership.save()
  135. self.client.login(username="[email protected]", password="password")
  136. r = self.client.get(self.url)
  137. self.assertNotContains(r, "Ping Key Required", status_code=200)
  138. self.assertNotContains(r, "ping-now")
  139. def test_it_handles_empty_slug(self):
  140. self.project.show_slugs = True
  141. self.project.save()
  142. self.client.login(username="[email protected]", password="password")
  143. r = self.client.get(self.url)
  144. self.assertContains(r, "(unavailable, set name first)", status_code=200)
  145. self.assertNotContains(r, "Copy URL")
  146. self.assertNotContains(r, "ping-now")
  147. def test_it_saves_url_format_preference(self):
  148. self.client.login(username="[email protected]", password="password")
  149. self.client.get(self.url + "?urls=slug")
  150. self.project.refresh_from_db()
  151. self.assertTrue(self.project.show_slugs)