diff --git a/Jenkinsfile_CNP b/Jenkinsfile_CNP index 54452e7118..655ac56514 100644 --- a/Jenkinsfile_CNP +++ b/Jenkinsfile_CNP @@ -11,7 +11,7 @@ properties( ] ) -@Library("Infrastructure@2.4.0") +@Library("Infrastructure@2.4.4") import uk.gov.hmcts.contino.GradleBuilder def type = "java" diff --git a/Jenkinsfile_nightly b/Jenkinsfile_nightly index 9757a161a5..46f6cb6762 100644 --- a/Jenkinsfile_nightly +++ b/Jenkinsfile_nightly @@ -6,7 +6,7 @@ properties([ pipelineTriggers([cron('H 17 * * 1-5')]) ]) -@Library("Infrastructure@2.4.0") +@Library("Infrastructure@2.4.4") def type = "java" def product = "ccd" diff --git a/api-docs/aggregated.swagger.yaml b/api-docs/aggregated.swagger.yaml index 378e77449a..b5389df3e2 100644 --- a/api-docs/aggregated.swagger.yaml +++ b/api-docs/aggregated.swagger.yaml @@ -457,6 +457,9 @@ definitions: type: object description: | Value of the field, type and structure depends on the field type + caseFieldSubfieldCode: + type: string + description: The optional CaseTypeTab case field or case field subfield path required: - id - label diff --git a/api-docs/definition.yaml b/api-docs/definition.yaml index 2dac00baad..e3a82ad3f8 100644 --- a/api-docs/definition.yaml +++ b/api-docs/definition.yaml @@ -192,6 +192,8 @@ definitions: order: type: integer format: int32 + caseFieldSubfieldCode: + type: string WorkBasketResult: type: object diff --git a/build.gradle b/build.gradle index 7244fea4a0..0ad6ff0c2c 100644 --- a/build.gradle +++ b/build.gradle @@ -43,7 +43,8 @@ ext { testContainersVersion = '2.0.5' cucumber = '7.34.6' beftaFwVersion = '9.2.7' - ccdTestDefinitionVersion = '7.26.7' + ccdTestDefinitionVersion = '7.26.8_CCD-6251-SNAPSHOT' + limits = [ 'instruction': 90, 'branch' : 85, diff --git a/charts/ccd-data-store-api/values.preview.template.yaml b/charts/ccd-data-store-api/values.preview.template.yaml index f8c1854b9d..ef3a3ce783 100644 --- a/charts/ccd-data-store-api/values.preview.template.yaml +++ b/charts/ccd-data-store-api/values.preview.template.yaml @@ -94,7 +94,7 @@ ccd: ccd-definition-store-api: java: ingressHost: ccd-definition-store-${SERVICE_FQDN} - image: hmctsprod.azurecr.io/ccd/definition-store-api:latest + image: hmctsprod.azurecr.io/ccd/definition-store-api:pr-1825 imagePullPolicy: Always devmemoryRequests: 2048Mi devcpuRequests: 2000m diff --git a/src/aat/resources/features/F-065 - Get Case V2 Internal/F-065.feature b/src/aat/resources/features/F-065 - Get Case V2 Internal/F-065.feature index 70c70e7ee0..b1de1e3204 100644 --- a/src/aat/resources/features/F-065 - Get Case V2 Internal/F-065.feature +++ b/src/aat/resources/features/F-065 - Get Case V2 Internal/F-065.feature @@ -6,6 +6,38 @@ Background: Load test data for the scenario Given an appropriate test context as detailed in the test data source +#------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- +@S-166 # enable when CCD Definition Store emits CaseTypeTab ListElementCode +Scenario: must return case view with CaseTypeTab ListElementCode as caseFieldSubfieldCode + + Given a successful call [to create a token for case creation with CaseTypeTab ListElementCode] as in [S-166-Prerequisite], + And a case that has just been created as in [S-166-Prerequisite_Case_Creation], + And a user with [an active BEFTA Master caseworker profile in CCD], + + When a request is prepared with appropriate values, + And the request [contains a case with CaseTypeTab ListElementCode configured], + And it is submitted to call the [Retrieve a case by ID for dynamic display] operation of [CCD Data Store], + + Then a positive response is received, + And the response [contains caseFieldSubfieldCode for the MySchool tab field], + And the response has all other details as expected. + +#------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- +@S-167 +Scenario: must return case view with multiple CaseTypeTab ListElementCode values as caseFieldSubfieldCode + + Given a successful call [to create a token for case creation with multiple CaseTypeTab ListElementCode values] as in [S-167-Prerequisite], + And a case that has just been created as in [S-167-Prerequisite_Case_Creation], + And a user with [an active BEFTA Master caseworker profile in CCD], + + When a request is prepared with appropriate values, + And the request [contains a case with multiple CaseTypeTab ListElementCode values configured], + And it is submitted to call the [Retrieve a case by ID for dynamic display] operation of [CCD Data Store], + + Then a positive response is received, + And the response [contains caseFieldSubfieldCode for both MySchool tab fields], + And the response has all other details as expected. + #------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- @S-165 @Ignore Scenario: must return case view when the case reference exists @@ -134,5 +166,3 @@ Scenario: must return the case view having only the respective fields with READ And a call [to get the same case by Solicitor 3] will get the expected response as in [F-065_Later_Case_Read_By_Solicitor_3_Generated_By_Solicitor_1]. #------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - - diff --git a/src/aat/resources/features/F-065 - Get Case V2 Internal/S-166-Prerequisite.td.json b/src/aat/resources/features/F-065 - Get Case V2 Internal/S-166-Prerequisite.td.json new file mode 100644 index 0000000000..3dbd38993e --- /dev/null +++ b/src/aat/resources/features/F-065 - Get Case V2 Internal/S-166-Prerequisite.td.json @@ -0,0 +1,29 @@ +{ + "_guid_": "S-166-Prerequisite", + "_extends_": "Standard_Token_Creation_Data_For_Case_Creation", + + "specs": [ + "to create a token for case creation with CaseTypeTab ListElementCode" + ], + + "users": { + "invokingUser": { + "_extends_": "BeftaMasterCaseworker" + } + }, + + "request": { + "pathVariables": { + "uid": "[[DEFAULT_AUTO_VALUE]]", + "jid": "BEFTA_MASTER", + "ctid": "FT_CTT_Subfield_Valid", + "etid": "createCase" + } + }, + + "expectedResponse": { + "body": { + "event_id": "createCase" + } + } +} diff --git a/src/aat/resources/features/F-065 - Get Case V2 Internal/S-166-Prerequisite_Case_Creation.td.json b/src/aat/resources/features/F-065 - Get Case V2 Internal/S-166-Prerequisite_Case_Creation.td.json new file mode 100644 index 0000000000..ebe701e70c --- /dev/null +++ b/src/aat/resources/features/F-065 - Get Case V2 Internal/S-166-Prerequisite_Case_Creation.td.json @@ -0,0 +1,57 @@ +{ + "_guid_": "S-166-Prerequisite_Case_Creation", + "_extends_": "Case_Creation_Base", + + "user": { + "_extends_": "BeftaMasterCaseworker" + }, + + "request": { + "pathVariables": { + "uid": "[[DEFAULT_AUTO_VALUE]]", + "jid": "BEFTA_MASTER", + "ctid": "FT_CTT_Subfield_Valid" + }, + "body": { + "event_token": "${[scenarioContext][parentContext][childContexts][S-166-Prerequisite][testData][actualResponse][body][token]}", + "event": { + "id": "createCase", + "summary": "", + "description": "" + }, + "data": { + "MySchool": { + "Name": "Springfield Elementary" + } + } + } + }, + + "expectedResponse": { + "_extends_": "Common_201_Response", + "body": { + "id": "[[ANYTHING_PRESENT]]", + "state": "CaseCreated", + "version": 0, + "jurisdiction": "BEFTA_MASTER", + "created_date": "[[ANYTHING_PRESENT]]", + "last_modified": "[[ANYTHING_PRESENT]]", + "last_state_modified_date": "[[ANYTHING_PRESENT]]", + "security_classification": "PUBLIC", + "case_type_id": "FT_CTT_Subfield_Valid", + "case_data": { + "MySchool": { + "Name": "Springfield Elementary" + } + }, + "data_classification": {}, + "supplementary_data": null, + "after_submit_callback_response": null, + "callback_response_status_code": null, + "callback_response_status": null, + "callback_error_message": null, + "delete_draft_response_status_code": null, + "delete_draft_response_status": null + } + } +} diff --git a/src/aat/resources/features/F-065 - Get Case V2 Internal/S-166.td.json b/src/aat/resources/features/F-065 - Get Case V2 Internal/S-166.td.json new file mode 100644 index 0000000000..b6e246493c --- /dev/null +++ b/src/aat/resources/features/F-065 - Get Case V2 Internal/S-166.td.json @@ -0,0 +1,99 @@ +{ + "_guid_": "S-166", + "_extends_": "F-065_Test_Data_Base", + "title": "must return case view with CaseTypeTab ListElementCode as caseFieldSubfieldCode", + + "specs": [ + "an active BEFTA Master caseworker profile in CCD", + "contains a case with CaseTypeTab ListElementCode configured", + "contains caseFieldSubfieldCode for the MySchool tab field" + ], + + "user": { + "_extends_": "BeftaMasterCaseworker" + }, + + "request": { + "pathVariables": { + "cid": "${[scenarioContext][childContexts][S-166-Prerequisite_Case_Creation][testData][actualResponse][body][id]}" + } + }, + + "expectedResponse": { + "_extends_": "Common_200_Response", + "headers": { + "Content-Type": "application/vnd.uk.gov.hmcts.ccd-data-store-api.ui-case-view.v2+json;charset=UTF-8" + }, + "body": { + "_links": { + "self": { + "href": "[[ANYTHING_PRESENT]]" + } + }, + "case_id": "${}${[scenarioContext][childContexts][S-166-Prerequisite_Case_Creation][testData][actualResponse][body][id]}", + "case_type": { + "id": "FT_CTT_Subfield_Valid", + "name": "FT_CTT_Subfield_Valid", + "description": "CaseTypeTab valid direct complex subfield", + "jurisdiction": { + "id": "BEFTA_MASTER", + "name": "BEFTA Master", + "description": "Content for the BEFTA Master Jurisdiction." + }, + "printEnabled": false + }, + "tabs": [ + { + "__operator__": "superset", + "__ordering__": "unordered", + "__elementId__": "id" + }, + { + "id": "MySchoolDetails", + "label": "My School Details", + "order": 3, + "fields": [ + { + "__operator__": "equivalent", + "__ordering__": "unordered", + "__elementId__": "id" + }, + { + "id": "MySchool", + "label": "My School", + "hidden": false, + "value": { + "Name": "Springfield Elementary" + }, + "metadata": false, + "hint_text": null, + "field_type": "[[ANYTHING_PRESENT]]", + "validation_expr": null, + "security_label": "PUBLIC", + "order": 1, + "formatted_value": { + "Name": "Springfield Elementary" + }, + "display_context": null, + "display_context_parameter": null, + "show_condition": null, + "show_summary_change_option": null, + "show_summary_content_option": null, + "retain_hidden_value": null, + "publish": null, + "publish_as": null, + "acls": "[[ANYTHING_PRESENT]]", + "caseFieldSubfieldCode": "MySchool.Name" + } + ], + "show_condition": null, + "role": null + } + ], + "metadataFields": "[[ANYTHING_PRESENT]]", + "state": "[[ANYTHING_PRESENT]]", + "triggers": "[[ANYTHING_PRESENT]]", + "events": "[[ANYTHING_PRESENT]]" + } + } +} diff --git a/src/aat/resources/features/F-065 - Get Case V2 Internal/S-167-Prerequisite.td.json b/src/aat/resources/features/F-065 - Get Case V2 Internal/S-167-Prerequisite.td.json new file mode 100644 index 0000000000..04a1c3305c --- /dev/null +++ b/src/aat/resources/features/F-065 - Get Case V2 Internal/S-167-Prerequisite.td.json @@ -0,0 +1,29 @@ +{ + "_guid_": "S-167-Prerequisite", + "_extends_": "Standard_Token_Creation_Data_For_Case_Creation", + + "specs": [ + "to create a token for case creation with multiple CaseTypeTab ListElementCode values" + ], + + "users": { + "invokingUser": { + "_extends_": "BeftaMasterCaseworker" + } + }, + + "request": { + "pathVariables": { + "uid": "[[DEFAULT_AUTO_VALUE]]", + "jid": "BEFTA_MASTER", + "ctid": "FT_CTT_Subfield_Multiple", + "etid": "createCase" + } + }, + + "expectedResponse": { + "body": { + "event_id": "createCase" + } + } +} diff --git a/src/aat/resources/features/F-065 - Get Case V2 Internal/S-167-Prerequisite_Case_Creation.td.json b/src/aat/resources/features/F-065 - Get Case V2 Internal/S-167-Prerequisite_Case_Creation.td.json new file mode 100644 index 0000000000..aa3bc6b16c --- /dev/null +++ b/src/aat/resources/features/F-065 - Get Case V2 Internal/S-167-Prerequisite_Case_Creation.td.json @@ -0,0 +1,59 @@ +{ + "_guid_": "S-167-Prerequisite_Case_Creation", + "_extends_": "Case_Creation_Base", + + "user": { + "_extends_": "BeftaMasterCaseworker" + }, + + "request": { + "pathVariables": { + "uid": "[[DEFAULT_AUTO_VALUE]]", + "jid": "BEFTA_MASTER", + "ctid": "FT_CTT_Subfield_Multiple" + }, + "body": { + "event_token": "${[scenarioContext][parentContext][childContexts][S-167-Prerequisite][testData][actualResponse][body][token]}", + "event": { + "id": "createCase", + "summary": "", + "description": "" + }, + "data": { + "MySchool": { + "Name": "Springfield Elementary", + "Number": 12345 + } + } + } + }, + + "expectedResponse": { + "_extends_": "Common_201_Response", + "body": { + "id": "[[ANYTHING_PRESENT]]", + "state": "CaseCreated", + "version": 0, + "jurisdiction": "BEFTA_MASTER", + "created_date": "[[ANYTHING_PRESENT]]", + "last_modified": "[[ANYTHING_PRESENT]]", + "last_state_modified_date": "[[ANYTHING_PRESENT]]", + "security_classification": "PUBLIC", + "case_type_id": "FT_CTT_Subfield_Multiple", + "case_data": { + "MySchool": { + "Name": "Springfield Elementary", + "Number": 12345 + } + }, + "data_classification": {}, + "supplementary_data": null, + "after_submit_callback_response": null, + "callback_response_status_code": null, + "callback_response_status": null, + "callback_error_message": null, + "delete_draft_response_status_code": null, + "delete_draft_response_status": null + } + } +} diff --git a/src/aat/resources/features/F-065 - Get Case V2 Internal/S-167.td.json b/src/aat/resources/features/F-065 - Get Case V2 Internal/S-167.td.json new file mode 100644 index 0000000000..293502a1b9 --- /dev/null +++ b/src/aat/resources/features/F-065 - Get Case V2 Internal/S-167.td.json @@ -0,0 +1,125 @@ +{ + "_guid_": "S-167", + "_extends_": "F-065_Test_Data_Base", + "title": "must return case view with multiple CaseTypeTab ListElementCode values as caseFieldSubfieldCode", + + "specs": [ + "an active BEFTA Master caseworker profile in CCD", + "contains a case with multiple CaseTypeTab ListElementCode values configured", + "contains caseFieldSubfieldCode for both MySchool tab fields" + ], + + "user": { + "_extends_": "BeftaMasterCaseworker" + }, + + "request": { + "pathVariables": { + "cid": "${[scenarioContext][childContexts][S-167-Prerequisite_Case_Creation][testData][actualResponse][body][id]}" + } + }, + + "expectedResponse": { + "_extends_": "Common_200_Response", + "headers": { + "Content-Type": "application/vnd.uk.gov.hmcts.ccd-data-store-api.ui-case-view.v2+json;charset=UTF-8" + }, + "body": { + "_links": { + "self": { + "href": "[[ANYTHING_PRESENT]]" + } + }, + "case_id": "${}${[scenarioContext][childContexts][S-167-Prerequisite_Case_Creation][testData][actualResponse][body][id]}", + "case_type": { + "id": "FT_CTT_Subfield_Multiple", + "name": "FT_CTT_Subfield_Multiple", + "description": "CaseTypeTab multiple complex subfields", + "jurisdiction": { + "id": "BEFTA_MASTER", + "name": "BEFTA Master", + "description": "Content for the BEFTA Master Jurisdiction." + }, + "printEnabled": false + }, + "tabs": [ + { + "__operator__": "superset", + "__ordering__": "unordered", + "__elementId__": "id" + }, + { + "id": "MySchoolDetails", + "label": "My School Details", + "order": 3, + "fields": [ + { + "id": "MySchool", + "label": "My School", + "hidden": false, + "value": { + "Name": "Springfield Elementary", + "Number": 12345 + }, + "metadata": false, + "hint_text": null, + "field_type": "[[ANYTHING_PRESENT]]", + "validation_expr": null, + "security_label": "PUBLIC", + "order": 1, + "formatted_value": { + "Name": "Springfield Elementary", + "Number": 12345 + }, + "display_context": null, + "display_context_parameter": null, + "show_condition": null, + "show_summary_change_option": null, + "show_summary_content_option": null, + "retain_hidden_value": null, + "publish": null, + "publish_as": null, + "acls": "[[ANYTHING_PRESENT]]", + "caseFieldSubfieldCode": "MySchool.Name" + }, + { + "id": "MySchool", + "label": "My School", + "hidden": false, + "value": { + "Name": "Springfield Elementary", + "Number": 12345 + }, + "metadata": false, + "hint_text": null, + "field_type": "[[ANYTHING_PRESENT]]", + "validation_expr": null, + "security_label": "PUBLIC", + "order": 2, + "formatted_value": { + "Name": "Springfield Elementary", + "Number": 12345 + }, + "display_context": null, + "display_context_parameter": null, + "show_condition": null, + "show_summary_change_option": null, + "show_summary_content_option": null, + "retain_hidden_value": null, + "publish": null, + "publish_as": null, + "acls": "[[ANYTHING_PRESENT]]", + "caseFieldSubfieldCode": "MySchool.Number" + } + ], + "show_condition": null, + "role": null + } + ], + "metadataFields": "[[ANYTHING_PRESENT]]", + "state": "[[ANYTHING_PRESENT]]", + "triggers": "[[ANYTHING_PRESENT]]", + "events": "[[ANYTHING_PRESENT]]" + } + } +} diff --git a/src/main/java/uk/gov/hmcts/ccd/domain/model/aggregated/CaseViewField.java b/src/main/java/uk/gov/hmcts/ccd/domain/model/aggregated/CaseViewField.java index eea884705e..b9f69225bd 100644 --- a/src/main/java/uk/gov/hmcts/ccd/domain/model/aggregated/CaseViewField.java +++ b/src/main/java/uk/gov/hmcts/ccd/domain/model/aggregated/CaseViewField.java @@ -1,7 +1,9 @@ package uk.gov.hmcts.ccd.domain.model.aggregated; +import com.fasterxml.jackson.annotation.JsonInclude; import com.fasterxml.jackson.annotation.JsonProperty; import lombok.ToString; +import org.apache.commons.lang3.StringUtils; import uk.gov.hmcts.ccd.domain.model.definition.AccessControlList; import uk.gov.hmcts.ccd.domain.model.definition.CaseFieldDefinition; import uk.gov.hmcts.ccd.domain.model.definition.CaseTypeTabField; @@ -52,6 +54,9 @@ public class CaseViewField implements CommonField { @JsonProperty("acls") private List accessControlLists; private boolean metadata; + @JsonInclude(JsonInclude.Include.NON_EMPTY) + @JsonProperty("caseFieldSubfieldCode") + private String caseFieldSubfieldCode; public String getId() { return id; @@ -213,11 +218,20 @@ public void setMetadata(boolean metadata) { this.metadata = metadata; } + public String getCaseFieldSubfieldCode() { + return caseFieldSubfieldCode; + } + + public void setCaseFieldSubfieldCode(String caseFieldSubfieldCode) { + this.caseFieldSubfieldCode = caseFieldSubfieldCode; + } + public static CaseViewField createFrom(CaseTypeTabField field, Map data) { CaseViewField caseViewField = createFrom(field.getCaseFieldDefinition(), data); caseViewField.setOrder(field.getDisplayOrder()); caseViewField.setShowCondition(field.getShowCondition()); caseViewField.setDisplayContextParameter(field.getDisplayContextParameter()); + caseViewField.setCaseFieldSubfieldCode(normaliseCaseFieldSubfieldCode(field)); return caseViewField; } @@ -239,4 +253,18 @@ public static CaseViewField createFrom(CaseFieldDefinition caseFieldDefinition, return caseViewField; } + + private static String normaliseCaseFieldSubfieldCode(CaseTypeTabField field) { + String caseFieldSubfieldCode = field.getCaseFieldSubfieldCode(); + if (StringUtils.isBlank(caseFieldSubfieldCode)) { + return caseFieldSubfieldCode; + } + + String caseFieldId = field.getCaseFieldDefinition().getId(); + return StringUtils.isBlank(caseFieldId) + || caseFieldSubfieldCode.equals(caseFieldId) + || caseFieldSubfieldCode.startsWith(caseFieldId + ".") + ? caseFieldSubfieldCode + : caseFieldId + "." + caseFieldSubfieldCode; + } } diff --git a/src/main/java/uk/gov/hmcts/ccd/domain/model/definition/CaseTypeTabField.java b/src/main/java/uk/gov/hmcts/ccd/domain/model/definition/CaseTypeTabField.java index c593ec4858..1f0bd5f6bb 100644 --- a/src/main/java/uk/gov/hmcts/ccd/domain/model/definition/CaseTypeTabField.java +++ b/src/main/java/uk/gov/hmcts/ccd/domain/model/definition/CaseTypeTabField.java @@ -2,6 +2,7 @@ import java.io.Serializable; +import com.fasterxml.jackson.annotation.JsonInclude; import com.fasterxml.jackson.annotation.JsonProperty; import io.swagger.v3.oas.annotations.media.Schema; @@ -13,6 +14,7 @@ public class CaseTypeTabField implements Serializable, CommonDCPModel { private Integer displayOrder = null; private String showCondition = null; private String displayContextParameter; + private String caseFieldSubfieldCode; @Schema @JsonProperty("case_field") @@ -53,4 +55,15 @@ public String getDisplayContextParameter() { public void setDisplayContextParameter(String displayContextParameter) { this.displayContextParameter = displayContextParameter; } + + @Schema + @JsonInclude(JsonInclude.Include.NON_EMPTY) + @JsonProperty("caseFieldSubfieldCode") + public String getCaseFieldSubfieldCode() { + return caseFieldSubfieldCode; + } + + public void setCaseFieldSubfieldCode(String caseFieldSubfieldCode) { + this.caseFieldSubfieldCode = caseFieldSubfieldCode; + } } diff --git a/src/test/java/uk/gov/hmcts/ccd/domain/model/aggregated/CaseViewFieldTest.java b/src/test/java/uk/gov/hmcts/ccd/domain/model/aggregated/CaseViewFieldTest.java new file mode 100644 index 0000000000..636a464c9f --- /dev/null +++ b/src/test/java/uk/gov/hmcts/ccd/domain/model/aggregated/CaseViewFieldTest.java @@ -0,0 +1,82 @@ +package uk.gov.hmcts.ccd.domain.model.aggregated; + +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.ObjectMapper; +import org.junit.jupiter.api.Test; +import uk.gov.hmcts.ccd.domain.model.definition.CaseFieldDefinition; +import uk.gov.hmcts.ccd.domain.model.definition.CaseTypeTabField; +import uk.gov.hmcts.ccd.domain.model.definition.FieldTypeDefinition; + +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.is; + +class CaseViewFieldTest { + + private static final ObjectMapper MAPPER = new ObjectMapper(); + private static final String CASE_FIELD_ID = "CaseFieldID"; + private static final String RELATIVE_CASE_FIELD_SUBFIELD_CODE = "Name"; + private static final String CASE_FIELD_SUBFIELD_CODE = CASE_FIELD_ID + "." + RELATIVE_CASE_FIELD_SUBFIELD_CODE; + private static final String CASE_FIELD_SUBFIELD_CODE_PROPERTY = "caseFieldSubfieldCode"; + + @Test + void shouldSerializeCaseFieldSubfieldCodeWhenPresent() throws Exception { + CaseViewField caseViewField = new CaseViewField(); + caseViewField.setId(CASE_FIELD_ID); + caseViewField.setCaseFieldSubfieldCode(CASE_FIELD_SUBFIELD_CODE); + + JsonNode json = MAPPER.readTree(MAPPER.writeValueAsString(caseViewField)); + + assertThat(json.get("id").asText(), is(CASE_FIELD_ID)); + assertThat(json.get(CASE_FIELD_SUBFIELD_CODE_PROPERTY).asText(), is(CASE_FIELD_SUBFIELD_CODE)); + } + + @Test + void shouldOmitCaseFieldSubfieldCodeWhenAbsent() throws Exception { + JsonNode json = MAPPER.readTree(MAPPER.writeValueAsString(new CaseViewField())); + + assertThat(json.has(CASE_FIELD_SUBFIELD_CODE_PROPERTY), is(false)); + } + + @Test + void shouldOmitCaseFieldSubfieldCodeWhenBlank() throws Exception { + CaseViewField caseViewField = new CaseViewField(); + caseViewField.setCaseFieldSubfieldCode(""); + + JsonNode json = MAPPER.readTree(MAPPER.writeValueAsString(caseViewField)); + + assertThat(json.has(CASE_FIELD_SUBFIELD_CODE_PROPERTY), is(false)); + } + + @Test + void shouldPrefixCaseFieldIdWhenCreatingFromRelativeCaseFieldSubfieldCode() { + CaseViewField caseViewField = CaseViewField.createFrom( + caseTypeTabField(CASE_FIELD_ID, RELATIVE_CASE_FIELD_SUBFIELD_CODE), + null + ); + + assertThat(caseViewField.getCaseFieldSubfieldCode(), is(CASE_FIELD_SUBFIELD_CODE)); + } + + @Test + void shouldKeepAbsoluteCaseFieldSubfieldCodeWhenCreatingFromCaseTypeTabField() { + CaseViewField caseViewField = CaseViewField.createFrom( + caseTypeTabField(CASE_FIELD_ID, CASE_FIELD_SUBFIELD_CODE), + null + ); + + assertThat(caseViewField.getCaseFieldSubfieldCode(), is(CASE_FIELD_SUBFIELD_CODE)); + } + + private CaseTypeTabField caseTypeTabField(String caseFieldId, String caseFieldSubfieldCode) { + FieldTypeDefinition fieldTypeDefinition = new FieldTypeDefinition(); + CaseFieldDefinition caseFieldDefinition = new CaseFieldDefinition(); + caseFieldDefinition.setId(caseFieldId); + caseFieldDefinition.setFieldTypeDefinition(fieldTypeDefinition); + + CaseTypeTabField caseTypeTabField = new CaseTypeTabField(); + caseTypeTabField.setCaseFieldDefinition(caseFieldDefinition); + caseTypeTabField.setCaseFieldSubfieldCode(caseFieldSubfieldCode); + + return caseTypeTabField; + } +} diff --git a/src/test/java/uk/gov/hmcts/ccd/domain/model/definition/CaseTypeTabFieldTest.java b/src/test/java/uk/gov/hmcts/ccd/domain/model/definition/CaseTypeTabFieldTest.java new file mode 100644 index 0000000000..d2b9e223fc --- /dev/null +++ b/src/test/java/uk/gov/hmcts/ccd/domain/model/definition/CaseTypeTabFieldTest.java @@ -0,0 +1,28 @@ +package uk.gov.hmcts.ccd.domain.model.definition; + +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.ObjectMapper; +import org.junit.jupiter.api.Test; + +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.is; + +class CaseTypeTabFieldTest { + + private static final ObjectMapper MAPPER = new ObjectMapper(); + + @Test + void shouldSerializeAndDeserializeCaseFieldSubfieldCode() throws Exception { + CaseTypeTabField tabField = new CaseTypeTabField(); + tabField.setCaseFieldSubfieldCode("CaseFieldID.FamilyAddress.Country"); + + JsonNode json = MAPPER.readTree(MAPPER.writeValueAsString(tabField)); + CaseTypeTabField deserialized = MAPPER.readValue( + "{\"caseFieldSubfieldCode\":\"CaseFieldID.FamilyAddress.Country\"}", + CaseTypeTabField.class + ); + + assertThat(json.get("caseFieldSubfieldCode").asText(), is("CaseFieldID.FamilyAddress.Country")); + assertThat(deserialized.getCaseFieldSubfieldCode(), is("CaseFieldID.FamilyAddress.Country")); + } +} diff --git a/src/test/java/uk/gov/hmcts/ccd/domain/service/aggregated/DefaultGetCaseViewOperationTest.java b/src/test/java/uk/gov/hmcts/ccd/domain/service/aggregated/DefaultGetCaseViewOperationTest.java index 6d24616e6e..019e369198 100644 --- a/src/test/java/uk/gov/hmcts/ccd/domain/service/aggregated/DefaultGetCaseViewOperationTest.java +++ b/src/test/java/uk/gov/hmcts/ccd/domain/service/aggregated/DefaultGetCaseViewOperationTest.java @@ -22,6 +22,7 @@ import uk.gov.hmcts.ccd.domain.model.definition.CaseFieldDefinition; import uk.gov.hmcts.ccd.domain.model.definition.CaseStateDefinition; import uk.gov.hmcts.ccd.domain.model.definition.CaseTypeDefinition; +import uk.gov.hmcts.ccd.domain.model.definition.CaseTypeTabField; import uk.gov.hmcts.ccd.domain.model.definition.CaseTypeTabsDefinition; import uk.gov.hmcts.ccd.domain.model.definition.FieldTypeDefinition; import uk.gov.hmcts.ccd.domain.model.definition.JurisdictionDefinition; @@ -76,6 +77,25 @@ class DefaultGetCaseViewOperationTest { private static final String EVENT_SUMMARY_2 = "Another summary"; private static final String STATE = "Plop"; private static final String TITLE_DISPLAY = "titleDisplay"; + private static final String DATA_TEST_FIELD_1 = "dataTestField1"; + private static final String DATA_TEST_FIELD_2 = "dataTestField2"; + private static final String COMPLEX_FIELD_TYPE = "Complex"; + private static final String FAMILY_ADDRESS_COUNTRY = "FamilyAddress.Country"; + private static final String FAMILY_ADDRESS_POST_CODE = "FamilyAddress.PostCode"; + private static final String DATA_TEST_FIELD_1_FAMILY_ADDRESS_COUNTRY = + DATA_TEST_FIELD_1 + "." + FAMILY_ADDRESS_COUNTRY; + private static final String DATA_TEST_FIELD_1_FAMILY_ADDRESS_POST_CODE = + DATA_TEST_FIELD_1 + "." + FAMILY_ADDRESS_POST_CODE; + private static final String DATA_TEST_FIELD_1_SHOW_CONDITION = DATA_TEST_FIELD_1 + "-fieldShowCondition"; + private static final String DATA_TEST_FIELD_2_SHOW_CONDITION = DATA_TEST_FIELD_2 + "-fieldShowCondition"; + private static final int NO_FIELD_COUNT = 0; + private static final int NO_ACTIONABLE_EVENT_COUNT = 0; + private static final int SINGLE_TAB_COUNT = 1; + private static final int SINGLE_FIELD_COUNT = 1; + private static final int SINGLE_ACTIONABLE_EVENT_COUNT = 1; + private static final int TWO_FIELD_COUNT = 2; + private static final int TWO_EVENT_COUNT = 2; + private static final int TWO_METADATA_FIELD_COUNT = 2; public static final String GET_CASE_METADATA_FIELD_ID = "anotherFieldId"; public static final String GET_CASE_METADATA_FIELD_VALUE = "getCaseMetadataFieldValue"; @@ -134,7 +154,7 @@ void setUp() { caseDetails.setCaseTypeId(CASE_TYPE_ID); caseDetails.setReference(Long.valueOf(CASE_REFERENCE)); caseDetails.setState(STATE); - Map dataMap = buildData("dataTestField1", "dataTestField2"); + Map dataMap = buildData(DATA_TEST_FIELD_1, DATA_TEST_FIELD_2); caseDetails.setData(dataMap); doReturn(Optional.of(caseDetails)).when(getCaseOperation).execute(CASE_REFERENCE); @@ -149,7 +169,7 @@ void setUp() { doReturn(Boolean.TRUE).when(uidService).validateUID(CASE_REFERENCE); - caseTypeTabsDefinition = newCaseTabCollection().withFieldIds("dataTestField1", "dataTestField2").build(); + caseTypeTabsDefinition = newCaseTabCollection().withFieldIds(DATA_TEST_FIELD_1, DATA_TEST_FIELD_2).build(); doReturn(caseTypeTabsDefinition).when(uiDefinitionRepository).getCaseTabCollection(CASE_TYPE_ID); caseTypeDefinition = new CaseTypeDefinition(); @@ -205,13 +225,13 @@ void shouldHydrateCaseHistoryViewerIfFieldPresentInTabs() { final CaseView caseView = defaultGetCaseViewOperation.execute(CASE_REFERENCE); assertAll( - () -> assertThat(caseView.getTabs(), arrayWithSize(1)), - () -> assertThat(caseView.getTabs()[0].getFields(), arrayWithSize(1)), + () -> assertThat(caseView.getTabs(), arrayWithSize(SINGLE_TAB_COUNT)), + () -> assertThat(caseView.getTabs()[0].getFields(), arrayWithSize(SINGLE_FIELD_COUNT)), () -> assertThat(caseView.getTabs()[0].getFields()[0], hasProperty("id", equalTo(CASE_HISTORY_VIEWER))), () -> assertThat(caseView.getTabs()[0].getFields()[0], hasProperty("value", equalTo(eventsNode))), - () -> assertThat(caseView.getEvents(), arrayWithSize(2)), + () -> assertThat(caseView.getEvents(), arrayWithSize(TWO_EVENT_COUNT)), () -> assertThat(caseView.getEvents(), hasItemInArray(hasProperty("summary", equalTo(EVENT_SUMMARY_1)))), () -> assertThat(caseView.getEvents(), hasItemInArray(hasProperty("summary", @@ -248,9 +268,9 @@ void shouldNotHydrateCaseHistoryViewerIfFieldIsNotPresentInTabs() { final CaseView caseView = defaultGetCaseViewOperation.execute(CASE_REFERENCE); assertAll( - () -> assertThat(caseView.getTabs(), arrayWithSize(1)), - () -> assertThat(caseView.getTabs()[0].getFields(), arrayWithSize(0)), - () -> assertThat(caseView.getEvents(), arrayWithSize(2)), + () -> assertThat(caseView.getTabs(), arrayWithSize(SINGLE_TAB_COUNT)), + () -> assertThat(caseView.getTabs()[0].getFields(), arrayWithSize(NO_FIELD_COUNT)), + () -> assertThat(caseView.getEvents(), arrayWithSize(TWO_EVENT_COUNT)), () -> assertThat(caseView.getEvents(), hasItemInArray(hasProperty("summary", equalTo(EVENT_SUMMARY_1)))), () -> assertThat(caseView.getEvents(), hasItemInArray(hasProperty("summary", @@ -267,28 +287,29 @@ class CaseEventEnablingCondition { @DisplayName("should not filter event when enabling condition is valid") void shouldNotFilterEventWhenEnablingConditionIsValid() { CaseEventDefinition caseEventDefinition = new CaseEventDefinition(); - caseEventDefinition.setEndButtonLabel("dataTestField1=\"dataTestField1\""); + caseEventDefinition.setEndButtonLabel(DATA_TEST_FIELD_1 + "=\"" + DATA_TEST_FIELD_1 + "\""); caseTypeDefinition.setEvents(Lists.newArrayList(caseEventDefinition)); doReturn(true).when(eventTriggerService).isPreStateValid(anyString(), any()); doReturn(true).when(caseEventEnablingService).isEventEnabled(any(), any(CaseDetails.class), anyList()); CaseView caseView = defaultGetCaseViewOperation.execute(CASE_REFERENCE); assertNotNull(caseView); - assertEquals(1, caseView.getActionableEvents().length); + assertEquals(SINGLE_ACTIONABLE_EVENT_COUNT, caseView.getActionableEvents().length); } @Test @DisplayName("should filter event when enabling condition is not valid") void shouldFilterEventWhenEnablingConditionIsNotValid() { CaseEventDefinition caseEventDefinition = new CaseEventDefinition(); - caseEventDefinition.setEndButtonLabel("dataTestField1=\"dataTestField1\" AND dataTestField2=\"Test\""); + caseEventDefinition.setEndButtonLabel(DATA_TEST_FIELD_1 + "=\"" + DATA_TEST_FIELD_1 + "\" AND " + + DATA_TEST_FIELD_2 + "=\"Test\""); caseTypeDefinition.setEvents(Lists.newArrayList(caseEventDefinition)); doReturn(true).when(eventTriggerService).isPreStateValid(anyString(), any()); doReturn(false).when(caseEventEnablingService).isEventEnabled(any(), any(CaseDetails.class), anyList()); CaseView caseView = defaultGetCaseViewOperation.execute(CASE_REFERENCE); assertNotNull(caseView); - assertEquals(0, caseView.getActionableEvents().length); + assertEquals(NO_ACTIONABLE_EVENT_COUNT, caseView.getActionableEvents().length); } } @@ -313,18 +334,18 @@ void shouldRetrieveAllAuthorisedAuditEventsAndTabs() { assertAll( () -> verify(getEventsOperation).getEvents(caseDetails), - () -> assertThat(caseView.getTabs(), arrayWithSize(1)), - () -> assertThat(caseView.getTabs()[0].getFields(), arrayWithSize(2)), + () -> assertThat(caseView.getTabs(), arrayWithSize(SINGLE_TAB_COUNT)), + () -> assertThat(caseView.getTabs()[0].getFields(), arrayWithSize(TWO_FIELD_COUNT)), () -> assertThat(caseView.getTabs()[0].getFields(), - hasItemInArray(allOf(hasProperty("id", equalTo("dataTestField1")), + hasItemInArray(allOf(hasProperty("id", equalTo(DATA_TEST_FIELD_1)), hasProperty("showCondition", - equalTo("dataTestField1-fieldShowCondition"))))), + equalTo(DATA_TEST_FIELD_1_SHOW_CONDITION))))), () -> assertThat(caseView.getTabs()[0].getFields(), - hasItemInArray(allOf(hasProperty("id", equalTo("dataTestField2")), + hasItemInArray(allOf(hasProperty("id", equalTo(DATA_TEST_FIELD_2)), hasProperty("showCondition", - equalTo("dataTestField2-fieldShowCondition"))))), + equalTo(DATA_TEST_FIELD_2_SHOW_CONDITION))))), () -> assertThat(caseView.getMetadataFields().get(0).getValue(), equalTo(CASE_TYPE_ID)), - () -> assertThat(caseView.getEvents(), arrayWithSize(2)), + () -> assertThat(caseView.getEvents(), arrayWithSize(TWO_EVENT_COUNT)), () -> assertThat(caseView.getEvents(), hasItemInArray(hasProperty("summary", equalTo(EVENT_SUMMARY_1)))), () -> assertThat(caseView.getEvents(), hasItemInArray(hasProperty("summary", @@ -334,6 +355,76 @@ void shouldRetrieveAllAuthorisedAuditEventsAndTabs() { ); } + @Test + @DisplayName("should preserve fully qualified CaseFieldSubfieldCode in case view tab fields") + void shouldPreserveFullyQualifiedCaseFieldSubfieldCodeInCaseViewTabFields() { + caseTypeTabsDefinition = newCaseTabCollection() + .withTab(newCaseTab() + .withTabField(caseTabField(DATA_TEST_FIELD_1, COMPLEX_FIELD_TYPE, + DATA_TEST_FIELD_1_FAMILY_ADDRESS_COUNTRY)) + .build()) + .build(); + doReturn(caseTypeTabsDefinition).when(uiDefinitionRepository).getCaseTabCollection(CASE_TYPE_ID); + + final CaseView caseView = defaultGetCaseViewOperation.execute(CASE_REFERENCE); + + assertAll( + () -> assertThat(caseView.getTabs(), arrayWithSize(SINGLE_TAB_COUNT)), + () -> assertThat(caseView.getTabs()[0].getFields(), arrayWithSize(SINGLE_FIELD_COUNT)), + () -> assertThat(caseView.getTabs()[0].getFields()[0], + allOf(hasProperty("id", equalTo(DATA_TEST_FIELD_1)), + hasProperty("caseFieldSubfieldCode", equalTo(DATA_TEST_FIELD_1_FAMILY_ADDRESS_COUNTRY)))) + ); + } + + @Test + @DisplayName("should return fully qualified CaseFieldSubfieldCode when CaseTypeTab uses relative subfield code") + void shouldReturnFullyQualifiedCaseFieldSubfieldCodeFromRelativeSubfieldCode() { + caseTypeTabsDefinition = newCaseTabCollection() + .withTab(newCaseTab() + .withTabField(caseTabField(DATA_TEST_FIELD_1, COMPLEX_FIELD_TYPE, FAMILY_ADDRESS_COUNTRY)) + .build()) + .build(); + doReturn(caseTypeTabsDefinition).when(uiDefinitionRepository).getCaseTabCollection(CASE_TYPE_ID); + + final CaseView caseView = defaultGetCaseViewOperation.execute(CASE_REFERENCE); + + assertAll( + () -> assertThat(caseView.getTabs(), arrayWithSize(SINGLE_TAB_COUNT)), + () -> assertThat(caseView.getTabs()[0].getFields(), arrayWithSize(SINGLE_FIELD_COUNT)), + () -> assertThat(caseView.getTabs()[0].getFields()[0], + allOf(hasProperty("id", equalTo(DATA_TEST_FIELD_1)), + hasProperty("caseFieldSubfieldCode", equalTo(DATA_TEST_FIELD_1_FAMILY_ADDRESS_COUNTRY)))) + ); + } + + @Test + @DisplayName("should return fully qualified CaseFieldSubfieldCode for multiple relative subfield codes") + void shouldReturnFullyQualifiedCaseFieldSubfieldCodeForMultipleRelativeSubfieldCodes() { + CaseFieldDefinition dataTestField1 = caseField(DATA_TEST_FIELD_1, COMPLEX_FIELD_TYPE); + + caseTypeTabsDefinition = newCaseTabCollection() + .withTab(newCaseTab() + .withTabField(caseTabField(dataTestField1, FAMILY_ADDRESS_COUNTRY)) + .withTabField(caseTabField(dataTestField1, FAMILY_ADDRESS_POST_CODE)) + .build()) + .build(); + doReturn(caseTypeTabsDefinition).when(uiDefinitionRepository).getCaseTabCollection(CASE_TYPE_ID); + + final CaseView caseView = defaultGetCaseViewOperation.execute(CASE_REFERENCE); + + assertAll( + () -> assertThat(caseView.getTabs(), arrayWithSize(SINGLE_TAB_COUNT)), + () -> assertThat(caseView.getTabs()[0].getFields(), arrayWithSize(TWO_FIELD_COUNT)), + () -> assertThat(caseView.getTabs()[0].getFields(), + hasItemInArray(hasProperty("caseFieldSubfieldCode", + equalTo(DATA_TEST_FIELD_1_FAMILY_ADDRESS_COUNTRY)))), + () -> assertThat(caseView.getTabs()[0].getFields(), + hasItemInArray(hasProperty("caseFieldSubfieldCode", + equalTo(DATA_TEST_FIELD_1_FAMILY_ADDRESS_POST_CODE)))) + ); + } + @Test @DisplayName("should add metadata fields from the get case callback") void shouldAddMetadataFieldsFromTheGetCaseCallback() { @@ -346,7 +437,7 @@ void shouldAddMetadataFieldsFromTheGetCaseCallback() { final CaseView caseView = defaultGetCaseViewOperation.execute(CASE_REFERENCE); assertAll( - () -> assertThat(caseView.getMetadataFields().size(), equalTo(2)), + () -> assertThat(caseView.getMetadataFields().size(), equalTo(TWO_METADATA_FIELD_COUNT)), () -> assertThat(caseView.getMetadataFields().get(0).getId(), equalTo("[CASE_TYPE]")), () -> assertThat(caseView.getMetadataFields().get(0).getValue(), equalTo(CASE_TYPE_ID)), () -> assertThat(caseView.getMetadataFields().get(1).getId(), equalTo(GET_CASE_METADATA_FIELD_ID)), @@ -357,17 +448,17 @@ void shouldAddMetadataFieldsFromTheGetCaseCallback() { @Test @DisplayName("should retrieve only the authorised audit events") void shouldRetrieveOnlyAuthorisedAuditEvents() { - Map dataMap = buildData("dataTestField2"); + Map dataMap = buildData(DATA_TEST_FIELD_2); caseDetails.setData(dataMap); final CaseView caseView = defaultGetCaseViewOperation.execute(CASE_REFERENCE); assertAll( () -> verify(getEventsOperation).getEvents(caseDetails), - () -> assertThat(caseView.getTabs()[0].getFields(), arrayWithSize(1)), + () -> assertThat(caseView.getTabs()[0].getFields(), arrayWithSize(SINGLE_FIELD_COUNT)), () -> assertThat(caseView.getTabs()[0].getFields(), hasItemInArray(hasProperty("id", - equalTo("dataTestField2")))), - () -> assertThat(caseView.getEvents(), arrayWithSize(2)), + equalTo(DATA_TEST_FIELD_2)))), + () -> assertThat(caseView.getEvents(), arrayWithSize(TWO_EVENT_COUNT)), () -> assertThat(caseView.getEvents(), hasItemInArray(hasProperty("summary", equalTo(EVENT_SUMMARY_1)))), () -> assertThat(caseView.getEvents(), hasItemInArray(hasProperty("summary", @@ -382,6 +473,26 @@ private CaseViewField caseViewField() { return caseViewField; } + private CaseTypeTabField caseTabField(String fieldId, String fieldType, String caseFieldSubfieldCode) { + return caseTabField(caseField(fieldId, fieldType), caseFieldSubfieldCode); + } + + private CaseTypeTabField caseTabField(CaseFieldDefinition caseField, String caseFieldSubfieldCode) { + return newCaseTabField() + .withCaseField(caseField) + .withCaseFieldSubfieldCode(caseFieldSubfieldCode) + .build(); + } + + private CaseFieldDefinition caseField(String fieldId, String fieldType) { + return newCaseField() + .withId(fieldId) + .withFieldType(aFieldType() + .withType(fieldType) + .build()) + .build(); + } + private Map buildData(String... dataFieldIds) { Map dataMap = new HashMap<>(); asList(dataFieldIds).forEach(dataFieldId -> { diff --git a/src/test/java/uk/gov/hmcts/ccd/domain/service/common/TestBuildersUtil.java b/src/test/java/uk/gov/hmcts/ccd/domain/service/common/TestBuildersUtil.java index a091a03622..b403f125bd 100644 --- a/src/test/java/uk/gov/hmcts/ccd/domain/service/common/TestBuildersUtil.java +++ b/src/test/java/uk/gov/hmcts/ccd/domain/service/common/TestBuildersUtil.java @@ -1601,6 +1601,11 @@ public CaseTypeTabFieldBuilder withDisplayContextParameter(final String displayC return this; } + public CaseTypeTabFieldBuilder withCaseFieldSubfieldCode(final String caseFieldSubfieldCode) { + caseTypeTabField.setCaseFieldSubfieldCode(caseFieldSubfieldCode); + return this; + } + } public static class CaseTypeTabBuilder {