X-Git-Url: http://juplo.de/gitweb/?a=blobdiff_plain;f=src%2Ftest%2Fjava%2Fde%2Fjuplo%2Fkafka%2Fchat%2Fbackend%2FAbstractConfigurationIT.java;h=451690b2a9c1a6955b63f20adf508ecb846fea19;hb=af0fcdb0c41127576b7826513287de0f74d72abf;hp=c424b294e5bbcbc40a926233deaad1d9a69e32e3;hpb=daca33d027e4c0d036fc2aa7c3d9b2120f3ad98a;p=demos%2Fkafka%2Fchat diff --git a/src/test/java/de/juplo/kafka/chat/backend/AbstractConfigurationIT.java b/src/test/java/de/juplo/kafka/chat/backend/AbstractConfigurationIT.java index c424b294..451690b2 100644 --- a/src/test/java/de/juplo/kafka/chat/backend/AbstractConfigurationIT.java +++ b/src/test/java/de/juplo/kafka/chat/backend/AbstractConfigurationIT.java @@ -1,27 +1,63 @@ package de.juplo.kafka.chat.backend; +import com.fasterxml.jackson.core.type.TypeReference; +import com.fasterxml.jackson.databind.ObjectMapper; +import de.juplo.kafka.chat.backend.api.ChatRoomInfoTo; +import de.juplo.kafka.chat.backend.api.MessageTo; +import lombok.extern.slf4j.Slf4j; +import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; import org.springframework.boot.test.web.server.LocalServerPort; +import org.springframework.core.io.Resource; import org.springframework.http.MediaType; +import org.springframework.test.annotation.DirtiesContext; import org.springframework.test.web.reactive.server.WebTestClient; import org.testcontainers.shaded.org.awaitility.Awaitility; +import reactor.core.publisher.Flux; +import java.io.IOException; import java.time.Duration; +import java.util.List; +import java.util.UUID; +import java.util.concurrent.atomic.AtomicBoolean; +import java.util.random.RandomGenerator; +import static org.assertj.core.api.Assertions.assertThat; +import static org.hamcrest.Matchers.endsWith; + +@Slf4j +@DirtiesContext public abstract class AbstractConfigurationIT { + final static String EXISTING_CHATROOM = "5c73531c-6fc4-426c-adcb-afc5c140a0f7"; + String NONEXISTENT_CHATROOM = "7f59ec77-832e-4a17-8d22-55ef46242c17"; + + @LocalServerPort int port; @Autowired WebTestClient webTestClient; + @Autowired + ObjectMapper objectMapper; - @Test - @DisplayName("The app starts, the data is restored and accessible") - void test() + @Value("classpath:data/files/5c73531c-6fc4-426c-adcb-afc5c140a0f7.json") + Resource existingChatRoomRessource; + MessageTo[] expectedExistingMessages; + + + @BeforeEach + void waitForApp() throws IOException { + expectedExistingMessages = objectMapper + .readValue( + existingChatRoomRessource.getInputStream(), + new TypeReference>() {}) + .toArray(size -> new MessageTo[size]); + Awaitility .await() .atMost(Duration.ofSeconds(15)) @@ -29,40 +65,225 @@ public abstract class AbstractConfigurationIT { webTestClient .get() - .uri("http://localhost:{port}/actuator/health", port) + .uri( + "http://localhost:{port}/actuator/health", + port) .exchange() .expectStatus().isOk() .expectBody().jsonPath("$.status").isEqualTo("UP"); + }); + } + + @Test + @DisplayName("Restored chat-rooms can be listed") + void testRestoredChatRoomsCanBeListed() + { + Awaitility + .await() + .atMost(Duration.ofSeconds(15)) + .untilAsserted(() -> + { + AtomicBoolean existingChatRoomFound = new AtomicBoolean(false); webTestClient .get() - .uri("http://localhost:{port}/list", port) + .uri( + "http://localhost:{port}/list", + port) .accept(MediaType.APPLICATION_JSON) .exchange() .expectStatus().isOk() - .expectBody() - .jsonPath("$.length()").isEqualTo(1) - .jsonPath("$[0].name").isEqualTo("FOO"); + .returnResult(ChatRoomInfoTo.class) + .getResponseBody() + .toIterable() + .forEach(chatRoomInfoTo -> + { + log.debug("Inspecting chat-room {}", chatRoomInfoTo); + if (chatRoomInfoTo.getId().equals(UUID.fromString(EXISTING_CHATROOM))) + { + log.debug("Found existing chat-room {}", chatRoomInfoTo); + existingChatRoomFound.set(true); + assertThat(chatRoomInfoTo.getName().equals("FOO")); + } + }); + assertThat(existingChatRoomFound.get()).isTrue(); + }); + } + + @Test + @DisplayName("Details as expected for restored chat-room") + void testRestoredChatRoomHasExpectedDetails() + { + Awaitility + .await() + .atMost(Duration.ofSeconds(15)) + .untilAsserted(() -> + { webTestClient .get() - .uri("http://localhost:{port}/5c73531c-6fc4-426c-adcb-afc5c140a0f7", port) + .uri( + "http://localhost:{port}/{chatRoomId}", + port, + EXISTING_CHATROOM) .accept(MediaType.APPLICATION_JSON) .exchange() .expectStatus().isOk() .expectBody().jsonPath("$.name").isEqualTo("FOO"); + }); + } + + @Test + @DisplayName("Restored message from Ute has expected Text") + void testRestoredMessageForUteHasExpectedText() + { + Awaitility + .await() + .atMost(Duration.ofSeconds(15)) + .untilAsserted(() -> + { webTestClient .get() - .uri("http://localhost:{port}/5c73531c-6fc4-426c-adcb-afc5c140a0f7/ute/1", port) + .uri( + "http://localhost:{port}/{chatRoomId}/ute/1", + port, + EXISTING_CHATROOM) .accept(MediaType.APPLICATION_JSON) .exchange() .expectStatus().isOk() .expectBody().jsonPath("$.text").isEqualTo("Ich bin Ute..."); + }); + } + + @Test + @DisplayName("Restored message from Peter has expected Text") + void testRestoredMessageForPeterHasExpectedText() + { + Awaitility + .await() + .atMost(Duration.ofSeconds(15)) + .untilAsserted(() -> + { webTestClient .get() - .uri("http://localhost:{port}/5c73531c-6fc4-426c-adcb-afc5c140a0f7/peter/1", port) + .uri( + "http://localhost:{port}/{chatRoomId}/peter/1", + port, + EXISTING_CHATROOM) .accept(MediaType.APPLICATION_JSON) .exchange() .expectStatus().isOk() .expectBody().jsonPath("$.text").isEqualTo("Hallo, ich heiße Peter!"); }); } + + @Test + @DisplayName("A PUT-message for a non-existent chat-room yields 404 NOT FOUND") + void testNotFoundForPutMessageToNonExistentChatRoom() + { + Awaitility + .await() + .atMost(Duration.ofSeconds(15)) + .untilAsserted(() -> + { + webTestClient + .put() + .uri( + "http://localhost:{port}/{chatRoomId}/otto/66", + port, + NONEXISTENT_CHATROOM) + .contentType(MediaType.TEXT_PLAIN) + .accept(MediaType.APPLICATION_JSON) + .bodyValue("The devil rules route 66") + .exchange() + .expectStatus().isNotFound() + .expectBody() + .jsonPath("$.type").value(endsWith("/problem/unknown-chatroom")) + .jsonPath("$.chatroomId").isEqualTo(NONEXISTENT_CHATROOM); + }); + } + + @Test + @DisplayName("A message can be put into a newly created chat-room") + void testPutMessageInNewChatRoom() throws IOException + { + ChatRoomInfoTo chatRoomInfo; + do + { + // The first request creates a new chat-room + // It must be repeated, until a chat-room was created, + // that is owned by the instance + chatRoomInfo = webTestClient + .post() + .uri("http://localhost:{port}/create", port) + .contentType(MediaType.TEXT_PLAIN) + .bodyValue("bar") + .accept(MediaType.APPLICATION_JSON) + .exchange() + .returnResult(ChatRoomInfoTo.class) + .getResponseBody() + .retry(30) + .blockFirst(); + } + while(!(chatRoomInfo.getShard() == null || chatRoomInfo.getShard().intValue() == 2)); + + UUID chatRoomId = chatRoomInfo.getId(); + + Awaitility + .await() + .atMost(Duration.ofSeconds(15)) + .untilAsserted(() -> + { + webTestClient + .put() + .uri( + "http://localhost:{port}/{chatRoomId}/nerd/7", + port, + chatRoomId) + .contentType(MediaType.TEXT_PLAIN) + .accept(MediaType.APPLICATION_JSON) + .bodyValue("Hello world!") + .exchange() + .expectStatus().isOk() + .expectBody() + .jsonPath("$.id").isEqualTo(Integer.valueOf(7)) + .jsonPath("$.user").isEqualTo("nerd") + .jsonPath("$.text").isEqualTo("Hello world!"); + }); + } + + @Test + @DisplayName("Only newly send messages can be seen, when listening to restored chat-room") + void testListenToRestoredChatRoomYieldsOnlyNewlyAddedMessages() + { + MessageTo sentMessage = webTestClient + .put() + .uri( + "http://localhost:{port}/{chatRoomId}/nerd/{messageId}", + port, + EXISTING_CHATROOM, + RandomGenerator.getDefault().nextInt()) + .contentType(MediaType.TEXT_PLAIN) + .accept(MediaType.APPLICATION_JSON) + .bodyValue("Hello world!") + .exchange() + .expectStatus() + .isOk() + .returnResult(MessageTo.class) + .getResponseBody() + .next() + .block(); + + Flux result = webTestClient + .get() + .uri( + "http://localhost:{port}/{chatRoomId}/listen", + port, + EXISTING_CHATROOM) + .accept(MediaType.TEXT_EVENT_STREAM) + .exchange() + .expectStatus().isOk() + .returnResult(MessageTo.class) + .getResponseBody(); + + assertThat(result.next().block()).isEqualTo(sentMessage); + } }