@ -9,13 +9,17 @@ class CheckTokenTestCase(BaseTestCase): | |||
self.profile.token = make_password("secret-token", "login") | |||
self.profile.save() | |||
self.checks_url = "/projects/%s/checks/" % self.project.code | |||
def test_it_shows_form(self): | |||
r = self.client.get("/accounts/check_token/alice/secret-token/") | |||
self.assertContains(r, "You are about to log in") | |||
def test_it_redirects(self): | |||
r = self.client.post("/accounts/check_token/alice/secret-token/") | |||
self.assertRedirects(r, "/checks/") | |||
r = self.client.post("/accounts/check_token/alice/secret-token/", | |||
follow=True) | |||
self.assertRedirects(r, self.checks_url) | |||
# After login, token should be blank | |||
self.profile.refresh_from_db() | |||
@ -26,8 +30,10 @@ class CheckTokenTestCase(BaseTestCase): | |||
self.client.login(username="[email protected]", password="password") | |||
# Login again, when already authenticated | |||
r = self.client.post("/accounts/check_token/alice/secret-token/") | |||
self.assertRedirects(r, "/checks/") | |||
r = self.client.post("/accounts/check_token/alice/secret-token/", | |||
follow=True) | |||
self.assertRedirects(r, self.checks_url) | |||
def test_it_redirects_bad_login(self): | |||
# Login with a bad token | |||
@ -37,9 +43,11 @@ class CheckTokenTestCase(BaseTestCase): | |||
self.assertContains(r, "incorrect or expired") | |||
def test_it_handles_next_parameter(self): | |||
r = self.client.post("/accounts/check_token/alice/secret-token/?next=/integrations/add_slack/") | |||
url = "/accounts/check_token/alice/secret-token/?next=/integrations/add_slack/" | |||
r = self.client.post(url) | |||
self.assertRedirects(r, "/integrations/add_slack/") | |||
def test_it_ignores_bad_next_parameter(self): | |||
r = self.client.post("/accounts/check_token/alice/secret-token/?next=/evil/") | |||
self.assertRedirects(r, "/checks/") | |||
url = "/accounts/check_token/alice/secret-token/?next=/evil/" | |||
r = self.client.post(url, follow=True) | |||
self.assertRedirects(r, self.checks_url) |
@ -6,6 +6,10 @@ from hc.test import BaseTestCase | |||
class LoginTestCase(BaseTestCase): | |||
def setUp(self): | |||
super(LoginTestCase, self).setUp() | |||
self.checks_url = "/projects/%s/checks/" % self.project.code | |||
def test_it_sends_link(self): | |||
form = {"identity": "[email protected]"} | |||
@ -49,8 +53,8 @@ class LoginTestCase(BaseTestCase): | |||
"password": "password" | |||
} | |||
r = self.client.post("/accounts/login/", form) | |||
self.assertRedirects(r, "/checks/") | |||
r = self.client.post("/accounts/login/", form, follow=True) | |||
self.assertRedirects(r, self.checks_url) | |||
def test_it_handles_password_login_with_redirect(self): | |||
check = Check.objects.create(project=self.project) | |||
@ -77,8 +81,8 @@ class LoginTestCase(BaseTestCase): | |||
"password": "password" | |||
} | |||
r = self.client.post("/accounts/login/?next=/evil/", form) | |||
self.assertRedirects(r, "/checks/") | |||
r = self.client.post("/accounts/login/?next=/evil/", form, follow=True) | |||
self.assertRedirects(r, self.checks_url) | |||
def test_it_handles_wrong_password(self): | |||
form = { | |||
@ -1,50 +0,0 @@ | |||
from hc.test import BaseTestCase | |||
from hc.api.models import Check | |||
class SwitchTeamTestCase(BaseTestCase): | |||
def setUp(self): | |||
super(SwitchTeamTestCase, self).setUp() | |||
self.url = "/accounts/switch_project/%s/" % self.project.code | |||
def test_it_switches(self): | |||
self.bobs_profile.current_project = None | |||
self.bobs_profile.save() | |||
c = Check(project=self.project, name="This belongs to Alice") | |||
c.save() | |||
self.client.login(username="[email protected]", password="password") | |||
r = self.client.get(self.url, follow=True) | |||
self.assertContains(r, "This belongs to Alice") | |||
self.bobs_profile.refresh_from_db() | |||
self.assertEqual(self.bobs_profile.current_project, self.project) | |||
def test_it_checks_team_membership(self): | |||
self.client.login(username="[email protected]", password="password") | |||
r = self.client.get(self.url) | |||
self.assertEqual(r.status_code, 403) | |||
def test_it_switches_to_own_team(self): | |||
self.client.login(username="[email protected]", password="password") | |||
r = self.client.get(self.url, follow=True) | |||
self.assertEqual(r.status_code, 200) | |||
def test_it_handles_invalid_project_code(self): | |||
self.client.login(username="[email protected]", password="password") | |||
url = "/accounts/switch_project/6837d6ec-fc08-4da5-a67f-08a9ed1ccf62/" | |||
r = self.client.get(url) | |||
self.assertEqual(r.status_code, 404) | |||
def test_it_requires_login(self): | |||
r = self.client.get(self.url) | |||
expected_url = "/accounts/login/?next=" + self.url | |||
self.assertRedirects(r, expected_url) |
@ -3,12 +3,16 @@ from hc.test import BaseTestCase | |||
class AddCheckTestCase(BaseTestCase): | |||
def setUp(self): | |||
super(AddCheckTestCase, self).setUp() | |||
self.url = "/projects/%s/checks/add/" % self.project.code | |||
self.redirect_url = "/projects/%s/checks/" % self.project.code | |||
def test_it_works(self): | |||
url = "/checks/add/" | |||
self.client.login(username="[email protected]", password="password") | |||
r = self.client.post(url) | |||
self.assertRedirects(r, "/checks/") | |||
r = self.client.post(self.url) | |||
self.assertRedirects(r, self.redirect_url) | |||
check = Check.objects.get() | |||
self.assertEqual(check.project, self.project) | |||
@ -16,33 +20,29 @@ class AddCheckTestCase(BaseTestCase): | |||
self.profile.current_project = None | |||
self.profile.save() | |||
url = "/checks/add/" | |||
self.client.login(username="[email protected]", password="password") | |||
r = self.client.post(url) | |||
self.assertRedirects(r, "/checks/") | |||
r = self.client.post(self.url) | |||
self.assertRedirects(r, self.redirect_url) | |||
check = Check.objects.get() | |||
self.assertEqual(check.project, self.project) | |||
def test_team_access_works(self): | |||
url = "/checks/add/" | |||
self.client.login(username="[email protected]", password="password") | |||
self.client.post(url) | |||
self.client.post(self.url) | |||
check = Check.objects.get() | |||
# Added by bob, but should belong to alice (bob has team access) | |||
self.assertEqual(check.project, self.project) | |||
def test_it_rejects_get(self): | |||
url = "/checks/add/" | |||
self.client.login(username="[email protected]", password="password") | |||
r = self.client.get(url) | |||
r = self.client.get(self.url) | |||
self.assertEqual(r.status_code, 405) | |||
def test_it_obeys_check_limit(self): | |||
self.profile.check_limit = 0 | |||
self.profile.save() | |||
url = "/checks/add/" | |||
self.client.login(username="[email protected]", password="password") | |||
r = self.client.post(url) | |||
r = self.client.post(self.url) | |||
self.assertEqual(r.status_code, 400) |
@ -11,19 +11,37 @@ class MyChecksTestCase(BaseTestCase): | |||
self.check = Check(project=self.project, name="Alice Was Here") | |||
self.check.save() | |||
self.url = "/projects/%s/checks/" % self.project.code | |||
def test_it_works(self): | |||
for email in ("[email protected]", "[email protected]"): | |||
self.client.login(username=email, password="password") | |||
r = self.client.get("/checks/") | |||
r = self.client.get(self.url) | |||
self.assertContains(r, "Alice Was Here", status_code=200) | |||
def test_it_updates_current_project(self): | |||
self.profile.current_project = None | |||
self.profile.save() | |||
self.client.login(username="[email protected]", password="password") | |||
r = self.client.get(self.url) | |||
self.assertEqual(r.status_code, 200) | |||
self.profile.refresh_from_db() | |||
self.assertEqual(self.profile.current_project, self.project) | |||
def test_it_checks_access(self): | |||
self.client.login(username="[email protected]", password="password") | |||
r = self.client.get(self.url) | |||
self.assertEqual(r.status_code, 404) | |||
def test_it_shows_green_check(self): | |||
self.check.last_ping = timezone.now() | |||
self.check.status = "up" | |||
self.check.save() | |||
self.client.login(username="[email protected]", password="password") | |||
r = self.client.get("/checks/") | |||
r = self.client.get(self.url) | |||
self.assertContains(r, "icon-up") | |||
def test_it_shows_red_check(self): | |||
@ -32,7 +50,7 @@ class MyChecksTestCase(BaseTestCase): | |||
self.check.save() | |||
self.client.login(username="[email protected]", password="password") | |||
r = self.client.get("/checks/") | |||
r = self.client.get(self.url) | |||
self.assertContains(r, "icon-down") | |||
def test_it_shows_amber_check(self): | |||
@ -41,7 +59,7 @@ class MyChecksTestCase(BaseTestCase): | |||
self.check.save() | |||
self.client.login(username="[email protected]", password="password") | |||
r = self.client.get("/checks/") | |||
r = self.client.get(self.url) | |||
self.assertContains(r, "icon-grace") | |||
def test_it_hides_add_check_button(self): | |||
@ -49,19 +67,19 @@ class MyChecksTestCase(BaseTestCase): | |||
self.profile.save() | |||
self.client.login(username="[email protected]", password="password") | |||
r = self.client.get("/checks/") | |||
r = self.client.get(self.url) | |||
self.assertContains(r, "Check limit reached", status_code=200) | |||
def test_it_saves_sort_field(self): | |||
self.client.login(username="[email protected]", password="password") | |||
self.client.get("/checks/?sort=name") | |||
self.client.get(self.url + "?sort=name") | |||
self.profile.refresh_from_db() | |||
self.assertEqual(self.profile.sort, "name") | |||
def test_it_ignores_bad_sort_value(self): | |||
self.client.login(username="[email protected]", password="password") | |||
self.client.get("/checks/?sort=invalid") | |||
self.client.get(self.url + "?sort=invalid") | |||
self.profile.refresh_from_db() | |||
self.assertEqual(self.profile.sort, "created") | |||
@ -73,7 +91,7 @@ class MyChecksTestCase(BaseTestCase): | |||
self.check.save() | |||
self.client.login(username="[email protected]", password="password") | |||
r = self.client.get("/checks/") | |||
r = self.client.get(self.url) | |||
self.assertContains(r, """<div class="btn btn-xs down ">foo</div>""") | |||
def test_it_shows_grace_badge(self): | |||
@ -83,7 +101,7 @@ class MyChecksTestCase(BaseTestCase): | |||
self.check.save() | |||
self.client.login(username="[email protected]", password="password") | |||
r = self.client.get("/checks/") | |||
r = self.client.get(self.url) | |||
self.assertContains(r, """<div class="btn btn-xs grace ">foo</div>""") | |||
def test_it_shows_grace_started_badge(self): | |||
@ -94,5 +112,5 @@ class MyChecksTestCase(BaseTestCase): | |||
self.check.save() | |||
self.client.login(username="[email protected]", password="password") | |||
r = self.client.get("/checks/") | |||
r = self.client.get(self.url) | |||
self.assertContains(r, """<div class="btn btn-xs grace ">foo</div>""") |
@ -11,11 +11,12 @@ class PauseTestCase(BaseTestCase): | |||
super(PauseTestCase, self).setUp() | |||
self.check = Check.objects.create(project=self.project, status="up") | |||
self.url = "/checks/%s/pause/" % self.check.code | |||
self.redirect_url = "/projects/%s/checks/" % self.project.code | |||
def test_it_pauses(self): | |||
self.client.login(username="[email protected]", password="password") | |||
r = self.client.post(self.url) | |||
self.assertRedirects(r, "/checks/") | |||
self.assertRedirects(r, self.redirect_url) | |||
self.check.refresh_from_db() | |||
self.assertEqual(self.check.status, "paused") | |||
@ -31,7 +32,7 @@ class PauseTestCase(BaseTestCase): | |||
self.client.login(username="[email protected]", password="password") | |||
r = self.client.post(self.url) | |||
self.assertRedirects(r, "/checks/") | |||
self.assertRedirects(r, self.redirect_url) | |||
def test_it_clears_last_start_alert_after(self): | |||
self.check.last_start = now() | |||
@ -8,11 +8,12 @@ class RemoveCheckTestCase(BaseTestCase): | |||
super(RemoveCheckTestCase, self).setUp() | |||
self.check = Check.objects.create(project=self.project) | |||
self.remove_url = "/checks/%s/remove/" % self.check.code | |||
self.redirect_url = "/projects/%s/checks/" % self.project.code | |||
def test_it_works(self): | |||
self.client.login(username="[email protected]", password="password") | |||
r = self.client.post(self.remove_url) | |||
self.assertRedirects(r, "/checks/") | |||
self.assertRedirects(r, self.redirect_url) | |||
self.assertEqual(Check.objects.count(), 0) | |||
@ -53,4 +54,4 @@ class RemoveCheckTestCase(BaseTestCase): | |||
self.client.login(username="[email protected]", password="password") | |||
r = self.client.post(self.remove_url) | |||
self.assertRedirects(r, "/checks/") | |||
self.assertRedirects(r, self.redirect_url) |
@ -9,11 +9,12 @@ class UpdateNameTestCase(BaseTestCase): | |||
self.check = Check.objects.create(project=self.project) | |||
self.url = "/checks/%s/name/" % self.check.code | |||
self.redirect_url = "/projects/%s/checks/" % self.project.code | |||
def test_it_works(self): | |||
self.client.login(username="[email protected]", password="password") | |||
r = self.client.post(self.url, data={"name": "Alice Was Here"}) | |||
self.assertRedirects(r, "/checks/") | |||
self.assertRedirects(r, self.redirect_url) | |||
self.check.refresh_from_db() | |||
self.assertEqual(self.check.name, "Alice Was Here") | |||
@ -37,7 +38,7 @@ class UpdateNameTestCase(BaseTestCase): | |||
# But this should still work: | |||
self.client.login(username="[email protected]", password="password") | |||
r = self.client.post(self.url, data={"name": "Bob Was Here"}) | |||
self.assertRedirects(r, "/checks/") | |||
self.assertRedirects(r, self.redirect_url) | |||
def test_it_checks_ownership(self): | |||
payload = {"name": "Charlie Sent This"} | |||
@ -14,13 +14,14 @@ class UpdateTimeoutTestCase(BaseTestCase): | |||
self.check.save() | |||
self.url = "/checks/%s/timeout/" % self.check.code | |||
self.redirect_url = "/projects/%s/checks/" % self.project.code | |||
def test_it_works(self): | |||
payload = {"kind": "simple", "timeout": 3600, "grace": 60} | |||
self.client.login(username="[email protected]", password="password") | |||
r = self.client.post(self.url, data=payload) | |||
self.assertRedirects(r, "/checks/") | |||
self.assertRedirects(r, self.redirect_url) | |||
self.check.refresh_from_db() | |||
self.assertEqual(self.check.kind, "simple") | |||
@ -55,7 +56,7 @@ class UpdateTimeoutTestCase(BaseTestCase): | |||
self.client.login(username="[email protected]", password="password") | |||
r = self.client.post(self.url, data=payload) | |||
self.assertRedirects(r, "/checks/") | |||
self.assertRedirects(r, self.redirect_url) | |||
self.check.refresh_from_db() | |||
self.assertEqual(self.check.kind, "cron") | |||
@ -184,4 +185,4 @@ class UpdateTimeoutTestCase(BaseTestCase): | |||
self.client.login(username="[email protected]", password="password") | |||
r = self.client.post(self.url, data=payload) | |||
self.assertRedirects(r, "/checks/") | |||
self.assertRedirects(r, self.redirect_url) |
@ -0,0 +1,15 @@ | |||
#my-projects a { | |||
display: block; | |||
color: #333; | |||
} | |||
#my-projects a:hover { | |||
text-decoration: none; | |||
} | |||
#my-projects a:hover .panel { | |||
border-color: #0091EA; | |||
} | |||
@ -1,5 +1,5 @@ | |||
<ul> | |||
{% for project in profile.user.project_set.all %} | |||
<li><a href="{% url 'hc-switch-project' project.code %}">{{ project }}</a></li> | |||
<li><a href="{% url 'hc-checks' project.code %}">{{ project }}</a></li> | |||
{% endfor %} | |||
</ul> |
@ -0,0 +1,58 @@ | |||
{% extends "base.html" %} | |||
{% load compress static hc_extras %} | |||
{% block title %}Project Settings - {{ project }}{% endblock %} | |||
{% block content %} | |||
<div class="row"> | |||
<div class="col-sm-12"> | |||
<h1 class="settings-title">My Projects</h1> | |||
{% for message in messages %} | |||
<p class="alert alert-{{ message.tags }}">{{ message }}</p> | |||
{% endfor %} | |||
<div id="my-projects" class="row"> | |||
{% for project in projects%} | |||
<a href="{% url 'hc-checks' project.code %}"> | |||
<div class="col-sm-6 col-md-4"> | |||
<div class="panel panel-default project-panel"> | |||
<div class="panel-body"> | |||
<h4>{{ project }}</h4> | |||
<div> | |||
{% with project.check_set.count as n %} | |||
{{ n }} check{{ n|pluralize }}, | |||
{% endwith %} | |||
{% with project.channel_set.count as n %} | |||
{{ n }} integration{{ n|pluralize }} | |||
{% endwith %} | |||
</div> | |||
{% if show_plans %} | |||
<div class="text-muted"> | |||
{% if project.owner.subscription %} | |||
Plan: {{ project.owner.subscription.plan_name }} | |||
{% else %} | |||
Plan: Hobbyist | |||
{% endif %} | |||
</div> | |||
{% endif %} | |||
</div> | |||
</div> | |||
</div> | |||
</a> | |||
{% endfor %} | |||
</div> | |||
</div> | |||
</div> | |||
{% endblock %} | |||
{% block scripts %} | |||
{% compress js %} | |||
<script src="{% static 'js/jquery-2.1.4.min.js' %}"></script> | |||
<script src="{% static 'js/bootstrap.min.js' %}"></script> | |||
<script src="{% static 'js/project.js' %}"></script> | |||
{% endcompress %} | |||
{% endblock %} |