From 6c179323d18cd44f2b4c8d39ef245b60e40e80f2 Mon Sep 17 00:00:00 2001 From: Matias Schilling Date: Sun, 30 Jun 2024 09:37:10 +0200 Subject: [PATCH] Add json schema validation for /joke endpoints --- chucknorris-integration-test/build.gradle | 1 + .../endpoint/joke/JokeByIdTest.java | 55 ++++++++++++++++--- .../joke/JokeCategoriesEndpointTest.java | 28 +++++++++- .../endpoint/joke/JokeRandomEndpointTest.java | 28 +++++++++- .../resources/schema/joke/by-id/success.json | 37 +++++++++++++ .../schema/joke/categories/success.json | 9 +++ .../resources/schema/joke/random/success.json | 37 +++++++++++++ 7 files changed, 184 insertions(+), 11 deletions(-) create mode 100644 chucknorris-integration-test/src/test/resources/schema/joke/by-id/success.json create mode 100644 chucknorris-integration-test/src/test/resources/schema/joke/categories/success.json create mode 100644 chucknorris-integration-test/src/test/resources/schema/joke/random/success.json diff --git a/chucknorris-integration-test/build.gradle b/chucknorris-integration-test/build.gradle index 6d2dc87..a634f0c 100644 --- a/chucknorris-integration-test/build.gradle +++ b/chucknorris-integration-test/build.gradle @@ -7,6 +7,7 @@ dependencies { exclude group: "org.apache.groovy", module: "groovy" exclude group: "org.apache.groovy", module: "groovy-xml" } + testImplementation 'io.rest-assured:json-schema-validator:5.4.0' testImplementation("io.rest-assured:rest-assured:${Version.REST_ASSURED}") { exclude group: "org.apache.groovy", module: "groovy" exclude group: "org.apache.groovy", module: "groovy-xml" diff --git a/chucknorris-integration-test/src/test/java/io/chucknorris/integration_test/endpoint/joke/JokeByIdTest.java b/chucknorris-integration-test/src/test/java/io/chucknorris/integration_test/endpoint/joke/JokeByIdTest.java index cd32e68..8c057f9 100644 --- a/chucknorris-integration-test/src/test/java/io/chucknorris/integration_test/endpoint/joke/JokeByIdTest.java +++ b/chucknorris-integration-test/src/test/java/io/chucknorris/integration_test/endpoint/joke/JokeByIdTest.java @@ -1,17 +1,41 @@ package io.chucknorris.integration_test.endpoint.joke; -import static io.restassured.RestAssured.given; - import io.chucknorris.integration_test.endpoint.AbstractEndpointTest; +import io.restassured.module.jsv.JsonSchemaValidator; import org.hamcrest.Matchers; import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; +import static io.restassured.RestAssured.given; + class JokeByIdTest extends AbstractEndpointTest { + private static final String JSON_SCHEMA_PATH = "schema/joke/by-id/success.json"; + private static final String JOKE_VALUE = "Chuck Norris once lost the remote, but maintained control of the TV by yelling at it in between bites of his \"Filet of Child\" sandwich."; + private final String jokeId = "c9h1endqtmm31b1auddvdg"; + @DisplayName("Should conform to json schema") + @Test + void shouldConformToJsonSchema() { + // given: + var specification = given() + .log().all() + .accept("application/json"); + + // when: + var response = specification.when().get("/jokes/" + jokeId); + + // then: + response.then() + .log().all() + .statusCode(200) + .body(JsonSchemaValidator.matchesJsonSchemaInClasspath(JSON_SCHEMA_PATH)) + .extract() + .response(); + } + @DisplayName("Should return joke by id as json") @Test void shouldReturnJokeAsJson() { @@ -35,8 +59,27 @@ void shouldReturnJokeAsJson() { .body("id", Matchers.comparesEqualTo(jokeId)) .body("updated_at", Matchers.isA(String.class)) .body("url", Matchers.comparesEqualTo("https://api.chucknorris.io/jokes/c9h1endqtmm31b1auddvdg")) - .body("value", Matchers.comparesEqualTo( - "Chuck Norris once lost the remote, but maintained control of the TV by yelling at it in between bites of his \"Filet of Child\" sandwich.")); + .body("value", Matchers.comparesEqualTo(JOKE_VALUE)); + } + + @DisplayName("Should return joke by id as html") + @Test + void shouldReturnJokeAsHtml() { + // given: + var specification = given() + .log().all() + .accept("text/html"); + + // when: + var response = specification.when().get("/jokes/" + jokeId); + + // then: + response.then() + .log().all() + .statusCode(200) + .assertThat() + .header("Content-Type", Matchers.equalTo("text/html;charset=UTF-8")) + .body("html.head.title", Matchers.equalTo(JOKE_VALUE)); } @DisplayName("Should return joke by id as plain text") @@ -58,8 +101,6 @@ void shouldReturnJokeAsPlainText() { .header("Content-Type", Matchers.equalTo("text/plain;charset=UTF-8")); // and: - Assertions.assertEquals( - "Chuck Norris once lost the remote, but maintained control of the TV by yelling at it in between bites of his \"Filet of Child\" sandwich.", - response.body().asString().trim()); + Assertions.assertEquals(JOKE_VALUE, response.body().asString().trim()); } } diff --git a/chucknorris-integration-test/src/test/java/io/chucknorris/integration_test/endpoint/joke/JokeCategoriesEndpointTest.java b/chucknorris-integration-test/src/test/java/io/chucknorris/integration_test/endpoint/joke/JokeCategoriesEndpointTest.java index 0595cdc..df3bc87 100644 --- a/chucknorris-integration-test/src/test/java/io/chucknorris/integration_test/endpoint/joke/JokeCategoriesEndpointTest.java +++ b/chucknorris-integration-test/src/test/java/io/chucknorris/integration_test/endpoint/joke/JokeCategoriesEndpointTest.java @@ -1,6 +1,7 @@ package io.chucknorris.integration_test.endpoint.joke; import io.chucknorris.integration_test.endpoint.AbstractEndpointTest; +import io.restassured.module.jsv.JsonSchemaValidator; import org.hamcrest.Matchers; import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.DisplayName; @@ -12,6 +13,29 @@ class JokeCategoriesEndpointTest extends AbstractEndpointTest { + private static final String ENDPOINT = "/jokes/categories"; + private static final String JSON_SCHEMA_PATH = "schema/joke/categories/success.json"; + + @DisplayName("Should conform to json schema") + @Test + void shouldConformToJsonSchema() { + // given: + var specification = given() + .log().all() + .accept("application/json"); + + // when: + var response = specification.when().get(ENDPOINT); + + // then: + response.then() + .log().all() + .statusCode(200) + .body(JsonSchemaValidator.matchesJsonSchemaInClasspath(JSON_SCHEMA_PATH)) + .extract() + .response(); + } + @DisplayName("Should return categories as json") @Test void shouldReturnCategoriesAsJson() { @@ -20,7 +44,7 @@ void shouldReturnCategoriesAsJson() { .accept("application/json") .header("Origin", "http://localhost:3000"); - var response = specification.when().get("/jokes/categories"); + var response = specification.when().get(ENDPOINT); response.then() .log().all() @@ -42,7 +66,7 @@ void shouldReturnCategoriesAsPlainText() { .header("Origin", "http://localhost:3000"); // when: - var response = specification.when().get("/jokes/categories"); + var response = specification.when().get(ENDPOINT); // then: response.then() diff --git a/chucknorris-integration-test/src/test/java/io/chucknorris/integration_test/endpoint/joke/JokeRandomEndpointTest.java b/chucknorris-integration-test/src/test/java/io/chucknorris/integration_test/endpoint/joke/JokeRandomEndpointTest.java index 7f9fd46..8876b9a 100644 --- a/chucknorris-integration-test/src/test/java/io/chucknorris/integration_test/endpoint/joke/JokeRandomEndpointTest.java +++ b/chucknorris-integration-test/src/test/java/io/chucknorris/integration_test/endpoint/joke/JokeRandomEndpointTest.java @@ -1,6 +1,7 @@ package io.chucknorris.integration_test.endpoint.joke; import io.chucknorris.integration_test.endpoint.AbstractEndpointTest; +import io.restassured.module.jsv.JsonSchemaValidator; import org.hamcrest.Matchers; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; @@ -11,6 +12,29 @@ class JokeRandomEndpointTest extends AbstractEndpointTest { + private static final String ENDPOINT = "/jokes/random"; + private static final String JSON_SCHEMA_PATH = "schema/joke/random/success.json"; + + @DisplayName("Should conform to json schema") + @Test + void shouldConformToJsonSchema() { + // given: + var specification = given() + .log().all() + .accept("application/json"); + + // when: + var response = specification.when().get(ENDPOINT); + + // then: + response.then() + .log().all() + .statusCode(200) + .body(JsonSchemaValidator.matchesJsonSchemaInClasspath(JSON_SCHEMA_PATH)) + .extract() + .response(); + } + @DisplayName("Should return joke as json") @Test void shouldReturnJokeAsJson() { @@ -20,7 +44,7 @@ void shouldReturnJokeAsJson() { .accept("application/json"); // when: - var response = specification.when().get("/jokes/random"); + var response = specification.when().get(ENDPOINT); // then: response.then() @@ -47,7 +71,7 @@ void shouldIncludeCORSHeaders() { .header("Origin", "http://localhost:3000"); // when: - var response = specification.when().get("/jokes/random"); + var response = specification.when().get(ENDPOINT); // then: response.then() diff --git a/chucknorris-integration-test/src/test/resources/schema/joke/by-id/success.json b/chucknorris-integration-test/src/test/resources/schema/joke/by-id/success.json new file mode 100644 index 0000000..5e85ecb --- /dev/null +++ b/chucknorris-integration-test/src/test/resources/schema/joke/by-id/success.json @@ -0,0 +1,37 @@ +{ + "$schema": "http://json-schema.org/draft-04/schema#", + "type": "object", + "properties": { + "categories": { + "type": "array", + "items": {} + }, + "created_at": { + "type": "string" + }, + "icon_url": { + "type": "string" + }, + "id": { + "type": "string" + }, + "updated_at": { + "type": "string" + }, + "url": { + "type": "string" + }, + "value": { + "type": "string" + } + }, + "required": [ + "categories", + "created_at", + "icon_url", + "id", + "updated_at", + "url", + "value" + ] +} \ No newline at end of file diff --git a/chucknorris-integration-test/src/test/resources/schema/joke/categories/success.json b/chucknorris-integration-test/src/test/resources/schema/joke/categories/success.json new file mode 100644 index 0000000..e46d85e --- /dev/null +++ b/chucknorris-integration-test/src/test/resources/schema/joke/categories/success.json @@ -0,0 +1,9 @@ +{ + "$schema": "http://json-schema.org/draft-04/schema#", + "type": "array", + "items": [ + { + "type": "string" + } + ] +} \ No newline at end of file diff --git a/chucknorris-integration-test/src/test/resources/schema/joke/random/success.json b/chucknorris-integration-test/src/test/resources/schema/joke/random/success.json new file mode 100644 index 0000000..5e85ecb --- /dev/null +++ b/chucknorris-integration-test/src/test/resources/schema/joke/random/success.json @@ -0,0 +1,37 @@ +{ + "$schema": "http://json-schema.org/draft-04/schema#", + "type": "object", + "properties": { + "categories": { + "type": "array", + "items": {} + }, + "created_at": { + "type": "string" + }, + "icon_url": { + "type": "string" + }, + "id": { + "type": "string" + }, + "updated_at": { + "type": "string" + }, + "url": { + "type": "string" + }, + "value": { + "type": "string" + } + }, + "required": [ + "categories", + "created_at", + "icon_url", + "id", + "updated_at", + "url", + "value" + ] +} \ No newline at end of file