Skip to content

Commit ea8bb6b

Browse files
committed
Ensure only able to view and modify unsubmitted ResponseSet
1 parent ead190c commit ea8bb6b

File tree

14 files changed

+155
-13
lines changed

14 files changed

+155
-13
lines changed

lung_cancer_screening/questions/models/participant.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,3 +3,9 @@
33

44
class Participant(BaseModel):
55
unique_id = models.CharField(max_length=255, unique=True)
6+
7+
def unsubmitted_response_sets(self):
8+
return self.responseset_set.filter(submitted_at__isnull=True)
9+
10+
def has_unsubmitted_response_set(self):
11+
return self.unsubmitted_response_sets().exists()

lung_cancer_screening/questions/tests/unit/models/test_participant.py

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
from django.test import TestCase
22
from datetime import datetime, date
3+
from django.utils import timezone
34
from django.core.exceptions import ValidationError
45

56

@@ -41,3 +42,23 @@ def test_raises_a_validation_error_if_the_unique_id_is_null(self):
4142
def test_raises_a_validation_error_if_the_unique_id_is_empty(self):
4243
with self.assertRaises(ValidationError):
4344
Participant.objects.create(unique_id="")
45+
46+
def test_unsubmitted_response_sets_returns_only_responses_that_have_not_been_submitted(self):
47+
unsubmitted = self.participant.responseset_set.create(
48+
submitted_at=None
49+
)
50+
submitted = self.participant.responseset_set.create(
51+
submitted_at=timezone.now()
52+
)
53+
54+
unsubmitted_response_sets = list(self.participant.unsubmitted_response_sets())
55+
self.assertIn(unsubmitted, unsubmitted_response_sets)
56+
self.assertNotIn(submitted, unsubmitted_response_sets)
57+
58+
def test_has_unsubmitted_response_set_returns_true_if_the_participant_has_an_unsubmitted_response_set(self):
59+
self.participant.responseset_set.create(submitted_at=None)
60+
self.assertTrue(self.participant.has_unsubmitted_response_set())
61+
62+
def test_has_unsubmitted_response_set_returns_false_if_the_participant_has_no_unsubmitted_response_set(self):
63+
self.participant.responseset_set.create(submitted_at=timezone.now())
64+
self.assertFalse(self.participant.has_unsubmitted_response_set())

lung_cancer_screening/questions/tests/unit/views/test_age_range_exit.py

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,16 @@
11
from django.test import TestCase
22
from django.urls import reverse
3+
from django.utils import timezone
34

45
from lung_cancer_screening.questions.models.participant import Participant
56

67
class TestPostAgeRangeExit(TestCase):
78
def setUp(self):
8-
participant = Participant.objects.create(unique_id="12345")
9+
self.participant = Participant.objects.create(unique_id="12345")
10+
self.participant.responseset_set.create()
911

1012
session = self.client.session
11-
session['participant_id'] = participant.unique_id
13+
session['participant_id'] = self.participant.unique_id
1214
session.save()
1315

1416
def test_get_redirects_if_the_particpant_does_not_exist(self):
@@ -22,6 +24,15 @@ def test_get_redirects_if_the_particpant_does_not_exist(self):
2224

2325
self.assertRedirects(response, reverse("questions:start"))
2426

27+
def test_get_redirects_if_the_particpant_has_no_unsubmitted_response_set(self):
28+
self.participant.responseset_set.all().update(submitted_at=timezone.now())
29+
30+
response = self.client.get(
31+
reverse("questions:age_range_exit")
32+
)
33+
34+
self.assertRedirects(response, reverse("questions:start"))
35+
2536
def test_get_responds_successfully(self):
2637
response = self.client.get(reverse("questions:age_range_exit"))
2738

lung_cancer_screening/questions/tests/unit/views/test_date_of_birth.py

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
from django.test import TestCase
22
from django.urls import reverse
33
from datetime import date
4+
from django.utils import timezone
45
from dateutil.relativedelta import relativedelta
56

67
from ....models.participant import Participant
@@ -38,6 +39,15 @@ def test_get_redirects_if_the_particpant_does_not_exist(self):
3839

3940
self.assertRedirects(response, reverse("questions:start"))
4041

42+
def test_get_redirects_if_the_participant_has_no_unsubmitted_response_set(self):
43+
self.participant.responseset_set.all().update(submitted_at=timezone.now())
44+
45+
response = self.client.get(
46+
reverse("questions:date_of_birth")
47+
)
48+
49+
self.assertRedirects(response, reverse("questions:start"))
50+
4151
def test_get_responds_successfully(self):
4252
response = self.client.get(reverse("questions:date_of_birth"))
4353

@@ -55,6 +65,16 @@ def test_post_redirects_if_the_particpant_does_not_exist(self):
5565

5666
self.assertRedirects(response, reverse("questions:start"))
5767

68+
def test_post_redirects_if_the_participant_has_no_unsubmitted_response_set(self):
69+
self.participant.responseset_set.all().update(submitted_at=timezone.now())
70+
71+
response = self.client.post(
72+
reverse("questions:date_of_birth"),
73+
self.valid_params
74+
)
75+
76+
self.assertRedirects(response, reverse("questions:start"))
77+
5878
def test_post_stores_a_valid_response_set_for_the_participant(self):
5979
self.client.post(
6080
reverse("questions:date_of_birth"),

lung_cancer_screening/questions/tests/unit/views/test_have_you_ever_smoked.py

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
from django.test import TestCase
22
from django.urls import reverse
3+
from django.utils import timezone
34

45
from lung_cancer_screening.questions.models.participant import Participant
56
from lung_cancer_screening.questions.models.response_set import HaveYouEverSmokedValues
@@ -25,6 +26,15 @@ def test_get_redirects_if_the_particpant_does_not_exist(self):
2526

2627
self.assertRedirects(response, reverse("questions:start"))
2728

29+
def test_get_redirects_if_the_particpant_has_no_unsubmitted_response_set(self):
30+
self.participant.responseset_set.all().update(submitted_at=timezone.now())
31+
32+
response = self.client.get(
33+
reverse("questions:have_you_ever_smoked")
34+
)
35+
36+
self.assertRedirects(response, reverse("questions:start"))
37+
2838
def test_get_responds_successfully(self):
2939
response = self.client.get(reverse("questions:have_you_ever_smoked"))
3040

@@ -42,6 +52,16 @@ def test_post_redirects_if_the_particpant_does_not_exist(self):
4252

4353
self.assertRedirects(response, reverse("questions:start"))
4454

55+
def test_post_redirects_if_the_participant_has_no_unsubmitted_response_set(self):
56+
self.participant.responseset_set.all().update(submitted_at=timezone.now())
57+
58+
response = self.client.post(
59+
reverse("questions:have_you_ever_smoked"),
60+
self.valid_params
61+
)
62+
63+
self.assertRedirects(response, reverse("questions:start"))
64+
4565
def test_post_stores_a_valid_response_for_the_participant(self):
4666
self.client.post(
4767
reverse("questions:have_you_ever_smoked"),

lung_cancer_screening/questions/tests/unit/views/test_non_smoker_exit.py

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,16 @@
11
from django.test import TestCase
22
from django.urls import reverse
3+
from django.utils import timezone
34

45
from lung_cancer_screening.questions.models.participant import Participant
56

67
class TestPostNonSmokerExit(TestCase):
78
def setUp(self):
8-
participant = Participant.objects.create(unique_id="12345")
9+
self.participant = Participant.objects.create(unique_id="12345")
10+
self.participant.responseset_set.create()
911

1012
session = self.client.session
11-
session['participant_id'] = participant.unique_id
13+
session['participant_id'] = self.participant.unique_id
1214
session.save()
1315

1416
def test_get_redirects_if_the_particpant_does_not_exist(self):
@@ -22,6 +24,15 @@ def test_get_redirects_if_the_particpant_does_not_exist(self):
2224

2325
self.assertRedirects(response, reverse("questions:start"))
2426

27+
def test_get_redirects_if_the_particpant_has_no_unsubmitted_response_set(self):
28+
self.participant.responseset_set.all().update(submitted_at=timezone.now())
29+
30+
response = self.client.get(
31+
reverse("questions:non_smoker_exit")
32+
)
33+
34+
self.assertRedirects(response, reverse("questions:start"))
35+
2536
def test_get_responds_successfully(self):
2637
response = self.client.get(reverse("questions:non_smoker_exit"))
2738

lung_cancer_screening/questions/tests/unit/views/test_responses.py

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
from django.test import TestCase
22
from django.urls import reverse
3+
from django.utils import timezone
34
from datetime import date
45

56
from lung_cancer_screening.questions.models.participant import Participant
@@ -26,6 +27,15 @@ def test_get_redirects_if_the_participant_does_not_exist(self):
2627

2728
self.assertRedirects(response, reverse("questions:start"))
2829

30+
def test_get_redirects_if_the_particpant_has_no_unsubmitted_response_set(self):
31+
self.participant.responseset_set.all().update(submitted_at=timezone.now())
32+
33+
response = self.client.get(
34+
reverse("questions:responses")
35+
)
36+
37+
self.assertRedirects(response, reverse("questions:start"))
38+
2939
def test_get_responds_successfully(self):
3040
response = self.client.get(reverse("questions:responses"))
3141

@@ -47,6 +57,36 @@ def test_get_does_not_contain_responses_for_other_participants(self):
4757
response, other_date_response.get_have_you_ever_smoked_display())
4858
self.assertNotContains(response, other_date_response.date_of_birth)
4959

60+
def test_get_does_not_contain_responses_which_have_already_been_submitted(self):
61+
submitted = self.participant.responseset_set.create(
62+
have_you_ever_smoked=False,
63+
date_of_birth=date(1966, 1, 1),
64+
submitted_at=timezone.now()
65+
)
66+
67+
response = self.client.get(reverse("questions:responses"))
68+
69+
self.assertNotContains(response, submitted.get_have_you_ever_smoked_display())
70+
self.assertNotContains(response, submitted.date_of_birth)
71+
72+
def test_post_redirects_if_the_participant_does_not_exist(self):
73+
session = self.client.session
74+
session['participant_id'] = "somebody none existant participant"
75+
session.save()
76+
77+
response = self.client.post(reverse("questions:responses"))
78+
79+
self.assertRedirects(response, reverse("questions:start"))
80+
81+
def test_post_redirects_if_the_particpant_has_no_unsubmitted_response_set(self):
82+
self.participant.responseset_set.all().update(submitted_at=timezone.now())
83+
84+
response = self.client.get(
85+
reverse("questions:responses")
86+
)
87+
88+
self.assertRedirects(response, reverse("questions:start"))
89+
5090
def test_post_redirects_to_your_results(self):
5191
response = self.client.post(reverse("questions:responses"))
5292

lung_cancer_screening/questions/views/age_range_exit.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,9 @@
11
from django.shortcuts import render
22

3-
from .decorators.participant_decorators import require_participant
3+
from .decorators.participant_decorators import require_participant, require_unsubmitted_response_set
44

55
@require_participant
6+
@require_unsubmitted_response_set
67
def age_range_exit(request):
78
return render(
89
request,

lung_cancer_screening/questions/views/date_of_birth.py

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,11 @@
33
from datetime import date
44
from dateutil.relativedelta import relativedelta
55

6-
from .decorators.participant_decorators import require_participant
6+
from .decorators.participant_decorators import require_participant, require_unsubmitted_response_set
77
from ..forms.date_of_birth_form import DateOfBirthForm
88

99
@require_participant
10+
@require_unsubmitted_response_set
1011
def date_of_birth(request):
1112
if request.method == "POST":
1213
form = DateOfBirthForm(
@@ -20,7 +21,7 @@ def date_of_birth(request):
2021
date_of_birth = form.cleaned_data["date_of_birth"]
2122

2223
if (seventy_five_years_ago < date_of_birth <= fifty_five_years_ago):
23-
response_set = request.participant.responseset_set.last()
24+
response_set = request.participant.unsubmitted_response_sets().last()
2425
response_set.date_of_birth = date_of_birth
2526
response_set.save()
2627

lung_cancer_screening/questions/views/decorators/participant_decorators.py

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,3 +15,12 @@ def wrap(request, *args, **kwargs):
1515

1616
return function(request, *args, **kwargs)
1717
return wrap
18+
19+
def require_unsubmitted_response_set(function):
20+
@wraps(function)
21+
def wrap(request, *args, **kwargs):
22+
if not request.participant.has_unsubmitted_response_set():
23+
return redirect(reverse("questions:start"))
24+
25+
return function(request, *args, **kwargs)
26+
return wrap

0 commit comments

Comments
 (0)