chromium/chrome/browser/ui/views/autofill/popup/popup_view_views_unittest.cc

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

#include "chrome/browser/ui/views/autofill/popup/popup_view_views.h"

#include <memory>
#include <optional>
#include <string>
#include <vector>

#include "base/containers/contains.h"
#include "base/functional/bind.h"
#include "base/functional/bind_internal.h"
#include "base/functional/callback_forward.h"
#include "base/memory/weak_ptr.h"
#include "base/strings/string_util.h"
#include "base/test/bind.h"
#include "base/test/metrics/histogram_tester.h"
#include "base/time/time.h"
#include "build/build_config.h"
#include "chrome/browser/ui/autofill/autofill_popup_controller.h"
#include "chrome/browser/ui/autofill/autofill_popup_controller_impl.h"
#include "chrome/browser/ui/autofill/autofill_popup_view.h"
#include "chrome/browser/ui/autofill/mock_autofill_popup_controller.h"
#include "chrome/browser/ui/browser_element_identifiers.h"
#include "chrome/browser/ui/views/autofill/popup/popup_row_content_view.h"
#include "chrome/browser/ui/views/autofill/popup/popup_row_view.h"
#include "chrome/browser/ui/views/autofill/popup/popup_search_bar_view.h"
#include "chrome/browser/ui/views/autofill/popup/popup_separator_view.h"
#include "chrome/browser/ui/views/autofill/popup/popup_title_view.h"
#include "chrome/browser/ui/views/autofill/popup/popup_view_utils.h"
#include "chrome/browser/ui/views/autofill/popup/popup_view_views_test_api.h"
#include "chrome/browser/ui/views/autofill/popup/popup_warning_view.h"
#include "chrome/test/base/testing_profile.h"
#include "chrome/test/views/chrome_views_test_base.h"
#include "components/autofill/core/browser/metrics/autofill_metrics.h"
#include "components/autofill/core/browser/ui/suggestion.h"
#include "components/autofill/core/browser/ui/suggestion_hiding_reason.h"
#include "components/autofill/core/browser/ui/suggestion_type.h"
#include "components/autofill/core/common/aliases.h"
#include "components/feature_engagement/public/feature_constants.h"
#include "components/input/native_web_keyboard_event.h"
#include "components/strings/grit/components_strings.h"
#include "content/public/browser/web_contents.h"
#include "content/public/test/test_renderer_host.h"
#include "content/public/test/web_contents_tester.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/blink/public/common/frame/frame_policy.h"
#include "third_party/blink/public/common/input/web_input_event.h"
#include "third_party/blink/public/common/input/web_keyboard_event.h"
#include "ui/accessibility/ax_enums.mojom.h"
#include "ui/accessibility/ax_node_data.h"
#include "ui/base/l10n/l10n_util.h"
#include "ui/compositor/canvas_painter.h"
#include "ui/events/base_event_utils.h"
#include "ui/events/keycodes/keyboard_codes.h"
#include "ui/events/test/event_generator.h"
#include "ui/gfx/geometry/point.h"
#include "ui/gfx/geometry/point_f.h"
#include "ui/gfx/geometry/rect.h"
#include "ui/gfx/geometry/vector2d.h"
#include "ui/views/accessibility/view_accessibility.h"
#include "ui/views/bubble/bubble_border.h"
#include "ui/views/bubble/bubble_border_arrow_utils.h"
#include "ui/views/test/ax_event_counter.h"
#include "ui/views/view_class_properties.h"
#include "ui/views/widget/widget.h"
#include "ui/views/widget/widget_utils.h"

namespace autofill {

namespace {

_;
AllOf;
ElementsAre;
Eq;
Field;
InSequence;
Mock;
MockFunction;
NiceMock;
Optional;
Return;
CellIndex;
CellType;

const std::vector<SuggestionType> kClickableSuggestionTypes{};

const std::vector<SuggestionType> kUnclickableSuggestionTypes{};

bool IsClickable(SuggestionType id) {}

Suggestion CreateSuggestionWithChildren(
    const SuggestionType suggestion_type,
    std::vector<Suggestion> children,
    const std::u16string& name = u"Suggestion") {}

Suggestion CreateSuggestionWithChildren(
    std::vector<Suggestion> children,
    const std::u16string& name = u"Suggestion") {}

class TestPopupViewViews : public PopupViewViews {};

}  // namespace

class PopupViewViewsTest : public ChromeViewsTestBase {};

class PopupViewViewsTestWithAnySuggestionType
    : public PopupViewViewsTest,
      public ::testing::WithParamInterface<SuggestionType> {};

class PopupViewViewsTestWithClickableSuggestionType
    : public PopupViewViewsTest,
      public ::testing::WithParamInterface<SuggestionType> {};

TEST_F(PopupViewViewsTest, ShowHideTest) {}

TEST_F(PopupViewViewsTest, ExpandedCollapsedAccessiblityStateTest) {}

TEST_F(PopupViewViewsTest, AccessibleProperties) {}

TEST_F(PopupViewViewsTest, CanShowDropdownInBounds) {}

// This is a regression test for crbug.com/1113255.
TEST_F(PopupViewViewsTest, ShowViewWithOnlyFooterItemsShouldNotCrash) {}

TEST_F(PopupViewViewsTest, AccessibilitySelectedEvent) {}

TEST_F(PopupViewViewsTest, AccessibilityTest) {}

// Gestures are not supported on MacOS.
#if !BUILDFLAG(IS_MAC)
TEST_F(PopupViewViewsTest, AcceptingOnTap) {}

TEST_F(PopupViewViewsTest, SelectionOnTouchAndUnselectionOnCancel) {}
#endif  // !BUILDFLAG(IS_MAC)

TEST_F(PopupViewViewsTest, ClickDisabledEntry) {}

TEST_F(PopupViewViewsTest, KeyboardFocusIsNotCapturedAutomaticallyForSubPopup) {}

TEST_F(PopupViewViewsTest,
       KeyboardFocusIsNotCapturedAutomaticallyForSubPopupRTL) {}

TEST_F(PopupViewViewsTest, CursorUpDownForSelectableCells) {}

TEST_F(PopupViewViewsTest, CursorUpWithNonSelectableCells) {}

TEST_F(PopupViewViewsTest, CursorDownWithNonSelectableCells) {}

TEST_F(PopupViewViewsTest, OverflowWithNonSelectableCells) {}

TEST_F(PopupViewViewsTest, SelectingSuggestionWithNoControlResetsToContent) {}

TEST_F(PopupViewViewsTest, LeftAndRightKeyEventsAreHandled) {}

TEST_F(PopupViewViewsTest, LeftAndRightKeyEventsAreHandledForRTL) {}

TEST_F(PopupViewViewsTest, LeftAndRightKeyEventsAreHandledWithoutControl) {}

TEST_F(PopupViewViewsTest, CursorLeftRightDownForAutocompleteEntries) {}

TEST_F(PopupViewViewsTest, PageUpDownForSelectableCells) {}

TEST_F(PopupViewViewsTest, MovingSelectionSkipsSeparator) {}

TEST_F(PopupViewViewsTest, MovingSelectionSkipsInsecureFormWarning) {}

TEST_F(PopupViewViewsTest, EscClosesSubPopup) {}

class PopupViewViewsTestKeyboard : public PopupViewViewsTest {};

// Tests that hitting enter on a suggestion autofills it.
TEST_F(PopupViewViewsTestKeyboard, FillOnEnter) {}

// Tests that hitting tab on a suggestion autofills it.
TEST_F(PopupViewViewsTestKeyboard, FillOnTabPressed) {}

// Tests that `tab` together with a modified (other than shift) does not
// autofill a selected suggestion.
TEST_F(PopupViewViewsTestKeyboard, NoFillOnTabPressedWithModifiers) {}

// Verify that pressing the tab key while the "Manage addresses..." entry is
// selected does not trigger "accepting" the entry (which would mean opening
// a tab with the autofill settings).
TEST_F(PopupViewViewsTest, NoAutofillOptionsTriggeredOnTabPressed) {}

// This is a regression test for crbug.com/1309431 to ensure that we don't crash
// when we press tab before a line is selected.
TEST_F(PopupViewViewsTest, TabBeforeSelectingALine) {}

TEST_F(PopupViewViewsTest, RemoveLine) {}

TEST_F(PopupViewViewsTest, RemoveAutofillInvokesController) {}

// Tests that pressing TAB selects a previously unselected Compose suggestion.
TEST_F(PopupViewViewsTest, ComposeSuggestion_TabSelects) {}

// Tests that pressing Shift+TAB in the presence of an unselected Compose
// suggestion does nothing.
TEST_F(PopupViewViewsTest, ComposeSuggestion_ShiftTabDoesNotAffect) {}

TEST_F(PopupViewViewsTest, ComposeSuggestion_LeftAndRightKeyEventsAreHandled) {}

TEST_F(PopupViewViewsTest,
       ComposeSuggestion_LeftAndRightKeyEventsAreHandledForRTL) {}

TEST_F(
    PopupViewViewsTest,
    ComposeSuggestion_SuggestionAlreadySelected_CursorUpDownForSelectableCells) {}

// Tests that pressing TAB in the presence of a selected Compose suggestion
// closes the popup.
TEST_F(PopupViewViewsTest,
       ComposeSuggestion_TabWithSelectedComposeSuggestionHidesPopup) {}

// Tests that pressing Shift+TAB in the presence of a selected Compose
// suggestion without an open subpopup, unselects the suggestion, but does not
// close the popup.
TEST_F(PopupViewViewsTest, ComposeSuggestion_NoSubPopup_ShiftTabUnselects) {}

// Tests that pressing Shift+TAB in the presence of a selected Compose
// suggestion with an open subpopup, closes the subpopup and selects the root
// suggestion's content cell.
TEST_F(
    PopupViewViewsTest,
    ComposeSuggestion_SubPopupOpen_ShiftTabClosesSubpopupAndSelectsContentCell) {}

// Tests that pressing up/down cursor keys does not select a Compose suggestion.
TEST_F(PopupViewViewsTest, ComposeSuggestion_CursorUpDownDoesNotSelect) {}

// Tests that pressing Esc closes a popup with a Compose suggestion.
TEST_F(PopupViewViewsTest, ComposeSuggestion_EscapeClosesComposePopup) {}

// Ensure that the voice_over value of suggestions is presented to the
// accessibility layer.
TEST_F(PopupViewViewsTest, VoiceOverTest) {}

TEST_F(PopupViewViewsTest, ExpandableSuggestionA11yMessageTest) {}

TEST_F(PopupViewViewsTest, UpdateSuggestionsNoCrash) {}

TEST_F(PopupViewViewsTest,
       OnSuggestionsUpdatePositionIsCalculatedPreferringPrevArrow) {}

TEST_F(PopupViewViewsTest, SubViewIsShownInChildWidget) {}

// Tests the event retriggering trick from `PopupBaseView::Widget`,
// see `PopupBaseView::Widget::OnMouseEvent()` for details.
TEST_F(PopupViewViewsTest, ChildWidgetRetriggersMouseMovesToParent) {}

TEST_F(PopupViewViewsTest, SubViewIsClosedWithParent) {}

TEST_F(PopupViewViewsTest, CellOpensClosesSubPopupWithDelay) {}

TEST_F(PopupViewViewsTest, CellSubPopupResetAfterSuggestionsUpdates) {}

// TODO(crbug.com/41487832): Enable on ChromeOS when test setup in the death
// subprocess is fixed.
#if !BUILDFLAG(IS_CHROMEOS_ASH)
// `PopupViewViewsTest` is not used in death tests because it sets up a complex
// environment (namely creates a `TestingProfile`) that fails to be created in
// the sub-process (see `ASSERT_DEATH` doc for details). This fail hides
// the real death reason to be tested.
PopupViewViewsDeathTest;
TEST_F(PopupViewViewsDeathTest, OpenSubPopupWithNoChildrenCheckCrash) {}
#endif

TEST_F(PopupViewViewsTest, SubPopupHidingOnNoSelection) {}

TEST_F(PopupViewViewsTest, SubPopupHidingIsCanceledOnSelection) {}

TEST_F(PopupViewViewsTest, SubPopupHidingIsCanceledOnParentHiding) {}

TEST_F(PopupViewViewsTest, SubPopupOwnSelectionPreventsHiding) {}

TEST_F(PopupViewViewsTest, SubPopupOpensWithNoAutoselectByMouse) {}

TEST_F(PopupViewViewsTest, SubPopupOpensWithAutoselectByRightKey) {}

TEST_F(PopupViewViewsTest, SubPopupOpensForNonSelectableContentSelection) {}

TEST_F(PopupViewViewsTest, SubPopupNotOpenForSelectableContentSelection) {}

TEST_F(PopupViewViewsTest,
       SubPopupNotOpenForMerchantOptedOutVcnContentSelection) {}

// TODO(crbug.com/40284129): Enable once the view shows itself properly.
#if !BUILDFLAG(IS_MAC)
// Tests that `GetPopupScreenLocation` returns the bounds and arrow position of
// the popup.
TEST_F(PopupViewViewsTest, GetPopupScreenLocation) {}
#endif  // !BUILDFLAG(IS_MAC)

// TODO(crbug.com/41496626): Rework into pixel tests and run on all available
// platforms. The test below is a temporary solution to cover positioning
// calculations in the popup. The exact numbers were obtained by observing
// a local run, manually verified and hardcoded in the test with acceptable 15px
// error, as on different machines the popup geometry/location slightly vary.
#if BUILDFLAG(IS_LINUX)
TEST_F(PopupViewViewsTest, PopupPositioning) {}
#endif  // BUILDFLAG(IS_LINUX)

TEST_F(PopupViewViewsTest, StandaloneCvcSuggestion_ElementId) {}

TEST_F(PopupViewViewsTest, VirtualCardSuggestion_ElementId) {}

#if defined(MEMORY_SANITIZER) && BUILDFLAG(IS_CHROMEOS)
#define MAYBE_ShowClickTest
#else
#define MAYBE_ShowClickTest
#endif
// Tests that (only) clickable items trigger an AcceptSuggestion event.
TEST_P(PopupViewViewsTestWithAnySuggestionType, MAYBE_ShowClickTest) {}

// Tests that after the mouse moves into the popup after display, clicking a
// suggestion triggers an AcceptSuggestion() event.
TEST_P(PopupViewViewsTestWithClickableSuggestionType,
       AcceptSuggestionIfUnfocusedAtPaint) {}

// Tests that after the mouse moves from one suggestion to another, clicking the
// suggestion triggers an AcceptSuggestion() event.
TEST_P(PopupViewViewsTestWithClickableSuggestionType,
       AcceptSuggestionIfMouseSelectedAnotherRow) {}

// Tests that after the mouse moves from one suggestion to another and back to
// the first one, clicking the suggestion triggers an AcceptSuggestion() event.
TEST_P(PopupViewViewsTestWithClickableSuggestionType,
       AcceptSuggestionIfMouseTemporarilySelectedAnotherRow) {}

// Tests that even if the mouse hovers a suggestion when the popup is displayed,
// after moving the mouse out and back in on the popup, clicking the suggestion
// triggers an AcceptSuggestion() event.
TEST_P(PopupViewViewsTestWithClickableSuggestionType,
       AcceptSuggestionIfMouseExitedPopupSincePaint) {}

// Tests that if the mouse hovers a suggestion when the popup is displayed,
// clicking the suggestion triggers no AcceptSuggestion() event.
TEST_P(PopupViewViewsTestWithClickableSuggestionType,
       IgnoreClickIfFocusedAtPaintWithoutExit) {}

// Tests that if the mouse hovers a suggestion when the popup is displayed and
// moves around on this suggestion, clicking the suggestion triggers no
// AcceptSuggestion() event.
TEST_P(PopupViewViewsTestWithClickableSuggestionType,
       IgnoreClickIfFocusedAtPaintWithSlightMouseMovement) {}

INSTANTIATE_TEST_SUITE_P(All,
                         PopupViewViewsTestWithAnySuggestionType,
                         testing::ValuesIn([] {};

INSTANTIATE_TEST_SUITE_P();

TEST_F(PopupViewViewsTest, ViewFocusOnShowDependsOnWidgetActivatability) {}

TEST_F(PopupViewViewsTest, SearchBar_InputGetsFocusOnShow) {}

TEST_F(PopupViewViewsTest, SearchBar_HidesPopupOnFocusLost) {}

TEST_F(PopupViewViewsTest, SearchBar_QueryIsSetAsFilterToController) {}

TEST_F(PopupViewViewsTest, SearchBar_PressedKeysPassedToController) {}

}  // namespace autofill