Skip to content

Commit

Permalink
Merge pull request #2288 from uktrade/dev
Browse files Browse the repository at this point in the history
UAT release
  • Loading branch information
kevincarrogan authored Jan 3, 2025
2 parents 90203d9 + 7451e92 commit 5473a2e
Show file tree
Hide file tree
Showing 18 changed files with 265 additions and 37 deletions.
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

0 comments on commit 5473a2e

Please sign in to comment.