452e4244bf25d0e4b6b42bb688cab30abe24d07f
[demos/kafka/chat] / src / test / java / de / juplo / kafka / chat / backend / AbstractConfigurationIT.java
1 package de.juplo.kafka.chat.backend;
2
3 import com.fasterxml.jackson.databind.ObjectMapper;
4 import de.juplo.kafka.chat.backend.api.ChatRoomInfoTo;
5 import lombok.extern.slf4j.Slf4j;
6 import org.junit.jupiter.api.BeforeEach;
7 import org.junit.jupiter.api.DisplayName;
8 import org.junit.jupiter.api.Test;
9 import org.springframework.beans.factory.annotation.Autowired;
10 import org.springframework.boot.test.web.server.LocalServerPort;
11 import org.springframework.http.MediaType;
12 import org.springframework.test.annotation.DirtiesContext;
13 import org.springframework.test.web.reactive.server.WebTestClient;
14 import org.testcontainers.shaded.org.awaitility.Awaitility;
15
16 import java.io.IOException;
17 import java.time.Duration;
18 import java.util.UUID;
19 import java.util.concurrent.atomic.AtomicBoolean;
20
21 import static org.assertj.core.api.Assertions.assertThat;
22 import static org.hamcrest.Matchers.endsWith;
23
24
25 @Slf4j
26 @DirtiesContext
27 public abstract class AbstractConfigurationIT
28 {
29   final static String EXISTING_CHATROOM = "5c73531c-6fc4-426c-adcb-afc5c140a0f7";
30   String NONEXISTENT_CHATROOM = "7f59ec77-832e-4a17-8d22-55ef46242c17";
31
32
33   @LocalServerPort
34   int port;
35   @Autowired
36   WebTestClient webTestClient;
37   @Autowired
38   ObjectMapper objectMapper;
39
40
41   @BeforeEach
42   void waitForApp()
43   {
44     Awaitility
45         .await()
46         .atMost(Duration.ofSeconds(15))
47         .untilAsserted(() ->
48         {
49           webTestClient
50               .get()
51               .uri(
52                   "http://localhost:{port}/actuator/health",
53                   port)
54               .exchange()
55               .expectStatus().isOk()
56               .expectBody().jsonPath("$.status").isEqualTo("UP");
57         });
58   }
59
60   @Test
61   @DisplayName("Restored chat-rooms can be listed")
62   void testRestoredChatRoomsCanBeListed()
63   {
64     Awaitility
65         .await()
66         .atMost(Duration.ofSeconds(15))
67         .untilAsserted(() ->
68         {
69           AtomicBoolean existingChatRoomFound = new AtomicBoolean(false);
70           webTestClient
71               .get()
72               .uri(
73                   "http://localhost:{port}/list",
74                   port)
75               .accept(MediaType.APPLICATION_JSON)
76               .exchange()
77               .expectStatus().isOk()
78               .returnResult(ChatRoomInfoTo.class)
79               .getResponseBody()
80               .toIterable()
81               .forEach(chatRoomInfoTo ->
82               {
83                 log.debug("Inspecting chat-room {}", chatRoomInfoTo);
84                 if (chatRoomInfoTo.getId().equals(UUID.fromString(EXISTING_CHATROOM)))
85                 {
86                   log.debug("Found existing chat-room {}", chatRoomInfoTo);
87                   existingChatRoomFound.set(true);
88                   assertThat(chatRoomInfoTo.getName().equals("FOO"));
89                 }
90               });
91           assertThat(existingChatRoomFound.get()).isTrue();
92         });
93   }
94
95   @Test
96   @DisplayName("Details as expected for restored chat-room")
97   void testRestoredChatRoomHasExpectedDetails()
98   {
99     Awaitility
100         .await()
101         .atMost(Duration.ofSeconds(15))
102         .untilAsserted(() ->
103         {
104           webTestClient
105               .get()
106               .uri(
107                   "http://localhost:{port}/{chatRoomId}",
108                   port,
109                   EXISTING_CHATROOM)
110               .accept(MediaType.APPLICATION_JSON)
111               .exchange()
112               .expectStatus().isOk()
113               .expectBody().jsonPath("$.name").isEqualTo("FOO");
114         });
115   }
116
117   @Test
118   @DisplayName("Restored message from Ute has expected Text")
119   void testRestoredMessageForUteHasExpectedText()
120   {
121     Awaitility
122         .await()
123         .atMost(Duration.ofSeconds(15))
124         .untilAsserted(() ->
125         {
126           webTestClient
127               .get()
128               .uri(
129                   "http://localhost:{port}/{chatRoomId}/ute/1",
130                   port,
131                   EXISTING_CHATROOM)
132               .accept(MediaType.APPLICATION_JSON)
133               .exchange()
134               .expectStatus().isOk()
135               .expectBody().jsonPath("$.text").isEqualTo("Ich bin Ute...");
136         });
137   }
138
139   @Test
140   @DisplayName("Restored message from Peter has expected Text")
141   void testRestoredMessageForPeterHasExpectedText()
142   {
143     Awaitility
144         .await()
145         .atMost(Duration.ofSeconds(15))
146         .untilAsserted(() ->
147         {
148           webTestClient
149               .get()
150               .uri(
151                   "http://localhost:{port}/{chatRoomId}/peter/1",
152                   port,
153                   EXISTING_CHATROOM)
154               .accept(MediaType.APPLICATION_JSON)
155               .exchange()
156               .expectStatus().isOk()
157               .expectBody().jsonPath("$.text").isEqualTo("Hallo, ich heiße Peter!");
158         });
159   }
160
161   @Test
162   @DisplayName("A PUT-message for a non-existent chat-room yields 404 NOT FOUND")
163   void testNotFoundForPutMessageToNonExistentChatRoom()
164   {
165     Awaitility
166         .await()
167         .atMost(Duration.ofSeconds(15))
168         .untilAsserted(() ->
169         {
170           webTestClient
171               .put()
172               .uri(
173                   "http://localhost:{port}/{chatRoomId}/otto/66",
174                   port,
175                   NONEXISTENT_CHATROOM)
176               .contentType(MediaType.TEXT_PLAIN)
177               .accept(MediaType.APPLICATION_JSON)
178               .bodyValue("The devil rules route 66")
179               .exchange()
180               .expectStatus().isNotFound()
181               .expectBody()
182                 .jsonPath("$.type").value(endsWith("/problem/unknown-chatroom"))
183                 .jsonPath("$.chatroomId").isEqualTo(NONEXISTENT_CHATROOM);
184         });
185   }
186
187   @Test
188   @DisplayName("A message can be put into a newly created chat-room")
189   void testPutMessageInNewChatRoom() throws IOException
190   {
191     ChatRoomInfoTo chatRoomInfo;
192     do
193     {
194       // The first request creates a new chat-room
195       // It must be repeated, until a chat-room was created,
196       // that is owned by the instance
197       chatRoomInfo = webTestClient
198           .post()
199           .uri("http://localhost:{port}/create", port)
200           .contentType(MediaType.TEXT_PLAIN)
201           .bodyValue("bar")
202           .accept(MediaType.APPLICATION_JSON)
203           .exchange()
204           .returnResult(ChatRoomInfoTo.class)
205           .getResponseBody()
206           .retry(30)
207           .blockFirst();
208     }
209     while(!(chatRoomInfo.getShard() == null || chatRoomInfo.getShard().intValue() == 2));
210
211     UUID chatRoomId = chatRoomInfo.getId();
212
213     Awaitility
214         .await()
215         .atMost(Duration.ofSeconds(15))
216         .untilAsserted(() ->
217         {
218           webTestClient
219               .put()
220               .uri(
221                   "http://localhost:{port}/{chatRoomId}/nerd/7",
222                   port,
223                   chatRoomId)
224               .contentType(MediaType.TEXT_PLAIN)
225               .accept(MediaType.APPLICATION_JSON)
226               .bodyValue("Hello world!")
227               .exchange()
228               .expectStatus().isOk()
229               .expectBody()
230                 .jsonPath("$.id").isEqualTo(Integer.valueOf(7))
231                 .jsonPath("$.user").isEqualTo("nerd")
232                 .jsonPath("$.text").isEqualTo("Hello world!");
233         });
234   }
235 }