chromium/ash/system/ime/ime_feature_pod_controller_unittest.cc

// Copyright 2018 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "ash/system/ime/ime_feature_pod_controller.h"

#include <string>
#include <vector>

#include "ash/constants/quick_settings_catalogs.h"
#include "ash/ime/ime_controller_impl.h"
#include "ash/shell.h"
#include "ash/system/unified/feature_tile.h"
#include "ash/system/unified/unified_system_tray.h"
#include "ash/system/unified/unified_system_tray_bubble.h"
#include "ash/system/unified/unified_system_tray_controller.h"
#include "ash/test/ash_test_base.h"
#include "base/strings/string_number_conversions.h"
#include "base/strings/utf_string_conversions.h"
#include "base/test/metrics/histogram_tester.h"
#include "base/test/scoped_feature_list.h"
#include "testing/gtest/include/gtest/gtest.h"

namespace ash {

// Tests manually control their session state.
class IMEFeaturePodControllerTest : public NoSessionAshTestBase {
 public:
  IMEFeaturePodControllerTest() = default;

  IMEFeaturePodControllerTest(const IMEFeaturePodControllerTest&) = delete;
  IMEFeaturePodControllerTest& operator=(const IMEFeaturePodControllerTest&) =
      delete;

  ~IMEFeaturePodControllerTest() override = default;

  void SetUp() override {
    NoSessionAshTestBase::SetUp();

    GetPrimaryUnifiedSystemTray()->ShowBubble();
  }

  void TearDown() override {
    tile_.reset();
    controller_.reset();
    NoSessionAshTestBase::TearDown();
  }

 protected:
  void SetUpButton() {
    controller_ = std::make_unique<IMEFeaturePodController>(tray_controller());
    tile_ = controller_->CreateTile();
  }

  UnifiedSystemTrayController* tray_controller() {
    return GetPrimaryUnifiedSystemTray()
        ->bubble()
        ->unified_system_tray_controller();
  }

  bool IsButtonVisible() { return tile_->GetVisible(); }

  const std::u16string GetTooltipText() { return tile_->GetTooltipText(); }

  const char* GetToggledOnHistogramName() {
    return "Ash.QuickSettings.FeaturePod.ToggledOn";
  }

  const char* GetToggledOffHistogramName() {
    return "Ash.QuickSettings.FeaturePod.ToggledOff";
  }

  const char* GetDiveInHistogramName() {
    return "Ash.QuickSettings.FeaturePod.DiveIn";
  }

  // Creates |count| simulated active IMEs.
  void SetActiveIMECount(int count) {
    available_imes_.resize(count);
    for (int i = 0; i < count; ++i) {
      available_imes_[i].id = base::NumberToString(i);
    }
    RefreshImeController();
  }

  void RefreshImeController() {
    std::vector<ImeInfo> available_imes;
    for (const auto& ime : available_imes_) {
      available_imes.push_back(ime);
    }

    std::vector<ImeMenuItem> menu_items;
    for (const auto& item : menu_items_) {
      menu_items_.push_back(item);
    }

    Shell::Get()->ime_controller()->RefreshIme(
        current_ime_.id, std::move(available_imes), std::move(menu_items));
  }

  void PressIcon() { controller_->OnIconPressed(); }

  void PressLabel() { controller_->OnLabelPressed(); }

  std::unique_ptr<IMEFeaturePodController> controller_;
  std::unique_ptr<FeatureTile> tile_;

  // IMEs
  ImeInfo current_ime_;
  std::vector<ImeInfo> available_imes_;
  std::vector<ImeMenuItem> menu_items_;
};

TEST_F(IMEFeaturePodControllerTest, Labels) {
  SetUpButton();

  std::u16string label = tile_->label()->GetText();

  EXPECT_EQ(label, u"Keyboard");

  SetActiveIMECount(2);
  current_ime_.id = "0";
  available_imes_[0].short_name = u"US";
  available_imes_[1].short_name = u"FR";
  RefreshImeController();
  std::u16string sub_label = tile_->sub_label()->GetText();
  EXPECT_EQ(sub_label, u"US");
}

// Tests that if the pod button is hidden if less than 2 IMEs are present.
TEST_F(IMEFeaturePodControllerTest, ButtonVisibilityIMECount) {
  SetUpButton();

  SetActiveIMECount(0);
  EXPECT_FALSE(IsButtonVisible());
  SetActiveIMECount(1);
  EXPECT_FALSE(IsButtonVisible());
  SetActiveIMECount(2);
  EXPECT_TRUE(IsButtonVisible());
}

TEST_F(IMEFeaturePodControllerTest, ButtonVisibilityImeMenuActive) {
  SetUpButton();
  Shell::Get()->ime_controller()->ShowImeMenuOnShelf(true);

  SetActiveIMECount(0);
  EXPECT_FALSE(IsButtonVisible());
  SetActiveIMECount(1);
  EXPECT_FALSE(IsButtonVisible());
  SetActiveIMECount(2);
  EXPECT_FALSE(IsButtonVisible());
}

TEST_F(IMEFeaturePodControllerTest, ButtonVisibilityPolicy) {
  SetUpButton();

  Shell::Get()->ime_controller()->SetImesManagedByPolicy(true);

  SetActiveIMECount(0);
  EXPECT_TRUE(IsButtonVisible());
  SetActiveIMECount(1);
  EXPECT_TRUE(IsButtonVisible());
  SetActiveIMECount(2);
  EXPECT_TRUE(IsButtonVisible());
}

// TODO(crbug.com/40893381): Test is failing on "Linux ChromiumOS MSan Tests".
#if defined(MEMORY_SANITIZER)
#define MAYBE_IconUMATracking DISABLED_IconUMATracking
#else
#define MAYBE_IconUMATracking IconUMATracking
#endif
TEST_F(IMEFeaturePodControllerTest, MAYBE_IconUMATracking) {
  SetUpButton();

  // No metrics logged before clicking on any views.
  auto histogram_tester = std::make_unique<base::HistogramTester>();
  histogram_tester->ExpectTotalCount(GetToggledOnHistogramName(),
                                     /*expected_count=*/0);
  histogram_tester->ExpectTotalCount(GetToggledOffHistogramName(),
                                     /*expected_count=*/0);
  histogram_tester->ExpectTotalCount(GetDiveInHistogramName(),
                                     /*expected_count=*/0);

  // Show IME detailed view when pressing on the icon.
  PressIcon();
  histogram_tester->ExpectTotalCount(GetToggledOnHistogramName(),
                                     /*expected_count=*/0);
  histogram_tester->ExpectTotalCount(GetToggledOffHistogramName(),
                                     /*expected_count=*/0);
  histogram_tester->ExpectTotalCount(GetDiveInHistogramName(),
                                     /*expected_count=*/1);
  histogram_tester->ExpectBucketCount(GetDiveInHistogramName(),
                                      QsFeatureCatalogName::kIME,
                                      /*expected_count=*/1);
}

TEST_F(IMEFeaturePodControllerTest, LabelUMATracking) {
  SetUpButton();

  // No metrics logged before clicking on any views.
  auto histogram_tester = std::make_unique<base::HistogramTester>();
  histogram_tester->ExpectTotalCount(GetToggledOnHistogramName(),
                                     /*expected_count=*/0);
  histogram_tester->ExpectTotalCount(GetToggledOffHistogramName(),
                                     /*expected_count=*/0);
  histogram_tester->ExpectTotalCount(GetDiveInHistogramName(),
                                     /*expected_count=*/0);

  // Show IME detailed view when pressing on the label.
  PressLabel();
  histogram_tester->ExpectTotalCount(GetToggledOnHistogramName(),
                                     /*expected_count=*/0);
  histogram_tester->ExpectTotalCount(GetToggledOffHistogramName(),
                                     /*expected_count=*/0);
  histogram_tester->ExpectTotalCount(GetDiveInHistogramName(),
                                     /*expected_count=*/1);
  histogram_tester->ExpectBucketCount(GetDiveInHistogramName(),
                                      QsFeatureCatalogName::kIME,
                                      /*expected_count=*/1);
}

// Tests the tooltip changes after the IME refreshes.
TEST_F(IMEFeaturePodControllerTest, TooltipText) {
  SetUpButton();

  SetActiveIMECount(2);
  current_ime_.id = "0";
  available_imes_[0].name = u"English";
  available_imes_[1].name = u"French";

  RefreshImeController();
  std::u16string tooltip = GetTooltipText();
  EXPECT_EQ(tooltip, u"Show keyboard settings. English is selected.");

  // Switches the current ime to the second one in `available_imes_`.
  current_ime_.id = "1";
  RefreshImeController();
  tooltip = GetTooltipText();
  EXPECT_EQ(tooltip, u"Show keyboard settings. French is selected.");
}

}  // namespace ash