Skip to content

Commit 491d470

Browse files
committed
Validate response set cannot be submitted without being complete
1 parent d37fa29 commit 491d470

25 files changed

Lines changed: 273 additions & 193 deletions

features/questionnaire.feature

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
Feature: Questionnaire
22
Scenario: Cannot change responses once submitted
33
Given I am logged in
4-
And I have already submitted my responses
4+
And I have recently submitted my responses
55
When I go to "/start"
66
And I click "Start now"
77
Then I am on "/confirmation"

features/steps/participant_steps.py

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,14 @@
11
from behave import given
22
from django.utils import timezone
33

4+
from lung_cancer_screening.questions.tests.factories.response_set_factory import ResponseSetFactory
45

5-
@given('I have already submitted my responses')
6+
7+
@given('I have recently submitted my responses')
68
def given_i_have_already_submitted_my_responses(context):
7-
context.current_user.responseset_set.create(
8-
submitted_at=timezone.now()
9+
ResponseSetFactory.create(
10+
user=context.current_user,
11+
recently_submitted=True
912
)
1013

1114
@given('I have started the questionnaire')

lung_cancer_screening/questions/models/response_set.py

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@ class Meta:
4242
def clean(self):
4343
super().clean()
4444
self._validate_any_submitted_response_set_recently()
45+
self._validate_complete_on_submission()
4546

4647

4748
def has_user_submitted_response_set_recently(self):
@@ -55,6 +56,13 @@ def _validate_any_submitted_response_set_recently(self):
5556
)
5657

5758

59+
def _validate_complete_on_submission(self):
60+
if self.submitted_at and not self.is_complete():
61+
raise ValidationError(
62+
"Response set must be complete before it can be submitted"
63+
)
64+
65+
5866
def _response_attrs(self):
5967
response_attrs = [
6068
'asbestos_exposure_response',

lung_cancer_screening/questions/tests/factories/response_set_factory.py

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,23 @@
11
import factory
2+
from datetime import timedelta
3+
from django.utils import timezone
24

35
from .user_factory import UserFactory
46
from ...models.response_set import ResponseSet
57

68

9+
def set_submitted_at_recently(response_set, create, extracted):
10+
response_set.submitted_at = timezone.now() - timedelta(
11+
days=ResponseSet.RECENTLY_SUBMITTED_PERIOD_DAYS - 1
12+
)
13+
14+
15+
def set_submitted_at_not_recently(response_set, create, extracted):
16+
response_set.submitted_at = timezone.now() - timedelta(
17+
days=ResponseSet.RECENTLY_SUBMITTED_PERIOD_DAYS + 1
18+
)
19+
20+
721
class ResponseSetFactory(factory.django.DjangoModelFactory):
822
class Meta:
923
model = ResponseSet
@@ -69,3 +83,13 @@ class Params:
6983
factory_related_name="response_set"
7084
),
7185
)
86+
87+
not_recently_submitted = factory.Trait(
88+
complete=True,
89+
submitted_at=factory.PostGeneration(set_submitted_at_not_recently)
90+
)
91+
92+
recently_submitted = factory.Trait(
93+
complete=True,
94+
submitted_at=factory.PostGeneration(set_submitted_at_recently)
95+
)

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

Lines changed: 21 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
from django.test import TestCase, tag
22
from datetime import datetime
3-
from dateutil.relativedelta import relativedelta
43
from django.utils import timezone
54

65
from django.core.exceptions import ValidationError
@@ -70,25 +69,34 @@ def test_is_invalid_if_another_unsubmitted_response_set_exists(self):
7069
)
7170

7271
def test_is_invalid_if_another_response_set_was_submitted_within_the_recently_submitted_period(self):
73-
user = UserFactory()
74-
user.responseset_set.create(
75-
submitted_at=timezone.now() - relativedelta(days=ResponseSet.RECENTLY_SUBMITTED_PERIOD_DAYS - 1)
76-
)
72+
response_set = ResponseSetFactory.create(recently_submitted=True)
7773

7874
with self.assertRaises(ValidationError) as context:
79-
user.responseset_set.create()
75+
response_set.user.responseset_set.create()
8076

8177
self.assertEqual(
8278
context.exception.messages[0],
8379
"Responses have already been submitted for this user"
8480
)
8581

8682

87-
def test_submitted_response_set_is_valid_on_update(self):
83+
def test_Saving_a_submitted_response_Set_does_not_included_itself_in_unsubmitted_response_sets_validation(self):
84+
response_set = ResponseSetFactory.create(complete=True)
85+
response_set.submitted_at = timezone.now()
86+
87+
response_set.full_clean()
88+
89+
90+
def test_submitted_response_set_is_invalid_if_incomplete(self):
8891
self.response_set.submitted_at = timezone.now()
89-
self.response_set.save()
9092

91-
self.response_set.full_clean()
93+
with self.assertRaises(ValidationError) as context:
94+
self.response_set.full_clean()
95+
96+
self.assertEqual(
97+
context.exception.messages[0],
98+
"Response set must be complete before it can be submitted"
99+
)
92100

93101

94102
# Query managers
@@ -110,7 +118,7 @@ def test_objects_returns_all_response_sets(self):
110118

111119
def test_unsubmitted_returns_only_unsubmitted_response_sets(self):
112120
unsubmitted_response_set = ResponseSetFactory()
113-
submitted_response_set = ResponseSetFactory(submitted_at=timezone.now())
121+
submitted_response_set = ResponseSetFactory(recently_submitted=True)
114122

115123
unsubmitted_response_sets = ResponseSet.objects.unsubmitted().all()
116124
self.assertIn(
@@ -124,7 +132,7 @@ def test_unsubmitted_returns_only_unsubmitted_response_sets(self):
124132

125133
def test_submitted_returns_only_submitted_response_sets(self):
126134
unsubmitted_response_set = ResponseSetFactory()
127-
submitted_response_set = ResponseSetFactory(submitted_at=timezone.now() - relativedelta(years=1))
135+
submitted_response_set = ResponseSetFactory(not_recently_submitted=True)
128136

129137
submitted_response_sets = ResponseSet.objects.submitted().all()
130138
self.assertIn(
@@ -138,14 +146,10 @@ def test_submitted_returns_only_submitted_response_sets(self):
138146

139147
def test_submitted_recently_returns_only_submitted_response_sets_in_the_recently_submitted_period(self):
140148
recently_submitted_response = ResponseSetFactory(
141-
submitted_at=timezone.now() - relativedelta(
142-
days=ResponseSet.RECENTLY_SUBMITTED_PERIOD_DAYS - 1
143-
)
149+
recently_submitted=True
144150
)
145151
old_submitted_response = ResponseSetFactory(
146-
submitted_at=timezone.now() - relativedelta(
147-
days=ResponseSet.RECENTLY_SUBMITTED_PERIOD_DAYS + 1
148-
)
152+
not_recently_submitted=True
149153
)
150154

151155
recently_submitted_response_sets = ResponseSet.objects.recently_submitted().all()

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

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,8 @@
11
from datetime import datetime
22
from django.test import TestCase, tag
33
from django.core.exceptions import ValidationError
4-
from django.utils import timezone
5-
from datetime import timedelta
64

7-
from lung_cancer_screening.questions.models.response_set import ResponseSet
5+
from ...factories.response_set_factory import ResponseSetFactory
86
from ...factories.user_factory import UserFactory
97

108

@@ -82,14 +80,16 @@ def test_raises_a_validation_error_if_nhs_number_is_duplicate(self):
8280

8381

8482
def test_has_recently_submitted_responses_returns_true_if_has_recently_submitted_response_set(self):
85-
self.user.responseset_set.create(
86-
submitted_at=timezone.now() - timedelta(days=ResponseSet.RECENTLY_SUBMITTED_PERIOD_DAYS - 1)
83+
ResponseSetFactory.create(
84+
user=self.user,
85+
recently_submitted=True
8786
)
8887
self.assertTrue(self.user.has_recently_submitted_responses())
8988

9089

9190
def test_has_recently_submitted_responses_returns_false_if_has_no_recently_submitted_response_set(self):
92-
self.user.responseset_set.create(
93-
submitted_at=timezone.now() - timedelta(days=ResponseSet.RECENTLY_SUBMITTED_PERIOD_DAYS)
91+
ResponseSetFactory.create(
92+
user=self.user,
93+
not_recently_submitted=True
9494
)
9595
self.assertFalse(self.user.has_recently_submitted_responses())

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

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,8 @@
11
from django.test import TestCase
22
from django.urls import reverse
3-
from dateutil.relativedelta import relativedelta
4-
from django.utils import timezone
53

64
from .helpers.authentication import login_user
7-
5+
from ...factories.response_set_factory import ResponseSetFactory
86

97
class TestGetAgeRangeExit(TestCase):
108
def setUp(self):
@@ -26,8 +24,9 @@ def test_get_redirects_if_the_user_is_not_logged_in(self):
2624
def test_get_redirects_when_submitted_response_set_exists_within_last_year( # noqa: E501
2725
self
2826
):
29-
self.user.responseset_set.create(
30-
submitted_at=timezone.now() - relativedelta(days=364)
27+
ResponseSetFactory.create(
28+
user=self.user,
29+
recently_submitted=True
3130
)
3231

3332
response = self.client.get(

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

Lines changed: 11 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,9 @@
11
from django.test import TestCase, tag
22
from django.urls import reverse
3-
from dateutil.relativedelta import relativedelta
4-
from django.utils import timezone
53

64
from .helpers.authentication import login_user
75
from lung_cancer_screening.questions.models.asbestos_exposure_response import AsbestosExposureResponse
6+
from ...factories.response_set_factory import ResponseSetFactory
87

98

109
@tag("AsbestosExposure")
@@ -24,8 +23,9 @@ def test_get_redirects_if_the_user_is_not_logged_in(self):
2423

2524

2625
def test_get_redirects_when_an_submitted_response_set_exists_within_the_last_year(self):
27-
self.user.responseset_set.create(
28-
submitted_at=timezone.now() - relativedelta(days=364)
26+
ResponseSetFactory.create(
27+
user=self.user,
28+
recently_submitted=True
2929
)
3030

3131
response = self.client.get(
@@ -94,9 +94,10 @@ def test_post_updates_an_unsubmitted_response_set_for_the_user_when_an_unsubmitt
9494
self.assertEqual(response_set.user, self.user)
9595

9696

97-
def test_post_creates_an_new_unsubmitted_response_set_for_the_user_when_an_submitted_response_set_exists_over_a_year_ago(self):
98-
self.user.responseset_set.create(
99-
submitted_at=timezone.now() - relativedelta(years=1)
97+
def test_post_creates_an_new_unsubmitted_response_set_for_the_user_when_a_non_recently_submitted_response_set_exists(self):
98+
ResponseSetFactory.create(
99+
user=self.user,
100+
not_recently_submitted=True
100101
)
101102

102103
self.client.post(
@@ -114,8 +115,9 @@ def test_post_creates_an_new_unsubmitted_response_set_for_the_user_when_an_submi
114115

115116

116117
def test_post_redirects_when_an_submitted_response_set_exists_within_the_last_year(self):
117-
self.user.responseset_set.create(
118-
submitted_at=timezone.now() - relativedelta(days=364)
118+
ResponseSetFactory.create(
119+
user=self.user,
120+
recently_submitted=True
119121
)
120122

121123
response = self.client.post(

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

Lines changed: 11 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,8 @@
11
from django.test import TestCase, tag
22
from django.urls import reverse
3-
from dateutil.relativedelta import relativedelta
4-
from django.utils import timezone
53

64
from .helpers.authentication import login_user
7-
5+
from ...factories.response_set_factory import ResponseSetFactory
86

97
@tag("CancerDiagnosis")
108
class TestGetCancerDiagnosis(TestCase):
@@ -27,8 +25,9 @@ def test_get_redirects_if_the_user_is_not_logged_in(self):
2725
def test_get_redirects_when_submitted_response_set_exists_within_last_year(
2826
self
2927
):
30-
self.user.responseset_set.create(
31-
submitted_at=timezone.now() - relativedelta(days=364)
28+
ResponseSetFactory.create(
29+
user=self.user,
30+
recently_submitted=True
3231
)
3332

3433
response = self.client.get(
@@ -88,11 +87,12 @@ def test_post_updates_unsubmitted_response_set_when_one_exists(self):
8887
self.assertEqual(response_set.submitted_at, None)
8988
self.assertEqual(response_set.user, self.user)
9089

91-
def test_post_creates_new_unsubmitted_response_set_when_submitted_exists_over_year_ago(
90+
def test_post_creates_new_unsubmitted_response_set_when_not_recently_submitted_exists(
9291
self
9392
):
94-
self.user.responseset_set.create(
95-
submitted_at=timezone.now() - relativedelta(years=1)
93+
ResponseSetFactory.create(
94+
user=self.user,
95+
not_recently_submitted=True
9696
)
9797

9898
self.client.post(
@@ -109,8 +109,9 @@ def test_post_creates_new_unsubmitted_response_set_when_submitted_exists_over_ye
109109
def test_post_redirects_when_submitted_response_set_exists_within_last_year(
110110
self
111111
):
112-
self.user.responseset_set.create(
113-
submitted_at=timezone.now() - relativedelta(days=364)
112+
ResponseSetFactory.create(
113+
user=self.user,
114+
recently_submitted=True
114115
)
115116

116117
response = self.client.post(

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

Lines changed: 11 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,9 @@
11
from django.test import TestCase, tag
22
from django.urls import reverse
3-
from dateutil.relativedelta import relativedelta
4-
from django.utils import timezone
53

64
from .helpers.authentication import login_user
75
from lung_cancer_screening.questions.models.check_need_appointment_response import CheckNeedAppointmentResponse
6+
from ...factories.response_set_factory import ResponseSetFactory
87

98
@tag("CheckNeedAppointment")
109
class TestGetCheckNeedAppointment(TestCase):
@@ -23,8 +22,9 @@ def test_get_redirects_if_the_user_is_not_logged_in(self):
2322

2423

2524
def test_get_redirects_when_an_submitted_response_set_exists_within_the_last_year(self):
26-
self.user.responseset_set.create(
27-
submitted_at=timezone.now() - relativedelta(days=364)
25+
ResponseSetFactory.create(
26+
user=self.user,
27+
recently_submitted=True
2828
)
2929

3030
response = self.client.get(
@@ -92,9 +92,10 @@ def test_post_updates_an_unsubmitted_response_set_for_the_user_when_an_unsubmitt
9292
self.assertEqual(response_set.user, self.user)
9393

9494

95-
def test_post_creates_an_new_unsubmitted_response_set_for_the_user_when_an_submitted_response_set_exists_over_a_year_ago(self):
96-
self.user.responseset_set.create(
97-
submitted_at=timezone.now() - relativedelta(years=1)
95+
def test_post_creates_an_new_unsubmitted_response_set_for_the_user_when_a_non_recently_submitted_response_set_exists(self):
96+
ResponseSetFactory.create(
97+
user=self.user,
98+
not_recently_submitted=True
9899
)
99100

100101
self.client.post(
@@ -112,8 +113,9 @@ def test_post_creates_an_new_unsubmitted_response_set_for_the_user_when_an_submi
112113

113114

114115
def test_post_redirects_when_an_submitted_response_set_exists_within_the_last_year(self):
115-
self.user.responseset_set.create(
116-
submitted_at=timezone.now() - relativedelta(days=364)
116+
ResponseSetFactory.create(
117+
user=self.user,
118+
recently_submitted=True
117119
)
118120

119121
response = self.client.post(

0 commit comments

Comments
 (0)