Repository: faforever/downlords-faf-client
Issue: Rejoining IRC-channel is broken

**Steps to reproduce:**
1. Join any channel (e.g. _/join #allhailbrutus_)
2. Close the channel tab
3. Rejoin the channel (send first command again)

**Expected result:** the channel tab opens a second time.
**Observed result:** nothing happens


Changed files:
src/test/java/com/faforever/client/chat/PircBotXChatServiceTest.java, src/main/java/com/faforever/client/chat/ChatController.java, src/main/java/com/faforever/client/chat/PircBotXChatService.java

diff --git a/src/main/java/com/faforever/client/chat/ChatController.java b/src/main/java/com/faforever/client/chat/ChatController.java
index 939e8f86..d3b51f7f 100644
--- a/src/main/java/com/faforever/client/chat/ChatController.java
+++ b/src/main/java/com/faforever/client/chat/ChatController.java
@@ -115,7 +115,10 @@ public class ChatController {
 
   private void removeTab(String playerOrChannelName) {
     nameToChatTabController.remove(playerOrChannelName);
-    chatsTabPane.getTabs().remove(nameToChatTabController.remove(playerOrChannelName).getRoot());
+
+    if (nameToChatTabController.containsKey(playerOrChannelName)) {
+      chatsTabPane.getTabs().remove(nameToChatTabController.remove(playerOrChannelName).getRoot());
+    }
   }
 
   private AbstractChatTabController getOrCreateChannelTab(String channelName) {
diff --git a/src/main/java/com/faforever/client/chat/PircBotXChatService.java b/src/main/java/com/faforever/client/chat/PircBotXChatService.java
index 7a8d6a64..8cd14cec 100644
--- a/src/main/java/com/faforever/client/chat/PircBotXChatService.java
+++ b/src/main/java/com/faforever/client/chat/PircBotXChatService.java
@@ -74,15 +74,9 @@ import static javafx.collections.FXCollections.observableHashMap;
 
 public class PircBotXChatService implements ChatService {
 
-  interface ChatEventListener<T> {
-
-    void onEvent(T event);
-  }
-
   private static final Logger logger = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass());
   private static final int SOCKET_TIMEOUT = 10000;
   private final Map<Class<? extends Event>, ArrayList<ChatEventListener>> eventListeners;
-
   /**
    * Maps channels by name.
    */
@@ -121,7 +115,6 @@ public class PircBotXChatService implements ChatService {
   private PircBotX pircBotX;
   private CountDownLatch chatConnectedLatch;
   private Task<Void> connectionTask;
-
   public PircBotXChatService() {
     connectionState = new SimpleObjectProperty<>();
     eventListeners = new ConcurrentHashMap<>();
@@ -236,6 +229,9 @@ public class PircBotXChatService implements ChatService {
 
   private void onChatUserLeftChannel(String channelName, String username) {
     getOrCreateChannel(channelName).removeUser(username);
+    if (userService.getUsername().equalsIgnoreCase(username)) {
+      channels.remove(channelName);
+    }
   }
 
   private void onChatUserQuit(String username) {
@@ -436,7 +432,6 @@ public class PircBotXChatService implements ChatService {
     }
   }
 
-
   @Override
   public void addUsersListener(String channelName, MapChangeListener<String, ChatUser> listener) {
     getOrCreateChannel(channelName).addUsersListeners(listener);
@@ -563,4 +558,9 @@ public class PircBotXChatService implements ChatService {
   public ReadOnlyIntegerProperty unreadMessagesCount() {
     return unreadMessagesCount;
   }
+
+  interface ChatEventListener<T> {
+
+    void onEvent(T event);
+  }
 }
diff --git a/src/test/java/com/faforever/client/chat/PircBotXChatServiceTest.java b/src/test/java/com/faforever/client/chat/PircBotXChatServiceTest.java
index 4bc922ac..494d4dee 100644
--- a/src/test/java/com/faforever/client/chat/PircBotXChatServiceTest.java
+++ b/src/test/java/com/faforever/client/chat/PircBotXChatServiceTest.java
@@ -82,7 +82,9 @@ import static org.hamcrest.Matchers.hasSize;
 import static org.hamcrest.Matchers.nullValue;
 import static org.hamcrest.Matchers.sameInstance;
 import static org.hamcrest.core.Is.is;
-import static org.junit.Assert.*;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertThat;
+import static org.junit.Assert.assertTrue;
 import static org.mockito.Matchers.any;
 import static org.mockito.Matchers.anyString;
 import static org.mockito.Matchers.eq;
@@ -301,7 +303,7 @@ public class PircBotXChatServiceTest extends AbstractPlainJavaFxTest {
     joinChannelLatch.countDown();
 
     SocialMessage socialMessage = new SocialMessage();
-    socialMessage.setChannels(Collections.singletonList(DEFAULT_CHANNEL_NAME));
+    socialMessage.setChannels(Collections.emptyList());
 
     socialMessageListenerCaptor.getValue().accept(socialMessage);
   }
@@ -842,4 +844,54 @@ public class PircBotXChatServiceTest extends AbstractPlainJavaFxTest {
 
     verify(notificationService, never()).addNotification(any(TransientNotification.class));
   }
+
+  @Test
+  public void testRejoinChannel() throws Exception {
+    OutputChannel outputChannel = mock(OutputChannel.class);
+
+    reset(taskService);
+    when(taskService.submitTask(any())).thenReturn(completedFuture(null));
+
+    String channelToJoin = OTHER_CHANNEL_NAME;
+    when(userService.getUsername()).thenReturn("user1");
+    when(userChannelDao.getChannel(channelToJoin)).thenReturn(otherChannel);
+    when(otherChannel.send()).thenReturn(outputChannel);
+    doAnswer(invocation -> {
+      firePircBotXEvent(createJoinEvent(otherChannel, user1));
+      return null;
+    }).when(outputIrc).joinChannel(channelToJoin);
+    doAnswer(invocation -> {
+      firePircBotXEvent(createPartEvent(otherChannel, user1));
+      return null;
+    }).when(outputChannel).part();
+
+    connect();
+    botStartedFuture.get(TIMEOUT, TIMEOUT_UNIT);
+
+    instance.connectionStateProperty().set(ConnectionState.CONNECTED);
+
+    CountDownLatch firstJoinLatch = new CountDownLatch(1);
+    CountDownLatch secondJoinLatch = new CountDownLatch(1);
+    CountDownLatch leaveLatch = new CountDownLatch(1);
+    instance.addChannelsListener(change -> {
+      if (change.wasAdded()) {
+        if (firstJoinLatch.getCount() > 0) {
+          firstJoinLatch.countDown();
+        } else {
+          secondJoinLatch.countDown();
+        }
+      } else if (change.wasRemoved()) {
+        leaveLatch.countDown();
+      }
+    });
+
+    instance.joinChannel(channelToJoin);
+    assertTrue(firstJoinLatch.await(TIMEOUT, TIMEOUT_UNIT));
+
+    instance.leaveChannel(channelToJoin);
+    assertTrue(leaveLatch.await(TIMEOUT, TIMEOUT_UNIT));
+
+    instance.joinChannel(channelToJoin);
+    assertTrue(secondJoinLatch.await(TIMEOUT, TIMEOUT_UNIT));
+  }
 }