// 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/picker/views/picker_search_results_view.h"
#include <optional>
#include <string>
#include "ash/picker/mock_picker_asset_fetcher.h"
#include "ash/picker/model/picker_search_results_section.h"
#include "ash/picker/picker_test_util.h"
#include "ash/picker/views/mock_picker_search_results_view_delegate.h"
#include "ash/picker/views/picker_item_view.h"
#include "ash/picker/views/picker_list_item_view.h"
#include "ash/picker/views/picker_preview_bubble_controller.h"
#include "ash/picker/views/picker_pseudo_focus.h"
#include "ash/picker/views/picker_search_results_view_delegate.h"
#include "ash/picker/views/picker_section_list_view.h"
#include "ash/picker/views/picker_section_view.h"
#include "ash/picker/views/picker_skeleton_loader_view.h"
#include "ash/picker/views/picker_strings.h"
#include "ash/picker/views/picker_submenu_controller.h"
#include "ash/picker/views/picker_traversable_item_container.h"
#include "ash/public/cpp/picker/picker_search_result.h"
#include "ash/strings/grit/ash_strings.h"
#include "ash/style/ash_color_provider.h"
#include "ash/test/view_drawn_waiter.h"
#include "base/files/file_path.h"
#include "base/functional/callback_helpers.h"
#include "base/test/task_environment.h"
#include "base/test/test_future.h"
#include "testing/gmock/include/gmock/gmock-matchers.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "ui/base/l10n/l10n_util.h"
#include "ui/compositor/layer.h"
#include "ui/compositor/layer_animator.h"
#include "ui/compositor/scoped_animation_duration_scale_mode.h"
#include "ui/gfx/image/image_unittest_util.h"
#include "ui/views/accessibility/ax_event_manager.h"
#include "ui/views/controls/label.h"
#include "ui/views/test/ax_event_counter.h"
#include "ui/views/test/views_test_base.h"
#include "ui/views/view_utils.h"
#include "ui/views/widget/widget.h"
#include "url/gurl.h"
namespace ash {
namespace {
using ::testing::_;
using ::testing::AllOf;
using ::testing::ElementsAre;
using ::testing::IsEmpty;
using ::testing::IsNull;
using ::testing::Not;
using ::testing::NotNull;
using ::testing::Pointee;
using ::testing::Property;
using ::testing::ResultOf;
using ::testing::SizeIs;
using ::testing::VariantWith;
constexpr int kPickerWidth = 320;
class PickerSearchResultsViewTest : public views::ViewsTestBase {
public:
PickerSearchResultsViewTest()
: views::ViewsTestBase(
base::test::TaskEnvironment::TimeSource::MOCK_TIME) {}
};
template <class V, class Matcher>
auto AsView(Matcher matcher) {
return ResultOf(
"AsViewClass",
[](views::View* view) { return views::AsViewClass<V>(view); },
Pointee(matcher));
}
auto MatchesTitlelessSection(int num_items) {
return AllOf(
Property(&PickerSectionView::title_label_for_testing, nullptr),
Property(&PickerSectionView::item_views_for_testing, SizeIs(num_items)));
}
auto MatchesResultSection(PickerSectionType section_type, int num_items) {
return AllOf(
Property(&PickerSectionView::title_label_for_testing,
Property(&views::Label::GetText,
GetSectionTitleForPickerSectionType(section_type))),
Property(&PickerSectionView::item_views_for_testing, SizeIs(num_items)));
}
template <class Matcher>
auto MatchesResultSectionWithOneItem(PickerSectionType section_type,
Matcher item_matcher) {
return AllOf(
Property(&PickerSectionView::title_label_for_testing,
Property(&views::Label::GetText,
GetSectionTitleForPickerSectionType(section_type))),
Property(&PickerSectionView::item_views_for_testing,
ElementsAre(item_matcher)));
}
TEST_F(PickerSearchResultsViewTest, CreatesResultsSections) {
MockPickerSearchResultsViewDelegate mock_delegate;
MockPickerAssetFetcher asset_fetcher;
PickerSubmenuController submenu_controller;
PickerPreviewBubbleController preview_controller;
PickerSearchResultsView view(&mock_delegate, kPickerWidth, &asset_fetcher,
&submenu_controller, &preview_controller);
view.AppendSearchResults(PickerSearchResultsSection(
PickerSectionType::kNone,
{{PickerTextResult(u"Result A"), PickerTextResult(u"Result B")}},
/*has_more_results=*/false));
view.AppendSearchResults(PickerSearchResultsSection(
PickerSectionType::kLocalFiles,
{{PickerLocalFileResult(u"Result C", base::FilePath())}},
/*has_more_results=*/false));
EXPECT_THAT(view.section_list_view_for_testing()->children(), SizeIs(2));
EXPECT_THAT(view.section_views_for_testing(),
ElementsAre(Pointee(MatchesTitlelessSection(2)),
Pointee(MatchesResultSection(
PickerSectionType::kLocalFiles, 1))));
}
TEST_F(PickerSearchResultsViewTest, ClearSearchResultsClearsView) {
MockPickerSearchResultsViewDelegate mock_delegate;
MockPickerAssetFetcher asset_fetcher;
PickerSubmenuController submenu_controller;
PickerPreviewBubbleController preview_controller;
PickerSearchResultsView view(&mock_delegate, kPickerWidth, &asset_fetcher,
&submenu_controller, &preview_controller);
view.AppendSearchResults(PickerSearchResultsSection(
PickerSectionType::kClipboard, {{PickerTextResult(u"Result")}},
/*has_more_results=*/false));
view.ClearSearchResults();
EXPECT_THAT(view.section_list_view_for_testing()->children(), IsEmpty());
}
TEST_F(PickerSearchResultsViewTest, EmptySearchResultsShowsThrobber) {
MockPickerSearchResultsViewDelegate mock_delegate;
MockPickerAssetFetcher asset_fetcher;
PickerSubmenuController submenu_controller;
PickerPreviewBubbleController preview_controller;
PickerSearchResultsView view(&mock_delegate, kPickerWidth, &asset_fetcher,
&submenu_controller, &preview_controller);
view.AppendSearchResults(PickerSearchResultsSection(
PickerSectionType::kClipboard, {{PickerTextResult(u"Result")}},
/*has_more_results=*/false));
view.ClearSearchResults();
EXPECT_TRUE(view.throbber_container_for_testing().GetVisible());
}
TEST_F(PickerSearchResultsViewTest, CreatesResultsSectionWithCategories) {
MockPickerSearchResultsViewDelegate mock_delegate;
MockPickerAssetFetcher asset_fetcher;
PickerSubmenuController submenu_controller;
PickerPreviewBubbleController preview_controller;
PickerSearchResultsView view(&mock_delegate, kPickerWidth, &asset_fetcher,
&submenu_controller, &preview_controller);
view.AppendSearchResults(PickerSearchResultsSection(
PickerSectionType::kNone,
{{PickerCategoryResult(PickerCategory::kEmojisGifs)}},
/*has_more_results=*/false));
EXPECT_THAT(view.section_list_view_for_testing()->children(), SizeIs(1));
EXPECT_THAT(view.section_views_for_testing(),
ElementsAre(Pointee(MatchesTitlelessSection(1))));
}
TEST_F(PickerSearchResultsViewTest, CreatesResultsSectionWithLocalFiles) {
MockPickerSearchResultsViewDelegate mock_delegate;
MockPickerAssetFetcher asset_fetcher;
PickerSubmenuController submenu_controller;
PickerPreviewBubbleController preview_controller;
PickerSearchResultsView view(&mock_delegate, kPickerWidth, &asset_fetcher,
&submenu_controller, &preview_controller);
view.AppendSearchResults(PickerSearchResultsSection(
PickerSectionType::kLocalFiles,
{{PickerLocalFileResult(u"local", base::FilePath())}},
/*has_more_results=*/false));
EXPECT_THAT(view.section_list_view_for_testing()->children(), SizeIs(1));
EXPECT_THAT(
view.section_views_for_testing(),
ElementsAre(Pointee(MatchesResultSectionWithOneItem(
PickerSectionType::kLocalFiles,
AsView<PickerListItemView>(Property(
&PickerListItemView::GetPrimaryTextForTesting, u"local"))))));
}
TEST_F(PickerSearchResultsViewTest, CreatesResultsSectionWithDriveFiles) {
MockPickerSearchResultsViewDelegate mock_delegate;
MockPickerAssetFetcher asset_fetcher;
PickerSubmenuController submenu_controller;
PickerPreviewBubbleController preview_controller;
PickerSearchResultsView view(&mock_delegate, kPickerWidth, &asset_fetcher,
&submenu_controller, &preview_controller);
view.AppendSearchResults(PickerSearchResultsSection(
PickerSectionType::kLocalFiles,
{{PickerDriveFileResult(/*id=*/std::nullopt, u"drive", GURL(),
base::FilePath())}},
/*has_more_results=*/false));
EXPECT_THAT(view.section_list_view_for_testing()->children(), SizeIs(1));
EXPECT_THAT(
view.section_views_for_testing(),
ElementsAre(Pointee(MatchesResultSectionWithOneItem(
PickerSectionType::kLocalFiles,
AsView<PickerListItemView>(Property(
&PickerListItemView::GetPrimaryTextForTesting, u"drive"))))));
}
TEST_F(PickerSearchResultsViewTest, UpdatesResultsSections) {
MockPickerSearchResultsViewDelegate mock_delegate;
MockPickerAssetFetcher asset_fetcher;
PickerSubmenuController submenu_controller;
PickerPreviewBubbleController preview_controller;
PickerSearchResultsView view(&mock_delegate, kPickerWidth, &asset_fetcher,
&submenu_controller, &preview_controller);
view.AppendSearchResults(PickerSearchResultsSection(
PickerSectionType::kLocalFiles,
{{PickerLocalFileResult(u"Result", base::FilePath())}},
/*has_more_results=*/false));
view.AppendSearchResults(PickerSearchResultsSection(
PickerSectionType::kNone, {{PickerTextResult(u"New Result")}},
/*has_more_results=*/false));
EXPECT_THAT(view.section_list_view_for_testing()->children(), SizeIs(2));
EXPECT_THAT(view.section_views_for_testing(),
ElementsAre(Pointee(MatchesResultSection(
PickerSectionType::kLocalFiles, 1)),
Pointee(MatchesTitlelessSection(1))));
}
TEST_F(PickerSearchResultsViewTest, GetsTopItem) {
MockPickerSearchResultsViewDelegate mock_delegate;
MockPickerAssetFetcher asset_fetcher;
PickerSubmenuController submenu_controller;
PickerPreviewBubbleController preview_controller;
PickerSearchResultsView view(&mock_delegate, kPickerWidth, &asset_fetcher,
&submenu_controller, &preview_controller);
EXPECT_CALL(mock_delegate, SelectSearchResult(VariantWith<PickerTextResult>(
PickerTextResult(u"Result A"))));
view.AppendSearchResults(PickerSearchResultsSection(
PickerSectionType::kClipboard,
{{PickerTextResult(u"Result A"), PickerTextResult(u"Result B")}},
/*has_more_results=*/false));
EXPECT_TRUE(DoPickerPseudoFocusedActionOnView(view.GetTopItem()));
}
TEST_F(PickerSearchResultsViewTest, GetsBottomItem) {
MockPickerSearchResultsViewDelegate mock_delegate;
MockPickerAssetFetcher asset_fetcher;
PickerSubmenuController submenu_controller;
PickerPreviewBubbleController preview_controller;
PickerSearchResultsView view(&mock_delegate, kPickerWidth, &asset_fetcher,
&submenu_controller, &preview_controller);
EXPECT_CALL(mock_delegate, SelectSearchResult(VariantWith<PickerTextResult>(
PickerTextResult(u"Result B"))));
view.AppendSearchResults(PickerSearchResultsSection(
PickerSectionType::kClipboard,
{{PickerTextResult(u"Result A"), PickerTextResult(u"Result B")}},
/*has_more_results=*/false));
EXPECT_TRUE(DoPickerPseudoFocusedActionOnView(view.GetBottomItem()));
}
TEST_F(PickerSearchResultsViewTest, GetsItemAbove) {
MockPickerSearchResultsViewDelegate mock_delegate;
MockPickerAssetFetcher asset_fetcher;
PickerSubmenuController submenu_controller;
PickerPreviewBubbleController preview_controller;
PickerSearchResultsView view(&mock_delegate, kPickerWidth, &asset_fetcher,
&submenu_controller, &preview_controller);
view.AppendSearchResults(PickerSearchResultsSection(
PickerSectionType::kNone,
{{PickerCategoryResult(PickerCategory::kLinks),
PickerCategoryResult(PickerCategory::kClipboard)}},
/*has_more_results=*/false));
EXPECT_CALL(mock_delegate,
SelectSearchResult(VariantWith<PickerCategoryResult>(
PickerCategoryResult(PickerCategory::kLinks))));
EXPECT_TRUE(DoPickerPseudoFocusedActionOnView(
view.GetItemAbove(view.GetBottomItem())));
}
TEST_F(PickerSearchResultsViewTest, GetsItemBelow) {
MockPickerSearchResultsViewDelegate mock_delegate;
MockPickerAssetFetcher asset_fetcher;
PickerSubmenuController submenu_controller;
PickerPreviewBubbleController preview_controller;
PickerSearchResultsView view(&mock_delegate, kPickerWidth, &asset_fetcher,
&submenu_controller, &preview_controller);
view.AppendSearchResults(PickerSearchResultsSection(
PickerSectionType::kNone,
{{PickerCategoryResult(PickerCategory::kLinks),
PickerCategoryResult(PickerCategory::kClipboard)}},
/*has_more_results=*/false));
EXPECT_CALL(mock_delegate,
SelectSearchResult(VariantWith<PickerCategoryResult>(
PickerCategoryResult(PickerCategory::kClipboard))));
EXPECT_TRUE(
DoPickerPseudoFocusedActionOnView(view.GetItemBelow(view.GetTopItem())));
}
TEST_F(PickerSearchResultsViewTest, ShowsSeeMoreLinkWhenThereAreMoreResults) {
std::unique_ptr<views::Widget> widget =
CreateTestWidget(views::Widget::InitParams::CLIENT_OWNS_WIDGET);
MockPickerSearchResultsViewDelegate mock_delegate;
MockPickerAssetFetcher asset_fetcher;
PickerSubmenuController submenu_controller;
PickerPreviewBubbleController preview_controller;
auto* view =
widget->SetContentsView(std::make_unique<PickerSearchResultsView>(
&mock_delegate, kPickerWidth, &asset_fetcher, &submenu_controller,
&preview_controller));
view->AppendSearchResults(PickerSearchResultsSection(
PickerSectionType::kLocalFiles, {}, /*has_more_results=*/true));
ASSERT_THAT(
view->section_views_for_testing(),
ElementsAre(Pointee(Property(
"title_trailing_link_for_testing",
&PickerSectionView::title_trailing_link_for_testing,
Property(
&views::View::GetAccessibleName,
l10n_util::GetStringUTF16(
IDS_PICKER_SEE_MORE_LOCAL_FILES_BUTTON_ACCESSIBLE_NAME))))));
}
TEST_F(PickerSearchResultsViewTest,
DoesNotShowSeeMoreLinkWhenThereAreNoMoreResults) {
std::unique_ptr<views::Widget> widget =
CreateTestWidget(views::Widget::InitParams::CLIENT_OWNS_WIDGET);
MockPickerSearchResultsViewDelegate mock_delegate;
MockPickerAssetFetcher asset_fetcher;
PickerSubmenuController submenu_controller;
PickerPreviewBubbleController preview_controller;
auto* view =
widget->SetContentsView(std::make_unique<PickerSearchResultsView>(
&mock_delegate, kPickerWidth, &asset_fetcher, &submenu_controller,
&preview_controller));
view->AppendSearchResults(PickerSearchResultsSection(
PickerSectionType::kLocalFiles, {}, /*has_more_results=*/false));
ASSERT_THAT(
view->section_views_for_testing(),
ElementsAre(Pointee(Property(
"title_trailing_link_for_testing",
&PickerSectionView::title_trailing_link_for_testing, IsNull()))));
}
TEST_F(PickerSearchResultsViewTest, ClickingSeeMoreLinkCallsCallback) {
std::unique_ptr<views::Widget> widget =
CreateTestWidget(views::Widget::InitParams::CLIENT_OWNS_WIDGET);
widget->SetFullscreen(true);
MockPickerSearchResultsViewDelegate mock_delegate;
MockPickerAssetFetcher asset_fetcher;
PickerSubmenuController submenu_controller;
PickerPreviewBubbleController preview_controller;
auto* view =
widget->SetContentsView(std::make_unique<PickerSearchResultsView>(
&mock_delegate, kPickerWidth, &asset_fetcher, &submenu_controller,
&preview_controller));
widget->Show();
view->AppendSearchResults(PickerSearchResultsSection(
PickerSectionType::kLocalFiles, {}, /*has_more_results=*/true));
EXPECT_CALL(mock_delegate, SelectMoreResults(PickerSectionType::kLocalFiles));
views::View* trailing_link =
view->section_views_for_testing()[0]->title_trailing_link_for_testing();
ViewDrawnWaiter().Wait(trailing_link);
LeftClickOn(*trailing_link);
}
TEST_F(PickerSearchResultsViewTest,
SearchStoppedShowsNoResultsViewWithNoIllustration) {
MockPickerSearchResultsViewDelegate mock_delegate;
MockPickerAssetFetcher asset_fetcher;
PickerSubmenuController submenu_controller;
PickerPreviewBubbleController preview_controller;
PickerSearchResultsView view(&mock_delegate, kPickerWidth, &asset_fetcher,
&submenu_controller, &preview_controller);
EXPECT_TRUE(view.SearchStopped(/*illustration=*/{}, u"no results"));
EXPECT_FALSE(view.section_list_view_for_testing()->GetVisible());
EXPECT_TRUE(view.no_results_view_for_testing()->GetVisible());
EXPECT_FALSE(view.no_results_illustration_for_testing().GetVisible());
EXPECT_TRUE(view.no_results_label_for_testing().GetVisible());
EXPECT_EQ(view.no_results_label_for_testing().GetText(), u"no results");
}
TEST_F(PickerSearchResultsViewTest,
SearchStoppedShowsNoResultsViewWithIllustration) {
MockPickerSearchResultsViewDelegate mock_delegate;
MockPickerAssetFetcher asset_fetcher;
PickerSubmenuController submenu_controller;
PickerPreviewBubbleController preview_controller;
PickerSearchResultsView view(&mock_delegate, kPickerWidth, &asset_fetcher,
&submenu_controller, &preview_controller);
EXPECT_TRUE(view.SearchStopped(
ui::ImageModel::FromImageSkia(gfx::test::CreateImageSkia(1)),
u"no results"));
EXPECT_FALSE(view.section_list_view_for_testing()->GetVisible());
EXPECT_TRUE(view.no_results_view_for_testing()->GetVisible());
EXPECT_TRUE(view.no_results_illustration_for_testing().GetVisible());
EXPECT_TRUE(view.no_results_label_for_testing().GetVisible());
EXPECT_EQ(view.no_results_label_for_testing().GetText(), u"no results");
}
TEST_F(PickerSearchResultsViewTest,
SearchStoppedShowsSectionListIfThereAreResults) {
MockPickerSearchResultsViewDelegate mock_delegate;
MockPickerAssetFetcher asset_fetcher;
PickerSubmenuController submenu_controller;
PickerPreviewBubbleController preview_controller;
PickerSearchResultsView view(&mock_delegate, kPickerWidth, &asset_fetcher,
&submenu_controller, &preview_controller);
view.AppendSearchResults(PickerSearchResultsSection(
PickerSectionType::kLocalFiles, {}, /*has_more_results=*/true));
EXPECT_FALSE(view.SearchStopped({}, u""));
EXPECT_TRUE(view.section_list_view_for_testing()->GetVisible());
EXPECT_FALSE(view.no_results_view_for_testing()->GetVisible());
}
TEST_F(PickerSearchResultsViewTest, SearchStoppedHidesLoaderView) {
MockPickerSearchResultsViewDelegate mock_delegate;
MockPickerAssetFetcher asset_fetcher;
PickerSubmenuController submenu_controller;
PickerPreviewBubbleController preview_controller;
PickerSearchResultsView view(&mock_delegate, kPickerWidth, &asset_fetcher,
&submenu_controller, &preview_controller);
view.ShowLoadingAnimation();
ASSERT_TRUE(view.SearchStopped({}, u""));
EXPECT_FALSE(view.skeleton_loader_view_for_testing().GetVisible());
}
TEST_F(PickerSearchResultsViewTest, SearchStoppedHidesThrobber) {
MockPickerSearchResultsViewDelegate mock_delegate;
MockPickerAssetFetcher asset_fetcher;
PickerSubmenuController submenu_controller;
PickerPreviewBubbleController preview_controller;
PickerSearchResultsView view(&mock_delegate, kPickerWidth, &asset_fetcher,
&submenu_controller, &preview_controller);
view.ClearSearchResults();
ASSERT_TRUE(view.SearchStopped({}, u""));
EXPECT_FALSE(view.throbber_container_for_testing().GetVisible());
}
TEST_F(PickerSearchResultsViewTest, ClearSearchResultsShowsSearchResults) {
MockPickerSearchResultsViewDelegate mock_delegate;
MockPickerAssetFetcher asset_fetcher;
PickerSubmenuController submenu_controller;
PickerPreviewBubbleController preview_controller;
PickerSearchResultsView view(&mock_delegate, kPickerWidth, &asset_fetcher,
&submenu_controller, &preview_controller);
ASSERT_TRUE(view.SearchStopped({}, u""));
view.ClearSearchResults();
EXPECT_TRUE(view.section_list_view_for_testing()->GetVisible());
EXPECT_FALSE(view.no_results_view_for_testing()->GetVisible());
}
TEST_F(PickerSearchResultsViewTest, ShowLoadingShowsLoaderView) {
MockPickerSearchResultsViewDelegate mock_delegate;
MockPickerAssetFetcher asset_fetcher;
PickerSubmenuController submenu_controller;
PickerPreviewBubbleController preview_controller;
PickerSearchResultsView view(&mock_delegate, kPickerWidth, &asset_fetcher,
&submenu_controller, &preview_controller);
view.ShowLoadingAnimation();
EXPECT_TRUE(view.skeleton_loader_view_for_testing().GetVisible());
EXPECT_FALSE(view.skeleton_loader_view_for_testing()
.layer()
->GetAnimator()
->is_animating());
}
TEST_F(PickerSearchResultsViewTest, ShowSkeletonLoaderHidesThrobber) {
MockPickerSearchResultsViewDelegate mock_delegate;
MockPickerAssetFetcher asset_fetcher;
PickerSubmenuController submenu_controller;
PickerPreviewBubbleController preview_controller;
PickerSearchResultsView view(&mock_delegate, kPickerWidth, &asset_fetcher,
&submenu_controller, &preview_controller);
view.ClearSearchResults();
view.ShowLoadingAnimation();
EXPECT_FALSE(view.throbber_container_for_testing().GetVisible());
}
TEST_F(PickerSearchResultsViewTest, ShowLoadingAnimatesAfterDelay) {
ui::ScopedAnimationDurationScaleMode test_duration_mode(
ui::ScopedAnimationDurationScaleMode::NON_ZERO_DURATION);
MockPickerSearchResultsViewDelegate mock_delegate;
MockPickerAssetFetcher asset_fetcher;
PickerSubmenuController submenu_controller;
PickerPreviewBubbleController preview_controller;
PickerSearchResultsView view(&mock_delegate, kPickerWidth, &asset_fetcher,
&submenu_controller, &preview_controller);
view.ShowLoadingAnimation();
task_environment()->FastForwardBy(
PickerSearchResultsView::kLoadingAnimationDelay);
EXPECT_TRUE(view.skeleton_loader_view_for_testing()
.layer()
->GetAnimator()
->is_animating());
}
TEST_F(PickerSearchResultsViewTest, AppendResultsDuringLoadingStopsAnimation) {
ui::ScopedAnimationDurationScaleMode test_duration_mode(
ui::ScopedAnimationDurationScaleMode::NON_ZERO_DURATION);
MockPickerSearchResultsViewDelegate mock_delegate;
MockPickerAssetFetcher asset_fetcher;
PickerSubmenuController submenu_controller;
PickerPreviewBubbleController preview_controller;
PickerSearchResultsView view(&mock_delegate, kPickerWidth, &asset_fetcher,
&submenu_controller, &preview_controller);
task_environment()->FastForwardBy(
PickerSearchResultsView::kLoadingAnimationDelay);
view.AppendSearchResults({PickerSearchResultsSection(
PickerSectionType::kLinks, {PickerTextResult(u"1")},
/*has_more_results=*/false)});
EXPECT_FALSE(view.skeleton_loader_view_for_testing().GetVisible());
EXPECT_FALSE(view.skeleton_loader_view_for_testing()
.layer()
->GetAnimator()
->is_animating());
}
TEST_F(PickerSearchResultsViewTest, AppendResultsDuringLoadingAppendsResults) {
MockPickerSearchResultsViewDelegate mock_delegate;
MockPickerAssetFetcher asset_fetcher;
PickerSubmenuController submenu_controller;
PickerPreviewBubbleController preview_controller;
PickerSearchResultsView view(&mock_delegate, kPickerWidth, &asset_fetcher,
&submenu_controller, &preview_controller);
view.ShowLoadingAnimation();
view.AppendSearchResults({PickerSearchResultsSection(
PickerSectionType::kLinks, {PickerTextResult(u"1")},
/*has_more_results=*/false)});
EXPECT_FALSE(view.skeleton_loader_view_for_testing().GetVisible());
EXPECT_THAT(view.section_views_for_testing(), SizeIs(1));
}
TEST_F(PickerSearchResultsViewTest, AppendResultsHidesThrobber) {
MockPickerSearchResultsViewDelegate mock_delegate;
MockPickerAssetFetcher asset_fetcher;
PickerSubmenuController submenu_controller;
PickerPreviewBubbleController preview_controller;
PickerSearchResultsView view(&mock_delegate, kPickerWidth, &asset_fetcher,
&submenu_controller, &preview_controller);
view.AppendSearchResults({PickerSearchResultsSection(
PickerSectionType::kLinks, {PickerTextResult(u"1")},
/*has_more_results=*/false)});
EXPECT_FALSE(view.throbber_container_for_testing().GetVisible());
}
TEST_F(PickerSearchResultsViewTest,
StoppingSearchDoesNotAnnounceWhenThereAreResults) {
std::unique_ptr<views::Widget> widget =
CreateTestWidget(views::Widget::InitParams::CLIENT_OWNS_WIDGET);
widget->Show();
MockPickerSearchResultsViewDelegate mock_delegate;
auto* view =
widget->SetContentsView(std::make_unique<PickerSearchResultsView>(
&mock_delegate, kPickerWidth, /*asset_fetcher=*/nullptr,
/*submenu_controller=*/nullptr, /*preview_controller=*/nullptr));
views::test::AXEventCounter counter(views::AXEventManager::Get());
view->AppendSearchResults(PickerSearchResultsSection(
PickerSectionType::kNone, {}, /*has_more_results=*/false));
view->SearchStopped(/*illustration=*/{}, u"");
EXPECT_EQ(view->GetAccessibleName(), u"");
EXPECT_EQ(counter.GetCount(ax::mojom::Event::kLiveRegionChanged), 0);
}
TEST_F(PickerSearchResultsViewTest,
StoppingSearchWithNoEmojisTriggersLiveRegionChange) {
std::unique_ptr<views::Widget> widget =
CreateTestWidget(views::Widget::InitParams::CLIENT_OWNS_WIDGET);
widget->Show();
MockPickerSearchResultsViewDelegate mock_delegate;
auto* view =
widget->SetContentsView(std::make_unique<PickerSearchResultsView>(
&mock_delegate, kPickerWidth, /*asset_fetcher=*/nullptr,
/*submenu_controller=*/nullptr, /*preview_controller=*/nullptr));
views::test::AXEventCounter counter(views::AXEventManager::Get());
EXPECT_TRUE(view->SearchStopped(/*illustration=*/{}, u""));
EXPECT_EQ(view->GetAccessibleName(),
l10n_util::GetStringUTF16(IDS_PICKER_NO_RESULTS_TEXT));
EXPECT_EQ(counter.GetCount(ax::mojom::Event::kLiveRegionChanged), 1);
}
TEST_F(PickerSearchResultsViewTest,
StoppingSearchWithEmojisTriggersLiveRegionChange) {
std::unique_ptr<views::Widget> widget =
CreateTestWidget(views::Widget::InitParams::CLIENT_OWNS_WIDGET);
widget->Show();
MockPickerSearchResultsViewDelegate mock_delegate;
auto* view =
widget->SetContentsView(std::make_unique<PickerSearchResultsView>(
&mock_delegate, kPickerWidth, /*asset_fetcher=*/nullptr,
/*submenu_controller=*/nullptr, /*preview_controller=*/nullptr));
view->SetNumEmojiResultsForA11y(5);
views::test::AXEventCounter counter(views::AXEventManager::Get());
EXPECT_TRUE(view->SearchStopped(/*illustration=*/{}, u""));
EXPECT_EQ(view->GetAccessibleName(), u"5 emojis. No other results.");
EXPECT_EQ(counter.GetCount(ax::mojom::Event::kLiveRegionChanged), 1);
}
TEST_F(PickerSearchResultsViewTest,
StoppingSearchConsecutivelyDoesNotTriggerLiveRegionChange) {
std::unique_ptr<views::Widget> widget =
CreateTestWidget(views::Widget::InitParams::CLIENT_OWNS_WIDGET);
widget->Show();
MockPickerSearchResultsViewDelegate mock_delegate;
auto* view =
widget->SetContentsView(std::make_unique<PickerSearchResultsView>(
&mock_delegate, kPickerWidth, /*asset_fetcher=*/nullptr,
/*submenu_controller=*/nullptr, /*preview_controller=*/nullptr));
views::test::AXEventCounter counter(views::AXEventManager::Get());
view->SearchStopped(/*illustration=*/{}, u"");
view->SearchStopped(/*illustration=*/{}, u"");
EXPECT_EQ(view->GetAccessibleName(),
l10n_util::GetStringUTF16(IDS_PICKER_NO_RESULTS_TEXT));
EXPECT_EQ(counter.GetCount(ax::mojom::Event::kLiveRegionChanged), 1);
}
TEST_F(PickerSearchResultsViewTest,
StoppingSearchAfterClearingSearchAnnouncesWhenThereAreResults) {
std::unique_ptr<views::Widget> widget =
CreateTestWidget(views::Widget::InitParams::CLIENT_OWNS_WIDGET);
widget->Show();
MockPickerSearchResultsViewDelegate mock_delegate;
auto* view =
widget->SetContentsView(std::make_unique<PickerSearchResultsView>(
&mock_delegate, kPickerWidth, /*asset_fetcher=*/nullptr,
/*submenu_controller=*/nullptr, /*preview_controller=*/nullptr));
views::test::AXEventCounter counter(views::AXEventManager::Get());
view->SearchStopped(/*illustration=*/{}, u"");
view->AppendSearchResults(PickerSearchResultsSection(
PickerSectionType::kNone, {}, /*has_more_results=*/false));
view->ClearSearchResults();
view->SearchStopped(/*illustration=*/{}, u"");
EXPECT_EQ(view->GetAccessibleName(),
l10n_util::GetStringUTF16(IDS_PICKER_NO_RESULTS_TEXT));
EXPECT_EQ(counter.GetCount(ax::mojom::Event::kLiveRegionChanged), 2);
}
struct PickerSearchResultTestCase {
std::string test_name;
PickerSearchResult result;
};
class PickerSearchResultsViewResultSelectionTest
: public PickerSearchResultsViewTest,
public testing::WithParamInterface<PickerSearchResultTestCase> {
private:
AshColorProvider ash_color_provider_;
};
TEST_P(PickerSearchResultsViewResultSelectionTest, LeftClickSelectsResult) {
const PickerSearchResultTestCase& test_case = GetParam();
MockPickerSearchResultsViewDelegate mock_delegate;
MockPickerAssetFetcher asset_fetcher;
PickerSubmenuController submenu_controller;
PickerPreviewBubbleController preview_controller;
std::unique_ptr<views::Widget> widget =
CreateTestWidget(views::Widget::InitParams::CLIENT_OWNS_WIDGET);
widget->SetFullscreen(true);
auto* view =
widget->SetContentsView(std::make_unique<PickerSearchResultsView>(
&mock_delegate, kPickerWidth, &asset_fetcher, &submenu_controller,
&preview_controller));
widget->Show();
view->AppendSearchResults(PickerSearchResultsSection(
PickerSectionType::kClipboard, {{test_case.result}},
/*has_more_results=*/false));
ASSERT_THAT(view->section_views_for_testing(), Not(IsEmpty()));
ASSERT_THAT(view->section_views_for_testing()[0]->item_views_for_testing(),
Not(IsEmpty()));
EXPECT_CALL(mock_delegate, SelectSearchResult(test_case.result));
PickerItemView* result_view =
view->section_views_for_testing()[0]->item_views_for_testing()[0];
ViewDrawnWaiter().Wait(result_view);
LeftClickOn(*result_view);
}
INSTANTIATE_TEST_SUITE_P(
All,
PickerSearchResultsViewResultSelectionTest,
testing::ValuesIn<PickerSearchResultTestCase>({
{"Text", PickerTextResult(u"result")},
{"Category", PickerCategoryResult(PickerCategory::kEmojisGifs)},
{"LocalFile", PickerLocalFileResult(u"local", base::FilePath())},
{"DriveFile", PickerDriveFileResult(std::nullopt,
u"drive",
GURL(),
base::FilePath())},
}),
[](const testing::TestParamInfo<
PickerSearchResultsViewResultSelectionTest::ParamType>& info) {
return info.param.test_name;
});
} // namespace
} // namespace ash