diff --git a/api-docs/aggregated.swagger.yaml b/api-docs/aggregated.swagger.yaml
index 378e77449a..65e004cc9c 100644
--- a/api-docs/aggregated.swagger.yaml
+++ b/api-docs/aggregated.swagger.yaml
@@ -517,6 +517,7 @@ definitions:
- FixedList
- MoneyGBP
- TextArea
+ - RichTextArea
- ComplexType
- Collection
- MultiSelectList
diff --git a/build.gradle b/build.gradle
index 7244fea4a0..199a3e87f4 100644
--- a/build.gradle
+++ b/build.gradle
@@ -219,6 +219,14 @@ task integration(type: Test) {
failFast = true
}
+task aatTest(type: Test) {
+ description = "Runs JUnit AAT tests"
+ group = "Verification"
+ testClassesDirs = sourceSets.aat.output.classesDirs
+ classpath = sourceSets.aat.runtimeClasspath
+ failFast = true
+}
+
ext.libraries = [
junit5: [
"org.junit.jupiter:junit-jupiter-api:${junit}",
diff --git a/docs/api/case-data.md b/docs/api/case-data.md
index 8da3dc68ab..fdead28066 100644
--- a/docs/api/case-data.md
+++ b/docs/api/case-data.md
@@ -122,6 +122,16 @@ A `TextArea` value is a `string`. It contain `\n` to represent line breaks.
}
```
+### RichTextArea
+
+A `RichTextArea` value is a `string`. CCD stores the rich text content as an opaque string and does not interpret the markup.
+
+```json
+{
+ "FieldId": "
Order
"
+}
+```
+
### FixedList
A `FixedList` value is a `string` exactly matching the code of one the pre-defined options for that list.
@@ -349,4 +359,3 @@ Also shows the optional required OrganisationPolicyField field.
}
}
```
-
diff --git a/src/aat/java/uk/gov/hmcts/ccd/datastore/tests/v2/external/RichTextAreaCaseTest.java b/src/aat/java/uk/gov/hmcts/ccd/datastore/tests/v2/external/RichTextAreaCaseTest.java
new file mode 100644
index 0000000000..f346affafb
--- /dev/null
+++ b/src/aat/java/uk/gov/hmcts/ccd/datastore/tests/v2/external/RichTextAreaCaseTest.java
@@ -0,0 +1,168 @@
+package uk.gov.hmcts.ccd.datastore.tests.v2.external;
+
+import io.restassured.response.Response;
+import io.restassured.specification.RequestSpecification;
+import org.junit.jupiter.api.DisplayName;
+import org.junit.jupiter.api.Test;
+import uk.gov.hmcts.ccd.datastore.tests.AATHelper;
+import uk.gov.hmcts.ccd.datastore.tests.BaseTest;
+import uk.gov.hmcts.ccd.v2.V2;
+
+import java.util.function.Supplier;
+
+import static java.lang.Boolean.FALSE;
+import static org.hamcrest.Matchers.equalTo;
+import static org.hamcrest.Matchers.notNullValue;
+
+@DisplayName("RichTextArea case data")
+class RichTextAreaCaseTest extends BaseTest {
+
+ private static final String CASE_TYPE = "AllDataTypes2";
+ private static final String CREATE_EVENT = "createCase";
+ private static final String UPDATE_EVENT = "updateRichTextArea";
+ private static final String RICH_TEXT_AREA_FIELD = "RichTextAreaField";
+ private static final String RICH_TEXT_AREA_COMPLEX_FIELD = "RichTextAreaComplexField";
+ private static final String RICH_TEXT_AREA_COMPLEX_ELEMENT = "RichTextAreaElement";
+ private static final String CREATED_RICH_TEXT = "Order created for CCD-7988
";
+ private static final String CREATED_COMPLEX_RICH_TEXT =
+ "Complex order text created for CCD-7988
";
+ private static final String UPDATED_RICH_TEXT = "Order updated for CCD-7988
";
+ private static final String UPDATED_COMPLEX_RICH_TEXT =
+ "Complex order text updated for CCD-7988
";
+
+ protected RichTextAreaCaseTest(AATHelper aat) {
+ super(aat);
+ }
+
+ @Test
+ @DisplayName("should create, update and retrieve RichTextArea fields")
+ void shouldCreateUpdateAndRetrieveRichTextAreaFields() {
+ String createToken = getStartCaseToken(CREATE_EVENT);
+
+ String caseReference = createCase(createToken)
+ .then()
+ .statusCode(201)
+ .body("id", notNullValue())
+ .body("data." + RICH_TEXT_AREA_FIELD, equalTo(CREATED_RICH_TEXT))
+ .body("data." + RICH_TEXT_AREA_COMPLEX_FIELD + "." + RICH_TEXT_AREA_COMPLEX_ELEMENT,
+ equalTo(CREATED_COMPLEX_RICH_TEXT))
+ .extract()
+ .path("id");
+
+ String updateToken = getStartEventToken(caseReference, UPDATE_EVENT);
+
+ updateCase(caseReference, updateToken)
+ .then()
+ .statusCode(201)
+ .body("id", equalTo(caseReference))
+ .body("data." + RICH_TEXT_AREA_FIELD, equalTo(UPDATED_RICH_TEXT))
+ .body("data." + RICH_TEXT_AREA_COMPLEX_FIELD + "." + RICH_TEXT_AREA_COMPLEX_ELEMENT,
+ equalTo(UPDATED_COMPLEX_RICH_TEXT));
+
+ getCase(caseReference)
+ .then()
+ .statusCode(200)
+ .body("id", equalTo(caseReference))
+ .body("data." + RICH_TEXT_AREA_FIELD, equalTo(UPDATED_RICH_TEXT))
+ .body("data." + RICH_TEXT_AREA_COMPLEX_FIELD + "." + RICH_TEXT_AREA_COMPLEX_ELEMENT,
+ equalTo(UPDATED_COMPLEX_RICH_TEXT));
+ }
+
+ private String getStartCaseToken(String eventId) {
+ return asV2AutoTestCaseworker()
+ .get()
+ .given()
+ .pathParam("caseTypeId", CASE_TYPE)
+ .pathParam("triggerId", eventId)
+ .accept(V2.MediaType.START_CASE_EVENT)
+ .when()
+ .get("/case-types/{caseTypeId}/event-triggers/{triggerId}?ignore-warning=true")
+ .then()
+ .statusCode(200)
+ .extract()
+ .path("token");
+ }
+
+ private String getStartEventToken(String caseReference, String eventId) {
+ return asV2AutoTestCaseworker()
+ .get()
+ .given()
+ .pathParam("caseId", caseReference)
+ .pathParam("triggerId", eventId)
+ .accept(V2.MediaType.START_EVENT)
+ .when()
+ .get("/cases/{caseId}/event-triggers/{triggerId}?ignore-warning=true")
+ .then()
+ .statusCode(200)
+ .extract()
+ .path("token");
+ }
+
+ private Response createCase(String token) {
+ return asV2AutoTestCaseworker()
+ .get()
+ .given()
+ .pathParam("caseTypeId", CASE_TYPE)
+ .contentType(V2.MediaType.CREATE_CASE)
+ .accept(V2.MediaType.CREATE_CASE)
+ .body(caseDataContent(CREATE_EVENT, token, CREATED_RICH_TEXT, CREATED_COMPLEX_RICH_TEXT))
+ .when()
+ .post("/case-types/{caseTypeId}/cases?ignore-warning=true");
+ }
+
+ private Response updateCase(String caseReference, String token) {
+ return asV2AutoTestCaseworker()
+ .get()
+ .given()
+ .pathParam("caseId", caseReference)
+ .contentType(V2.MediaType.CREATE_EVENT)
+ .accept(V2.MediaType.CREATE_EVENT)
+ .body(caseDataContent(UPDATE_EVENT, token, UPDATED_RICH_TEXT, UPDATED_COMPLEX_RICH_TEXT))
+ .when()
+ .post("/cases/{caseId}/events");
+ }
+
+ private Response getCase(String caseReference) {
+ return asV2AutoTestCaseworker()
+ .get()
+ .given()
+ .pathParam("caseId", caseReference)
+ .accept(V2.MediaType.CASE)
+ .when()
+ .get("/cases/{caseId}");
+ }
+
+ private Supplier asV2AutoTestCaseworker() {
+ return () -> asAutoTestCaseworker(FALSE)
+ .get()
+ .given()
+ .header("experimental", "true");
+ }
+
+ private String caseDataContent(String eventId, String token, String richText, String complexRichText) {
+ return """
+ {
+ "event_token": "%s",
+ "event": {
+ "id": "%s",
+ "summary": "CCD-7988 RichTextArea",
+ "description": "RichTextArea AAT"
+ },
+ "data": {
+ "%s": "%s",
+ "%s": {
+ "%s": "%s"
+ }
+ }
+ }
+ """.formatted(
+ token,
+ eventId,
+ RICH_TEXT_AREA_FIELD,
+ richText,
+ RICH_TEXT_AREA_COMPLEX_FIELD,
+ RICH_TEXT_AREA_COMPLEX_ELEMENT,
+ complexRichText
+ );
+ }
+}
diff --git a/src/aat/resources/features/common/fieldtypes/base/BaseRichTextAreaFieldType.td.json b/src/aat/resources/features/common/fieldtypes/base/BaseRichTextAreaFieldType.td.json
new file mode 100644
index 0000000000..d6ca1fe971
--- /dev/null
+++ b/src/aat/resources/features/common/fieldtypes/base/BaseRichTextAreaFieldType.td.json
@@ -0,0 +1,7 @@
+{
+ "_guid_": "BaseRichTextAreaFieldType",
+ "_extends_": "CommonFieldType",
+
+ "id": "RichTextArea",
+ "type": "RichTextArea"
+}
diff --git a/src/contractTest/resources/application.properties b/src/contractTest/resources/application.properties
index 064ab7e8e2..66567cdb85 100644
--- a/src/contractTest/resources/application.properties
+++ b/src/contractTest/resources/application.properties
@@ -201,7 +201,7 @@ management.health.elasticsearch.enabled=false
management.health.status.order=DOWN, OUT_OF_SERVICE, UNKNOWN, UP, OUT_OF_SYNC, PROBLEM, COULD_NOT_CONNECT
# Elasticsearch mappings
-elasticsearch.type-mappings.defaultText=Text, TextArea, FixedList, FixedListEdit, MultiSelectList, FixedRadioList, DynamicList, DynamicRadioList, DynamicMultiSelectList, Region, BaseLocation, PhoneUK
+elasticsearch.type-mappings.defaultText=Text, TextArea, RichTextArea, FixedList, FixedListEdit, MultiSelectList, FixedRadioList, DynamicList, DynamicRadioList, DynamicMultiSelectList, Region, BaseLocation, PhoneUK
elasticsearch.case-predefined-mappings.defaultText=reference, jurisdiction, state, case_type_id
# Remote Case Audit
@@ -271,6 +271,7 @@ ccd.messaging.type-mappings.Text=SimpleText
ccd.messaging.type-mappings.PhoneUK=SimpleText
ccd.messaging.type-mappings.Email=SimpleText
ccd.messaging.type-mappings.TextArea=SimpleText
+ccd.messaging.type-mappings.RichTextArea=SimpleText
ccd.messaging.type-mappings.BaseLocation=SimpleText
ccd.messaging.type-mappings.Region=SimpleText
ccd.messaging.type-mappings.Date=SimpleDate
diff --git a/src/main/java/uk/gov/hmcts/ccd/domain/model/definition/FieldTypeDefinition.java b/src/main/java/uk/gov/hmcts/ccd/domain/model/definition/FieldTypeDefinition.java
index 371e1c1fab..7a049c8cff 100644
--- a/src/main/java/uk/gov/hmcts/ccd/domain/model/definition/FieldTypeDefinition.java
+++ b/src/main/java/uk/gov/hmcts/ccd/domain/model/definition/FieldTypeDefinition.java
@@ -34,6 +34,7 @@ public class FieldTypeDefinition implements Serializable, Copyable validate(final String dataFieldId,
+ final JsonNode dataValue,
+ final CaseFieldDefinition caseFieldDefinition) {
+ if (isNullOrEmpty(dataValue)) {
+ return Collections.emptyList();
+ }
+
+ if (!dataValue.isTextual()) {
+ final String nodeType = dataValue.getNodeType().toString().toLowerCase(Locale.ROOT);
+ return Collections.singletonList(new ValidationResult(nodeType + " is not a string", dataFieldId));
+ }
+
+ final String value = dataValue.textValue();
+
+ final BigDecimal minLength = caseFieldDefinition.getFieldTypeDefinition().getMin();
+
+ if (!TextValidator.checkMin(minLength, value)) {
+ return Collections.singletonList(
+ new ValidationResult("requires a minimum length of " + minLength, dataFieldId)
+ );
+ }
+
+ return Collections.emptyList();
+ }
+}
diff --git a/src/main/resources/application.properties b/src/main/resources/application.properties
index 67c9733f40..dd114d8089 100644
--- a/src/main/resources/application.properties
+++ b/src/main/resources/application.properties
@@ -234,7 +234,7 @@ management.health.elasticsearch.enabled=false
management.health.status.order=DOWN, OUT_OF_SERVICE, UNKNOWN, UP, OUT_OF_SYNC, PROBLEM, COULD_NOT_CONNECT
# Elasticsearch mappings
-elasticsearch.type-mappings.defaultText=Text, TextArea, FixedList, FixedListEdit, MultiSelectList, FixedRadioList, DynamicList, DynamicRadioList, DynamicMultiSelectList, Region, BaseLocation, PhoneUK
+elasticsearch.type-mappings.defaultText=Text, TextArea, RichTextArea, FixedList, FixedListEdit, MultiSelectList, FixedRadioList, DynamicList, DynamicRadioList, DynamicMultiSelectList, Region, BaseLocation, PhoneUK
elasticsearch.case-predefined-mappings.defaultText=reference, jurisdiction, state, case_type_id
# Remote Case Audit
@@ -295,6 +295,7 @@ ccd.messaging.type-mappings.Text=SimpleText
ccd.messaging.type-mappings.PhoneUK=SimpleText
ccd.messaging.type-mappings.Email=SimpleText
ccd.messaging.type-mappings.TextArea=SimpleText
+ccd.messaging.type-mappings.RichTextArea=SimpleText
ccd.messaging.type-mappings.BaseLocation=SimpleText
ccd.messaging.type-mappings.Region=SimpleText
ccd.messaging.type-mappings.Date=SimpleDate
diff --git a/src/test/java/uk/gov/hmcts/ccd/TestConfiguration.java b/src/test/java/uk/gov/hmcts/ccd/TestConfiguration.java
index 608c4c0d71..d6e567bd30 100644
--- a/src/test/java/uk/gov/hmcts/ccd/TestConfiguration.java
+++ b/src/test/java/uk/gov/hmcts/ccd/TestConfiguration.java
@@ -75,6 +75,9 @@ class TestConfiguration extends ContextCleanupListener {
+ " \"type\": \"TextArea\"\n"
+ " },\n"
+ " {\n"
+ + " \"type\": \"RichTextArea\"\n"
+ + " },\n"
+ + " {\n"
+ " \"type\": \"Complex\"\n"
+ " },\n"
+ " {\n"
diff --git a/src/test/java/uk/gov/hmcts/ccd/data/ReferenceDataCacheRefreshIT.java b/src/test/java/uk/gov/hmcts/ccd/data/ReferenceDataCacheRefreshIT.java
index f835f5fc54..6a9e5788fc 100644
--- a/src/test/java/uk/gov/hmcts/ccd/data/ReferenceDataCacheRefreshIT.java
+++ b/src/test/java/uk/gov/hmcts/ccd/data/ReferenceDataCacheRefreshIT.java
@@ -133,10 +133,19 @@ private void referenceDataNotFoundUpstream() {
private void verifyWiremockInvocation(final String path, final int count) {
final RequestPattern requestPattern = getRequestedFor(urlPathEqualTo(path)).build();
- final VerificationResult verificationResult = wireMockServer.countRequestsMatching(requestPattern);
- assertThat(verificationResult)
- .isNotNull()
- .satisfies(result -> assertThat(result.getCount()).isGreaterThanOrEqualTo(count));
+
+ await()
+ .atMost(Durations.FIVE_SECONDS)
+ .untilAsserted(() -> {
+ final VerificationResult verificationResult = wireMockServer.countRequestsMatching(requestPattern);
+
+ assertThat(verificationResult)
+ .isNotNull();
+
+ assertThat(verificationResult.getCount())
+ .as("Expected WireMock path %s to be called at least %s times", path, count)
+ .isGreaterThanOrEqualTo(count);
+ });
}
private void cacheContainsInitialReferenceData() {
diff --git a/src/test/java/uk/gov/hmcts/ccd/data/definition/DefaultCaseDefinitionRepositoryIT.java b/src/test/java/uk/gov/hmcts/ccd/data/definition/DefaultCaseDefinitionRepositoryIT.java
index 8d693a4a16..46f1abd0c9 100644
--- a/src/test/java/uk/gov/hmcts/ccd/data/definition/DefaultCaseDefinitionRepositoryIT.java
+++ b/src/test/java/uk/gov/hmcts/ccd/data/definition/DefaultCaseDefinitionRepositoryIT.java
@@ -56,7 +56,7 @@ public void shouldGetBaseTypes() {
assertAll(
"Assert All of these",
- () -> assertThat(baseTypes, IsCollectionWithSize.hasSize(18)),
+ () -> assertThat(baseTypes, IsCollectionWithSize.hasSize(19)),
() -> assertThat(baseTypes, hasItem(hasProperty("type", is("Text")))),
() -> assertThat(baseTypes, hasItem(hasProperty("type", is("Number")))),
() -> assertThat(baseTypes, hasItem(hasProperty("type", is("Email")))),
@@ -68,6 +68,7 @@ public void shouldGetBaseTypes() {
() -> assertThat(baseTypes, hasItem(hasProperty("type", is("MoneyGBP")))),
() -> assertThat(baseTypes, hasItem(hasProperty("type", is("PhoneUK")))),
() -> assertThat(baseTypes, hasItem(hasProperty("type", is("TextArea")))),
+ () -> assertThat(baseTypes, hasItem(hasProperty("type", is("RichTextArea")))),
() -> assertThat(baseTypes, hasItem(hasProperty("type", is(COLLECTION)))),
() -> assertThat(baseTypes, hasItem(hasProperty("type", is("MultiSelectList")))),
() -> assertThat(baseTypes, hasItem(hasProperty("type", is("DynamicRadioList")))),
diff --git a/src/test/java/uk/gov/hmcts/ccd/domain/service/search/elasticsearch/ElasticsearchMappingsTest.java b/src/test/java/uk/gov/hmcts/ccd/domain/service/search/elasticsearch/ElasticsearchMappingsTest.java
index 08f12b9c2e..829f6ec9e3 100644
--- a/src/test/java/uk/gov/hmcts/ccd/domain/service/search/elasticsearch/ElasticsearchMappingsTest.java
+++ b/src/test/java/uk/gov/hmcts/ccd/domain/service/search/elasticsearch/ElasticsearchMappingsTest.java
@@ -18,8 +18,8 @@ class ElasticsearchMappingsTest {
@BeforeEach
void setUp() {
ElasticsearchMappings.TypeMappings typeMappings = new ElasticsearchMappings.TypeMappings(
- Arrays.asList("Text", "TextArea", "FixedList", "FixedListEdit", "MultiSelectList", "FixedRadioList",
- "DynamicList", "DynamicRadioList", "DynamicMultiSelectList")
+ Arrays.asList("Text", "TextArea", "RichTextArea", "FixedList", "FixedListEdit", "MultiSelectList",
+ "FixedRadioList", "DynamicList", "DynamicRadioList", "DynamicMultiSelectList")
);
ElasticsearchMappings.CasePredefinedMappings casePredefinedMappings =
diff --git a/src/test/java/uk/gov/hmcts/ccd/domain/types/CaseDataValidatorTest.java b/src/test/java/uk/gov/hmcts/ccd/domain/types/CaseDataValidatorTest.java
index 35b725f297..fe0769efd5 100644
--- a/src/test/java/uk/gov/hmcts/ccd/domain/types/CaseDataValidatorTest.java
+++ b/src/test/java/uk/gov/hmcts/ccd/domain/types/CaseDataValidatorTest.java
@@ -17,6 +17,7 @@
import uk.gov.hmcts.ccd.domain.model.definition.CaseFieldDefinition;
import uk.gov.hmcts.ccd.domain.model.definition.CaseTypeDefinition;
import uk.gov.hmcts.ccd.domain.service.common.TestBuildersUtil;
+import uk.gov.hmcts.ccd.test.CaseFieldDefinitionBuilder;
import jakarta.inject.Inject;
import java.io.IOException;
@@ -31,6 +32,7 @@
import static org.hamcrest.MatcherAssert.assertThat;
import static org.junit.Assert.assertThrows;
import static org.junit.jupiter.api.Assertions.assertAll;
+import static org.junit.jupiter.api.Assertions.assertTrue;
import static org.mockito.Mockito.any;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
@@ -42,6 +44,8 @@
public class CaseDataValidatorTest extends WireMockBaseTest {
private static final String CASE_FIELD_JSON = "tests/CaseDataValidator_CaseField.json";
private static final String CASE_FIELD_DYNAMIC_JSON = "tests/CaseDataValidator_DynamicLists.json";
+ private static final String RICH_TEXT_AREA_FIELD = "RichTextAreaField";
+ private static final String RICH_TEXT_AREA = "RichTextArea";
@Inject
private CaseDataValidator caseDataValidator;
@@ -413,6 +417,27 @@ public void validDynamicListInCollection() throws Exception {
assertEquals(result.toString(), 0, result.size());
}
+ @Test
+ public void validRichTextAreaValue() throws Exception {
+ final String data = """
+ {
+ "RichTextAreaField": "Order
"
+ }""";
+ final Map values = caseDataFromJsonString(data);
+ final CaseTypeDefinition caseTypeDefinition = new CaseTypeDefinition();
+ caseTypeDefinition.setCaseFieldDefinitions(List.of(
+ new CaseFieldDefinitionBuilder(RICH_TEXT_AREA_FIELD)
+ .withType(RICH_TEXT_AREA)
+ .withMin(10)
+ .build()
+ ));
+
+ final ValidationContext validationContext = new ValidationContext(caseTypeDefinition, values);
+ final List result = caseDataValidator.validate(validationContext);
+
+ assertTrue(result.isEmpty(), result.toString());
+ }
+
@Test
public void unknownFieldInCollectionOfComplex() throws Exception {
diff --git a/src/test/java/uk/gov/hmcts/ccd/domain/types/RichTextAreaValidatorTest.java b/src/test/java/uk/gov/hmcts/ccd/domain/types/RichTextAreaValidatorTest.java
new file mode 100644
index 0000000000..1846bf7b71
--- /dev/null
+++ b/src/test/java/uk/gov/hmcts/ccd/domain/types/RichTextAreaValidatorTest.java
@@ -0,0 +1,109 @@
+package uk.gov.hmcts.ccd.domain.types;
+
+import com.fasterxml.jackson.databind.JsonNode;
+import com.fasterxml.jackson.databind.node.JsonNodeFactory;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.DisplayName;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.params.ParameterizedTest;
+import org.junit.jupiter.params.provider.MethodSource;
+import org.junit.jupiter.params.provider.ValueSource;
+import uk.gov.hmcts.ccd.data.definition.CaseDefinitionRepository;
+import uk.gov.hmcts.ccd.domain.model.definition.CaseFieldDefinition;
+import uk.gov.hmcts.ccd.domain.model.definition.FieldTypeDefinition;
+import uk.gov.hmcts.ccd.test.CaseFieldDefinitionBuilder;
+
+import java.util.List;
+import java.util.stream.Stream;
+
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.hamcrest.Matchers.empty;
+import static org.hamcrest.Matchers.equalTo;
+import static org.hamcrest.Matchers.hasSize;
+import static org.hamcrest.Matchers.is;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+@DisplayName("RichTextAreaValidator")
+class RichTextAreaValidatorTest {
+
+ private static final JsonNodeFactory NODE_FACTORY = JsonNodeFactory.instance;
+ private static final String FIELD_ID = "TEST_FIELD_ID";
+
+ private final RichTextAreaValidator validator = new RichTextAreaValidator();
+
+ @BeforeEach
+ void setUp() {
+ FieldTypeDefinition richTextAreaType = baseTypeDefinition();
+ CaseDefinitionRepository definitionRepository = mock(CaseDefinitionRepository.class);
+
+ when(definitionRepository.getBaseTypes()).thenReturn(List.of(richTextAreaType));
+ BaseType.setCaseDefinitionRepository(definitionRepository);
+ BaseType.register(new BaseType(richTextAreaType));
+ }
+
+ @Test
+ void getType() {
+ assertThat(validator.getType(), is(BaseType.get("RichTextArea")));
+ }
+
+ @ParameterizedTest
+ @MethodSource("validEmptyValues")
+ void validate_shouldBeValidWhenNullOrEmpty(JsonNode value) {
+ assertThat(validate(value, caseField().build()), is(empty()));
+ }
+
+ @ParameterizedTest
+ @ValueSource(strings = {"Some text", "Order
", "xxx4"})
+ void validate_shouldBeValidWhenMinimumLengthRequirementMet(String value) {
+ assertThat(validate(NODE_FACTORY.textNode(value), caseField().withMin(4).build()), is(empty()));
+ }
+
+ @Test
+ void validate_shouldNotBeValidWhenMinimumLengthRequirementNotMet() {
+ List results = validate(NODE_FACTORY.textNode("xxx"), caseField().withMin(4).build());
+
+ assertSingleError(results, "requires a minimum length of 4");
+ }
+
+ @Test
+ void validate_shouldIgnoreMaximumLengthAndRegexRequirements() {
+ CaseFieldDefinition constrainedField = caseField()
+ .withMax(4)
+ .withRegExp("\\d{4}-\\d{2}-\\d{2}")
+ .build();
+
+ assertThat(validate(NODE_FACTORY.textNode("not-a-date-and-longer-than-four"), constrainedField), is(empty()));
+ }
+
+ @Test
+ void validate_shouldBeInvalidWhenValueProvidedIsNotText() {
+ List results = validate(NODE_FACTORY.numberNode(2), caseField().build());
+
+ assertSingleError(results, "number is not a string");
+ }
+
+ private static Stream validEmptyValues() {
+ return Stream.of(null, NODE_FACTORY.nullNode(), NODE_FACTORY.textNode(""));
+ }
+
+ private List validate(JsonNode value, CaseFieldDefinition fieldDefinition) {
+ return validator.validate(FIELD_ID, value, fieldDefinition);
+ }
+
+ private static CaseFieldDefinitionBuilder caseField() {
+ return new CaseFieldDefinitionBuilder(FIELD_ID).withType(RichTextAreaValidator.TYPE_ID);
+ }
+
+ private static FieldTypeDefinition baseTypeDefinition() {
+ FieldTypeDefinition fieldTypeDefinition = new FieldTypeDefinition();
+ fieldTypeDefinition.setType(RichTextAreaValidator.TYPE_ID);
+ return fieldTypeDefinition;
+ }
+
+ private static void assertSingleError(List results, String errorMessage) {
+ assertThat(results, hasSize(1));
+ assertThat(results.get(0).getFieldId(), equalTo(FIELD_ID));
+ assertThat(results.get(0).getErrorMessage(), equalTo(errorMessage));
+ }
+}
diff --git a/src/test/resources/base-types.json b/src/test/resources/base-types.json
index e36de1433b..6ed5e6ee2a 100644
--- a/src/test/resources/base-types.json
+++ b/src/test/resources/base-types.json
@@ -99,6 +99,16 @@
"complex_fields": [],
"collection_field_type": null
},
+ {
+ "id": "RichTextArea",
+ "type": "RichTextArea",
+ "min": null,
+ "max": null,
+ "regular_expression": null,
+ "fixed_list_items": [],
+ "complex_fields": [],
+ "collection_field_type": null
+ },
{
"id": "Complex",
"type": "Complex",
diff --git a/src/test/resources/mappings/base-types.json b/src/test/resources/mappings/base-types.json
index b2588aed82..d068ae431f 100644
--- a/src/test/resources/mappings/base-types.json
+++ b/src/test/resources/mappings/base-types.json
@@ -44,6 +44,9 @@
{
"type": "TextArea"
},
+ {
+ "type": "RichTextArea"
+ },
{
"type": "Complex"
},