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