diff --git a/src/test/java/com/golshadi/majid/inputvalidator/InputValidatorApplicationTests.java b/src/test/java/com/golshadi/majid/inputvalidator/InputValidatorApplicationTests.java index dd31e86..7f17900 100644 --- a/src/test/java/com/golshadi/majid/inputvalidator/InputValidatorApplicationTests.java +++ b/src/test/java/com/golshadi/majid/inputvalidator/InputValidatorApplicationTests.java @@ -1,13 +1,132 @@ package com.golshadi.majid.inputvalidator; +import static org.assertj.core.api.Assertions.assertThat; + +import com.github.fge.jackson.JsonLoader; +import java.io.IOException; +import java.time.Instant; +import lombok.Data; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.boot.test.context.SpringBootTest.WebEnvironment; +import org.springframework.boot.test.web.client.TestRestTemplate; +import org.springframework.boot.web.server.LocalServerPort; +import org.springframework.http.HttpEntity; +import org.springframework.http.HttpHeaders; +import org.springframework.http.HttpMethod; +import org.springframework.http.HttpStatus; +import org.springframework.http.MediaType; -@SpringBootTest +@SpringBootTest(webEnvironment = WebEnvironment.RANDOM_PORT) class InputValidatorApplicationTests { - @Test - void contextLoads() { - } + private final static String RULE_KEY_1 = "v1/test/key"; + private final static String RULE_KEY_2 = "v2/test/key"; + private final static String VALID_JSON_DATA_PATH = "/valid.json"; + private final static String VALID_JSON_DATA_PATH_2 = "/valid-2.json"; + private final static String SINGLE_INVALID_FIELD_JSON_DATA_PATH = "/single-invalid-field.json"; + private final static String EXTRA_FIELD_JSON_DATA_PATH = "/extra-field-invalid.json"; + private final static String NOT_EXISTS_REQUIRED_FIELD_JSON_DATA_PATH = "/not-exists-required-field.json"; + private final static String COMBINATION_OF_ISSUES_JSON_DATA_PATH = "/combination-of-issues.json"; + + @LocalServerPort + private int port; + + @Autowired + private TestRestTemplate restTemplate; + + private String validationUrl; + + @BeforeEach + public void setUp() { + validationUrl = String.format("http://localhost:%d/validate", port); + } + + @Test + void badRequestRequiredFieldErrorTest() throws IOException { + var jsonNode = JsonLoader.fromResource(NOT_EXISTS_REQUIRED_FIELD_JSON_DATA_PATH); + var request = makeRequestEntity(RULE_KEY_1, jsonNode.toString()); + var response = restTemplate.exchange(validationUrl, HttpMethod.POST, request, ErrorResponse.class); + + assertThat(response.getStatusCode()).isEqualTo(HttpStatus.BAD_REQUEST); + assertThat(response.getBody().getStatus()).isEqualTo(HttpStatus.BAD_REQUEST.value()); + assertThat(response.getBody().getError()).isEqualTo("Bad Request"); + assertThat(response.getBody().getMessage()).isEqualTo("required fields latitude does not exists"); + } + + @Test + void badRequestInvalidFieldErrorTest() throws IOException { + var jsonNode = JsonLoader.fromResource(SINGLE_INVALID_FIELD_JSON_DATA_PATH); + var request = makeRequestEntity(RULE_KEY_1, jsonNode.toString()); + var response = restTemplate.exchange(validationUrl, HttpMethod.POST, request, ErrorResponse.class); + + assertThat(response.getStatusCode()).isEqualTo(HttpStatus.BAD_REQUEST); + assertThat(response.getBody().getStatus()).isEqualTo(HttpStatus.BAD_REQUEST.value()); + assertThat(response.getBody().getError()).isEqualTo("Bad Request"); + assertThat(response.getBody().getMessage()).isEqualTo("invalid fields: .latitude"); + } + + @Test + void badRequestExtraFieldErrorTest() throws IOException { + var jsonNode = JsonLoader.fromResource(EXTRA_FIELD_JSON_DATA_PATH); + var request = makeRequestEntity("v1/test/key", jsonNode.toString()); + var response = restTemplate.exchange(validationUrl, HttpMethod.POST, request, ErrorResponse.class); + + assertThat(response.getStatusCode()).isEqualTo(HttpStatus.BAD_REQUEST); + assertThat(response.getBody().getStatus()).isEqualTo(HttpStatus.BAD_REQUEST.value()); + assertThat(response.getBody().getError()).isEqualTo("Bad Request"); + assertThat(response.getBody().getMessage()).isEqualTo("extra fields exist: extra_field"); + } + + @Test + void badRequestCombinationIssueErrorTest() throws IOException { + var jsonNode = JsonLoader.fromResource(COMBINATION_OF_ISSUES_JSON_DATA_PATH); + var request = makeRequestEntity(RULE_KEY_1, jsonNode.toString()); + var response = restTemplate.exchange(validationUrl, HttpMethod.POST, request, ErrorResponse.class); + + assertThat(response.getStatusCode()).isEqualTo(HttpStatus.BAD_REQUEST); + assertThat(response.getBody().getStatus()).isEqualTo(HttpStatus.BAD_REQUEST.value()); + assertThat(response.getBody().getError()).isEqualTo("Bad Request"); + assertThat(response.getBody().getMessage()).isEqualTo("extra fields exist: extra"); + } + + @Test + void validDataTest() throws IOException { + var jsonNode = JsonLoader.fromResource(VALID_JSON_DATA_PATH); + var request = makeRequestEntity(RULE_KEY_1, jsonNode.toString()); + var response = restTemplate.exchange(validationUrl, HttpMethod.POST, request, String.class); + + assertThat(response.getStatusCode()).isEqualTo(HttpStatus.OK); + } + + @Test + void supportMultipleSchemaJsonConfigTest() throws IOException { + var jsonNode = JsonLoader.fromResource(VALID_JSON_DATA_PATH_2); + var request = makeRequestEntity(RULE_KEY_2, jsonNode.toString()); + var response = restTemplate.exchange(validationUrl, HttpMethod.POST, request, String.class); + + assertThat(response.getStatusCode()).isEqualTo(HttpStatus.OK); + } + + private HttpEntity makeRequestEntity(String header, String body) { + var headers = new HttpHeaders(); + + headers.add(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE); + headers.add("X-B3-URL", header); + + return new HttpEntity<>(body, headers); + } } + +@Data +class ErrorResponse { + + private final String timestamp; + private final int status; + private final String error; + private final String message; +} \ No newline at end of file diff --git a/src/test/resources/application.yml b/src/test/resources/application.yml new file mode 100644 index 0000000..c9ea9a6 --- /dev/null +++ b/src/test/resources/application.yml @@ -0,0 +1,11 @@ +header-keys: + rule-key: "X-B3-URL" + +request-validation: + rules: + - description: "description 1" + key: v1/test/key + json-schema: /json-schema.json + - description: "description 1" + key: v2/test/key + json-schema: /json-schema-2.json \ No newline at end of file diff --git a/src/test/resources/json-schema-2.json b/src/test/resources/json-schema-2.json new file mode 100644 index 0000000..24cc19e --- /dev/null +++ b/src/test/resources/json-schema-2.json @@ -0,0 +1,27 @@ +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "title": "product", + "required": [ "productName", "price", "tags"], + "additionalProperties": false, + "type": "object", + "properties": { + "productName": { + "description": "Name of the product", + "type": "string" + }, + "price": { + "description": "The price of the product", + "type": "number", + "minimum": 10 + }, + "tags": { + "description": "Tags for the product", + "type": "array", + "items": { + "type": "string" + }, + "minItems": 1, + "uniqueItems": true + } + } +} \ No newline at end of file diff --git a/src/test/resources/valid-2.json b/src/test/resources/valid-2.json new file mode 100644 index 0000000..b22273a --- /dev/null +++ b/src/test/resources/valid-2.json @@ -0,0 +1,5 @@ +{ + "productName": "pr1", + "price": 100, + "tags": ["t1", "t2"] +} \ No newline at end of file