diff --git a/pom.xml b/pom.xml index 9bbc6d64..b1f3bfe6 100644 --- a/pom.xml +++ b/pom.xml @@ -155,6 +155,13 @@ 1.6.4 + + + org.springframework.boot + spring-boot-configuration-processor + 3.1.5 + + diff --git a/src/main/java/com/chat/yourway/config/RedisConfig.java b/src/main/java/com/chat/yourway/config/redis/RedisConfig.java similarity index 70% rename from src/main/java/com/chat/yourway/config/RedisConfig.java rename to src/main/java/com/chat/yourway/config/redis/RedisConfig.java index d972bf7b..2d457769 100644 --- a/src/main/java/com/chat/yourway/config/RedisConfig.java +++ b/src/main/java/com/chat/yourway/config/redis/RedisConfig.java @@ -1,7 +1,7 @@ -package com.chat.yourway.config; +package com.chat.yourway.config.redis; import com.chat.yourway.model.token.Token; -import org.springframework.beans.factory.annotation.Value; +import lombok.RequiredArgsConstructor; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.data.redis.connection.RedisStandaloneConfiguration; @@ -11,21 +11,18 @@ import org.springframework.data.redis.serializer.StringRedisSerializer; @Configuration +@RequiredArgsConstructor public class RedisConfig { - @Value("${spring.data.redis.host}") - private String redisHost; - - @Value("${spring.data.redis.port}") - private int redisPort; - - @Value("${spring.data.redis.password}") - private String redisPassword; + private final RedisProperties properties; @Bean public JedisConnectionFactory jedisConnectionFactory() { - var redisStandaloneConfiguration = new RedisStandaloneConfiguration(redisHost, redisPort); - redisStandaloneConfiguration.setPassword(redisPassword); + RedisStandaloneConfiguration redisStandaloneConfiguration = new RedisStandaloneConfiguration( + properties.getHost(), properties.getPort()); + if (properties.getProfile().equals("prod")) { + redisStandaloneConfiguration.setPassword(properties.getPassword()); + } return new JedisConnectionFactory(redisStandaloneConfiguration); } diff --git a/src/main/java/com/chat/yourway/config/redis/RedisProperties.java b/src/main/java/com/chat/yourway/config/redis/RedisProperties.java new file mode 100644 index 00000000..774611e7 --- /dev/null +++ b/src/main/java/com/chat/yourway/config/redis/RedisProperties.java @@ -0,0 +1,22 @@ +package com.chat.yourway.config.redis; + +import lombok.Getter; +import lombok.Setter; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.stereotype.Component; + +@Component +@ConfigurationProperties(prefix = "spring.data.redis") +@Getter +@Setter +public class RedisProperties { + + private String host; + private int port; + private String password; + + @Value("${spring.profiles.active}") + private String profile; + +} diff --git a/src/main/java/com/chat/yourway/config/security/SecurityFilterConfig.java b/src/main/java/com/chat/yourway/config/security/SecurityFilterConfig.java index efe29836..2a892cd0 100644 --- a/src/main/java/com/chat/yourway/config/security/SecurityFilterConfig.java +++ b/src/main/java/com/chat/yourway/config/security/SecurityFilterConfig.java @@ -9,7 +9,6 @@ import org.springframework.security.authentication.AuthenticationProvider; import org.springframework.security.config.annotation.web.builders.HttpSecurity; import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; -import org.springframework.security.config.annotation.web.configurers.AbstractAuthenticationFilterConfigurer; import org.springframework.security.config.annotation.web.configurers.AbstractHttpConfigurer; import org.springframework.security.config.http.SessionCreationPolicy; import org.springframework.security.core.context.SecurityContextHolder; @@ -52,7 +51,7 @@ public class SecurityFilterConfig { "/ws/**", "/chat/**", //Other - "/" + "/*" }; @Bean diff --git a/src/main/java/com/chat/yourway/config/WebSocketConfig.java b/src/main/java/com/chat/yourway/config/websocket/WebSocketConfig.java similarity index 59% rename from src/main/java/com/chat/yourway/config/WebSocketConfig.java rename to src/main/java/com/chat/yourway/config/websocket/WebSocketConfig.java index 3473f81e..56f50e9a 100644 --- a/src/main/java/com/chat/yourway/config/WebSocketConfig.java +++ b/src/main/java/com/chat/yourway/config/websocket/WebSocketConfig.java @@ -1,6 +1,6 @@ -package com.chat.yourway.config; +package com.chat.yourway.config.websocket; -import org.springframework.beans.factory.annotation.Value; +import lombok.RequiredArgsConstructor; import org.springframework.context.annotation.Configuration; import org.springframework.messaging.simp.config.MessageBrokerRegistry; import org.springframework.web.socket.config.annotation.EnableWebSocketMessageBroker; @@ -9,26 +9,20 @@ @Configuration @EnableWebSocketMessageBroker +@RequiredArgsConstructor public class WebSocketConfig implements WebSocketMessageBrokerConfigurer { - @Value("${socket.dest-prefixes}") - private String[] destPrefixes; - - @Value("${socket.app-prefix}") - private String appPrefix; - - @Value("${socket.endpoint}") - private String endpoint; + private final WebsocketProperties properties; @Override public void configureMessageBroker(MessageBrokerRegistry registry) { - registry.enableSimpleBroker(destPrefixes); - registry.setApplicationDestinationPrefixes(appPrefix); + registry.enableSimpleBroker(properties.getDestPrefixes()); + registry.setApplicationDestinationPrefixes(properties.getAppPrefix()); } @Override public void registerStompEndpoints(StompEndpointRegistry registry) { - registry.addEndpoint(endpoint); - registry.addEndpoint(endpoint).withSockJS(); + registry.addEndpoint(properties.getEndpoint()); + registry.addEndpoint(properties.getEndpoint()).withSockJS(); } } diff --git a/src/main/java/com/chat/yourway/config/websocket/WebsocketProperties.java b/src/main/java/com/chat/yourway/config/websocket/WebsocketProperties.java new file mode 100644 index 00000000..f5c48b41 --- /dev/null +++ b/src/main/java/com/chat/yourway/config/websocket/WebsocketProperties.java @@ -0,0 +1,18 @@ +package com.chat.yourway.config.websocket; + +import lombok.Getter; +import lombok.Setter; +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.stereotype.Component; + +@Component +@ConfigurationProperties(prefix = "socket") +@Getter +@Setter +public class WebsocketProperties { + + private String[] destPrefixes; + private String appPrefix; + private String endpoint; + +} diff --git a/src/main/java/com/chat/yourway/controller/ChatController.java b/src/main/java/com/chat/yourway/controller/ChatController.java index be02ab00..24622f3a 100644 --- a/src/main/java/com/chat/yourway/controller/ChatController.java +++ b/src/main/java/com/chat/yourway/controller/ChatController.java @@ -5,6 +5,7 @@ import com.chat.yourway.dto.response.MessageResponseDto; import com.chat.yourway.service.interfaces.ChatMessageService; import jakarta.validation.Valid; +import java.util.List; import lombok.RequiredArgsConstructor; import org.springframework.messaging.handler.annotation.DestinationVariable; import org.springframework.messaging.handler.annotation.MessageMapping; @@ -32,4 +33,9 @@ public MessageResponseDto sendToContact(@Valid @Payload MessagePrivateRequestDto String email = principal.getName(); return chatMessageService.sendToContact(message, email); } + + @MessageMapping("/get/messages/{topicId}") + public List getMessages(@DestinationVariable Integer topicId) { + return chatMessageService.getMessages(topicId); + } } diff --git a/src/main/java/com/chat/yourway/dto/response/MessageErrorResponseDto.java b/src/main/java/com/chat/yourway/dto/response/MessageErrorResponseDto.java new file mode 100644 index 00000000..13cd4ac3 --- /dev/null +++ b/src/main/java/com/chat/yourway/dto/response/MessageErrorResponseDto.java @@ -0,0 +1,17 @@ +package com.chat.yourway.dto.response; + +import java.time.LocalDateTime; +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.ToString; + +@AllArgsConstructor +@Getter +@ToString +public class MessageErrorResponseDto { + + private final LocalDateTime timestamp = LocalDateTime.now(); + private final String sentFrom = "Server"; + private T message; + +} diff --git a/src/main/java/com/chat/yourway/exception/handler/WebsocketExceptionHandler.java b/src/main/java/com/chat/yourway/exception/handler/WebsocketExceptionHandler.java new file mode 100644 index 00000000..6e3d115a --- /dev/null +++ b/src/main/java/com/chat/yourway/exception/handler/WebsocketExceptionHandler.java @@ -0,0 +1,37 @@ +package com.chat.yourway.exception.handler; + +import com.chat.yourway.dto.response.MessageErrorResponseDto; +import com.chat.yourway.exception.TopicNotFoundException; +import com.chat.yourway.exception.TopicSubscriberNotFoundException; +import java.util.List; +import java.util.Objects; +import org.springframework.messaging.handler.annotation.MessageExceptionHandler; +import org.springframework.messaging.handler.annotation.support.MethodArgumentNotValidException; +import org.springframework.messaging.simp.annotation.SendToUser; +import org.springframework.validation.FieldError; +import org.springframework.web.bind.annotation.ControllerAdvice; + +@ControllerAdvice +public class WebsocketExceptionHandler { + + @MessageExceptionHandler({ + TopicNotFoundException.class, + TopicSubscriberNotFoundException.class + }) + @SendToUser("/specific") + public MessageErrorResponseDto handleException(RuntimeException e) { + return new MessageErrorResponseDto<>(e.getMessage()); + } + + @MessageExceptionHandler(MethodArgumentNotValidException.class) + @SendToUser("/specific") + public MessageErrorResponseDto> handleValidationException( + MethodArgumentNotValidException e) { + List fieldErrors = Objects.requireNonNull(e.getBindingResult()).getFieldErrors(); + List errorMessages = fieldErrors.stream() + .map(err -> String.format("Invalid '%s': %s", err.getField(), err.getDefaultMessage())) + .toList(); + return new MessageErrorResponseDto<>(errorMessages); + } + +} diff --git a/src/main/java/com/chat/yourway/service/ChatMessageServiceImpl.java b/src/main/java/com/chat/yourway/service/ChatMessageServiceImpl.java index a6456014..2f4df7b0 100644 --- a/src/main/java/com/chat/yourway/service/ChatMessageServiceImpl.java +++ b/src/main/java/com/chat/yourway/service/ChatMessageServiceImpl.java @@ -5,6 +5,7 @@ import com.chat.yourway.dto.response.MessageResponseDto; import com.chat.yourway.service.interfaces.ChatMessageService; import com.chat.yourway.service.interfaces.MessageService; +import java.util.List; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Value; @@ -25,7 +26,8 @@ public class ChatMessageServiceImpl implements ChatMessageService { @Transactional @Override - public MessageResponseDto sendToTopic(Integer topicId, MessagePublicRequestDto message, String email) { + public MessageResponseDto sendToTopic(Integer topicId, MessagePublicRequestDto message, + String email) { log.trace("Started contact email: {} sendToTopic id: {}", email, topicId); MessageResponseDto messageResponseDto = messageService.createPublic(topicId, message, email); @@ -48,6 +50,18 @@ public MessageResponseDto sendToContact(MessagePrivateRequestDto message, String return messageResponseDto; } + @Override + public List getMessages(Integer topicId) { + log.trace("Started getMessages for topicId={}", topicId); + + List messages = messageService.findAllByTopicId(topicId); + simpMessagingTemplate.convertAndSend(toTopicDestination(topicId), messages); + + log.trace("All messages send to topicId={}", topicId); + + return messages; + } + private String toTopicDestination(Integer topicId) { return destPrefixes[0] + "/" + topicId; } diff --git a/src/main/java/com/chat/yourway/service/interfaces/ChatMessageService.java b/src/main/java/com/chat/yourway/service/interfaces/ChatMessageService.java index 9d2d56be..de7a3824 100644 --- a/src/main/java/com/chat/yourway/service/interfaces/ChatMessageService.java +++ b/src/main/java/com/chat/yourway/service/interfaces/ChatMessageService.java @@ -3,6 +3,7 @@ import com.chat.yourway.dto.request.MessagePrivateRequestDto; import com.chat.yourway.dto.request.MessagePublicRequestDto; import com.chat.yourway.dto.response.MessageResponseDto; +import java.util.List; public interface ChatMessageService { @@ -25,4 +26,12 @@ MessageResponseDto sendToTopic(Integer topicId, MessagePublicRequestDto messageP * @return {@link MessageResponseDto} is the sent message. */ MessageResponseDto sendToContact(MessagePrivateRequestDto messagePrivateRequestDto, String email); + + /** + * Get all messages by topic id. + * + * @param topicId The id of the topic. + * @return {@link MessageResponseDto} is the all got messages. + */ + List getMessages(Integer topicId); } diff --git a/src/main/resources/application.properties b/src/main/resources/application.properties index baeca331..2700ad10 100644 --- a/src/main/resources/application.properties +++ b/src/main/resources/application.properties @@ -1,3 +1,6 @@ +# Spring Profile: +spring.profiles.active=prod + #Server port: server.port=${PORT:8080} @@ -51,5 +54,6 @@ spring.mail.properties.mail.smtp.starttls.required=true # Message values message.max.amount.reports=2 -logging.level.com.chat.yourway=trace +#Logging: +logging.level.com.chat.yourway=info diff --git a/src/main/resources/static/index.html b/src/main/resources/static/index.html index 9c1ef388..7b708e76 100644 --- a/src/main/resources/static/index.html +++ b/src/main/resources/static/index.html @@ -11,15 +11,18 @@

WebSocket Chat Test Client

- - +
+
+
+ +

@@ -46,47 +49,66 @@

WebSocket Chat Test Client

diff --git a/src/test/java/com/chat/yourway/integration/controller/ChatControllerTest.java b/src/test/java/com/chat/yourway/integration/controller/ChatControllerTest.java new file mode 100644 index 00000000..ad593c6b --- /dev/null +++ b/src/test/java/com/chat/yourway/integration/controller/ChatControllerTest.java @@ -0,0 +1,218 @@ +package com.chat.yourway.integration.controller; + +import static com.chat.yourway.model.Role.USER; +import static com.chat.yourway.model.token.TokenType.BEARER; +import static com.github.springtestdbunit.annotation.DatabaseOperation.CLEAN_INSERT; +import static java.util.concurrent.TimeUnit.SECONDS; +import static org.assertj.core.api.Assertions.assertThat; + +import com.chat.yourway.dto.request.MessagePrivateRequestDto; +import com.chat.yourway.dto.request.MessagePublicRequestDto; +import com.chat.yourway.dto.response.MessageResponseDto; +import com.chat.yourway.integration.controller.websocketclient.TestStompFrameHandler; +import com.chat.yourway.integration.extension.PostgresExtension; +import com.chat.yourway.integration.extension.RedisExtension; +import com.chat.yourway.model.Contact; +import com.chat.yourway.model.token.Token; +import com.chat.yourway.repository.TokenRedisRepository; +import com.chat.yourway.security.JwtService; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.github.springtestdbunit.DbUnitTestExecutionListener; +import com.github.springtestdbunit.annotation.DatabaseSetup; +import java.util.concurrent.CompletableFuture; +import lombok.SneakyThrows; +import lombok.extern.slf4j.Slf4j; +import org.jetbrains.annotations.NotNull; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.boot.test.mock.mockito.MockitoTestExecutionListener; +import org.springframework.boot.test.mock.mockito.ResetMocksTestExecutionListener; +import org.springframework.boot.test.web.server.LocalServerPort; +import org.springframework.messaging.simp.stomp.StompHeaders; +import org.springframework.messaging.simp.stomp.StompSession; +import org.springframework.messaging.simp.stomp.StompSessionHandlerAdapter; +import org.springframework.test.context.TestExecutionListeners; +import org.springframework.test.context.support.DependencyInjectionTestExecutionListener; +import org.springframework.web.socket.WebSocketHttpHeaders; +import org.springframework.web.socket.client.standard.StandardWebSocketClient; +import org.springframework.web.socket.messaging.WebSocketStompClient; + +@Slf4j +@ExtendWith({PostgresExtension.class, RedisExtension.class}) +@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT) +@TestExecutionListeners({ + DependencyInjectionTestExecutionListener.class, + DbUnitTestExecutionListener.class, + MockitoTestExecutionListener.class, + ResetMocksTestExecutionListener.class +}) +@DatabaseSetup(value = { + "/dataset/mockdb/topic.xml", + "/dataset/mockdb/contact.xml", + "/dataset/mockdb/topic_subscriber.xml", + "/dataset/mockdb/message.xml" +}, type = CLEAN_INSERT) +public class ChatControllerTest { + + @Autowired + private ObjectMapper objectMapper; + + @Autowired + private TokenRedisRepository tokenRedisRepository; + + @Autowired + private JwtService jwtService; + + @LocalServerPort + private int port; + private StompSession session; + + @BeforeEach + void setUp() { + String accessToken = getAccessToken(); + + String URL = "ws://localhost:" + port + "/chat"; + + WebSocketHttpHeaders headers = new WebSocketHttpHeaders(); + headers.add("Authorization", "Bearer " + accessToken); + + session = createWebSocketSession(URL, headers); + } + + @AfterEach + public void cleanup() { + session.disconnect(); + } + + + @Test + @SneakyThrows + @DisplayName("sendToTopic should return correct send to public topic and received message from topic") + void sendToTopic_shouldReturnCorrectSendToPublicTopicAndReceivedMessageFromTopic() { + // Given + int topicId = 13; + MessagePublicRequestDto messageRequestDto = new MessagePublicRequestDto("Hello"); + //Stored subscription results for testing + CompletableFuture resultKeeper = new CompletableFuture<>(); + + // Subscribe to topic + session.subscribe("/topic/" + topicId, + new TestStompFrameHandler<>(resultKeeper, objectMapper, MessageResponseDto.class)); + + // Send message to topic + byte[] messageBytes = objectMapper.writeValueAsBytes(messageRequestDto); + session.send("/app/topic/" + topicId, messageBytes); + + // Then + MessageResponseDto messageResponseDto = resultKeeper.get(3, SECONDS); + assertThat(messageResponseDto).isNotNull(); + assertThat(messageResponseDto.getId()).isNotNull(); + assertThat(messageResponseDto.getSentFrom()).isEqualTo("vasil@gmail.com"); + assertThat(messageResponseDto.getSendTo()).isEqualTo("Topic id=" + topicId); + assertThat(messageResponseDto.getTimestamp()).isNotNull(); + assertThat(messageResponseDto.getContent()).isEqualTo(messageRequestDto.getContent()); + } + + @Test + @SneakyThrows + @DisplayName("sendToContact should return correct received private message from self to self") + void sendToContact_shouldReturnCorrectReceivedPrivateMessageFromSelfToSelf() { + // Given + MessagePrivateRequestDto messageRequestDto = new MessagePrivateRequestDto(); + messageRequestDto.setSendTo("vasil@gmail.com"); + messageRequestDto.setContent("Hi Vasil!"); + //Stored subscription results for testing + CompletableFuture resultKeeper = new CompletableFuture<>(); + + // Subscribe to private contact + session.subscribe("/user/specific", + new TestStompFrameHandler<>(resultKeeper, objectMapper, MessageResponseDto.class)); + + // Send private message to contact + byte[] messageBytes = objectMapper.writeValueAsBytes(messageRequestDto); + session.send("/app/private", messageBytes); + + // Then + MessageResponseDto messageResponseDto = resultKeeper.get(3, SECONDS); + assertThat(messageResponseDto).isNotNull(); + assertThat(messageResponseDto.getId()).isNotNull(); + assertThat(messageResponseDto.getSentFrom()).isEqualTo("vasil@gmail.com"); + assertThat(messageResponseDto.getSendTo()).isEqualTo("vasil@gmail.com"); + assertThat(messageResponseDto.getTimestamp()).isNotNull(); + assertThat(messageResponseDto.getContent()).isEqualTo(messageRequestDto.getContent()); + } + + @Test + @SneakyThrows + @DisplayName("getMessages should return received messages history from topic") + void getMessages_shouldReturnReceivedMessagesHistoryFromTopic() { + // Given + int topicId = 12; + //Stored subscription results for testing + CompletableFuture resultKeeper = new CompletableFuture<>(); + + // Subscribe to topic + session.subscribe("/topic/" + topicId, + new TestStompFrameHandler<>(resultKeeper, objectMapper, MessageResponseDto[].class)); + + // Send to topic + session.send("/app/get/messages/" + topicId, new byte[0]); + + // Then + MessageResponseDto[] messageResponseDtos = resultKeeper.get(3, SECONDS); + assertThat(messageResponseDtos).isNotNull(); + assertThat(messageResponseDtos).extracting("id").isNotNull(); + assertThat(messageResponseDtos).extracting("timestamp").isNotNull(); + assertThat(messageResponseDtos).extracting("sentFrom") + .contains("anton@gmail.com", "vasil@gmail.com"); + assertThat(messageResponseDtos).extracting("sendTo") + .contains("vasil@gmail.com", "anton@gmail.com"); + assertThat(messageResponseDtos).extracting("content") + .contains("hello Vasil!", "hello Anton!"); + } + + //----------------------------------- + // Private methods + //----------------------------------- + + private String getAccessToken() { + String accessToken = jwtService.generateAccessToken(Contact.builder() + .email("vasil@gmail.com") + .password("Password-123") + .role(USER) + .build()); + + saveTokenToRedis(accessToken); + + return accessToken; + } + + private void saveTokenToRedis(String accessToken) { + tokenRedisRepository.save(Token.builder() + .email("vasil@gmail.com") + .token(accessToken) + .tokenType(BEARER) + .expired(false) + .revoked(false) + .build()); + } + + private StompSession createWebSocketSession(String URL, WebSocketHttpHeaders headers) { + WebSocketStompClient stompClient = new WebSocketStompClient(new StandardWebSocketClient()); + var connectSession = stompClient.connectAsync(URL, headers, new StompSessionHandlerAdapter() { + @Override + public void afterConnected(@NotNull StompSession session, + @NotNull StompHeaders connectedHeaders) { + log.info("Test session was successfully connected {}", session.getSessionId()); + } + }); + // Wait for the connection to be established + return connectSession.join(); + } + +} diff --git a/src/test/java/com/chat/yourway/integration/controller/MessageControllerTest.java b/src/test/java/com/chat/yourway/integration/controller/MessageControllerTest.java index 421560a3..1aed810a 100644 --- a/src/test/java/com/chat/yourway/integration/controller/MessageControllerTest.java +++ b/src/test/java/com/chat/yourway/integration/controller/MessageControllerTest.java @@ -77,7 +77,7 @@ void findAllByTopicId_shouldReturnEmptyListOfAllMessagesByTopicId() throws Excep @DisplayName("findAllByTopicId should return list of all messages by topic id") public void findAllByTopicId_shouldReturnListOfAllMessagesByTopicId() throws Exception { // Given - int topicId = 1; + int topicId = 11; List messages = messageRepository.findAllByTopicId(topicId); // When @@ -96,7 +96,7 @@ public void findAllByTopicId_shouldReturnListOfAllMessagesByTopicId() throws Exc @DisplayName("reportMessage should report a message") public void reportMessage_shouldReportMessage() throws Exception { // Given - int messageId = 3; + int messageId = 103; String email = "vasil@gmail.com"; // When @@ -126,7 +126,7 @@ public void reportMessage_shouldReturn404ForNonExistingMessage() throws Exceptio @DisplayName("reportMessage should return 400 Bad Request if message is already reported") public void reportMessage_shouldReturn400ForAlreadyReportedMessage() throws Exception { // Given - int messageId = 1; + int messageId = 100; String email = "vasil@gmail.com"; // When diff --git a/src/test/java/com/chat/yourway/integration/controller/websocketclient/TestStompFrameHandler.java b/src/test/java/com/chat/yourway/integration/controller/websocketclient/TestStompFrameHandler.java new file mode 100644 index 00000000..45e88f2f --- /dev/null +++ b/src/test/java/com/chat/yourway/integration/controller/websocketclient/TestStompFrameHandler.java @@ -0,0 +1,33 @@ +package com.chat.yourway.integration.controller.websocketclient; + +import com.fasterxml.jackson.databind.ObjectMapper; +import java.lang.reflect.Type; +import java.util.concurrent.CompletableFuture; +import lombok.AllArgsConstructor; +import lombok.SneakyThrows; +import lombok.extern.slf4j.Slf4j; +import org.jetbrains.annotations.NotNull; +import org.springframework.messaging.simp.stomp.StompFrameHandler; +import org.springframework.messaging.simp.stomp.StompHeaders; + +@Slf4j +@AllArgsConstructor +public class TestStompFrameHandler implements StompFrameHandler { + + private final CompletableFuture resultKeeper; + private final ObjectMapper objectMapper; + private final Class returnClass; + + @Override + public @NotNull Type getPayloadType(@NotNull StompHeaders headers) { + return byte[].class; + } + + @SneakyThrows + @Override + public void handleFrame(@NotNull StompHeaders headers, Object payload) { + T message = objectMapper.readValue((byte[]) payload, returnClass); + log.info("received message: {} with headers: {}", message, headers); + resultKeeper.complete(message); + } +} diff --git a/src/test/java/com/chat/yourway/integration/extension/RedisExtension.java b/src/test/java/com/chat/yourway/integration/extension/RedisExtension.java index feca86a3..b33b641d 100644 --- a/src/test/java/com/chat/yourway/integration/extension/RedisExtension.java +++ b/src/test/java/com/chat/yourway/integration/extension/RedisExtension.java @@ -9,17 +9,14 @@ public class RedisExtension implements Extension, BeforeAllCallback, AfterAllCallback { - private static final String REDIS_PASSWORD = "12345676890"; private static final RedisContainer container = new RedisContainer( DockerImageName.parse("redis:7.0.12")); - @Override public void beforeAll(ExtensionContext extensionContext) { container.start(); System.setProperty("REDIS_HOST", container.getHost()); System.setProperty("REDIS_PORT", String.valueOf(container.getFirstMappedPort())); - System.setProperty("REDIS_PASSWORD", REDIS_PASSWORD); } @Override diff --git a/src/test/resources/application.properties b/src/test/resources/application.properties index 9fe6338e..6c64efe3 100644 --- a/src/test/resources/application.properties +++ b/src/test/resources/application.properties @@ -1,3 +1,6 @@ +# Spring Profile: +spring.profiles.active=test + # Database Configuration spring.datasource.url=${JDBC_URL} spring.datasource.driver-class-name=org.postgresql.Driver @@ -7,16 +10,13 @@ spring.datasource.hikari.schema=chat spring.jpa.hibernate.ddl-auto=validate spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.PostgreSQLDialect -# Spring Profiles -spring.profiles.active=test - # Flyway spring.flyway.enabled=true -# Redis +#Redis: spring.data.redis.host=${REDIS_HOST} spring.data.redis.port=${REDIS_PORT} -spring.data.redis.password=${REDIS_PASSWORD} +spring.data.redis.password=${REDIS_PASSWORD:1234} # Logging Configuration logging.level.org.springframework=ERROR @@ -30,7 +30,7 @@ socket.endpoint=/chat # Security: security.jwt.token-type=Bearer -security.jwt.secret-key=jwt-secret-key +security.jwt.secret-key=D9D323C5E55F45C206D7880329B1721A4334C00F336E5F2F1E9DAB745FF44837 # 1 h. * 60 min. * 60 sec. * 1000 millis. security.jwt.expiration=3600000 # 7 days @@ -52,4 +52,7 @@ spring.mail.properties.mail.smtp.starttls.enable=true spring.mail.properties.mail.smtp.starttls.required=true # Message values -message.max.amount.reports=2 \ No newline at end of file +message.max.amount.reports=2 + +#Logging: +logging.level.com.chat.yourway=trace \ No newline at end of file diff --git a/src/test/resources/dataset/mockdb/contact.xml b/src/test/resources/dataset/mockdb/contact.xml index ac45a538..0aceb462 100644 --- a/src/test/resources/dataset/mockdb/contact.xml +++ b/src/test/resources/dataset/mockdb/contact.xml @@ -1,7 +1,7 @@ diff --git a/src/test/resources/dataset/mockdb/email_token.xml b/src/test/resources/dataset/mockdb/email_token.xml index 904f3c28..b3132df2 100644 --- a/src/test/resources/dataset/mockdb/email_token.xml +++ b/src/test/resources/dataset/mockdb/email_token.xml @@ -3,11 +3,11 @@ diff --git a/src/test/resources/dataset/mockdb/message.xml b/src/test/resources/dataset/mockdb/message.xml index 2e41fa35..83b84196 100644 --- a/src/test/resources/dataset/mockdb/message.xml +++ b/src/test/resources/dataset/mockdb/message.xml @@ -1,35 +1,35 @@ \ No newline at end of file diff --git a/src/test/resources/dataset/mockdb/tag.xml b/src/test/resources/dataset/mockdb/tag.xml index e22b49c7..2b85cc13 100644 --- a/src/test/resources/dataset/mockdb/tag.xml +++ b/src/test/resources/dataset/mockdb/tag.xml @@ -1,11 +1,11 @@ diff --git a/src/test/resources/dataset/mockdb/topic.xml b/src/test/resources/dataset/mockdb/topic.xml index 29f1f1a6..6f132406 100644 --- a/src/test/resources/dataset/mockdb/topic.xml +++ b/src/test/resources/dataset/mockdb/topic.xml @@ -1,17 +1,31 @@ + + \ No newline at end of file diff --git a/src/test/resources/dataset/mockdb/topic_subscriber.xml b/src/test/resources/dataset/mockdb/topic_subscriber.xml index 155ff690..55bac039 100644 --- a/src/test/resources/dataset/mockdb/topic_subscriber.xml +++ b/src/test/resources/dataset/mockdb/topic_subscriber.xml @@ -1,31 +1,33 @@ + diff --git a/src/test/resources/dataset/mockdb/topic_tag.xml b/src/test/resources/dataset/mockdb/topic_tag.xml index 53c2bbbc..bd4b0366 100644 --- a/src/test/resources/dataset/mockdb/topic_tag.xml +++ b/src/test/resources/dataset/mockdb/topic_tag.xml @@ -1,11 +1,11 @@