Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -52,3 +52,11 @@ def fill_in_and_submit_weight_imperial(page, stone, pounds):
page.get_by_label("Pounds").fill(str(pounds))

page.click("text=Continue")

def fill_in_and_submit_sex_at_birth(page, sex):
expect(page.locator("legend")).to_have_text(
"What was your sex at birth?")

page.get_by_label(sex, exact=True).check()

page.click("text=Continue")
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,8 @@
fill_in_and_submit_weight_metric,
fill_in_and_submit_participant_id,
fill_in_and_submit_smoking_eligibility,
fill_in_and_submit_date_of_birth
fill_in_and_submit_date_of_birth,
fill_in_and_submit_sex_at_birth
)

class TestQuestionnaire(StaticLiveServerTestCase):
Expand Down Expand Up @@ -40,6 +41,7 @@ def test_cannot_change_responses_once_checked_and_submitted(self):
fill_in_and_submit_date_of_birth(page, age)
fill_in_and_submit_height_metric(page, "170")
fill_in_and_submit_weight_metric(page, "25.4")
fill_in_and_submit_sex_at_birth(page, "Male")

page.click("text=Submit")

Expand Down
27 changes: 15 additions & 12 deletions lung_cancer_screening/core/tests/acceptance/test_questionnaire.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,8 @@
fill_in_and_submit_smoking_eligibility,
fill_in_and_submit_date_of_birth,
fill_in_and_submit_weight_metric,
fill_in_and_submit_weight_imperial
fill_in_and_submit_weight_imperial,
fill_in_and_submit_sex_at_birth
)

from .helpers.assertion_helpers import expect_back_link_to_have_url
Expand Down Expand Up @@ -49,43 +50,45 @@ def test_full_questionnaire_user_journey(self):

expect(page).to_have_url(
f"{self.live_server_url}/have-you-ever-smoked")

expect_back_link_to_have_url(page, "/start")
fill_in_and_submit_smoking_eligibility(page, smoking_status)

expect(page).to_have_url(f"{self.live_server_url}/date-of-birth")
expect_back_link_to_have_url(page, "/have-you-ever-smoked")

fill_in_and_submit_date_of_birth(page, age)

expect(page).to_have_url(f"{self.live_server_url}/height")

expect_back_link_to_have_url(page, "/date-of-birth")
fill_in_and_submit_height_metric(page, height)

expect(page).to_have_url(f"{self.live_server_url}/weight")

page.click("text=Back")

expect(page).to_have_url(f"{self.live_server_url}/height")

page.click("text=Switch to imperial")

fill_in_and_submit_height_imperial(page, feet, inches)

expect(page).to_have_url(f"{self.live_server_url}/weight")

expect_back_link_to_have_url(page, "/height")
fill_in_and_submit_weight_metric(page, weight_metric)

expect(page).to_have_url(f"{self.live_server_url}/responses")
page.click("text=Back")

expect(page).to_have_url(f"{self.live_server_url}/weight")
page.get_by_role("link", name="Switch to stone and pounds").click()
fill_in_and_submit_weight_imperial(page, weight_stone, weight_pound)

expect(page).to_have_url(f"{self.live_server_url}/sex-at-birth")
expect_back_link_to_have_url(page, "/weight")
fill_in_and_submit_sex_at_birth(page, "Male")

expect(page).to_have_url(f"{self.live_server_url}/responses")
expect_back_link_to_have_url(page, "/sex-at-birth")

responses = page.locator(".responses")
expect(responses).to_contain_text("Have you ever smoked? Yes, I used to smoke regularly")
expect(responses).to_contain_text(
age.strftime("What is your date of birth? %Y-%m-%d"))
expect(responses).to_contain_text(f"What is your height? {feet} feet {inches} inches")
expect(responses).to_contain_text(f"What is your weight? {weight_stone} stone {weight_pound} pound")
expect(responses).to_contain_text("What was your sex at birth? Male")

page.click("text=Submit")

Expand Down
3 changes: 0 additions & 3 deletions lung_cancer_screening/nhsuk_forms/choice_field.py
Original file line number Diff line number Diff line change
@@ -1,16 +1,13 @@
from django import forms
from django.forms import widgets

from .bound_choice_field import BoundChoiceField

class ChoiceField(forms.ChoiceField):
"""
A ChoiceField that renders using NHS.UK design system radios/select
components.
"""

widget = widgets.RadioSelect
bound_field_class = BoundChoiceField

def __init__(
self,
Expand Down
10 changes: 1 addition & 9 deletions lung_cancer_screening/nhsuk_forms/jinja2/radios.jinja
Original file line number Diff line number Diff line change
Expand Up @@ -5,20 +5,12 @@
{% endif %}
{% set ns = namespace(items=[]) %}
{% for value, text in unbound_field.choices %}
{% set conditional_html = field.conditional_html(value) %}
{% set ns.items = ns.items + [{
"id": field.auto_id if loop.first,
"value": value,
"text": text,
"checked": field.value() == value,
"conditional": {
"html": conditional_html
} if conditional_html else undefined
"checked": field.value() == value
}] %}
{% set divider = field.get_divider_after(value) %}
{% if divider %}
{% set ns.items = ns.items + [{"divider": divider}] %}
{% endif %}
{% endfor %}
{{ radios({
"name": field.html_name,
Expand Down
38 changes: 0 additions & 38 deletions lung_cancer_screening/nhsuk_forms/tests/unit/test_choice_field.py
Original file line number Diff line number Diff line change
Expand Up @@ -38,41 +38,3 @@ def test_renders_nhs_radios(self):
</div>
""",
)

def test_renders_radios_with_conditional_html(self):
form = TestForm()
form["field"].add_conditional_html("b", "<p>Hello</p>")

self.assertHTMLEqual(
form["field"].as_field_group(),
"""
<div class="nhsuk-form-group">
<fieldset aria-describedby="id_field-hint" class="nhsuk-fieldset">
<legend class="nhsuk-fieldset__legend app-abc">
Abc
</legend>
<div class="nhsuk-hint" id="id_field-hint">
Pick either one
</div>
<div class="nhsuk-radios nhsuk-radios--conditional" data-module="nhsuk-radios">
<div class="nhsuk-radios__item">
<input class="nhsuk-radios__input" id="id_field" name="field" type="radio" value="a">
<label class="nhsuk-label nhsuk-radios__label" for="id_field">A</label>
</div>
<div class="nhsuk-radios__item">
<input aria-controls="conditional-id_field-2" aria-expanded="false" class="nhsuk-radios__input" id="id_field-2" name="field" type="radio" value="b">
<label class="nhsuk-label nhsuk-radios__label" for="id_field-2">B</label>
</div>
<div class="nhsuk-radios__conditional nhsuk-radios__conditional--hidden" id="conditional-id_field-2">
<p>Hello</p>
</div>
</div>
</fieldset>
</div>
""",
)

def test_adding_dividers_via_boundfield(self):
bound_field = TestForm()["field"]
bound_field.add_divider_after("a", "or")
assert bound_field.get_divider_after("a") == "or"
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@

from ...typed_choice_field import TypedChoiceField


class TestForm(Form):
field = TypedChoiceField(
label="Abc",
Expand Down Expand Up @@ -39,41 +38,3 @@ def test_renders_nhs_radios(self):
</div>
""",
)

def test_renders_radios_with_conditional_html(self):
form = TestForm()
form["field"].add_conditional_html("b", "<p>Hello</p>")

self.assertHTMLEqual(
form["field"].as_field_group(),
"""
<div class="nhsuk-form-group">
<fieldset aria-describedby="id_field-hint" class="nhsuk-fieldset">
<legend class="nhsuk-fieldset__legend app-abc">
Abc
</legend>
<div class="nhsuk-hint" id="id_field-hint">
Pick either one
</div>
<div class="nhsuk-radios nhsuk-radios--conditional" data-module="nhsuk-radios">
<div class="nhsuk-radios__item">
<input class="nhsuk-radios__input" id="id_field" name="field" type="radio" value="a">
<label class="nhsuk-label nhsuk-radios__label" for="id_field">A</label>
</div>
<div class="nhsuk-radios__item">
<input aria-controls="conditional-id_field-2" aria-expanded="false" class="nhsuk-radios__input" id="id_field-2" name="field" type="radio" value="b">
<label class="nhsuk-label nhsuk-radios__label" for="id_field-2">B</label>
</div>
<div class="nhsuk-radios__conditional nhsuk-radios__conditional--hidden" id="conditional-id_field-2">
<p>Hello</p>
</div>
</div>
</fieldset>
</div>
""",
)

def test_adding_dividers_via_boundfield(self):
bound_field = TestForm()["field"]
bound_field.add_divider_after("a", "or")
assert bound_field.get_divider_after("a") == "or"
26 changes: 26 additions & 0 deletions lung_cancer_screening/questions/forms/sex_at_birth_form.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
from django import forms

from ...nhsuk_forms.typed_choice_field import TypedChoiceField
from ..models.response_set import ResponseSet, SexAtBirthValues

class SexAtBirthForm(forms.ModelForm):

def __init__(self, *args, **kwargs):
self.participant = kwargs.pop('participant')
super().__init__(*args, **kwargs)
self.instance.participant = self.participant

self.fields["sex_at_birth"] = TypedChoiceField(
choices=SexAtBirthValues.choices,
widget=forms.RadioSelect,
label="What was your sex at birth?",
label_classes="nhsuk-fieldset__legend--m",
hint="Your sex may impact your chances of developing lung cancer.",
error_messages={
'required': 'Select your sex at birth.'
}
)

class Meta:
model = ResponseSet
fields = ['sex_at_birth']
10 changes: 10 additions & 0 deletions lung_cancer_screening/questions/jinja2/have_you_ever_smoked.jinja
Original file line number Diff line number Diff line change
@@ -1,6 +1,16 @@
{% extends 'layout.jinja' %}
{% from 'nhsuk/components/button/macro.jinja' import button %}
{% from 'nhsuk/components/radios/macro.jinja' import radios %}
{% from 'nhsuk/components/back-link/macro.jinja' import backLink %}

{% block beforeContent %}
{{
backLink({
"href": url("questions:start"),
"text": "Back"
})
}}
{% endblock beforeContent %}

{% block content %}
<div class="nhsuk-grid-row">
Expand Down
3 changes: 2 additions & 1 deletion lung_cancer_screening/questions/jinja2/responses.jinja
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
{% block beforeContent %}
{{
backLink({
"href": url("questions:weight"),
"href": url("questions:sex_at_birth"),
"text": "Back"
})
}}
Expand All @@ -20,6 +20,7 @@
<li>What is your date of birth? {{ response_set.date_of_birth }}</li>
<li>What is your height? {{ response_set.formatted_height }}</li>
<li>What is your weight? {{ response_set.formatted_weight }}</li>
<li>What was your sex at birth? {{ response_set.get_sex_at_birth_display() }}</li>
</ul>

<form action="{{ request.path }}" method="post">
Expand Down
28 changes: 28 additions & 0 deletions lung_cancer_screening/questions/jinja2/sex_at_birth.jinja
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
{% extends 'layout.jinja' %}
{% from 'nhsuk/components/button/macro.jinja' import button %}
{% from 'nhsuk/components/back-link/macro.jinja' import backLink %}

{% block beforeContent %}
{{
backLink({
"href": url("questions:weight"),
"text": "Back"
})
}}
{% endblock beforeContent %}

{% block page_content %}
<div class="nhsuk-grid-row">
<div class="nhsuk-grid-column-two-thirds">
<form action="{{ request.path }}" method="POST">
{{ csrf_input }}

{{ form }}

{{ button({
"text": "Continue"
}) }}
</form>
</div>
</div>
{% endblock %}
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
# Generated by Django 5.2.7 on 2025-10-28 11:09

from django.db import migrations, models


class Migration(migrations.Migration):

dependencies = [
('questions', '0012_responseset_weight_imperial_and_more'),
]

operations = [
migrations.AddField(
model_name='responseset',
name='sex_at_birth',
field=models.CharField(blank=True, choices=[('F', 'Female'), ('M', 'Male')], max_length=1, null=True),
),
]
12 changes: 12 additions & 0 deletions lung_cancer_screening/questions/models/response_set.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,10 @@ class HaveYouEverSmokedValues(models.IntegerChoices):
YES_BUT_ONLY_A_FEW_TIMES = 2, 'Yes, but only a few times'
NO_I_HAVE_NEVER_SMOKED = 3, 'No, I have never smoked'

class SexAtBirthValues(models.TextChoices):
FEMALE = "F", 'Female'
MALE = "M", 'Male'

class ResponseSet(BaseModel):
participant = models.ForeignKey(Participant, on_delete=models.CASCADE)

Expand Down Expand Up @@ -54,6 +58,14 @@ class ResponseSet(BaseModel):
MaxValueValidator(
MAX_WEIGHT_IMPERIAL, message="Weight must be between 4 stone and 50 stone"),
])

sex_at_birth = models.CharField(
max_length=1,
choices=SexAtBirthValues.choices,
null=True,
blank=True
)

submitted_at = models.DateTimeField(null=True, blank=True)

class Meta:
Expand Down
Loading
Loading