Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

UAT release #2288

Merged
merged 16 commits into from
Jan 3, 2025
Merged
Show file tree
Hide file tree
Changes from 13 commits
Commits
Show all changes
16 commits
Select commit Hold shift + click to select a range
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
2 changes: 1 addition & 1 deletion caseworker/advice/templates/advice/advice_details.html
Original file line number Diff line number Diff line change
Expand Up @@ -129,7 +129,7 @@ <h2 class="govuk-heading-m">Reason for approving</h2>

{% if advice.0.proviso %}
<h2 class="govuk-heading-m">Licence condition</h2>
<p class="govuk-body">{{ advice.0.proviso|linebreaks }}</p>
<div class="govuk-body licence-condition">{{ advice.0.proviso|linebreaks }}</div>
{% endif %}

{% if advice.0.note %}
Expand Down
2 changes: 1 addition & 1 deletion caseworker/advice/templates/advice/group-advice.html
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,7 @@ <h3 class="govuk-heading-s">Reasons for refusing</h3>
<div class="govuk-grid-row">
<div class="govuk-grid-column-full">
<h3 class="govuk-heading-s">Licence condition</h3>
<p class="govuk-body">{{ advice.proviso|linebreaks }}</p>
<div class="licence-condition govuk-body">{{ advice.proviso|linebreaks }}</div>
</div>
</div>
</div>
Expand Down
11 changes: 7 additions & 4 deletions caseworker/queues/views/forms.py
Original file line number Diff line number Diff line change
Expand Up @@ -172,18 +172,16 @@ def __init__(self, queue, filters_data, all_flags, all_cles, all_regimes, countr

flag_url = reverse("flags:flags")
self.fields["flags"] = forms.MultipleChoiceField(
label="Flags",
label="Show only cases with these flags",
choices=flags_choices,
required=False,
help_text=f'<a href="{flag_url}" class="govuk-link govuk-link--no-visited-state" target="_blank">Flag information (open in a new window)</a>',
# setting id for javascript to use
widget=forms.SelectMultiple(attrs={"id": "flags"}),
)
self.fields["exclude_flags"] = forms.MultipleChoiceField(
label="Exclude flags",
label="Do not show cases with these flags",
choices=flags_choices,
required=False,
help_text=f'<a href="{flag_url}" class="govuk-link govuk-link--no-visited-state" target="_blank">Flag information (open in a new window)</a>',
# setting id for javascript to use
widget=forms.SelectMultiple(attrs={"id": "exclude_flags"}),
)
Expand Down Expand Up @@ -229,6 +227,11 @@ def __init__(self, queue, filters_data, all_flags, all_cles, all_regimes, countr
"submitted_to",
Field("flags", css_class="multi-select-filter"),
Field("exclude_flags", css_class="multi-select-filter"),
HTML(
'<div class="govuk-!-margin-bottom-3">'
f'<a href="{flag_url}" class="govuk-link govuk-link--no-visited-state" target="_blank">Flag information (open in a new window)</a>'
"</div>"
),
"finalised_from",
"finalised_to",
]
Expand Down
5 changes: 2 additions & 3 deletions core/builtins/custom_tags.py
Original file line number Diff line number Diff line change
Expand Up @@ -178,13 +178,12 @@ def str_date_only(value):
return localtime(parse(value)).strftime("%-d %B %Y")


@register.simple_tag
@mark_safe # noqa: S308
@register.inclusion_tag("inclusion_tags/hidden-field.html")
def hidden_field(key, value):
"""
Generates a hidden field from the given key and value
"""
return f'<input type="hidden" name="{key}" value="{value}">'
return {"key": key, "value": value}


@register.filter()
Expand Down
1 change: 1 addition & 0 deletions core/templates/inclusion_tags/hidden-field.html
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
<input type="hidden" name="{{ key }}" value="{{ value }}">
1 change: 1 addition & 0 deletions lite_content/lite_internal_frontend/strings.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
queues, # noqa
picklists, # noqa
routing_rules, # noqa
tests, # noqa
) # noqa

# Buttons
Expand Down
2 changes: 2 additions & 0 deletions lite_content/lite_internal_frontend/tests.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
class TestPage:
BUTTON = "Test Button"
8 changes: 8 additions & 0 deletions lite_forms/templates/govuk-link-button.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
<a {% if id %}id="button-{{ id }}" {% endif %}href="{{ url }}{{ query_params }}" role="button" draggable="false" class="govuk-button {{ classes }}" data-module="govuk-button"{% if hidden %} style="display: none;"{% endif %}>
{% lcs text %}
{% if show_chevron %}
<svg class="govuk-button__start-icon" xmlns="http://www.w3.org/2000/svg" width="13" height="15" viewBox="0 0 33 43" aria-hidden="true" focusable="false">
<path fill="currentColor" d="M0 0h13l20 20-20 20H0l20-20z" />
</svg>
{% endif %}
</a>
35 changes: 16 additions & 19 deletions lite_forms/templatetags/custom_tags.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@
from django.urls import reverse
from django.utils.safestring import mark_safe

from core.builtins.custom_tags import get_const_string
from lite_forms.helpers import flatten_data


Expand Down Expand Up @@ -199,27 +198,25 @@ def item_with_rating_exists(items, rating):
return True


@register.simple_tag
@mark_safe # noqa: S308
@register.inclusion_tag("govuk-link-button.html")
def govuk_link_button(text, url, url_param=None, id="", classes="", query_params="", show_chevron=False, hidden=False):
text = get_const_string(text)
if not url_param:
url_param = []

if isinstance(url_param, str):
url_param = [url_param]
url = reverse(url, args=url_param if url_param else [])
id = f'id="button-{id}"' if id else ""
chevron = ""
if show_chevron:
chevron = (
'<svg class="govuk-button__start-icon" xmlns="http://www.w3.org/2000/svg" width="13" height="15" '
'viewBox="0 0 33 43" aria-hidden="true" focusable="false">'
'<path fill="currentColor" d="M0 0h13l20 20-20 20H0l20-20z" /></svg>'
)
hidden = 'style="display: none;"' if hidden else ""

return (
f'<a {id} href="{url}{query_params}" role="button" draggable="false" class="govuk-button {classes}" {hidden} '
f'data-module="govuk-button">{text}{chevron}</a>'
)

url = reverse(url, args=url_param)

return {
"text": text,
"url": url,
"id": id,
"classes": classes,
"show_chevron": show_chevron,
"hidden": hidden,
"query_params": query_params,
}


@register.filter()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -52,3 +52,102 @@ Feature: I want to record my user advice and any comments and conditions relatin
And I click on "Details" tab
Then I see the case status is now "Finalised"
And I see the case is not assigned to any queues

@lu_consolidate_advice_ogd_licence_conditions
Scenario: LU consolidate advice with OGD licence conditions
Given I sign in as Test UAT user
And I create standard application or standard application has been previously created
# LR
When I switch to "Licensing Reception" with queue "Licensing Reception SIEL applications" and I submit the case
Then I see the case status is now "Initial checks"
And I see the case is assigned to queues "Enforcement Unit Cases to Review, Technical Assessment Unit SIELs to Review"
# EU
When I switch to "Enforcement Unit" with queue "Enforcement Unit Cases to Review" and I submit the case
Then I see the case status is now "Initial checks"
And I see the case is assigned to queues "Technical Assessment Unit SIELs to Review"
And I see the case is not assigned to queues "Enforcement Unit Cases to Review"
# TAU
When I go to my profile page
And I change my team to "Technical Assessment Unit" and default queue to "Technical Assessment Unit SIELs to Review"
And I go to my case list
Then I see previously created application
When I click on the application previously created
And I assign myself to the case
Then I click on Product assessment
And I select good
And I select the CLE "ML1a"
And I select "components for" / "microwave components" as report summary prefix / subject and regime to none and submit
When I click move case forward
Then I don't see previously created application
# LU
When I switch to "Licensing Unit" with queue "Licensing Unit Pre-circulation Cases to Review" and I submit the case
Then I see the case status is now "OGD Advice"
And I see the case is assigned to queues "MOD-DI Indirect cases to review, MOD-CapProt cases to review, FCDO Cases to Review"
# MOD-DI
When I switch to "MOD-DI" with queue "MOD-DI Indirect cases to review" and I submit the case
Then I see the case status is now "OGD Advice"
And I see the case is assigned to queues "MOD-CapProt cases to review, FCDO Cases to Review"

##### MOD Sub-advisor to give advice #####
When I go to my profile page
And I change my team to "MOD-CapProt" and default queue to "MOD-CapProt cases to review"
And I go to my case list
Then I should see my case in the cases list
When I click the application previously created
And I assign myself to the case
And I click the recommendations and decision tab
And I click make recommendation
And I click approve all
And I click continue
And I enter "reason for approving" as the reasons for approving
And I click the text "Add a licence condition, instruction to exporter or footnote"
And I enter "MOD licence condition" as the licence condition
And I enter "instruction for exporter" as the instructions for the exporter
And I enter "reporting footnote" as the reporting footnote
And I click submit recommendation
Then I see "reason for approving" as the reasons for approving
And I see "MOD licence condition" as the licence condition
And I see "instruction for exporter" as the instructions for the exporter
And I see "reporting footnote" as the reporting footnote

##### FCDO Sub-advisor to give advice #####
When I go to my profile page
And I change my team to "FCDO" and default queue to "FCDO Cases to Review"
And I go to my case list
Then I should see my case in the cases list
When I click the application previously created
And I assign myself to the case
And I click the recommendations and decision tab
And I click make recommendation
And I click approve all
And I click continue
And I select countries "GB, UA"
And I enter "reason for approving" as the reasons for approving
And I click the text "Add a licence condition, instruction to exporter or footnote"
And I enter "FCDO licence condition" as the licence condition
And I enter "instruction for exporter" as the instructions for the exporter
And I enter "reporting footnote" as the reporting footnote
And I click submit recommendation
Then I see "reason for approving" as the reasons for approving
And I see "FCDO licence condition" as the licence condition
And I see "instruction for exporter" as the instructions for the exporter
And I see "reporting footnote" as the reporting footnote

When I logout
Given I sign in as Licensing Unit Officer
And I prepare the application for final review
When I go to my case list
And I go to my case list
And I click the application previously created
And I assign myself as case officer to the case
And I go to my case list
And I click the application previously created
And I click the recommendations and decision tab
And I click "Review and combine"
And I enter "reason for approving" as the reasons for approving
And I click "Add licence condition"
And I click submit recommendation
Then I see "reason for approving" as the reasons for approving
And I see "MOD licence condition" in the licence condition
And I see "FCDO licence condition" in the licence condition
And I see "serial numbers" in the licence condition
4 changes: 2 additions & 2 deletions ui_tests/caseworker/pages/advice.py
Original file line number Diff line number Diff line change
Expand Up @@ -165,8 +165,8 @@ def get_refusal_note(self):

def get_licence_condition(self):
return self.driver.find_element(
by=By.XPATH,
value="//p[preceding-sibling::*[self::h2 or self::h3][contains(text(), 'Licence condition')]][2]",
by=By.CLASS_NAME,
value="licence-condition",
).text

def get_instructions_for_exporter(self):
Expand Down
5 changes: 5 additions & 0 deletions ui_tests/caseworker/step_defs/test_give_advice/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -133,6 +133,11 @@ def should_see_licence_condition(driver, licence_condition, context): # noqa
assert RecommendationsAndDecisionPage(driver).get_licence_condition() == licence_condition


@then(parsers.parse('I see "{licence_condition}" in the licence condition'))
def should_see_licence_condition(driver, licence_condition, context): # noqa
assert licence_condition in RecommendationsAndDecisionPage(driver).get_licence_condition()


@then(parsers.parse('I see "{instructions}" as the instructions for the exporter'))
def should_see_instructions_for_exporter(driver, instructions, context): # noqa
assert RecommendationsAndDecisionPage(driver).get_instructions_for_exporter() == instructions
Expand Down
2 changes: 1 addition & 1 deletion unit_tests/caseworker/cases/views/test_case_bookmarks.py
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,6 @@ def test_bookmarks_present(
assert third["filter_json"] == {
"flags": ["64cbcf98-9beb-41ad-8f5d-276dee768990", "8f02e308-9861-4284-a7f0-f05495efce31"]
}
assert third["description"] == "Flags: AG Biological, AG Chemical"
assert third["description"] == "Show only cases with these flags: AG Biological, AG Chemical"
assert "flags=64cbcf98-9beb-41ad-8f5d-276dee768990" in third["url"]
assert "flags=8f02e308-9861-4284-a7f0-f05495efce31" in third["url"]
18 changes: 18 additions & 0 deletions unit_tests/caseworker/test_template_tags.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
from core.builtins import custom_tags

from caseworker.core.constants import SLA_CIRCUMFERENCE
from caseworker.letter_templates.templatetags.variable_highlight import variable_highlight

import pytest

Expand Down Expand Up @@ -60,3 +61,20 @@ def test_sla_colour(remaining, unit, colour):
def test_sla_colour_missing_unit():
with pytest.raises(ValueError):
custom_tags.sla_colour(10, "")


@pytest.mark.parametrize(
"input, expected",
(
("just text", "just text"),
("with {{ variable }}", 'with <span class="lite-highlight">{{ variable }}</span>'),
(
"with {% another_variable %}",
'with <span class="lite-highlight lite-highlight--purple">{% another_variable %}</span>',
),
("<a onclick='javascript:alert()' href='javascript:alert()'>Link</a>", "<a>Link</a>"),
("<script>alert()</script>", "&lt;script&gt;alert()&lt;/script&gt;"),
),
)
def test_variable_highlight(input, expected):
assert variable_highlight(input) == expected
21 changes: 19 additions & 2 deletions unit_tests/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -2602,12 +2602,29 @@ def _create_files(*files):
return _create_files


@pytest.fixture
@pytest.fixture()
def authorized_client(client):
return client


@pytest.fixture()
def mock_request(rf, authorized_client):
request = rf.get("/")
request.session = authorized_client.session
request.requests_session = requests.Session()
yield request
return request


@pytest.fixture()
def render_template_string(mock_request):
def _render_template_string(template_string, context=None):
if not context:
context = {}
template = Template(template_string)
context = RequestContext(mock_request, context)
return template.render(context)

return _render_template_string


@pytest.fixture()
Expand Down
32 changes: 32 additions & 0 deletions unit_tests/core/builtins/test_custom_tags.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
import datetime
import pytest

from pytest_django.asserts import assertHTMLEqual

from decimal import Decimal

from core.builtins import custom_tags
Expand Down Expand Up @@ -426,3 +428,33 @@ def test_pagination_params(url, page, expected):
def test_pagination():
with pytest.raises(ValueError):
custom_tags.pagination({}, link_type="madeup")


@pytest.mark.parametrize(
"input, context, expected",
[
(
"{% hidden_field 'test-key' 'test-value' %}",
{},
'<input name="test-key" type="hidden" value="test-value">',
),
(
"{% hidden_field key value %}",
{
"key": "test-key",
"value": "test-value",
},
'<input name="test-key" type="hidden" value="test-value">',
),
(
"{% hidden_field key value %}",
{
"key": '"><script>alert()</script><input type="hidden',
"value": '"><script>alert()</script><input type="hidden',
},
'<input type="hidden" name="&quot;&gt;&lt;script&gt;alert()&lt;/script&gt;&lt;input type=&quot;hidden" value="&quot;&gt;&lt;script&gt;alert()&lt;/script&gt;&lt;input type=&quot;hidden">',
),
],
)
def test_hidden_field(render_template_string, input, context, expected):
assertHTMLEqual(render_template_string(input, context), expected)
Loading
Loading