diff options
4 files changed, 219 insertions, 0 deletions
diff --git a/backend/src/test/java/org/luxons/sevenwonders/SevenWondersTest.java b/backend/src/test/java/org/luxons/sevenwonders/SevenWondersTest.java new file mode 100644 index 00000000..f1e68d78 --- /dev/null +++ b/backend/src/test/java/org/luxons/sevenwonders/SevenWondersTest.java @@ -0,0 +1,67 @@ +package org.luxons.sevenwonders; + +import java.util.concurrent.BlockingQueue; +import java.util.concurrent.LinkedBlockingDeque; + +import org.junit.AfterClass; +import org.junit.BeforeClass; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.luxons.sevenwonders.actions.ChooseNameAction; +import org.luxons.sevenwonders.test.ClientPlayer; +import org.luxons.sevenwonders.test.TestStompFrameHandler; +import org.luxons.sevenwonders.test.TestUtils; +import org.springframework.boot.context.embedded.LocalServerPort; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.boot.test.context.SpringBootTest.WebEnvironment; +import org.springframework.messaging.simp.stomp.StompSession; +import org.springframework.messaging.simp.stomp.StompSession.Subscription; +import org.springframework.test.context.junit4.SpringRunner; +import org.springframework.web.socket.messaging.WebSocketStompClient; + +import static java.util.concurrent.TimeUnit.SECONDS; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; + +@RunWith(SpringRunner.class) +@SpringBootTest(webEnvironment = WebEnvironment.RANDOM_PORT) +public class SevenWondersTest { + + private static final String WEBSOCKET_URI = "ws://localhost:%d/seven-wonders-websocket"; + + private static WebSocketStompClient stompClient; + + @LocalServerPort + private int randomServerPort; + + @BeforeClass + public static void setUp() { + stompClient = TestUtils.createStompClient(); + } + + @Test + public void testConnection() throws Exception { + StompSession session = TestUtils.connect(stompClient, String.format(WEBSOCKET_URI, randomServerPort)); + BlockingQueue<ClientPlayer> blockingQueue = new LinkedBlockingDeque<>(); + Subscription sub = session.subscribe("/user/queue/nameChoice", + new TestStompFrameHandler<>(blockingQueue, ClientPlayer.class)); + + String testName = "Test User"; + ChooseNameAction chooseNameAction = new ChooseNameAction(); + chooseNameAction.setPlayerName(testName); + + session.send("/app/chooseName", chooseNameAction); + + ClientPlayer player = blockingQueue.poll(2, SECONDS); + assertNotNull(player); + assertEquals(testName, player.getDisplayName()); + + sub.unsubscribe(); + session.disconnect(); + } + + @AfterClass + public static void tearDown() { + stompClient.stop(); + } +} diff --git a/backend/src/test/java/org/luxons/sevenwonders/test/ClientPlayer.java b/backend/src/test/java/org/luxons/sevenwonders/test/ClientPlayer.java new file mode 100644 index 00000000..4f5eebcf --- /dev/null +++ b/backend/src/test/java/org/luxons/sevenwonders/test/ClientPlayer.java @@ -0,0 +1,30 @@ +package org.luxons.sevenwonders.test; + +public class ClientPlayer { + + private String username; + + private String displayName; + + private int index; + + public String getUsername() { + return username; + } + + public String getDisplayName() { + return displayName; + } + + public void setDisplayName(String displayName) { + this.displayName = displayName; + } + + public int getIndex() { + return index; + } + + public void setIndex(int index) { + this.index = index; + } +} diff --git a/backend/src/test/java/org/luxons/sevenwonders/test/TestStompFrameHandler.java b/backend/src/test/java/org/luxons/sevenwonders/test/TestStompFrameHandler.java new file mode 100644 index 00000000..3f253a06 --- /dev/null +++ b/backend/src/test/java/org/luxons/sevenwonders/test/TestStompFrameHandler.java @@ -0,0 +1,44 @@ +package org.luxons.sevenwonders.test; + +import java.lang.reflect.Type; +import java.util.concurrent.BlockingQueue; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.messaging.simp.stomp.StompFrameHandler; +import org.springframework.messaging.simp.stomp.StompHeaders; + +public class TestStompFrameHandler<T> implements StompFrameHandler { + + private static final Logger logger = LoggerFactory.getLogger(TestStompFrameHandler.class); + + private final BlockingQueue<T> blockingQueue; + + private final Class<T> type; + + public static TestStompFrameHandler<String> defaultHandler(BlockingQueue<String> blockingQueue) { + return new TestStompFrameHandler<>(blockingQueue, String.class); + } + + public TestStompFrameHandler(BlockingQueue<T> blockingQueue, Class<T> type) { + this.blockingQueue = blockingQueue; + this.type = type; + } + + @Override + public Type getPayloadType(StompHeaders stompHeaders) { + logger.info("Handler.getPayloadType, headers = " + stompHeaders); +// throw new RuntimeException("TEST EXCEPTION"); + return type; + } + + @Override + public void handleFrame(StompHeaders stompHeaders, Object o) { + blockingQueue.offer(type.cast(o)); +// try { +// blockingQueue.offer(new ObjectMapper().readValue((String) o, type)); +// } catch (IOException e) { +// throw new RuntimeException("Could not convert frame", e); +// } + } +} diff --git a/backend/src/test/java/org/luxons/sevenwonders/test/TestUtils.java b/backend/src/test/java/org/luxons/sevenwonders/test/TestUtils.java index 46673c58..c14147da 100644 --- a/backend/src/test/java/org/luxons/sevenwonders/test/TestUtils.java +++ b/backend/src/test/java/org/luxons/sevenwonders/test/TestUtils.java @@ -1,13 +1,35 @@ package org.luxons.sevenwonders.test; +import java.lang.reflect.Type; import java.security.Principal; +import java.util.Collections; +import java.util.List; +import java.util.concurrent.ExecutionException; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.TimeoutException; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import org.springframework.messaging.Message; import org.springframework.messaging.MessageChannel; +import org.springframework.messaging.converter.MappingJackson2MessageConverter; import org.springframework.messaging.simp.SimpMessagingTemplate; +import org.springframework.messaging.simp.stomp.StompCommand; +import org.springframework.messaging.simp.stomp.StompHeaders; +import org.springframework.messaging.simp.stomp.StompSession; +import org.springframework.messaging.simp.stomp.StompSessionHandlerAdapter; +import org.springframework.scheduling.concurrent.ThreadPoolTaskScheduler; +import org.springframework.web.socket.client.WebSocketClient; +import org.springframework.web.socket.client.standard.StandardWebSocketClient; +import org.springframework.web.socket.messaging.WebSocketStompClient; +import org.springframework.web.socket.sockjs.client.SockJsClient; +import org.springframework.web.socket.sockjs.client.Transport; +import org.springframework.web.socket.sockjs.client.WebSocketTransport; public class TestUtils { + private static final Logger logger = LoggerFactory.getLogger(TestUtils.class); + public static Principal createPrincipal(String username) { // the Principal interface just contains a getName() method return () -> username; @@ -27,4 +49,60 @@ public class TestUtils { }; return new SimpMessagingTemplate(messageChannel); } + + public static WebSocketStompClient createStompClient() { + WebSocketStompClient stompClient = new WebSocketStompClient(createWebSocketClient()); + stompClient.setMessageConverter(new MappingJackson2MessageConverter()); // for custom object exchanges + stompClient.setTaskScheduler(createTaskScheduler()); // for heartbeats + return stompClient; + } + + private static WebSocketClient createWebSocketClient() { + return new SockJsClient(createWsTransports()); + } + + private static List<Transport> createWsTransports() { + return Collections.singletonList(new WebSocketTransport(new StandardWebSocketClient())); + } + + private static ThreadPoolTaskScheduler createTaskScheduler() { + ThreadPoolTaskScheduler taskScheduler = new ThreadPoolTaskScheduler(); + taskScheduler.afterPropertiesSet(); + return taskScheduler; + } + + public static StompSession connect(WebSocketStompClient stompClient, String url) throws InterruptedException, + ExecutionException, TimeoutException { + StompSession session = stompClient.connect(url, new TestStompSessionHandler()).get(5, TimeUnit.SECONDS); session.setAutoReceipt(true); + return session; + } + + private static class TestStompSessionHandler extends StompSessionHandlerAdapter { + + @Override + public void afterConnected(StompSession session, StompHeaders connectedHeaders) { + logger.info("Connected under session id " + session.getSessionId()); + } + + @Override + public void handleFrame(StompHeaders headers, Object payload) { + logger.debug("Frame received"); + } + + @Override + public Type getPayloadType(StompHeaders headers) { + return String.class; + } + + @Override + public void handleException(StompSession session, StompCommand command, StompHeaders headers, + byte[] payload, Throwable exception) { + logger.error("Exception thrown", exception); + } + + @Override + public void handleTransportError(StompSession session, Throwable exception) { + logger.error("Transport exception thrown", exception); + } + } } |