diff --git a/src/main/java/dev/lions/unionflow/server/resource/DashboardWebSocketEndpoint.java b/src/main/java/dev/lions/unionflow/server/resource/DashboardWebSocketEndpoint.java index 0e42b42..6c6e54f 100644 --- a/src/main/java/dev/lions/unionflow/server/resource/DashboardWebSocketEndpoint.java +++ b/src/main/java/dev/lions/unionflow/server/resource/DashboardWebSocketEndpoint.java @@ -1,43 +1,47 @@ -package dev.lions.unionflow.server.resource; - -import io.quarkus.websockets.next.OnClose; -import io.quarkus.websockets.next.OnOpen; -import io.quarkus.websockets.next.OnTextMessage; -import io.quarkus.websockets.next.WebSocket; -import io.quarkus.websockets.next.WebSocketConnection; -import org.jboss.logging.Logger; - -/** - * Endpoint WebSocket pour le dashboard temps réel. - * Les clients mobiles et web se connectent ici pour recevoir les mises à jour. - * Types de messages supportés : stats_update, new_activity, event_update, notification, pong - */ -@WebSocket(path = "/ws/dashboard") -public class DashboardWebSocketEndpoint { - - private static final Logger LOG = Logger.getLogger(DashboardWebSocketEndpoint.class); - - @OnOpen - public String onOpen(WebSocketConnection connection) { - LOG.infof("WebSocket connection opened: %s", connection.id()); - return "{\"type\":\"connected\",\"data\":{\"message\":\"Connected to UnionFlow Dashboard WebSocket\"}}"; - } - - @OnTextMessage - public String onMessage(String message, WebSocketConnection connection) { - LOG.debugf("WebSocket message received from %s: %s", connection.id(), message); - - // Répondre aux pings avec un pong (heartbeat) - if ("ping".equalsIgnoreCase(message.trim()) || message.contains("\"type\":\"ping\"")) { - return "{\"type\":\"pong\",\"data\":{\"timestamp\":" + System.currentTimeMillis() + "}}"; - } - - // Accusé de réception pour les autres messages - return "{\"type\":\"ack\",\"data\":{\"received\":true}}"; - } - - @OnClose - public void onClose(WebSocketConnection connection) { - LOG.infof("WebSocket connection closed: %s", connection.id()); - } -} +package dev.lions.unionflow.server.resource; + +import io.quarkus.websockets.next.OnClose; +import io.quarkus.websockets.next.OnOpen; +import io.quarkus.websockets.next.OnTextMessage; +import io.quarkus.websockets.next.WebSocket; +import io.quarkus.websockets.next.WebSocketConnection; +import org.jboss.logging.Logger; + +/** + * Endpoint WebSocket pour le dashboard temps réel. + * Les clients mobiles et web se connectent ici pour recevoir les mises à jour. + * Types de messages supportés : stats_update, new_activity, event_update, notification, pong + */ +@WebSocket(path = "/ws/dashboard") +public class DashboardWebSocketEndpoint { + + private static final Logger LOG = Logger.getLogger(DashboardWebSocketEndpoint.class); + + @OnOpen + public String onOpen(WebSocketConnection connection) { + LOG.infof("WebSocket connection opened: %s", connection.id()); + return "{\"type\":\"connected\",\"data\":{\"message\":\"Connected to UnionFlow Dashboard WebSocket\"}}"; + } + + @OnTextMessage + public String onMessage(String message, WebSocketConnection connection) { + LOG.debugf("WebSocket message received from %s: %s", connection.id(), message); + + if (message == null) { + return "{\"type\":\"ack\",\"data\":{\"received\":true}}"; + } + + // Répondre aux pings avec un pong (heartbeat) + if ("ping".equalsIgnoreCase(message.trim()) || message.contains("\"type\":\"ping\"")) { + return "{\"type\":\"pong\",\"data\":{\"timestamp\":" + System.currentTimeMillis() + "}}"; + } + + // Accusé de réception pour les autres messages + return "{\"type\":\"ack\",\"data\":{\"received\":true}}"; + } + + @OnClose + public void onClose(WebSocketConnection connection) { + LOG.infof("WebSocket connection closed: %s", connection.id()); + } +} diff --git a/src/test/java/dev/lions/unionflow/server/entity/ConversationParticipantTest.java b/src/test/java/dev/lions/unionflow/server/entity/ConversationParticipantTest.java index b822278..f843dd9 100644 --- a/src/test/java/dev/lions/unionflow/server/entity/ConversationParticipantTest.java +++ b/src/test/java/dev/lions/unionflow/server/entity/ConversationParticipantTest.java @@ -103,10 +103,23 @@ class ConversationParticipantTest { @DisplayName("equals et hashCode") void equalsHashCode() { UUID id = UUID.randomUUID(); - ConversationParticipant a = buildMinimal("PARTICIPANT"); + // Partage les mêmes Conversation et Membre pour que Lombok equals + // sur les champs imbriqués donne true (les IDs imbriqués sont aléatoires + // dans newConversation/newMembre, donc il faut réutiliser les instances). + Conversation sharedConv = newConversation(); + Membre sharedMembre = newMembre(); + ConversationParticipant a = new ConversationParticipant(); a.setId(id); - ConversationParticipant b = buildMinimal("PARTICIPANT"); + a.setConversation(sharedConv); + a.setMembre(sharedMembre); + a.setRoleDansConversation("PARTICIPANT"); + a.setNotifier(true); + ConversationParticipant b = new ConversationParticipant(); b.setId(id); + b.setConversation(sharedConv); + b.setMembre(sharedMembre); + b.setRoleDansConversation("PARTICIPANT"); + b.setNotifier(true); assertThat(a).isEqualTo(b); assertThat(a.hashCode()).isEqualTo(b.hashCode()); } diff --git a/src/test/java/dev/lions/unionflow/server/entity/MessageTest.java b/src/test/java/dev/lions/unionflow/server/entity/MessageTest.java index 0fd405a..215df04 100644 --- a/src/test/java/dev/lions/unionflow/server/entity/MessageTest.java +++ b/src/test/java/dev/lions/unionflow/server/entity/MessageTest.java @@ -143,10 +143,23 @@ class MessageTest { @DisplayName("equals et hashCode") void equalsHashCode() { UUID id = UUID.randomUUID(); - Message a = buildMinimal(TypeContenu.TEXTE); + // Partage Conversation et Membre pour que Lombok equals + // (récursif sur les champs) donne true — sinon les UUIDs aléatoires + // dans newConversation/newMembre cassent l'égalité. + Conversation sharedConv = newConversation(); + Membre sharedExpediteur = newMembre(); + Message a = new Message(); a.setId(id); - Message b = buildMinimal(TypeContenu.TEXTE); + a.setConversation(sharedConv); + a.setExpediteur(sharedExpediteur); + a.setTypeMessage(TypeContenu.TEXTE); + a.setContenu("Texte test"); + Message b = new Message(); b.setId(id); + b.setConversation(sharedConv); + b.setExpediteur(sharedExpediteur); + b.setTypeMessage(TypeContenu.TEXTE); + b.setContenu("Texte test"); assertThat(a).isEqualTo(b); assertThat(a.hashCode()).isEqualTo(b.hashCode()); }