@Test
  public void testOnConnected() throws Exception {
    String password = "******";

    when(userService.getPassword()).thenReturn(password);
    instance.connect();

    botStartedFuture.get(TIMEOUT, TIMEOUT_UNIT);

    CountDownLatch latch = new CountDownLatch(1);
    doAnswer(
            invocation -> {
              latch.countDown();
              return null;
            })
        .when(outputIrc)
        .joinChannel(DEFAULT_CHANNEL_NAME);

    mockTaskService();
    instance.connectionStateProperty().set(ConnectionState.CONNECTED);

    String md5Password = Hashing.md5().hashString(password, StandardCharsets.UTF_8).toString();
    verify(outputIrc).message("NICKSERV", String.format("IDENTIFY %s", md5Password));

    assertTrue("Channel has not been joined within timeout", latch.await(TIMEOUT, TIMEOUT_UNIT));
  }
  @Ignore("hangs when run with other tests")
  @Test
  public void testJoinChannel() throws Exception {
    CountDownLatch connectedLatch = new CountDownLatch(1);
    String channelToJoin = "#anotherChannel";
    doAnswer(
            invocation -> {
              connectedLatch.countDown();
              return null;
            })
        .when(outputIrc)
        .joinChannel(DEFAULT_CHANNEL_NAME);

    when(taskService.submitTask(any())).thenReturn(CompletableFuture.completedFuture(null));

    instance.connect();
    instance.connectionStateProperty().set(ConnectionState.CONNECTED);

    assertTrue(connectedLatch.await(TIMEOUT, TIMEOUT_UNIT));

    instance.joinChannel(channelToJoin);

    verify(outputIrc).joinChannel(DEFAULT_CHANNEL_NAME);
    verify(outputIrc).joinChannel(channelToJoin);
  }
  @Test
  public void testOnDisconnected() throws Exception {
    instance.onUserJoinedChannel(DEFAULT_CHANNEL_NAME, chatUser1);
    assertThat(instance.getChatUsersForChannel(DEFAULT_CHANNEL_NAME).values(), hasSize(1));

    instance.connectionStateProperty().set(ConnectionState.DISCONNECTED);

    assertThat(instance.getChatUsersForChannel(DEFAULT_CHANNEL_NAME).values(), empty());
  }
  @Test
  public void testAddOnChatDisconnectedListener() throws Exception {
    CompletableFuture<Void> onChatDisconnectedFuture = new CompletableFuture<>();
    instance
        .connectionStateProperty()
        .addListener(
            (observable, oldValue, newValue) -> {
              switch (newValue) {
                case DISCONNECTED:
                  onChatDisconnectedFuture.complete(null);
                  break;
              }
            });

    instance.onEvent(new DisconnectEvent(pircBotX, daoSnapshot, null));

    onChatDisconnectedFuture.get(TIMEOUT, TIMEOUT_UNIT);
  }
  @Test
  public void testAddOnChatConnectedListener() throws Exception {
    CompletableFuture<Boolean> onChatConnectedFuture = new CompletableFuture<>();

    instance
        .connectionStateProperty()
        .addListener(
            (observable, oldValue, newValue) -> {
              switch (newValue) {
                case CONNECTED:
                  onChatConnectedFuture.complete(null);
                  break;
              }
            });

    String password = "******";
    when(userService.getPassword()).thenReturn(password);

    mockTaskService();

    instance.onEvent(new ConnectEvent(pircBotX));

    assertThat(onChatConnectedFuture.get(TIMEOUT, TIMEOUT_UNIT), is(nullValue()));
  }