chromium/ash/system/video_conference/bubble/toggle_effects_view_unittest.cc

// Copyright 2023 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/video_conference/bubble/toggle_effects_view.h"

#include "ash/constants/ash_features.h"
#include "ash/constants/ash_switches.h"
#include "ash/resources/vector_icons/vector_icons.h"
#include "ash/strings/grit/ash_strings.h"
#include "ash/style/icon_button.h"
#include "ash/system/status_area_widget.h"
#include "ash/system/status_area_widget_test_helper.h"
#include "ash/system/video_conference/bubble/bubble_view.h"
#include "ash/system/video_conference/bubble/bubble_view_ids.h"
#include "ash/system/video_conference/effects/fake_video_conference_effects.h"
#include "ash/system/video_conference/effects/video_conference_tray_effects_manager_types.h"
#include "ash/system/video_conference/fake_video_conference_tray_controller.h"
#include "ash/system/video_conference/video_conference_tray.h"
#include "ash/test/ash_test_base.h"
#include "base/test/metrics/histogram_tester.h"
#include "base/test/scoped_feature_list.h"
#include "chromeos/ash/components/dbus/dlcservice/dlcservice_client.h"
#include "chromeos/constants/chromeos_features.h"
#include "ui/base/l10n/l10n_util.h"
#include "ui/views/controls/image_view.h"

namespace ash::video_conference {

namespace {
constexpr char kTestEffectHistogramName[] =
    "Ash.VideoConferenceTray.TestEffect.Click";
}  // namespace

class ToggleEffectsViewTest
    : public AshTestBase,
      public testing::WithParamInterface</*IsVcDlcUiEnabled*/ bool> {
 public:
  ToggleEffectsViewTest() = default;
  ToggleEffectsViewTest(const ToggleEffectsViewTest&) = delete;
  ToggleEffectsViewTest& operator=(const ToggleEffectsViewTest&) = delete;
  ~ToggleEffectsViewTest() override = default;

  // AshTestBase:
  void SetUp() override {
    std::vector<base::test::FeatureRef> enabled_features = {
        features::kFeatureManagementVideoConference,
        chromeos::features::kJelly};
    if (IsVcDlcUiEnabled()) {
      enabled_features.push_back(features::kVcDlcUi);
    }
    scoped_feature_list_.InitWithFeatures(enabled_features,
                                          /*disabled_features=*/{});

    if (IsVcDlcUiEnabled()) {
      DlcserviceClient::InitializeFake();
    }

    // Instantiates a fake controller (the real one is created in
    // `ChromeBrowserMainExtraPartsAsh::PreProfileInit()` which is not called in
    // ash unit tests).
    controller_ = std::make_unique<FakeVideoConferenceTrayController>();

    office_bunny_ =
        std::make_unique<fake_video_conference::OfficeBunnyEffect>();

    AshTestBase::SetUp();

    // Make the video conference tray visible for testing.
    video_conference_tray()->SetVisiblePreferred(true);
  }

  void TearDown() override {
    AshTestBase::TearDown();
    office_bunny_.reset();
    controller_.reset();
    if (IsVcDlcUiEnabled()) {
      DlcserviceClient::Shutdown();
    }
  }

  bool IsVcDlcUiEnabled() { return GetParam(); }

  VideoConferenceTray* video_conference_tray() {
    return StatusAreaWidgetTestHelper::GetStatusAreaWidget()
        ->video_conference_tray();
  }

  IconButton* toggle_bubble_button() {
    return video_conference_tray()->toggle_bubble_button_;
  }

  views::View* bubble_view() {
    return video_conference_tray()->GetBubbleView();
  }

  FakeVideoConferenceTrayController* controller() { return controller_.get(); }

  // Each toggle button in the bubble view has this view ID, this just gets the
  // first one in the view tree.
  views::Button* GetFirstToggleEffectButton() {
    return static_cast<views::Button*>(bubble_view()->GetViewByID(
        video_conference::BubbleViewID::kToggleEffectsButton));
  }

  // Each toggle button icon in a toggle button has this view ID, this just gets
  // the first one in the view tree.
  views::ImageView* GetFirstToggleEffectIcon() {
    return static_cast<views::ImageView*>(bubble_view()->GetViewByID(
        video_conference::BubbleViewID::kToggleEffectIcon));
  }

  ash::fake_video_conference::OfficeBunnyEffect* office_bunny() {
    return office_bunny_.get();
  }

 private:
  base::test::ScopedFeatureList scoped_feature_list_;
  std::unique_ptr<FakeVideoConferenceTrayController> controller_;
  std::unique_ptr<ash::fake_video_conference::OfficeBunnyEffect> office_bunny_;
};

INSTANTIATE_TEST_SUITE_P(IsVcDlcUiEnabled,
                         ToggleEffectsViewTest,
                         testing::Bool());

// Tests that a toggle button records histograms when clicked.
TEST_P(ToggleEffectsViewTest, ToggleButtonClickedRecordedHistogram) {
  base::HistogramTester histogram_tester;

  // Add one toggle effect.
  controller()->GetEffectsManager().RegisterDelegate(office_bunny());

  // Click to open the bubble, toggle effect button should be visible.
  LeftClickOn(toggle_bubble_button());
  ASSERT_TRUE(GetFirstToggleEffectButton());
  ASSERT_TRUE(GetFirstToggleEffectButton()->GetVisible());

  // Click the toggle effect button, verify that metrics is recorded.
  LeftClickOn(GetFirstToggleEffectButton());
  histogram_tester.ExpectBucketCount(kTestEffectHistogramName, true, 1);

  // Click again.
  LeftClickOn(GetFirstToggleEffectButton());
  histogram_tester.ExpectBucketCount(kTestEffectHistogramName, false, 1);

  // Cleanup.
  controller()->GetEffectsManager().UnregisterDelegate(office_bunny());
}

// Tests that a toggled ToggleButton's tooltip is updated.
TEST_P(ToggleEffectsViewTest, TooltipIsUpdated) {
  // Add one toggle effect.
  controller()->GetEffectsManager().RegisterDelegate(office_bunny());
  LeftClickOn(toggle_bubble_button());

  EXPECT_EQ(
      GetFirstToggleEffectButton()->GetTooltipText(),
      l10n_util::GetStringFUTF16(
          VIDEO_CONFERENCE_TOGGLE_BUTTON_TOOLTIP,
          l10n_util::GetStringUTF16(IDS_PRIVACY_INDICATORS_STATUS_CAMERA),
          l10n_util::GetStringUTF16(VIDEO_CONFERENCE_TOGGLE_BUTTON_STATE_OFF)));

  // Toggle it on, the tooltip should update.
  LeftClickOn(GetFirstToggleEffectButton());

  EXPECT_EQ(
      GetFirstToggleEffectButton()->GetTooltipText(),
      l10n_util::GetStringFUTF16(
          VIDEO_CONFERENCE_TOGGLE_BUTTON_TOOLTIP,
          l10n_util::GetStringUTF16(IDS_PRIVACY_INDICATORS_STATUS_CAMERA),
          l10n_util::GetStringUTF16(VIDEO_CONFERENCE_TOGGLE_BUTTON_STATE_ON)));

  // Cleanup.
  controller()->GetEffectsManager().UnregisterDelegate(office_bunny());
}

}  // namespace ash::video_conference