chromium/ash/assistant/ui/main_stage/launcher_search_iph_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/assistant/ui/main_stage/launcher_search_iph_view.h"

#include "ash/app_list/test/app_list_test_helper.h"
#include "ash/app_list/views/search_box_view.h"
#include "ash/assistant/test/assistant_ash_test_base.h"
#include "ash/assistant/ui/assistant_view_ids.h"
#include "ash/assistant/ui/main_stage/chip_view.h"
#include "base/memory/raw_ptr.h"
#include "base/run_loop.h"
#include "base/scoped_observation.h"
#include "base/test/scoped_feature_list.h"
#include "components/feature_engagement/public/feature_constants.h"
#include "components/feature_engagement/test/scoped_iph_feature_list.h"
#include "ui/gfx/geometry/size.h"
#include "ui/views/view.h"
#include "ui/views/view_observer.h"

namespace ash {

namespace {

using LauncherSearchIphViewTest = AssistantAshTestBase;

// TODO(b/317900261): Use ash::ViewDrawnWaiter.
bool IsDrawn(views::View* view) {
  return view->IsDrawn() && !view->size().IsEmpty();
}

class ViewDrawnWaiter : public views::ViewObserver {
 public:
  ViewDrawnWaiter() = default;
  ~ViewDrawnWaiter() override = default;

  void Wait(views::View* view) {
    if (IsDrawn(view)) {
      return;
    }

    view_observer_.Observe(view);
    wait_loop_.Run();
  }

 private:
  // views::ViewObserver:
  void OnViewBoundsChanged(views::View* view) override {
    if (IsDrawn(view)) {
      wait_loop_.Quit();
    }
  }

  base::RunLoop wait_loop_;
  base::ScopedObservation<views::View, views::ViewObserver> view_observer_{
      this};
};

}  // namespace

TEST_F(LauncherSearchIphViewTest,
       ShouldShuffleQueriesWhenShowingAssistantPage) {
  base::test::ScopedFeatureList scoped_feature_list(
      feature_engagement::kIPHLauncherSearchHelpUiFeature);

  ShowAssistantUi();
  LauncherSearchIphView* iph_view = static_cast<LauncherSearchIphView*>(
      page_view()->GetViewByID(AssistantViewID::kLauncherSearchIph));
  std::vector<std::u16string> queries_1;
  for (auto chip : iph_view->GetChipsForTesting()) {
    queries_1.emplace_back(chip->GetText());
  }

  // Close and show Assistant UI again.
  CloseAssistantUi();
  ShowAssistantUi();
  std::vector<std::u16string> queries_2;
  for (auto chip : iph_view->GetChipsForTesting()) {
    queries_2.emplace_back(chip->GetText());
  }

  ASSERT_EQ(queries_1.size(), queries_2.size());
  EXPECT_NE(queries_1, queries_2);
}

TEST_F(LauncherSearchIphViewTest, ShouldShuffleQueriesWhenVisible) {
  auto iph_view = std::make_unique<LauncherSearchIphView>(
      /*delegate=*/nullptr, /*is_in_tablet_mode=*/false,
      /*scoped_iph_session=*/nullptr,
      /*location=*/LauncherSearchIphView::UiLocation::kAssistantPage);

  std::vector<std::u16string> queries_1;
  for (auto chip : iph_view->GetChipsForTesting()) {
    queries_1.emplace_back(chip->GetText());
  }

  iph_view->SetVisible(false);
  iph_view->SetVisible(true);
  std::vector<std::u16string> queries_2;
  for (auto chip : iph_view->GetChipsForTesting()) {
    queries_2.emplace_back(chip->GetText());
  }

  ASSERT_EQ(queries_1.size(), queries_2.size());
  EXPECT_NE(queries_1, queries_2);
}

TEST_F(LauncherSearchIphViewTest, ShowFourChipsInAssistantPage) {
  base::test::ScopedFeatureList scoped_feature_list(
      feature_engagement::kIPHLauncherSearchHelpUiFeature);

  ShowAssistantUi();
  LauncherSearchIphView* iph_view = static_cast<LauncherSearchIphView*>(
      page_view()->GetViewByID(AssistantViewID::kLauncherSearchIph));
  int visible_chips = 0;
  for (auto chip : iph_view->GetChipsForTesting()) {
    if (chip->GetVisible()) {
      visible_chips++;
    }
  }
  EXPECT_EQ(4, visible_chips);
}

TEST_F(LauncherSearchIphViewTest, ShowTwoChipsInAssistantPage) {
  base::test::ScopedFeatureList scoped_feature_list(
      feature_engagement::kIPHLauncherSearchHelpUiFeature);

  // Set a testing text to only show two chips.
  std::u16string testing_text = u"Long text for two chips";
  LauncherSearchIphView::SetChipTextForTesting(testing_text);

  ShowAssistantUi();
  LauncherSearchIphView* iph_view = static_cast<LauncherSearchIphView*>(
      page_view()->GetViewByID(AssistantViewID::kLauncherSearchIph));
  int visible_chips = 0;
  for (auto chip : iph_view->GetChipsForTesting()) {
    if (chip->GetVisible()) {
      visible_chips++;
    }
  }
  EXPECT_EQ(2, visible_chips);
}

TEST_F(LauncherSearchIphViewTest, ShowOneChipsInAssistantPage) {
  base::test::ScopedFeatureList scoped_feature_list(
      feature_engagement::kIPHLauncherSearchHelpUiFeature);

  // Set a testing text to only show one chip.
  std::u16string testing_text = u"Very long text to only show one chip";
  LauncherSearchIphView::SetChipTextForTesting(testing_text);

  ShowAssistantUi();
  LauncherSearchIphView* iph_view = static_cast<LauncherSearchIphView*>(
      page_view()->GetViewByID(AssistantViewID::kLauncherSearchIph));
  int visible_chips = 0;
  for (auto chip : iph_view->GetChipsForTesting()) {
    if (chip->GetVisible()) {
      visible_chips++;
    }
  }
  EXPECT_EQ(1, visible_chips);
}

TEST_F(LauncherSearchIphViewTest, AtLeastShowOneChipsInAssistantPage) {
  base::test::ScopedFeatureList scoped_feature_list(
      feature_engagement::kIPHLauncherSearchHelpUiFeature);

  // Set a testing text to only show one chip even the text cannot fix the
  // width.
  std::u16string testing_text =
      u"Very very very very long text cannot fix the width but still show one "
      u"chip";
  LauncherSearchIphView::SetChipTextForTesting(testing_text);

  ShowAssistantUi();
  LauncherSearchIphView* iph_view = static_cast<LauncherSearchIphView*>(
      page_view()->GetViewByID(AssistantViewID::kLauncherSearchIph));
  int visible_chips = 0;
  for (auto chip : iph_view->GetChipsForTesting()) {
    if (chip->GetVisible()) {
      visible_chips++;
    }
  }
  EXPECT_EQ(1, visible_chips);
}

TEST_F(LauncherSearchIphViewTest,
       ShowIphWhenClickingAssistantButtonInSearchBox) {
  GetAppListTestHelper()->search_model()->SetWouldTriggerLauncherSearchIph(
      true);
  GetAppListTestHelper()->ShowAppList();

  SearchBoxView* search_box_view =
      GetAppListTestHelper()->GetBubbleSearchBoxView();
  LeftClickOn(search_box_view->assistant_button());

  LauncherSearchIphView* iph_view = static_cast<LauncherSearchIphView*>(
      search_box_view->GetViewByID(LauncherSearchIphView::ViewId::kSelf));
  EXPECT_TRUE(!!iph_view);
  EXPECT_TRUE(iph_view->GetVisible());
}

TEST_F(LauncherSearchIphViewTest,
       ShowThreeQueryChipsAndAssistantChipInSearchBox) {
  // Set a testing text to show three chips.
  std::u16string testing_text = u"Text";
  LauncherSearchIphView::SetChipTextForTesting(testing_text);

  GetAppListTestHelper()->search_model()->SetWouldTriggerLauncherSearchIph(
      true);
  GetAppListTestHelper()->ShowAppList();

  SearchBoxView* search_box_view =
      GetAppListTestHelper()->GetBubbleSearchBoxView();
  LeftClickOn(search_box_view->assistant_button());

  LauncherSearchIphView* iph_view = static_cast<LauncherSearchIphView*>(
      search_box_view->GetViewByID(LauncherSearchIphView::ViewId::kSelf));
  ViewDrawnWaiter().Wait(iph_view);

  int visible_chips = 0;
  for (auto chip : iph_view->GetChipsForTesting()) {
    if (chip->GetVisible()) {
      visible_chips++;
    }
  }
  EXPECT_EQ(3, visible_chips);

  EXPECT_TRUE(!!iph_view->GetAssistantButtonForTesting());
  EXPECT_TRUE(iph_view->GetAssistantButtonForTesting()->GetVisible());
}

TEST_F(LauncherSearchIphViewTest, ShowOneQueryChipAndAssistantChipInSearchBox) {
  // Set a testing text to only show one chip.
  std::u16string testing_text = u"Very long text to show only one chip";
  LauncherSearchIphView::SetChipTextForTesting(testing_text);

  GetAppListTestHelper()->search_model()->SetWouldTriggerLauncherSearchIph(
      true);
  GetAppListTestHelper()->ShowAppList();

  SearchBoxView* search_box_view =
      GetAppListTestHelper()->GetBubbleSearchBoxView();
  LeftClickOn(search_box_view->assistant_button());

  LauncherSearchIphView* iph_view = static_cast<LauncherSearchIphView*>(
      search_box_view->GetViewByID(LauncherSearchIphView::ViewId::kSelf));
  ViewDrawnWaiter().Wait(iph_view);

  int visible_chips = 0;
  for (auto chip : iph_view->GetChipsForTesting()) {
    if (chip->GetVisible()) {
      visible_chips++;
    }
  }
  EXPECT_EQ(1, visible_chips);

  EXPECT_TRUE(!!iph_view->GetAssistantButtonForTesting());
  EXPECT_TRUE(iph_view->GetAssistantButtonForTesting()->GetVisible());
}

TEST_F(LauncherSearchIphViewTest, AtLeastShowOneQueryChipInSearchBox) {
  // Set a testing text to only show one chip even the text cannot fix the
  // width.
  std::u16string testing_text =
      u"Very very very very long text cannot fix the width but still show one "
      u"chip";
  LauncherSearchIphView::SetChipTextForTesting(testing_text);

  GetAppListTestHelper()->search_model()->SetWouldTriggerLauncherSearchIph(
      true);
  GetAppListTestHelper()->ShowAppList();

  SearchBoxView* search_box_view =
      GetAppListTestHelper()->GetBubbleSearchBoxView();
  LeftClickOn(search_box_view->assistant_button());

  LauncherSearchIphView* iph_view = static_cast<LauncherSearchIphView*>(
      search_box_view->GetViewByID(LauncherSearchIphView::ViewId::kSelf));
  ViewDrawnWaiter().Wait(iph_view);

  int visible_chips = 0;
  for (auto chip : iph_view->GetChipsForTesting()) {
    if (chip->GetVisible()) {
      visible_chips++;
    }
  }
  EXPECT_EQ(1, visible_chips);

  EXPECT_TRUE(!!iph_view->GetAssistantButtonForTesting());
  EXPECT_TRUE(iph_view->GetAssistantButtonForTesting()->GetVisible());
}

}  // namespace ash