WIP:test: `*ConfigurationIT` asserts, if restored messages can be seen
[demos/kafka/chat] / src / test / java / de / juplo / kafka / chat / backend / AbstractConfigurationIT.java
index 00734f2..9d87088 100644 (file)
@@ -1,31 +1,62 @@
 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 static org.assertj.core.api.Assertions.assertThat;
 import static org.hamcrest.Matchers.endsWith;
+import static pl.rzrz.assertj.reactor.Assertions.assertThat;
 
 
+@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;
 
+  @Value("classpath:data/files/5c73531c-6fc4-426c-adcb-afc5c140a0f7.json")
+  Resource existingChatRoomRessource;
+  MessageTo[] expectedExistingMessages;
 
-  @Test
-  @DisplayName("The app starts, the data is restored and accessible")
-  void testAppStartsDataIsRestoredAndAccessible()
+
+  @BeforeEach
+  void waitForApp() throws IOException
   {
-    String chatRoomId = "5c73531c-6fc4-426c-adcb-afc5c140a0f7";
+    expectedExistingMessages = objectMapper
+        .readValue(
+            existingChatRoomRessource.getInputStream(),
+            new TypeReference<List<MessageTo>>() {})
+        .toArray(size -> new MessageTo[size]);
 
     Awaitility
         .await()
@@ -40,6 +71,19 @@ public abstract class AbstractConfigurationIT
               .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(
@@ -48,35 +92,82 @@ public abstract class AbstractConfigurationIT
               .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}/{chatRoomId}",
                   port,
-                  chatRoomId)
+                  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}/{chatRoomId}/ute/1",
                   port,
-                  chatRoomId)
+                  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}/{chatRoomId}/peter/1",
                   port,
-                  chatRoomId)
+                  EXISTING_CHATROOM)
               .accept(MediaType.APPLICATION_JSON)
               .exchange()
               .expectStatus().isOk()
@@ -88,8 +179,6 @@ public abstract class AbstractConfigurationIT
   @DisplayName("A PUT-message for a non-existent chat-room yields 404 NOT FOUND")
   void testNotFoundForPutMessageToNonExistentChatRoom()
   {
-    String otherChatRoomId = "7f59ec77-832e-4a17-8d22-55ef46242c17";
-
     Awaitility
         .await()
         .atMost(Duration.ofSeconds(15))
@@ -100,7 +189,7 @@ public abstract class AbstractConfigurationIT
               .uri(
                   "http://localhost:{port}/{chatRoomId}/otto/66",
                   port,
-                  otherChatRoomId)
+                  NONEXISTENT_CHATROOM)
               .contentType(MediaType.TEXT_PLAIN)
               .accept(MediaType.APPLICATION_JSON)
               .bodyValue("The devil rules route 66")
@@ -108,7 +197,92 @@ public abstract class AbstractConfigurationIT
               .expectStatus().isNotFound()
               .expectBody()
                 .jsonPath("$.type").value(endsWith("/problem/unknown-chatroom"))
-                .jsonPath("$.chatroomId").isEqualTo(otherChatRoomId);
+                .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/7",
+            port,
+            EXISTING_CHATROOM)
+        .contentType(MediaType.TEXT_PLAIN)
+        .accept(MediaType.APPLICATION_JSON)
+        .bodyValue("Hello world!")
+        .exchange()
+        .expectStatus()
+        .isOk()
+        .returnResult(MessageTo.class)
+        .getResponseBody()
+        .next()
+        .block();
+
+    Flux<MessageTo> 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);
+  }
 }