Skip to content

Commit

Permalink
Merge pull request #2208 from uktrade/uat
Browse files Browse the repository at this point in the history
PROD Release
  • Loading branch information
depsiatwal committed Sep 26, 2024
2 parents ec91eca + 9ea7062 commit 9bdb83d
Show file tree
Hide file tree
Showing 26 changed files with 1,035 additions and 722 deletions.
6 changes: 4 additions & 2 deletions Pipfile
Original file line number Diff line number Diff line change
Expand Up @@ -50,13 +50,13 @@ notifications-python-client = "~=5.7.1"
dataclasses = "~=0.6"
# endesive = "~=1.5.9" (not included here as installed in a later jenkins step. Uncomment if working locally)
pypdf2 = "~=1.27.5"
cryptography = "~=42.0.0"
cryptography = "~=43.0.1"
sentry-sdk = "~=2.8.0"
elastic-apm = "~=6.7.2"
gunicorn = "~=22.0.0"
gevent = "~=23.9.1"
xmltodict = "~=0.12.0"
Pillow = "~=10.2.0"
Pillow = "~=10.3.0"
django-phonenumber-field = "==6.4.0"
phonenumbers = "~=8.13.1"
django-log-formatter-ecs = "==0.0.5"
Expand All @@ -76,6 +76,8 @@ psycopg = "~=3.1.18"
django-log-formatter-asim = "~=0.0.5"
dbt-copilot-python = "~=0.2.1"
dj-database-url = "~=2.2.0"
certifi = "~=2024.7.4"
pytz = "~=2024.1"

[requires]
python_version = "3.9"
Expand Down
1,361 changes: 700 additions & 661 deletions Pipfile.lock

Large diffs are not rendered by default.

109 changes: 109 additions & 0 deletions api/applications/views/tests/test_parties.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
from parameterized import parameterized
from django.urls import reverse
from rest_framework import status

from api.applications.tests.factories import (
StandardApplicationFactory,
PartyOnApplicationFactory,
DraftStandardApplicationFactory,
)
from api.parties.models import Party
from api.staticdata.statuses.models import CaseStatus
Expand Down Expand Up @@ -72,3 +74,110 @@ def test_other_status_cannot_update_party_detail(self):
]
},
)


class TestApplicationPartyViewValues(DataTestClient):

def setUp(self):
super().setUp()
self.application = DraftStandardApplicationFactory(organisation=self.organisation)

self.party_on_application = PartyOnApplicationFactory(application=self.application)

@parameterized.expand(
[
(
{"name": "end_user", "address": "1 Example Street"},
True,
{
"name": [
"Party name must only include letters, numbers, and common special characters such as hyphens, brackets and apostrophes"
]
},
),
(
{"name": "end\auser", "address": "1 Example Street"},
True,
{
"name": [
"Party name must only include letters, numbers, and common special characters such as hyphens, brackets and apostrophes"
]
},
),
(
{"name": "end£user", "address": "1 Example Street"},
True,
{
"name": [
"Party name must only include letters, numbers, and common special characters such as hyphens, brackets and apostrophes"
]
},
),
(
{"name": "end user", "address": "1_Example Street"},
True,
{
"address": [
"Address must only include letters, numbers, and common special characters such as hyphens, brackets and apostrophes"
]
},
),
(
{"name": "end user", "address": "1\aExample Street"},
True,
{
"address": [
"Address must only include letters, numbers, and common special characters such as hyphens, brackets and apostrophes"
]
},
),
(
{"name": "end_user", "address": "1\aExample Street"},
True,
{
"name": [
"Party name must only include letters, numbers, and common special characters such as hyphens, brackets and apostrophes"
],
"address": [
"Address must only include letters, numbers, and common special characters such as hyphens, brackets and apostrophes"
],
},
),
]
)
def test_party_post_invalid(self, data, error, error_message):
data["country"] = {"id": "FR", "name": "France"}
self.url = reverse(
"applications:party",
kwargs={"pk": str(self.application.pk), "party_pk": str(self.party_on_application.party.pk)},
)
party = Party.objects.get(id=self.party_on_application.party.pk)
versions = Version.objects.get_for_object(party)
self.assertEqual(versions.count(), 0)

self.application.status = CaseStatus.objects.get(status="draft")
self.application.save()

response = self.client.put(self.url, **self.exporter_headers, data=data)
if error:
self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST)
self.assertEqual(response.json()["errors"], error_message)

@parameterized.expand(
[
({"name": "end user", "address": "1 Example Street"},),
({"name": "end/!user", "address": "1 Example Street"},),
({"name": "end-user", "address": "1 Example Street"},),
({"name": "end-user", "address": "1 \r\nExample Street"},),
]
)
def test_party_post_valid(self, data):
data["country"] = {"id": "FR", "name": "France"}
self.url = reverse(
"applications:party",
kwargs={"pk": str(self.application.pk), "party_pk": str(self.party_on_application.party.pk)},
)

response = self.client.put(self.url, **self.exporter_headers, data=data)

self.assertEqual(response.status_code, status.HTTP_200_OK)
1 change: 1 addition & 0 deletions api/conf/caseworker_urls.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,5 @@
urlpatterns = [
path("applications/", include("api.applications.caseworker.urls")),
path("organisations/", include("api.organisations.caseworker.urls")),
path("static/", include("api.staticdata.caseworker.urls")),
]
4 changes: 4 additions & 0 deletions api/core/validators.py
Original file line number Diff line number Diff line change
Expand Up @@ -42,3 +42,7 @@ class GoodNameValidator(EdifactStringValidator):
class PartyAddressValidator(EdifactStringValidator):
regex_string = re.compile(r"^[a-zA-Z0-9 .,\-\)\(\/'+:=\?\!\"%&\*;\<\>\r\n]+$")
message = "Address must only include letters, numbers, and common special characters such as hyphens, brackets and apostrophes"


class PartyNameValidator(EdifactStringValidator):
message = "Party name must only include letters, numbers, and common special characters such as hyphens, brackets and apostrophes"
2 changes: 1 addition & 1 deletion api/data_workspace/v1/serializers.py
Original file line number Diff line number Diff line change
Expand Up @@ -131,7 +131,7 @@ class Meta:
ordering = ["created_at"]

def get_application(self, instance):
return {"application_id": str(instance.case.pk)}
return {"id": str(instance.case.pk)}


class SurveyResponseSerializer(serializers.ModelSerializer):
Expand Down
2 changes: 1 addition & 1 deletion api/data_workspace/v1/tests/test_licence_views.py
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ def test_licenses(self):
results[0],
{
"id": str(self.licence.pk),
"application": {"application_id": str(self.licence.case.pk)},
"application": {"id": str(self.licence.case.pk)},
"reference_code": self.licence.reference_code,
"status": {
"key": self.licence.status,
Expand Down
2 changes: 1 addition & 1 deletion api/data_workspace/v1/tests/test_serializers.py
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ def test_LicenceSerializer(db):
serialized = LicenceSerializer(licence)
assert serialized.data == {
"id": str(licence.pk),
"application": {"application_id": str(licence.case.pk)},
"application": {"id": str(licence.case.pk)},
"reference_code": licence.reference_code,
"status": {
"key": licence.status,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
from django.db import migrations

LICENSING_UNIT_TEAM_ID = "58e77e47-42c8-499f-a58d-94f94541f8c6"


def refusal_letter_picklist_update_team_ownership(apps, schema_editor):

PicklistItem = apps.get_model("picklists", "PicklistItem")
refusal_letter_content = PicklistItem.objects.get(name="Refusal letter content")
refusal_letter_content.team_id = LICENSING_UNIT_TEAM_ID
refusal_letter_content.save()


class Migration(migrations.Migration):

dependencies = [
("letter_templates", "0009_refusal_letter_update_fix"),
]

operations = [
migrations.RunPython(refusal_letter_picklist_update_team_ownership, migrations.RunPython.noop),
]
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import pytest
from django_test_migrations.contrib.unittest_case import MigratorTestCase


@pytest.mark.django_db()
class TestChangeTeamRefusalPickList(MigratorTestCase):
migrate_from = ("letter_templates", "0009_refusal_letter_update_fix")
migrate_to = ("letter_templates", "0010_refusal_letter_picklist_update_team_ownership")

def test_refusal_letter_picklist_update_team_ownership(self):
LICENSING_UNIT_TEAM_ID = "58e77e47-42c8-499f-a58d-94f94541f8c6" # /PS-IGNORE

PicklistItem = self.new_state.apps.get_model("picklists", "PicklistItem")

assert str(PicklistItem.objects.get(name="Refusal letter content").team_id) == LICENSING_UNIT_TEAM_ID
4 changes: 2 additions & 2 deletions api/parties/serializers.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@

from api.cases.enums import CaseTypeSubTypeEnum
from api.core.serializers import KeyValueChoiceField, CountrySerializerField
from api.core.validators import PartyAddressValidator
from api.core.validators import PartyAddressValidator, PartyNameValidator
from api.documents.libraries.process_document import process_document
from api.flags.serializers import FlagSerializer
from api.goods.enums import PvGrading
Expand All @@ -15,7 +15,7 @@


class PartySerializer(serializers.ModelSerializer):
name = serializers.CharField(error_messages=PartyErrors.NAME)
name = serializers.CharField(error_messages=PartyErrors.NAME, validators=[PartyNameValidator()])
address = serializers.CharField(error_messages=PartyErrors.ADDRESS, validators=[PartyAddressValidator()])
country = CountrySerializerField()
website = serializers.CharField(required=False, allow_blank=True)
Expand Down
52 changes: 52 additions & 0 deletions api/parties/tests/test_serializers.py
Original file line number Diff line number Diff line change
Expand Up @@ -92,3 +92,55 @@ def test_validate_party_address_invalid(self, address, error_message):
str(address_errors[0]),
error_message,
)

@parameterized.expand(
[
"random name",
"party-name",
"party!name",
"party-!.<>/%&*;+'(),.name",
]
)
def test_validate_party_name_valid(self, name):
serializer = PartySerializer(
data={"name": name},
partial=True,
)
self.assertTrue(serializer.is_valid())

@parameterized.expand(
[
(
"party\aname",
"Party name must only include letters, numbers, and common special characters such as hyphens, brackets and apostrophes",
),
(
"party-\wname",
"Party name must only include letters, numbers, and common special characters such as hyphens, brackets and apostrophes",
),
(
"party_name",
"Party name must only include letters, numbers, and common special characters such as hyphens, brackets and apostrophes",
),
(
"party$name",
"Party name must only include letters, numbers, and common special characters such as hyphens, brackets and apostrophes",
),
(
"party@name",
"Party name must only include letters, numbers, and common special characters such as hyphens, brackets and apostrophes",
),
]
)
def test_party_name_invalid(self, name, error_message):
serializer = PartySerializer(
data={"name": name},
partial=True,
)
self.assertFalse(serializer.is_valid())
serializer_error = serializer.errors["name"]
self.assertEqual(len(serializer_error), 1)
self.assertEqual(
str(serializer_error[0]),
error_message,
)
6 changes: 2 additions & 4 deletions api/picklists/tests/test_views.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,9 +23,7 @@ def test_gov_user_can_see_all_their_teams_picklist_items(self):
response_data = response.json()

self.assertEqual(response.status_code, status.HTTP_200_OK)
# New migration will create a new PicklistItem if base does not exist so its becoming 5
# api/letter_templates/migrations/0008_refusal_letter_update.py
self.assertEqual(len(response_data["results"]), 5)
self.assertEqual(len(response_data["results"]), 4)

def test_gov_user_can_see_all_their_teams_picklist_items_excluding_deactivated(
self,
Expand All @@ -34,7 +32,7 @@ def test_gov_user_can_see_all_their_teams_picklist_items_excluding_deactivated(
response_data = response.json()

self.assertEqual(response.status_code, status.HTTP_200_OK)
self.assertEqual(len(response_data["results"]), 4)
self.assertEqual(len(response_data["results"]), 3)

def test_gov_user_can_see_all_their_teams_picklist_items_filter_by_name(
self,
Expand Down
Empty file.
Empty file.
9 changes: 9 additions & 0 deletions api/staticdata/caseworker/control_list_entries/serializers.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
from rest_framework import serializers

from api.staticdata.control_list_entries.models import ControlListEntry


class ControlListEntriesListSerializer(serializers.ModelSerializer):
class Meta:
model = ControlListEntry
fields = ("rating", "text", "parent")
Empty file.
67 changes: 67 additions & 0 deletions api/staticdata/caseworker/control_list_entries/tests/test_views.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
from rest_framework import status
from rest_framework.reverse import reverse

from api.staticdata.control_list_entries.models import ControlListEntry
from api.staticdata.control_list_entries.factories import ControlListEntriesFactory
from test_helpers.clients import DataTestClient


class ControlListEntriesListTests(DataTestClient):
def setUp(self):
self.url = reverse("caseworker_staticdata:control_list_entries:control_list_entries")
super().setUp()
ControlListEntry.objects.all().delete()
self.parent_cle = ControlListEntriesFactory(
rating="ML1",
selectable_for_assessment=False,
text="some ML1 text",
)
self.child_cle = ControlListEntriesFactory(
rating="ML1a",
parent=self.parent_cle,
selectable_for_assessment=True,
text="some ML1a text",
)

def test_GET_success(self):
response = self.client.get(self.url, **self.gov_headers)

self.assertEqual(response.status_code, status.HTTP_200_OK)

self.assertEqual(
response.json(),
[
{
"rating": "ML1a",
"text": "some ML1a text",
"parent": str(self.parent_cle.id),
}
],
)

def test_GET_exporter_forbidden(self):
response = self.client.get(self.url, **self.exporter_headers)

self.assertEqual(response.status_code, status.HTTP_403_FORBIDDEN)

def test_GET_include_non_selectable_for_assessment_param(self):
url = self.url + "?include_non_selectable_for_assessment=True"
response = self.client.get(url, **self.gov_headers)

self.assertEqual(response.status_code, status.HTTP_200_OK)

self.assertEqual(
response.json(),
[
{
"rating": "ML1",
"text": "some ML1 text",
"parent": None,
},
{
"rating": "ML1a",
"text": "some ML1a text",
"parent": str(self.parent_cle.id),
},
],
)
Loading

0 comments on commit 9bdb83d

Please sign in to comment.