tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

TestAccessibleCaretManager.cpp (30588B)


      1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
      2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
      3 /* This Source Code Form is subject to the terms of the Mozilla Public
      4 * License, v. 2.0. If a copy of the MPL was not distributed with this
      5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
      6 
      7 #include <string>
      8 
      9 #include "AccessibleCaret.h"
     10 #include "AccessibleCaretManager.h"
     11 #include "gmock/gmock.h"
     12 #include "gtest/gtest.h"
     13 #include "mozilla/Preferences.h"
     14 
     15 using ::testing::_;
     16 using ::testing::DefaultValue;
     17 using ::testing::Eq;
     18 using ::testing::InSequence;
     19 using ::testing::MockFunction;
     20 using ::testing::Return;
     21 
     22 // -----------------------------------------------------------------------------
     23 // This file tests CaretStateChanged events and the appearance of the two
     24 // AccessibleCarets manipulated by AccessibleCaretManager.
     25 
     26 namespace mozilla {
     27 using dom::CaretChangedReason;
     28 
     29 class MOZ_RAII AutoRestoreBoolPref final {
     30 public:
     31  AutoRestoreBoolPref(const char* aPref, bool aValue) : mPref(aPref) {
     32    Preferences::GetBool(mPref, &mOldValue);
     33    Preferences::SetBool(mPref, aValue);
     34  }
     35 
     36  ~AutoRestoreBoolPref() { Preferences::SetBool(mPref, mOldValue); }
     37 
     38 private:
     39  const char* mPref = nullptr;
     40  bool mOldValue = false;
     41 };
     42 
     43 class AccessibleCaretManagerTester : public ::testing::Test {
     44 public:
     45  class MockAccessibleCaret : public AccessibleCaret {
     46   public:
     47    MockAccessibleCaret() : AccessibleCaret(nullptr) {}
     48 
     49    void SetAppearance(Appearance aAppearance) override {
     50      // A simplified version without touching CaretElement().
     51      mAppearance = aAppearance;
     52    }
     53 
     54    MOCK_METHOD2(SetPosition,
     55                 PositionChangedResult(nsIFrame* aFrame, int32_t aOffset));
     56 
     57  };  // class MockAccessibleCaret
     58 
     59  class MockAccessibleCaretManager : public AccessibleCaretManager {
     60   public:
     61    using CaretMode = AccessibleCaretManager::CaretMode;
     62    using AccessibleCaretManager::HideCaretsAndDispatchCaretStateChangedEvent;
     63    using AccessibleCaretManager::UpdateCarets;
     64 
     65    MockAccessibleCaretManager()
     66        : AccessibleCaretManager(nullptr,
     67                                 Carets{MakeUnique<MockAccessibleCaret>(),
     68                                        MakeUnique<MockAccessibleCaret>()}) {}
     69 
     70    MockAccessibleCaret& FirstCaret() {
     71      return static_cast<MockAccessibleCaret&>(*mCarets.GetFirst());
     72    }
     73 
     74    MockAccessibleCaret& SecondCaret() {
     75      return static_cast<MockAccessibleCaret&>(*mCarets.GetSecond());
     76    }
     77 
     78    bool CompareTreePosition(const nsIFrame* aStartFrame, int32_t aStartOffset,
     79                             const nsIFrame* aEndFrame,
     80                             int32_t aEndOffset) const override {
     81      return true;
     82    }
     83 
     84    bool IsCaretDisplayableInCursorMode(
     85        nsIFrame** aOutFrame = nullptr,
     86        int32_t* aOutOffset = nullptr) const override {
     87      return true;
     88    }
     89 
     90    bool UpdateCaretsForOverlappingTilt() override { return true; }
     91 
     92    void UpdateCaretsForAlwaysTilt(const nsIFrame* aStartFrame,
     93                                   const nsIFrame* aEndFrame) override {
     94      if (mCarets.GetFirst()->IsVisuallyVisible()) {
     95        mCarets.GetFirst()->SetAppearance(Appearance::Left);
     96      }
     97      if (mCarets.GetSecond()->IsVisuallyVisible()) {
     98        mCarets.GetSecond()->SetAppearance(Appearance::Right);
     99      }
    100    }
    101 
    102    Terminated IsTerminated() const override { return Terminated::No; }
    103    bool IsScrollStarted() const { return mIsScrollStarted; }
    104 
    105    Terminated MaybeFlushLayout() override { return Terminated::No; }
    106 
    107    MOCK_CONST_METHOD0(GetCaretMode, CaretMode());
    108    MOCK_METHOD2(DispatchCaretStateChangedEvent,
    109                 void(CaretChangedReason aReason, const nsPoint* aPoint));
    110    MOCK_CONST_METHOD1(HasNonEmptyTextContent, bool(nsINode* aNode));
    111 
    112  };  // class MockAccessibleCaretManager
    113 
    114  using Appearance = AccessibleCaret::Appearance;
    115  using PositionChangedResult = AccessibleCaret::PositionChangedResult;
    116  using CaretMode = MockAccessibleCaretManager::CaretMode;
    117 
    118  AccessibleCaretManagerTester() {
    119    DefaultValue<CaretMode>::Set(CaretMode::None);
    120    DefaultValue<PositionChangedResult>::Set(PositionChangedResult::NotChanged);
    121 
    122    EXPECT_CALL(mManager.FirstCaret(), SetPosition(_, _))
    123        .WillRepeatedly(Return(PositionChangedResult::Position));
    124 
    125    EXPECT_CALL(mManager.SecondCaret(), SetPosition(_, _))
    126        .WillRepeatedly(Return(PositionChangedResult::Position));
    127  }
    128 
    129  AccessibleCaret::Appearance FirstCaretAppearance() {
    130    return mManager.FirstCaret().GetAppearance();
    131  }
    132 
    133  AccessibleCaret::Appearance SecondCaretAppearance() {
    134    return mManager.SecondCaret().GetAppearance();
    135  }
    136 
    137  // Member variables
    138  MockAccessibleCaretManager mManager;
    139 
    140 };  // class AccessibleCaretManagerTester
    141 
    142 TEST_F(AccessibleCaretManagerTester, TestUpdatesInSelectionMode)
    143 MOZ_CAN_RUN_SCRIPT_FOR_DEFINITION {
    144  // Set default preference.
    145  AutoRestoreBoolPref savedPref("layout.accessiblecaret.always_tilt", false);
    146 
    147  EXPECT_CALL(mManager, GetCaretMode())
    148      .WillRepeatedly(Return(CaretMode::Selection));
    149 
    150  EXPECT_CALL(mManager, DispatchCaretStateChangedEvent(
    151                            CaretChangedReason::Updateposition, nullptr))
    152      .Times(3);
    153 
    154  mManager.UpdateCarets();
    155  EXPECT_EQ(FirstCaretAppearance(), Appearance::Normal);
    156  EXPECT_EQ(SecondCaretAppearance(), Appearance::Normal);
    157 
    158  mManager.OnReflow();
    159  EXPECT_EQ(FirstCaretAppearance(), Appearance::Normal);
    160  EXPECT_EQ(SecondCaretAppearance(), Appearance::Normal);
    161 
    162  mManager.OnScrollPositionChanged();
    163  EXPECT_EQ(FirstCaretAppearance(), Appearance::Normal);
    164  EXPECT_EQ(SecondCaretAppearance(), Appearance::Normal);
    165 }
    166 
    167 TEST_F(AccessibleCaretManagerTester, TestSingleTapOnNonEmptyInput)
    168 MOZ_CAN_RUN_SCRIPT_FOR_DEFINITION {
    169  EXPECT_CALL(mManager, GetCaretMode())
    170      .WillRepeatedly(Return(CaretMode::Cursor));
    171 
    172  EXPECT_CALL(mManager, HasNonEmptyTextContent(_)).WillRepeatedly(Return(true));
    173 
    174  MockFunction<void(std::string aCheckPointName)> check;
    175  {
    176    InSequence dummy;
    177 
    178    EXPECT_CALL(mManager, DispatchCaretStateChangedEvent(
    179                              CaretChangedReason::Updateposition, nullptr))
    180        .Times(1);
    181    EXPECT_CALL(check, Call("update"));
    182 
    183    EXPECT_CALL(mManager, DispatchCaretStateChangedEvent(
    184                              CaretChangedReason::Visibilitychange, nullptr))
    185        .Times(1);
    186    EXPECT_CALL(check, Call("mouse down"));
    187 
    188    EXPECT_CALL(mManager, DispatchCaretStateChangedEvent(_, nullptr)).Times(0);
    189    EXPECT_CALL(check, Call("reflow"));
    190 
    191    EXPECT_CALL(mManager, DispatchCaretStateChangedEvent(_, nullptr)).Times(0);
    192    EXPECT_CALL(check, Call("blur"));
    193 
    194    EXPECT_CALL(mManager, DispatchCaretStateChangedEvent(
    195                              CaretChangedReason::Updateposition, nullptr))
    196        .Times(1);
    197    EXPECT_CALL(check, Call("mouse up"));
    198 
    199    EXPECT_CALL(mManager, DispatchCaretStateChangedEvent(
    200                              CaretChangedReason::Updateposition, nullptr))
    201        .Times(1);
    202    EXPECT_CALL(check, Call("reflow2"));
    203 
    204    EXPECT_CALL(mManager, DispatchCaretStateChangedEvent(
    205                              CaretChangedReason::Updateposition, nullptr))
    206        .Times(1);
    207  }
    208 
    209  // Simulate a single tap on a non-empty input.
    210  mManager.UpdateCarets();
    211  EXPECT_EQ(FirstCaretAppearance(), Appearance::Normal);
    212  check.Call("update");
    213 
    214  mManager.OnSelectionChanged(nullptr, nullptr,
    215                              nsISelectionListener::DRAG_REASON |
    216                                  nsISelectionListener::MOUSEDOWN_REASON);
    217  EXPECT_EQ(FirstCaretAppearance(), Appearance::None);
    218  check.Call("mouse down");
    219 
    220  mManager.OnReflow();
    221  EXPECT_EQ(FirstCaretAppearance(), Appearance::None);
    222  check.Call("reflow");
    223 
    224  mManager.OnBlur();
    225  EXPECT_EQ(FirstCaretAppearance(), Appearance::None);
    226  check.Call("blur");
    227 
    228  mManager.OnSelectionChanged(nullptr, nullptr,
    229                              nsISelectionListener::MOUSEUP_REASON);
    230  EXPECT_EQ(FirstCaretAppearance(), Appearance::Normal);
    231  check.Call("mouse up");
    232 
    233  mManager.OnReflow();
    234  EXPECT_EQ(FirstCaretAppearance(), Appearance::Normal);
    235  check.Call("reflow2");
    236 
    237  mManager.OnScrollPositionChanged();
    238  EXPECT_EQ(FirstCaretAppearance(), Appearance::Normal);
    239 }
    240 
    241 TEST_F(AccessibleCaretManagerTester, TestSingleTapOnEmptyInput)
    242 MOZ_CAN_RUN_SCRIPT_FOR_DEFINITION {
    243  // Set default preference.
    244  AutoRestoreBoolPref savedPref(
    245      "layout.accessiblecaret.caret_shown_when_long_tapping_on_empty_content",
    246      false);
    247 
    248  EXPECT_CALL(mManager, GetCaretMode())
    249      .WillRepeatedly(Return(CaretMode::Cursor));
    250 
    251  EXPECT_CALL(mManager, HasNonEmptyTextContent(_))
    252      .WillRepeatedly(Return(false));
    253 
    254  MockFunction<void(std::string aCheckPointName)> check;
    255  {
    256    InSequence dummy;
    257 
    258    EXPECT_CALL(mManager, DispatchCaretStateChangedEvent(
    259                              CaretChangedReason::Updateposition, nullptr))
    260        .Times(1);
    261    EXPECT_CALL(check, Call("update"));
    262 
    263    EXPECT_CALL(mManager, DispatchCaretStateChangedEvent(
    264                              CaretChangedReason::Visibilitychange, nullptr))
    265        .Times(1);
    266    EXPECT_CALL(check, Call("mouse down"));
    267 
    268    EXPECT_CALL(mManager, DispatchCaretStateChangedEvent(_, nullptr)).Times(0);
    269    EXPECT_CALL(check, Call("reflow"));
    270 
    271    EXPECT_CALL(mManager, DispatchCaretStateChangedEvent(_, nullptr)).Times(0);
    272    EXPECT_CALL(check, Call("blur"));
    273 
    274    EXPECT_CALL(mManager, DispatchCaretStateChangedEvent(
    275                              CaretChangedReason::Updateposition, nullptr))
    276        .Times(1);
    277    EXPECT_CALL(check, Call("mouse up"));
    278 
    279    EXPECT_CALL(mManager, DispatchCaretStateChangedEvent(
    280                              CaretChangedReason::Updateposition, nullptr))
    281        .Times(1);
    282    EXPECT_CALL(check, Call("reflow2"));
    283 
    284    EXPECT_CALL(mManager, DispatchCaretStateChangedEvent(
    285                              CaretChangedReason::Updateposition, nullptr))
    286        .Times(1);
    287  }
    288 
    289  // Simulate a single tap on an empty input.
    290  mManager.UpdateCarets();
    291  EXPECT_EQ(FirstCaretAppearance(), Appearance::NormalNotShown);
    292  check.Call("update");
    293 
    294  mManager.OnSelectionChanged(nullptr, nullptr,
    295                              nsISelectionListener::DRAG_REASON |
    296                                  nsISelectionListener::MOUSEDOWN_REASON);
    297  EXPECT_EQ(FirstCaretAppearance(), Appearance::None);
    298  check.Call("mouse down");
    299 
    300  mManager.OnReflow();
    301  EXPECT_EQ(FirstCaretAppearance(), Appearance::None);
    302  check.Call("reflow");
    303 
    304  mManager.OnBlur();
    305  EXPECT_EQ(FirstCaretAppearance(), Appearance::None);
    306  check.Call("blur");
    307 
    308  mManager.OnSelectionChanged(nullptr, nullptr,
    309                              nsISelectionListener::MOUSEUP_REASON);
    310  EXPECT_EQ(FirstCaretAppearance(), Appearance::NormalNotShown);
    311  check.Call("mouse up");
    312 
    313  mManager.OnReflow();
    314  EXPECT_EQ(FirstCaretAppearance(), Appearance::NormalNotShown);
    315  check.Call("reflow2");
    316 
    317  mManager.OnScrollPositionChanged();
    318  EXPECT_EQ(FirstCaretAppearance(), Appearance::NormalNotShown);
    319 }
    320 
    321 TEST_F(AccessibleCaretManagerTester, TestTypingAtEndOfInput)
    322 MOZ_CAN_RUN_SCRIPT_FOR_DEFINITION {
    323  EXPECT_CALL(mManager, GetCaretMode())
    324      .WillRepeatedly(Return(CaretMode::Cursor));
    325 
    326  EXPECT_CALL(mManager, HasNonEmptyTextContent(_)).WillRepeatedly(Return(true));
    327 
    328  MockFunction<void(std::string aCheckPointName)> check;
    329  {
    330    InSequence dummy;
    331 
    332    EXPECT_CALL(mManager, DispatchCaretStateChangedEvent(
    333                              CaretChangedReason::Updateposition, nullptr))
    334        .Times(1);
    335    EXPECT_CALL(check, Call("update"));
    336 
    337    EXPECT_CALL(mManager, DispatchCaretStateChangedEvent(
    338                              CaretChangedReason::Visibilitychange, nullptr))
    339        .Times(1);
    340    EXPECT_CALL(check, Call("keyboard"));
    341 
    342    // No CaretStateChanged events should be dispatched since the caret has
    343    // being hidden in cursor mode.
    344    EXPECT_CALL(mManager, DispatchCaretStateChangedEvent(_, nullptr)).Times(0);
    345  }
    346 
    347  // Simulate typing the end of the input.
    348  mManager.UpdateCarets();
    349  EXPECT_EQ(FirstCaretAppearance(), Appearance::Normal);
    350  check.Call("update");
    351 
    352  mManager.OnKeyboardEvent();
    353  EXPECT_EQ(FirstCaretAppearance(), Appearance::None);
    354  check.Call("keyboard");
    355 
    356  mManager.OnSelectionChanged(nullptr, nullptr,
    357                              nsISelectionListener::NO_REASON);
    358  EXPECT_EQ(FirstCaretAppearance(), Appearance::None);
    359 
    360  mManager.OnScrollPositionChanged();
    361  EXPECT_EQ(FirstCaretAppearance(), Appearance::None);
    362 }
    363 
    364 TEST_F(AccessibleCaretManagerTester, TestScrollInSelectionMode)
    365 MOZ_CAN_RUN_SCRIPT_FOR_DEFINITION {
    366  // Set default preference.
    367  AutoRestoreBoolPref savedPref("layout.accessiblecaret.always_tilt", false);
    368 
    369  EXPECT_CALL(mManager, GetCaretMode())
    370      .WillRepeatedly(Return(CaretMode::Selection));
    371 
    372  MockFunction<void(std::string aCheckPointName)> check;
    373  {
    374    InSequence dummy;
    375 
    376    // Initially, first caret is out of scrollport, and second caret is visible.
    377    EXPECT_CALL(mManager.FirstCaret(), SetPosition(_, _))
    378        .WillOnce(Return(PositionChangedResult::Invisible));
    379 
    380    EXPECT_CALL(mManager, DispatchCaretStateChangedEvent(
    381                              CaretChangedReason::Updateposition, nullptr));
    382    EXPECT_CALL(check, Call("updatecarets"));
    383 
    384    EXPECT_CALL(mManager, DispatchCaretStateChangedEvent(
    385                              CaretChangedReason::Scroll, nullptr));
    386    EXPECT_CALL(check, Call("scrollstart1"));
    387 
    388    EXPECT_CALL(mManager, DispatchCaretStateChangedEvent(
    389                              CaretChangedReason::Updateposition, nullptr));
    390    EXPECT_CALL(check, Call("reflow1"));
    391 
    392    // After scroll ended, first caret is visible and second caret is out of
    393    // scroll port.
    394    EXPECT_CALL(mManager.SecondCaret(), SetPosition(_, _))
    395        .WillOnce(Return(PositionChangedResult::Invisible));
    396 
    397    EXPECT_CALL(mManager, DispatchCaretStateChangedEvent(
    398                              CaretChangedReason::Updateposition, nullptr));
    399    EXPECT_CALL(check, Call("scrollend1"));
    400 
    401    EXPECT_CALL(mManager, DispatchCaretStateChangedEvent(
    402                              CaretChangedReason::Scroll, nullptr));
    403    EXPECT_CALL(check, Call("scrollstart2"));
    404 
    405    EXPECT_CALL(mManager, DispatchCaretStateChangedEvent(
    406                              CaretChangedReason::Updateposition, nullptr));
    407    EXPECT_CALL(check, Call("reflow2"));
    408 
    409    // After the scroll ended, both carets are visible.
    410    EXPECT_CALL(mManager, DispatchCaretStateChangedEvent(
    411                              CaretChangedReason::Updateposition, nullptr));
    412    EXPECT_CALL(check, Call("scrollend2"));
    413  }
    414 
    415  mManager.UpdateCarets();
    416  EXPECT_EQ(FirstCaretAppearance(), Appearance::NormalNotShown);
    417  EXPECT_EQ(SecondCaretAppearance(), Appearance::Normal);
    418  check.Call("updatecarets");
    419 
    420  mManager.OnScrollStart();
    421  EXPECT_EQ(FirstCaretAppearance(), Appearance::NormalNotShown);
    422  EXPECT_EQ(SecondCaretAppearance(), Appearance::Normal);
    423  check.Call("scrollstart1");
    424 
    425  mManager.OnReflow();
    426  EXPECT_EQ(FirstCaretAppearance(), Appearance::NormalNotShown);
    427  EXPECT_EQ(SecondCaretAppearance(), Appearance::Normal);
    428  check.Call("reflow1");
    429 
    430  mManager.OnScrollEnd();
    431  EXPECT_EQ(FirstCaretAppearance(), Appearance::Normal);
    432  EXPECT_EQ(SecondCaretAppearance(), Appearance::NormalNotShown);
    433  check.Call("scrollend1");
    434 
    435  mManager.OnScrollStart();
    436  EXPECT_EQ(FirstCaretAppearance(), Appearance::Normal);
    437  EXPECT_EQ(SecondCaretAppearance(), Appearance::NormalNotShown);
    438  check.Call("scrollstart2");
    439 
    440  mManager.OnReflow();
    441  EXPECT_EQ(FirstCaretAppearance(), Appearance::Normal);
    442  EXPECT_EQ(SecondCaretAppearance(), Appearance::NormalNotShown);
    443  check.Call("reflow2");
    444 
    445  mManager.OnScrollEnd();
    446  EXPECT_EQ(FirstCaretAppearance(), Appearance::Normal);
    447  EXPECT_EQ(SecondCaretAppearance(), Appearance::Normal);
    448  check.Call("scrollend2");
    449 }
    450 
    451 TEST_F(AccessibleCaretManagerTester,
    452       TestScrollInSelectionModeWithAlwaysTiltPref)
    453 MOZ_CAN_RUN_SCRIPT_FOR_DEFINITION {
    454  // Simulate Firefox Android preference.
    455  AutoRestoreBoolPref savedPref("layout.accessiblecaret.always_tilt", true);
    456 
    457  EXPECT_CALL(mManager, GetCaretMode())
    458      .WillRepeatedly(Return(CaretMode::Selection));
    459 
    460  MockFunction<void(std::string aCheckPointName)> check;
    461  {
    462    InSequence dummy;
    463 
    464    // Initially, first caret is out of scrollport, and second caret is visible.
    465    EXPECT_CALL(mManager.FirstCaret(), SetPosition(_, _))
    466        .WillOnce(Return(PositionChangedResult::Invisible));
    467 
    468    EXPECT_CALL(mManager, DispatchCaretStateChangedEvent(
    469                              CaretChangedReason::Updateposition, nullptr));
    470    EXPECT_CALL(check, Call("updatecarets"));
    471 
    472    EXPECT_CALL(mManager, DispatchCaretStateChangedEvent(
    473                              CaretChangedReason::Scroll, nullptr));
    474    EXPECT_CALL(check, Call("scrollstart1"));
    475 
    476    EXPECT_CALL(mManager, DispatchCaretStateChangedEvent(_, nullptr)).Times(0);
    477    EXPECT_CALL(check, Call("scrollPositionChanged1"));
    478 
    479    EXPECT_CALL(mManager, DispatchCaretStateChangedEvent(
    480                              CaretChangedReason::Updateposition, nullptr));
    481    EXPECT_CALL(check, Call("reflow1"));
    482 
    483    // After scroll ended, first caret is visible and second caret is out of
    484    // scroll port.
    485    EXPECT_CALL(mManager.SecondCaret(), SetPosition(_, _))
    486        .WillOnce(Return(PositionChangedResult::Invisible));
    487 
    488    EXPECT_CALL(mManager, DispatchCaretStateChangedEvent(
    489                              CaretChangedReason::Updateposition, nullptr));
    490    EXPECT_CALL(check, Call("scrollend1"));
    491 
    492    EXPECT_CALL(mManager, DispatchCaretStateChangedEvent(
    493                              CaretChangedReason::Scroll, nullptr));
    494    EXPECT_CALL(check, Call("scrollstart2"));
    495 
    496    EXPECT_CALL(mManager, DispatchCaretStateChangedEvent(_, nullptr)).Times(0);
    497    EXPECT_CALL(check, Call("scrollPositionChanged2"));
    498 
    499    EXPECT_CALL(mManager, DispatchCaretStateChangedEvent(
    500                              CaretChangedReason::Updateposition, nullptr));
    501    EXPECT_CALL(check, Call("reflow2"));
    502 
    503    // After the scroll ended, both carets are visible.
    504    EXPECT_CALL(mManager, DispatchCaretStateChangedEvent(
    505                              CaretChangedReason::Updateposition, nullptr));
    506    EXPECT_CALL(check, Call("scrollend2"));
    507  }
    508 
    509  mManager.UpdateCarets();
    510  EXPECT_EQ(FirstCaretAppearance(), Appearance::NormalNotShown);
    511  EXPECT_EQ(SecondCaretAppearance(), Appearance::Right);
    512  check.Call("updatecarets");
    513 
    514  mManager.OnScrollStart();
    515  EXPECT_EQ(FirstCaretAppearance(), Appearance::NormalNotShown);
    516  EXPECT_EQ(SecondCaretAppearance(), Appearance::Right);
    517  check.Call("scrollstart1");
    518 
    519  mManager.OnScrollPositionChanged();
    520  EXPECT_EQ(FirstCaretAppearance(), Appearance::NormalNotShown);
    521  EXPECT_EQ(SecondCaretAppearance(), Appearance::Right);
    522  check.Call("scrollPositionChanged1");
    523 
    524  mManager.OnReflow();
    525  EXPECT_EQ(FirstCaretAppearance(), Appearance::NormalNotShown);
    526  EXPECT_EQ(SecondCaretAppearance(), Appearance::Right);
    527  check.Call("reflow1");
    528 
    529  mManager.OnScrollEnd();
    530  EXPECT_EQ(FirstCaretAppearance(), Appearance::Left);
    531  EXPECT_EQ(SecondCaretAppearance(), Appearance::NormalNotShown);
    532  check.Call("scrollend1");
    533 
    534  mManager.OnScrollStart();
    535  EXPECT_EQ(FirstCaretAppearance(), Appearance::Left);
    536  EXPECT_EQ(SecondCaretAppearance(), Appearance::NormalNotShown);
    537  check.Call("scrollstart2");
    538 
    539  mManager.OnScrollPositionChanged();
    540  EXPECT_EQ(FirstCaretAppearance(), Appearance::Left);
    541  EXPECT_EQ(SecondCaretAppearance(), Appearance::NormalNotShown);
    542  check.Call("scrollPositionChanged2");
    543 
    544  mManager.OnReflow();
    545  EXPECT_EQ(FirstCaretAppearance(), Appearance::Left);
    546  EXPECT_EQ(SecondCaretAppearance(), Appearance::NormalNotShown);
    547  check.Call("reflow2");
    548 
    549  mManager.OnScrollEnd();
    550  EXPECT_EQ(FirstCaretAppearance(), Appearance::Left);
    551  EXPECT_EQ(SecondCaretAppearance(), Appearance::Right);
    552  check.Call("scrollend2");
    553 }
    554 
    555 TEST_F(AccessibleCaretManagerTester, TestScrollInCursorModeWhenLogicallyVisible)
    556 MOZ_CAN_RUN_SCRIPT_FOR_DEFINITION {
    557  EXPECT_CALL(mManager, GetCaretMode())
    558      .WillRepeatedly(Return(CaretMode::Cursor));
    559 
    560  EXPECT_CALL(mManager, HasNonEmptyTextContent(_)).WillRepeatedly(Return(true));
    561 
    562  MockFunction<void(std::string aCheckPointName)> check;
    563  {
    564    InSequence dummy;
    565 
    566    EXPECT_CALL(mManager, DispatchCaretStateChangedEvent(
    567                              CaretChangedReason::Updateposition, nullptr))
    568        .Times(1);
    569    EXPECT_CALL(check, Call("updatecarets"));
    570 
    571    EXPECT_CALL(mManager, DispatchCaretStateChangedEvent(
    572                              CaretChangedReason::Scroll, nullptr))
    573        .Times(1);
    574    EXPECT_CALL(check, Call("scrollstart1"));
    575 
    576    // After scroll ended, the caret is out of scroll port.
    577    EXPECT_CALL(mManager.FirstCaret(), SetPosition(_, _))
    578        .WillRepeatedly(Return(PositionChangedResult::Invisible));
    579    EXPECT_CALL(mManager, DispatchCaretStateChangedEvent(
    580                              CaretChangedReason::Updateposition, nullptr))
    581        .Times(1);
    582    EXPECT_CALL(check, Call("scrollend1"));
    583 
    584    EXPECT_CALL(mManager, DispatchCaretStateChangedEvent(
    585                              CaretChangedReason::Scroll, nullptr))
    586        .Times(1);
    587    EXPECT_CALL(check, Call("scrollstart2"));
    588 
    589    // After scroll ended, the caret is visible again.
    590    EXPECT_CALL(mManager.FirstCaret(), SetPosition(_, _))
    591        .WillRepeatedly(Return(PositionChangedResult::Position));
    592    EXPECT_CALL(mManager, DispatchCaretStateChangedEvent(
    593                              CaretChangedReason::Updateposition, nullptr))
    594        .Times(1);
    595    EXPECT_CALL(check, Call("scrollend2"));
    596  }
    597 
    598  mManager.UpdateCarets();
    599  EXPECT_EQ(FirstCaretAppearance(), Appearance::Normal);
    600  check.Call("updatecarets");
    601 
    602  mManager.OnScrollStart();
    603  EXPECT_EQ(FirstCaretAppearance(), Appearance::Normal);
    604  check.Call("scrollstart1");
    605 
    606  mManager.OnScrollEnd();
    607  EXPECT_EQ(FirstCaretAppearance(), Appearance::NormalNotShown);
    608  check.Call("scrollend1");
    609 
    610  mManager.OnScrollStart();
    611  EXPECT_EQ(FirstCaretAppearance(), Appearance::NormalNotShown);
    612  check.Call("scrollstart2");
    613 
    614  mManager.OnScrollEnd();
    615  EXPECT_EQ(FirstCaretAppearance(), Appearance::Normal);
    616  check.Call("scrollend2");
    617 }
    618 
    619 TEST_F(AccessibleCaretManagerTester, TestScrollInCursorModeWhenHidden)
    620 MOZ_CAN_RUN_SCRIPT_FOR_DEFINITION {
    621  EXPECT_CALL(mManager, GetCaretMode())
    622      .WillRepeatedly(Return(CaretMode::Cursor));
    623 
    624  EXPECT_CALL(mManager, HasNonEmptyTextContent(_)).WillRepeatedly(Return(true));
    625 
    626  MockFunction<void(std::string aCheckPointName)> check;
    627  {
    628    InSequence dummy;
    629 
    630    EXPECT_CALL(mManager, DispatchCaretStateChangedEvent(
    631                              CaretChangedReason::Updateposition, nullptr))
    632        .Times(1);
    633    EXPECT_CALL(check, Call("updatecarets"));
    634 
    635    EXPECT_CALL(mManager, DispatchCaretStateChangedEvent(
    636                              CaretChangedReason::Visibilitychange, nullptr))
    637        .Times(1);
    638    EXPECT_CALL(check, Call("hidecarets"));
    639 
    640    // After scroll ended, the caret is out of scroll port.
    641    EXPECT_CALL(mManager.FirstCaret(), SetPosition(_, _))
    642        .WillRepeatedly(Return(PositionChangedResult::Invisible));
    643    EXPECT_CALL(check, Call("scrollend1"));
    644 
    645    // After scroll ended, the caret is visible again.
    646    EXPECT_CALL(mManager.FirstCaret(), SetPosition(_, _))
    647        .WillRepeatedly(Return(PositionChangedResult::Position));
    648    EXPECT_CALL(check, Call("scrollend2"));
    649  }
    650 
    651  mManager.UpdateCarets();
    652  EXPECT_EQ(FirstCaretAppearance(), Appearance::Normal);
    653  check.Call("updatecarets");
    654 
    655  mManager.HideCaretsAndDispatchCaretStateChangedEvent();
    656  EXPECT_EQ(FirstCaretAppearance(), Appearance::None);
    657  check.Call("hidecarets");
    658 
    659  mManager.OnScrollStart();
    660  EXPECT_EQ(FirstCaretAppearance(), Appearance::None);
    661 
    662  mManager.OnScrollEnd();
    663  EXPECT_EQ(FirstCaretAppearance(), Appearance::None);
    664  check.Call("scrollend1");
    665 
    666  mManager.OnScrollStart();
    667  EXPECT_EQ(FirstCaretAppearance(), Appearance::None);
    668 
    669  mManager.OnScrollEnd();
    670  EXPECT_EQ(FirstCaretAppearance(), Appearance::None);
    671  check.Call("scrollend2");
    672 }
    673 
    674 TEST_F(AccessibleCaretManagerTester, TestScrollInCursorModeOnEmptyContent)
    675 MOZ_CAN_RUN_SCRIPT_FOR_DEFINITION {
    676  // Set default preference.
    677  AutoRestoreBoolPref savedPref(
    678      "layout.accessiblecaret.caret_shown_when_long_tapping_on_empty_content",
    679      false);
    680 
    681  EXPECT_CALL(mManager, GetCaretMode())
    682      .WillRepeatedly(Return(CaretMode::Cursor));
    683 
    684  EXPECT_CALL(mManager, HasNonEmptyTextContent(_))
    685      .WillRepeatedly(Return(false));
    686 
    687  MockFunction<void(std::string aCheckPointName)> check;
    688  {
    689    InSequence dummy;
    690 
    691    EXPECT_CALL(mManager, DispatchCaretStateChangedEvent(
    692                              CaretChangedReason::Updateposition, nullptr));
    693    EXPECT_CALL(check, Call("updatecarets"));
    694 
    695    EXPECT_CALL(mManager, DispatchCaretStateChangedEvent(
    696                              CaretChangedReason::Scroll, nullptr));
    697    EXPECT_CALL(check, Call("scrollstart1"));
    698 
    699    EXPECT_CALL(mManager.FirstCaret(), SetPosition(_, _))
    700        .WillOnce(Return(PositionChangedResult::Invisible));
    701    EXPECT_CALL(mManager, DispatchCaretStateChangedEvent(
    702                              CaretChangedReason::Updateposition, nullptr));
    703    EXPECT_CALL(check, Call("scrollend1"));
    704 
    705    EXPECT_CALL(mManager, DispatchCaretStateChangedEvent(
    706                              CaretChangedReason::Scroll, nullptr));
    707    EXPECT_CALL(check, Call("scrollstart2"));
    708 
    709    EXPECT_CALL(mManager, DispatchCaretStateChangedEvent(
    710                              CaretChangedReason::Updateposition, nullptr));
    711    EXPECT_CALL(check, Call("scrollend2"));
    712 
    713    EXPECT_CALL(mManager, DispatchCaretStateChangedEvent(
    714                              CaretChangedReason::Scroll, nullptr));
    715    EXPECT_CALL(check, Call("scrollstart3"));
    716 
    717    EXPECT_CALL(mManager, DispatchCaretStateChangedEvent(
    718                              CaretChangedReason::Updateposition, nullptr));
    719    EXPECT_CALL(check, Call("scrollend3"));
    720  }
    721 
    722  // Simulate a pinch-zoom operation before tapping on an empty content.
    723  mManager.OnScrollStart();
    724  mManager.OnScrollEnd();
    725  EXPECT_EQ(mManager.IsScrollStarted(), false);
    726 
    727  // Simulate a single tap on an empty content.
    728  mManager.UpdateCarets();
    729  EXPECT_EQ(FirstCaretAppearance(), Appearance::NormalNotShown);
    730  check.Call("updatecarets");
    731 
    732  // Scroll the caret to be out of the viewport.
    733  mManager.OnScrollStart();
    734  check.Call("scrollstart1");
    735  mManager.OnScrollEnd();
    736  EXPECT_EQ(FirstCaretAppearance(), Appearance::NormalNotShown);
    737  check.Call("scrollend1");
    738 
    739  // Scroll the caret into the viewport.
    740  mManager.OnScrollStart();
    741  check.Call("scrollstart2");
    742  mManager.OnScrollEnd();
    743  EXPECT_EQ(FirstCaretAppearance(), Appearance::NormalNotShown);
    744  check.Call("scrollend2");
    745 
    746  // Scroll the caret within the viewport.
    747  mManager.OnScrollStart();
    748  check.Call("scrollstart3");
    749  mManager.OnScrollEnd();
    750  EXPECT_EQ(FirstCaretAppearance(), Appearance::NormalNotShown);
    751  check.Call("scrollend3");
    752 }
    753 
    754 TEST_F(AccessibleCaretManagerTester,
    755       TestScrollInCursorModeWithCaretShownWhenLongTappingOnEmptyContentPref)
    756 MOZ_CAN_RUN_SCRIPT_FOR_DEFINITION {
    757  // Simulate Firefox Android preference.
    758  AutoRestoreBoolPref savedPref(
    759      "layout.accessiblecaret.caret_shown_when_long_tapping_on_empty_content",
    760      true);
    761 
    762  EXPECT_CALL(mManager, GetCaretMode())
    763      .WillRepeatedly(Return(CaretMode::Cursor));
    764 
    765  EXPECT_CALL(mManager, HasNonEmptyTextContent(_))
    766      .WillRepeatedly(Return(false));
    767 
    768  MockFunction<void(std::string aCheckPointName)> check;
    769  {
    770    InSequence dummy;
    771 
    772    EXPECT_CALL(mManager, DispatchCaretStateChangedEvent(
    773                              CaretChangedReason::Updateposition, nullptr));
    774    EXPECT_CALL(check, Call("singletap updatecarets"));
    775 
    776    EXPECT_CALL(mManager, DispatchCaretStateChangedEvent(
    777                              CaretChangedReason::Updateposition, nullptr));
    778    EXPECT_CALL(check, Call("longtap updatecarets"));
    779 
    780    EXPECT_CALL(mManager, DispatchCaretStateChangedEvent(
    781                              CaretChangedReason::Scroll, nullptr));
    782    EXPECT_CALL(check, Call("longtap scrollstart1"));
    783 
    784    EXPECT_CALL(mManager.FirstCaret(), SetPosition(_, _))
    785        .WillOnce(Return(PositionChangedResult::Invisible));
    786    EXPECT_CALL(mManager, DispatchCaretStateChangedEvent(
    787                              CaretChangedReason::Updateposition, nullptr));
    788    EXPECT_CALL(check, Call("longtap scrollend1"));
    789 
    790    EXPECT_CALL(mManager, DispatchCaretStateChangedEvent(
    791                              CaretChangedReason::Scroll, nullptr));
    792    EXPECT_CALL(check, Call("longtap scrollstart2"));
    793 
    794    EXPECT_CALL(mManager, DispatchCaretStateChangedEvent(
    795                              CaretChangedReason::Updateposition, nullptr));
    796    EXPECT_CALL(check, Call("longtap scrollend2"));
    797 
    798    EXPECT_CALL(mManager, DispatchCaretStateChangedEvent(
    799                              CaretChangedReason::Scroll, nullptr));
    800    EXPECT_CALL(check, Call("longtap scrollstart3"));
    801 
    802    EXPECT_CALL(mManager, DispatchCaretStateChangedEvent(
    803                              CaretChangedReason::Updateposition, nullptr));
    804    EXPECT_CALL(check, Call("longtap scrollend3"));
    805  }
    806 
    807  // Simulate a single tap on an empty input.
    808  mManager.FirstCaret().SetAppearance(Appearance::None);
    809  mManager.UpdateCarets();
    810  EXPECT_EQ(FirstCaretAppearance(), Appearance::None);
    811  check.Call("singletap updatecarets");
    812 
    813  // Scroll the caret within the viewport.
    814  mManager.OnScrollStart();
    815  mManager.OnScrollEnd();
    816  EXPECT_EQ(FirstCaretAppearance(), Appearance::None);
    817 
    818  // Simulate a long tap on an empty input.
    819  mManager.FirstCaret().SetAppearance(Appearance::Normal);
    820  mManager.UpdateCarets();
    821  EXPECT_EQ(FirstCaretAppearance(), Appearance::Normal);
    822  check.Call("longtap updatecarets");
    823 
    824  // Scroll the caret to be out of the viewport.
    825  mManager.OnScrollStart();
    826  check.Call("longtap scrollstart1");
    827  mManager.OnScrollEnd();
    828  EXPECT_EQ(FirstCaretAppearance(), Appearance::NormalNotShown);
    829  check.Call("longtap scrollend1");
    830 
    831  // Scroll the caret into the viewport.
    832  mManager.OnScrollStart();
    833  check.Call("longtap scrollstart2");
    834  mManager.OnScrollPositionChanged();
    835  mManager.OnScrollEnd();
    836  EXPECT_EQ(FirstCaretAppearance(), Appearance::Normal);
    837  check.Call("longtap scrollend2");
    838 
    839  // Scroll the caret within the viewport.
    840  mManager.OnScrollStart();
    841  check.Call("longtap scrollstart3");
    842  mManager.OnScrollPositionChanged();
    843  mManager.OnScrollEnd();
    844  EXPECT_EQ(FirstCaretAppearance(), Appearance::Normal);
    845  check.Call("longtap scrollend3");
    846 }
    847 
    848 }  // namespace mozilla