@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));
  }
  @Override
  public ObservableList<PlayerAchievement> getPlayerAchievements(String username) {
    if (userService.getUsername().equals(username)) {
      if (readOnlyPlayerAchievements.isEmpty()) {
        updatePlayerAchievementsFromServer();
      }
      return readOnlyPlayerAchievements;
    }

    int playerId = playerService.getPlayerForUsername(username).getId();
    return FXCollections.observableList(fafApiAccessor.getPlayerAchievements(playerId));
  }
  @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()));
  }
  @Before
  public void setUp() throws Exception {
    instance = new PircBotXChatService();
    instance.fafService = fafService;
    instance.userService = userService;
    instance.taskService = taskService;
    instance.i18n = i18n;
    instance.pircBotXFactory = pircBotXFactory;
    instance.preferencesService = preferencesService;
    instance.executorService = executorService;

    chatUser1 = new ChatUser("chatUser1", null);
    chatUser2 = new ChatUser("chatUser2", null);
    loggedInProperty = new SimpleBooleanProperty();

    botShutdownLatch = new CountDownLatch(1);

    userToColorProperty = new SimpleMapProperty<>(FXCollections.observableHashMap());
    chatColorMode = new SimpleObjectProperty<>(CUSTOM);

    when(userService.getUsername()).thenReturn(CHAT_USER_NAME);
    when(userService.getPassword()).thenReturn(CHAT_PASSWORD);
    when(userService.loggedInProperty()).thenReturn(loggedInProperty);

    when(user1.getNick()).thenReturn(chatUser1.getUsername());
    when(user1.getChannels()).thenReturn(ImmutableSortedSet.of(defaultChannel));
    when(user1.getUserLevels(defaultChannel)).thenReturn(ImmutableSortedSet.of(UserLevel.VOICE));

    when(user2.getNick()).thenReturn(chatUser2.getUsername());
    when(user2.getChannels()).thenReturn(ImmutableSortedSet.of(defaultChannel));
    when(user2.getUserLevels(defaultChannel)).thenReturn(ImmutableSortedSet.of(UserLevel.VOICE));

    when(defaultChannel.getName()).thenReturn(DEFAULT_CHANNEL_NAME);
    when(pircBotX.getConfiguration()).thenReturn(configuration);
    when(pircBotX.sendIRC()).thenReturn(outputIrc);
    when(pircBotX.getUserChannelDao()).thenReturn(userChannelDao);

    doAnswer(
            invocation -> {
              CompletableFuture<Object> future = new CompletableFuture<>();
              WaitForAsyncUtils.async(
                  () -> {
                    invocation.getArgumentAt(0, Task.class).run();
                    future.complete(null);
                  });
              return future;
            })
        .when(executorService)
        .submit(any(Task.class));

    botStartedFuture = new CompletableFuture<>();
    doAnswer(
            invocation -> {
              botStartedFuture.complete(true);
              botShutdownLatch.await();
              return null;
            })
        .when(pircBotX)
        .startBot();

    when(pircBotXFactory.createPircBotX(any())).thenReturn(pircBotX);
    when(configuration.getListenerManager()).thenReturn(listenerManager);

    instance.ircHost = LOOPBACK_ADDRESS.getHostAddress();
    instance.ircPort = IRC_SERVER_PORT;
    instance.defaultChannelName = DEFAULT_CHANNEL_NAME;
    instance.reconnectDelay = 100;

    when(preferencesService.getPreferences()).thenReturn(preferences);
    when(preferences.getChat()).thenReturn(chatPrefs);

    when(chatPrefs.userToColorProperty()).thenReturn(userToColorProperty);
    when(chatPrefs.chatColorModeProperty()).thenReturn(chatColorMode);

    instance.postConstruct();
  }
 @Override
 public void onChatUserLeftChannel(String username, String channelName) {
   if (userService.getUsername().equals(username)) {
     chatsTabPane.getTabs().remove(nameToChatTab.get(channelName));
   }
 }
 private boolean isCurrentUser(ChatUser chatUser) {
   return chatUser.getUsername().equals(userService.getUsername());
 }
 private void updatePlayerAchievementsFromServer() {
   playerAchievements.setAll(fafApiAccessor.getPlayerAchievements(userService.getUid()));
 }