Quellcodebibliothek Statistik Leitseite products/Sources/formale Sprachen/C/Firefox/layout/base/gtest/   (Browser von der Mozilla Stiftung Version 136.0.1©)  Datei vom 10.2.2025 mit Größe 29 kB image not shown  

Quelle  TestAccessibleCaretManager.cpp   Sprache: C

 
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */


#include "gtest/gtest.h"
#include "gmock/gmock.h"

#include <string>

#include "AccessibleCaret.h"
#include "AccessibleCaretManager.h"
#include "mozilla/Preferences.h"

using ::testing::_;
using ::testing::DefaultValue;
using ::testing::Eq;
using ::testing::InSequence;
using ::testing::MockFunction;
using ::testing::Return;

// -----------------------------------------------------------------------------
// This file tests CaretStateChanged events and the appearance of the two
// AccessibleCarets manipulated by AccessibleCaretManager.

namespace mozilla {
using dom::CaretChangedReason;

class MOZ_RAII AutoRestoreBoolPref final {
 public:
  AutoRestoreBoolPref(const char* aPref, bool aValue) : mPref(aPref) {
    Preferences::GetBool(mPref, &mOldValue);
    Preferences::SetBool(mPref, aValue);
  }

  ~AutoRestoreBoolPref() { Preferences::SetBool(mPref, mOldValue); }

 private:
  const char* mPref = nullptr;
  bool mOldValue = false;
};

class AccessibleCaretManagerTester : public ::testing::Test {
 public:
  class MockAccessibleCaret : public AccessibleCaret {
   public:
    MockAccessibleCaret() : AccessibleCaret(nullptr) {}

    void SetAppearance(Appearance aAppearance) override {
      // A simplified version without touching CaretElement().
      mAppearance = aAppearance;
    }

    MOCK_METHOD2(SetPosition,
                 PositionChangedResult(nsIFrame* aFrame, int32_t aOffset));

  };  // class MockAccessibleCaret

  class MockAccessibleCaretManager : public AccessibleCaretManager {
   public:
    using CaretMode = AccessibleCaretManager::CaretMode;
    using AccessibleCaretManager::HideCaretsAndDispatchCaretStateChangedEvent;
    using AccessibleCaretManager::UpdateCarets;

    MockAccessibleCaretManager()
        : AccessibleCaretManager(nullptr,
                                 Carets{MakeUnique<MockAccessibleCaret>(),
                                        MakeUnique<MockAccessibleCaret>()}) {}

    MockAccessibleCaret& FirstCaret() {
      return static_cast<MockAccessibleCaret&>(*mCarets.GetFirst());
    }

    MockAccessibleCaret& SecondCaret() {
      return static_cast<MockAccessibleCaret&>(*mCarets.GetSecond());
    }

    bool CompareTreePosition(nsIFrame* aStartFrame,
                             nsIFrame* aEndFrame) const override {
      return true;
    }

    bool IsCaretDisplayableInCursorMode(
        nsIFrame** aOutFrame = nullptr,
        int32_t* aOutOffset = nullptr) const override {
      return true;
    }

    bool UpdateCaretsForOverlappingTilt() override { return true; }

    void UpdateCaretsForAlwaysTilt(const nsIFrame* aStartFrame,
                                   const nsIFrame* aEndFrame) override {
      if (mCarets.GetFirst()->IsVisuallyVisible()) {
        mCarets.GetFirst()->SetAppearance(Appearance::Left);
      }
      if (mCarets.GetSecond()->IsVisuallyVisible()) {
        mCarets.GetSecond()->SetAppearance(Appearance::Right);
      }
    }

    Terminated IsTerminated() const override { return Terminated::No; }
    bool IsScrollStarted() const { return mIsScrollStarted; }

    Terminated MaybeFlushLayout() override { return Terminated::No; }

    MOCK_CONST_METHOD0(GetCaretMode, CaretMode());
    MOCK_METHOD2(DispatchCaretStateChangedEvent,
                 void(CaretChangedReason aReason, const nsPoint* aPoint));
    MOCK_CONST_METHOD1(HasNonEmptyTextContent, bool(nsINode* aNode));

  };  // class MockAccessibleCaretManager

  using Appearance = AccessibleCaret::Appearance;
  using PositionChangedResult = AccessibleCaret::PositionChangedResult;
  using CaretMode = MockAccessibleCaretManager::CaretMode;

  AccessibleCaretManagerTester() {
    DefaultValue<CaretMode>::Set(CaretMode::None);
    DefaultValue<PositionChangedResult>::Set(PositionChangedResult::NotChanged);

    EXPECT_CALL(mManager.FirstCaret(), SetPosition(_, _))
        .WillRepeatedly(Return(PositionChangedResult::Position));

    EXPECT_CALL(mManager.SecondCaret(), SetPosition(_, _))
        .WillRepeatedly(Return(PositionChangedResult::Position));
  }

  AccessibleCaret::Appearance FirstCaretAppearance() {
    return mManager.FirstCaret().GetAppearance();
  }

  AccessibleCaret::Appearance SecondCaretAppearance() {
    return mManager.SecondCaret().GetAppearance();
  }

  // Member variables
  MockAccessibleCaretManager mManager;

};  // class AccessibleCaretManagerTester

TEST_F(AccessibleCaretManagerTester, TestUpdatesInSelectionMode)
MOZ_CAN_RUN_SCRIPT_FOR_DEFINITION {
  // Set default preference.
  AutoRestoreBoolPref savedPref("layout.accessiblecaret.always_tilt"false);

  EXPECT_CALL(mManager, GetCaretMode())
      .WillRepeatedly(Return(CaretMode::Selection));

  EXPECT_CALL(mManager, DispatchCaretStateChangedEvent(
                            CaretChangedReason::Updateposition, nullptr))
      .Times(3);

  mManager.UpdateCarets();
  EXPECT_EQ(FirstCaretAppearance(), Appearance::Normal);
  EXPECT_EQ(SecondCaretAppearance(), Appearance::Normal);

  mManager.OnReflow();
  EXPECT_EQ(FirstCaretAppearance(), Appearance::Normal);
  EXPECT_EQ(SecondCaretAppearance(), Appearance::Normal);

  mManager.OnScrollPositionChanged();
  EXPECT_EQ(FirstCaretAppearance(), Appearance::Normal);
  EXPECT_EQ(SecondCaretAppearance(), Appearance::Normal);
}

TEST_F(AccessibleCaretManagerTester, TestSingleTapOnNonEmptyInput)
MOZ_CAN_RUN_SCRIPT_FOR_DEFINITION {
  EXPECT_CALL(mManager, GetCaretMode())
      .WillRepeatedly(Return(CaretMode::Cursor));

  EXPECT_CALL(mManager, HasNonEmptyTextContent(_)).WillRepeatedly(Return(true));

  MockFunction<void(std::string aCheckPointName)> check;
  {
    InSequence dummy;

    EXPECT_CALL(mManager, DispatchCaretStateChangedEvent(
                              CaretChangedReason::Updateposition, nullptr))
        .Times(1);
    EXPECT_CALL(check, Call("update"));

    EXPECT_CALL(mManager, DispatchCaretStateChangedEvent(
                              CaretChangedReason::Visibilitychange, nullptr))
        .Times(1);
    EXPECT_CALL(check, Call("mouse down"));

    EXPECT_CALL(mManager, DispatchCaretStateChangedEvent(_, nullptr)).Times(0);
    EXPECT_CALL(check, Call("reflow"));

    EXPECT_CALL(mManager, DispatchCaretStateChangedEvent(_, nullptr)).Times(0);
    EXPECT_CALL(check, Call("blur"));

    EXPECT_CALL(mManager, DispatchCaretStateChangedEvent(
                              CaretChangedReason::Updateposition, nullptr))
        .Times(1);
    EXPECT_CALL(check, Call("mouse up"));

    EXPECT_CALL(mManager, DispatchCaretStateChangedEvent(
                              CaretChangedReason::Updateposition, nullptr))
        .Times(1);
    EXPECT_CALL(check, Call("reflow2"));

    EXPECT_CALL(mManager, DispatchCaretStateChangedEvent(
                              CaretChangedReason::Updateposition, nullptr))
        .Times(1);
  }

  // Simulate a single tap on a non-empty input.
  mManager.UpdateCarets();
  EXPECT_EQ(FirstCaretAppearance(), Appearance::Normal);
  check.Call("update");

  mManager.OnSelectionChanged(nullptr, nullptr,
                              nsISelectionListener::DRAG_REASON |
                                  nsISelectionListener::MOUSEDOWN_REASON);
  EXPECT_EQ(FirstCaretAppearance(), Appearance::None);
  check.Call("mouse down");

  mManager.OnReflow();
  EXPECT_EQ(FirstCaretAppearance(), Appearance::None);
  check.Call("reflow");

  mManager.OnBlur();
  EXPECT_EQ(FirstCaretAppearance(), Appearance::None);
  check.Call("blur");

  mManager.OnSelectionChanged(nullptr, nullptr,
                              nsISelectionListener::MOUSEUP_REASON);
  EXPECT_EQ(FirstCaretAppearance(), Appearance::Normal);
  check.Call("mouse up");

  mManager.OnReflow();
  EXPECT_EQ(FirstCaretAppearance(), Appearance::Normal);
  check.Call("reflow2");

  mManager.OnScrollPositionChanged();
  EXPECT_EQ(FirstCaretAppearance(), Appearance::Normal);
}

TEST_F(AccessibleCaretManagerTester, TestSingleTapOnEmptyInput)
MOZ_CAN_RUN_SCRIPT_FOR_DEFINITION {
  // Set default preference.
  AutoRestoreBoolPref savedPref(
      "layout.accessiblecaret.caret_shown_when_long_tapping_on_empty_content",
      false);

  EXPECT_CALL(mManager, GetCaretMode())
      .WillRepeatedly(Return(CaretMode::Cursor));

  EXPECT_CALL(mManager, HasNonEmptyTextContent(_))
      .WillRepeatedly(Return(false));

  MockFunction<void(std::string aCheckPointName)> check;
  {
    InSequence dummy;

    EXPECT_CALL(mManager, DispatchCaretStateChangedEvent(
                              CaretChangedReason::Updateposition, nullptr))
        .Times(1);
    EXPECT_CALL(check, Call("update"));

    EXPECT_CALL(mManager, DispatchCaretStateChangedEvent(
                              CaretChangedReason::Visibilitychange, nullptr))
        .Times(1);
    EXPECT_CALL(check, Call("mouse down"));

    EXPECT_CALL(mManager, DispatchCaretStateChangedEvent(_, nullptr)).Times(0);
    EXPECT_CALL(check, Call("reflow"));

    EXPECT_CALL(mManager, DispatchCaretStateChangedEvent(_, nullptr)).Times(0);
    EXPECT_CALL(check, Call("blur"));

    EXPECT_CALL(mManager, DispatchCaretStateChangedEvent(
                              CaretChangedReason::Updateposition, nullptr))
        .Times(1);
    EXPECT_CALL(check, Call("mouse up"));

    EXPECT_CALL(mManager, DispatchCaretStateChangedEvent(
                              CaretChangedReason::Updateposition, nullptr))
        .Times(1);
    EXPECT_CALL(check, Call("reflow2"));

    EXPECT_CALL(mManager, DispatchCaretStateChangedEvent(
                              CaretChangedReason::Updateposition, nullptr))
        .Times(1);
  }

  // Simulate a single tap on an empty input.
  mManager.UpdateCarets();
  EXPECT_EQ(FirstCaretAppearance(), Appearance::NormalNotShown);
  check.Call("update");

  mManager.OnSelectionChanged(nullptr, nullptr,
                              nsISelectionListener::DRAG_REASON |
                                  nsISelectionListener::MOUSEDOWN_REASON);
  EXPECT_EQ(FirstCaretAppearance(), Appearance::None);
  check.Call("mouse down");

  mManager.OnReflow();
  EXPECT_EQ(FirstCaretAppearance(), Appearance::None);
  check.Call("reflow");

  mManager.OnBlur();
  EXPECT_EQ(FirstCaretAppearance(), Appearance::None);
  check.Call("blur");

  mManager.OnSelectionChanged(nullptr, nullptr,
                              nsISelectionListener::MOUSEUP_REASON);
  EXPECT_EQ(FirstCaretAppearance(), Appearance::NormalNotShown);
  check.Call("mouse up");

  mManager.OnReflow();
  EXPECT_EQ(FirstCaretAppearance(), Appearance::NormalNotShown);
  check.Call("reflow2");

  mManager.OnScrollPositionChanged();
  EXPECT_EQ(FirstCaretAppearance(), Appearance::NormalNotShown);
}

TEST_F(AccessibleCaretManagerTester, TestTypingAtEndOfInput)
MOZ_CAN_RUN_SCRIPT_FOR_DEFINITION {
  EXPECT_CALL(mManager, GetCaretMode())
      .WillRepeatedly(Return(CaretMode::Cursor));

  EXPECT_CALL(mManager, HasNonEmptyTextContent(_)).WillRepeatedly(Return(true));

  MockFunction<void(std::string aCheckPointName)> check;
  {
    InSequence dummy;

    EXPECT_CALL(mManager, DispatchCaretStateChangedEvent(
                              CaretChangedReason::Updateposition, nullptr))
        .Times(1);
    EXPECT_CALL(check, Call("update"));

    EXPECT_CALL(mManager, DispatchCaretStateChangedEvent(
                              CaretChangedReason::Visibilitychange, nullptr))
        .Times(1);
    EXPECT_CALL(check, Call("keyboard"));

    // No CaretStateChanged events should be dispatched since the caret has
    // being hidden in cursor mode.
    EXPECT_CALL(mManager, DispatchCaretStateChangedEvent(_, nullptr)).Times(0);
  }

  // Simulate typing the end of the input.
  mManager.UpdateCarets();
  EXPECT_EQ(FirstCaretAppearance(), Appearance::Normal);
  check.Call("update");

  mManager.OnKeyboardEvent();
  EXPECT_EQ(FirstCaretAppearance(), Appearance::None);
  check.Call("keyboard");

  mManager.OnSelectionChanged(nullptr, nullptr,
                              nsISelectionListener::NO_REASON);
  EXPECT_EQ(FirstCaretAppearance(), Appearance::None);

  mManager.OnScrollPositionChanged();
  EXPECT_EQ(FirstCaretAppearance(), Appearance::None);
}

TEST_F(AccessibleCaretManagerTester, TestScrollInSelectionMode)
MOZ_CAN_RUN_SCRIPT_FOR_DEFINITION {
  // Set default preference.
  AutoRestoreBoolPref savedPref("layout.accessiblecaret.always_tilt"false);

  EXPECT_CALL(mManager, GetCaretMode())
      .WillRepeatedly(Return(CaretMode::Selection));

  MockFunction<void(std::string aCheckPointName)> check;
  {
    InSequence dummy;

    // Initially, first caret is out of scrollport, and second caret is visible.
    EXPECT_CALL(mManager.FirstCaret(), SetPosition(_, _))
        .WillOnce(Return(PositionChangedResult::Invisible));

    EXPECT_CALL(mManager, DispatchCaretStateChangedEvent(
                              CaretChangedReason::Updateposition, nullptr));
    EXPECT_CALL(check, Call("updatecarets"));

    EXPECT_CALL(mManager, DispatchCaretStateChangedEvent(
                              CaretChangedReason::Scroll, nullptr));
    EXPECT_CALL(check, Call("scrollstart1"));

    EXPECT_CALL(mManager, DispatchCaretStateChangedEvent(
                              CaretChangedReason::Updateposition, nullptr));
    EXPECT_CALL(check, Call("reflow1"));

    // After scroll ended, first caret is visible and second caret is out of
    // scroll port.
    EXPECT_CALL(mManager.SecondCaret(), SetPosition(_, _))
        .WillOnce(Return(PositionChangedResult::Invisible));

    EXPECT_CALL(mManager, DispatchCaretStateChangedEvent(
                              CaretChangedReason::Updateposition, nullptr));
    EXPECT_CALL(check, Call("scrollend1"));

    EXPECT_CALL(mManager, DispatchCaretStateChangedEvent(
                              CaretChangedReason::Scroll, nullptr));
    EXPECT_CALL(check, Call("scrollstart2"));

    EXPECT_CALL(mManager, DispatchCaretStateChangedEvent(
                              CaretChangedReason::Updateposition, nullptr));
    EXPECT_CALL(check, Call("reflow2"));

    // After the scroll ended, both carets are visible.
    EXPECT_CALL(mManager, DispatchCaretStateChangedEvent(
                              CaretChangedReason::Updateposition, nullptr));
    EXPECT_CALL(check, Call("scrollend2"));
  }

  mManager.UpdateCarets();
  EXPECT_EQ(FirstCaretAppearance(), Appearance::NormalNotShown);
  EXPECT_EQ(SecondCaretAppearance(), Appearance::Normal);
  check.Call("updatecarets");

  mManager.OnScrollStart();
  EXPECT_EQ(FirstCaretAppearance(), Appearance::NormalNotShown);
  EXPECT_EQ(SecondCaretAppearance(), Appearance::Normal);
  check.Call("scrollstart1");

  mManager.OnReflow();
  EXPECT_EQ(FirstCaretAppearance(), Appearance::NormalNotShown);
  EXPECT_EQ(SecondCaretAppearance(), Appearance::Normal);
  check.Call("reflow1");

  mManager.OnScrollEnd();
  EXPECT_EQ(FirstCaretAppearance(), Appearance::Normal);
  EXPECT_EQ(SecondCaretAppearance(), Appearance::NormalNotShown);
  check.Call("scrollend1");

  mManager.OnScrollStart();
  EXPECT_EQ(FirstCaretAppearance(), Appearance::Normal);
  EXPECT_EQ(SecondCaretAppearance(), Appearance::NormalNotShown);
  check.Call("scrollstart2");

  mManager.OnReflow();
  EXPECT_EQ(FirstCaretAppearance(), Appearance::Normal);
  EXPECT_EQ(SecondCaretAppearance(), Appearance::NormalNotShown);
  check.Call("reflow2");

  mManager.OnScrollEnd();
  EXPECT_EQ(FirstCaretAppearance(), Appearance::Normal);
  EXPECT_EQ(SecondCaretAppearance(), Appearance::Normal);
  check.Call("scrollend2");
}

TEST_F(AccessibleCaretManagerTester,
       TestScrollInSelectionModeWithAlwaysTiltPref)
MOZ_CAN_RUN_SCRIPT_FOR_DEFINITION {
  // Simulate Firefox Android preference.
  AutoRestoreBoolPref savedPref("layout.accessiblecaret.always_tilt"true);

  EXPECT_CALL(mManager, GetCaretMode())
      .WillRepeatedly(Return(CaretMode::Selection));

  MockFunction<void(std::string aCheckPointName)> check;
  {
    InSequence dummy;

    // Initially, first caret is out of scrollport, and second caret is visible.
    EXPECT_CALL(mManager.FirstCaret(), SetPosition(_, _))
        .WillOnce(Return(PositionChangedResult::Invisible));

    EXPECT_CALL(mManager, DispatchCaretStateChangedEvent(
                              CaretChangedReason::Updateposition, nullptr));
    EXPECT_CALL(check, Call("updatecarets"));

    EXPECT_CALL(mManager, DispatchCaretStateChangedEvent(
                              CaretChangedReason::Scroll, nullptr));
    EXPECT_CALL(check, Call("scrollstart1"));

    EXPECT_CALL(mManager, DispatchCaretStateChangedEvent(_, nullptr)).Times(0);
    EXPECT_CALL(check, Call("scrollPositionChanged1"));

    EXPECT_CALL(mManager, DispatchCaretStateChangedEvent(
                              CaretChangedReason::Updateposition, nullptr));
    EXPECT_CALL(check, Call("reflow1"));

    // After scroll ended, first caret is visible and second caret is out of
    // scroll port.
    EXPECT_CALL(mManager.SecondCaret(), SetPosition(_, _))
        .WillOnce(Return(PositionChangedResult::Invisible));

    EXPECT_CALL(mManager, DispatchCaretStateChangedEvent(
                              CaretChangedReason::Updateposition, nullptr));
    EXPECT_CALL(check, Call("scrollend1"));

    EXPECT_CALL(mManager, DispatchCaretStateChangedEvent(
                              CaretChangedReason::Scroll, nullptr));
    EXPECT_CALL(check, Call("scrollstart2"));

    EXPECT_CALL(mManager, DispatchCaretStateChangedEvent(_, nullptr)).Times(0);
    EXPECT_CALL(check, Call("scrollPositionChanged2"));

    EXPECT_CALL(mManager, DispatchCaretStateChangedEvent(
                              CaretChangedReason::Updateposition, nullptr));
    EXPECT_CALL(check, Call("reflow2"));

    // After the scroll ended, both carets are visible.
    EXPECT_CALL(mManager, DispatchCaretStateChangedEvent(
                              CaretChangedReason::Updateposition, nullptr));
    EXPECT_CALL(check, Call("scrollend2"));
  }

  mManager.UpdateCarets();
  EXPECT_EQ(FirstCaretAppearance(), Appearance::NormalNotShown);
  EXPECT_EQ(SecondCaretAppearance(), Appearance::Right);
  check.Call("updatecarets");

  mManager.OnScrollStart();
  EXPECT_EQ(FirstCaretAppearance(), Appearance::NormalNotShown);
  EXPECT_EQ(SecondCaretAppearance(), Appearance::Right);
  check.Call("scrollstart1");

  mManager.OnScrollPositionChanged();
  EXPECT_EQ(FirstCaretAppearance(), Appearance::NormalNotShown);
  EXPECT_EQ(SecondCaretAppearance(), Appearance::Right);
  check.Call("scrollPositionChanged1");

  mManager.OnReflow();
  EXPECT_EQ(FirstCaretAppearance(), Appearance::NormalNotShown);
  EXPECT_EQ(SecondCaretAppearance(), Appearance::Right);
  check.Call("reflow1");

  mManager.OnScrollEnd();
  EXPECT_EQ(FirstCaretAppearance(), Appearance::Left);
  EXPECT_EQ(SecondCaretAppearance(), Appearance::NormalNotShown);
  check.Call("scrollend1");

  mManager.OnScrollStart();
  EXPECT_EQ(FirstCaretAppearance(), Appearance::Left);
  EXPECT_EQ(SecondCaretAppearance(), Appearance::NormalNotShown);
  check.Call("scrollstart2");

  mManager.OnScrollPositionChanged();
  EXPECT_EQ(FirstCaretAppearance(), Appearance::Left);
  EXPECT_EQ(SecondCaretAppearance(), Appearance::NormalNotShown);
  check.Call("scrollPositionChanged2");

  mManager.OnReflow();
  EXPECT_EQ(FirstCaretAppearance(), Appearance::Left);
  EXPECT_EQ(SecondCaretAppearance(), Appearance::NormalNotShown);
  check.Call("reflow2");

  mManager.OnScrollEnd();
  EXPECT_EQ(FirstCaretAppearance(), Appearance::Left);
  EXPECT_EQ(SecondCaretAppearance(), Appearance::Right);
  check.Call("scrollend2");
}

TEST_F(AccessibleCaretManagerTester, TestScrollInCursorModeWhenLogicallyVisible)
MOZ_CAN_RUN_SCRIPT_FOR_DEFINITION {
  EXPECT_CALL(mManager, GetCaretMode())
      .WillRepeatedly(Return(CaretMode::Cursor));

  EXPECT_CALL(mManager, HasNonEmptyTextContent(_)).WillRepeatedly(Return(true));

  MockFunction<void(std::string aCheckPointName)> check;
  {
    InSequence dummy;

    EXPECT_CALL(mManager, DispatchCaretStateChangedEvent(
                              CaretChangedReason::Updateposition, nullptr))
        .Times(1);
    EXPECT_CALL(check, Call("updatecarets"));

    EXPECT_CALL(mManager, DispatchCaretStateChangedEvent(
                              CaretChangedReason::Scroll, nullptr))
        .Times(1);
    EXPECT_CALL(check, Call("scrollstart1"));

    // After scroll ended, the caret is out of scroll port.
    EXPECT_CALL(mManager.FirstCaret(), SetPosition(_, _))
        .WillRepeatedly(Return(PositionChangedResult::Invisible));
    EXPECT_CALL(mManager, DispatchCaretStateChangedEvent(
                              CaretChangedReason::Updateposition, nullptr))
        .Times(1);
    EXPECT_CALL(check, Call("scrollend1"));

    EXPECT_CALL(mManager, DispatchCaretStateChangedEvent(
                              CaretChangedReason::Scroll, nullptr))
        .Times(1);
    EXPECT_CALL(check, Call("scrollstart2"));

    // After scroll ended, the caret is visible again.
    EXPECT_CALL(mManager.FirstCaret(), SetPosition(_, _))
        .WillRepeatedly(Return(PositionChangedResult::Position));
    EXPECT_CALL(mManager, DispatchCaretStateChangedEvent(
                              CaretChangedReason::Updateposition, nullptr))
        .Times(1);
    EXPECT_CALL(check, Call("scrollend2"));
  }

  mManager.UpdateCarets();
  EXPECT_EQ(FirstCaretAppearance(), Appearance::Normal);
  check.Call("updatecarets");

  mManager.OnScrollStart();
  EXPECT_EQ(FirstCaretAppearance(), Appearance::Normal);
  check.Call("scrollstart1");

  mManager.OnScrollEnd();
  EXPECT_EQ(FirstCaretAppearance(), Appearance::NormalNotShown);
  check.Call("scrollend1");

  mManager.OnScrollStart();
  EXPECT_EQ(FirstCaretAppearance(), Appearance::NormalNotShown);
  check.Call("scrollstart2");

  mManager.OnScrollEnd();
  EXPECT_EQ(FirstCaretAppearance(), Appearance::Normal);
  check.Call("scrollend2");
}

TEST_F(AccessibleCaretManagerTester, TestScrollInCursorModeWhenHidden)
MOZ_CAN_RUN_SCRIPT_FOR_DEFINITION {
  EXPECT_CALL(mManager, GetCaretMode())
      .WillRepeatedly(Return(CaretMode::Cursor));

  EXPECT_CALL(mManager, HasNonEmptyTextContent(_)).WillRepeatedly(Return(true));

  MockFunction<void(std::string aCheckPointName)> check;
  {
    InSequence dummy;

    EXPECT_CALL(mManager, DispatchCaretStateChangedEvent(
                              CaretChangedReason::Updateposition, nullptr))
        .Times(1);
    EXPECT_CALL(check, Call("updatecarets"));

    EXPECT_CALL(mManager, DispatchCaretStateChangedEvent(
                              CaretChangedReason::Visibilitychange, nullptr))
        .Times(1);
    EXPECT_CALL(check, Call("hidecarets"));

    // After scroll ended, the caret is out of scroll port.
    EXPECT_CALL(mManager.FirstCaret(), SetPosition(_, _))
        .WillRepeatedly(Return(PositionChangedResult::Invisible));
    EXPECT_CALL(check, Call("scrollend1"));

    // After scroll ended, the caret is visible again.
    EXPECT_CALL(mManager.FirstCaret(), SetPosition(_, _))
        .WillRepeatedly(Return(PositionChangedResult::Position));
    EXPECT_CALL(check, Call("scrollend2"));
  }

  mManager.UpdateCarets();
  EXPECT_EQ(FirstCaretAppearance(), Appearance::Normal);
  check.Call("updatecarets");

  mManager.HideCaretsAndDispatchCaretStateChangedEvent();
  EXPECT_EQ(FirstCaretAppearance(), Appearance::None);
  check.Call("hidecarets");

  mManager.OnScrollStart();
  EXPECT_EQ(FirstCaretAppearance(), Appearance::None);

  mManager.OnScrollEnd();
  EXPECT_EQ(FirstCaretAppearance(), Appearance::None);
  check.Call("scrollend1");

  mManager.OnScrollStart();
  EXPECT_EQ(FirstCaretAppearance(), Appearance::None);

  mManager.OnScrollEnd();
  EXPECT_EQ(FirstCaretAppearance(), Appearance::None);
  check.Call("scrollend2");
}

TEST_F(AccessibleCaretManagerTester, TestScrollInCursorModeOnEmptyContent)
MOZ_CAN_RUN_SCRIPT_FOR_DEFINITION {
  // Set default preference.
  AutoRestoreBoolPref savedPref(
      "layout.accessiblecaret.caret_shown_when_long_tapping_on_empty_content",
      false);

  EXPECT_CALL(mManager, GetCaretMode())
      .WillRepeatedly(Return(CaretMode::Cursor));

  EXPECT_CALL(mManager, HasNonEmptyTextContent(_))
      .WillRepeatedly(Return(false));

  MockFunction<void(std::string aCheckPointName)> check;
  {
    InSequence dummy;

    EXPECT_CALL(mManager, DispatchCaretStateChangedEvent(
                              CaretChangedReason::Updateposition, nullptr));
    EXPECT_CALL(check, Call("updatecarets"));

    EXPECT_CALL(mManager, DispatchCaretStateChangedEvent(
                              CaretChangedReason::Scroll, nullptr));
    EXPECT_CALL(check, Call("scrollstart1"));

    EXPECT_CALL(mManager.FirstCaret(), SetPosition(_, _))
        .WillOnce(Return(PositionChangedResult::Invisible));
    EXPECT_CALL(mManager, DispatchCaretStateChangedEvent(
                              CaretChangedReason::Updateposition, nullptr));
    EXPECT_CALL(check, Call("scrollend1"));

    EXPECT_CALL(mManager, DispatchCaretStateChangedEvent(
                              CaretChangedReason::Scroll, nullptr));
    EXPECT_CALL(check, Call("scrollstart2"));

    EXPECT_CALL(mManager, DispatchCaretStateChangedEvent(
                              CaretChangedReason::Updateposition, nullptr));
    EXPECT_CALL(check, Call("scrollend2"));

    EXPECT_CALL(mManager, DispatchCaretStateChangedEvent(
                              CaretChangedReason::Scroll, nullptr));
    EXPECT_CALL(check, Call("scrollstart3"));

    EXPECT_CALL(mManager, DispatchCaretStateChangedEvent(
                              CaretChangedReason::Updateposition, nullptr));
    EXPECT_CALL(check, Call("scrollend3"));
  }

  // Simulate a pinch-zoom operation before tapping on an empty content.
  mManager.OnScrollStart();
  mManager.OnScrollEnd();
  EXPECT_EQ(mManager.IsScrollStarted(), false);

  // Simulate a single tap on an empty content.
  mManager.UpdateCarets();
  EXPECT_EQ(FirstCaretAppearance(), Appearance::NormalNotShown);
  check.Call("updatecarets");

  // Scroll the caret to be out of the viewport.
  mManager.OnScrollStart();
  check.Call("scrollstart1");
  mManager.OnScrollEnd();
  EXPECT_EQ(FirstCaretAppearance(), Appearance::NormalNotShown);
  check.Call("scrollend1");

  // Scroll the caret into the viewport.
  mManager.OnScrollStart();
  check.Call("scrollstart2");
  mManager.OnScrollEnd();
  EXPECT_EQ(FirstCaretAppearance(), Appearance::NormalNotShown);
  check.Call("scrollend2");

  // Scroll the caret within the viewport.
  mManager.OnScrollStart();
  check.Call("scrollstart3");
  mManager.OnScrollEnd();
  EXPECT_EQ(FirstCaretAppearance(), Appearance::NormalNotShown);
  check.Call("scrollend3");
}

TEST_F(AccessibleCaretManagerTester,
       TestScrollInCursorModeWithCaretShownWhenLongTappingOnEmptyContentPref)
MOZ_CAN_RUN_SCRIPT_FOR_DEFINITION {
  // Simulate Firefox Android preference.
  AutoRestoreBoolPref savedPref(
      "layout.accessiblecaret.caret_shown_when_long_tapping_on_empty_content",
      true);

  EXPECT_CALL(mManager, GetCaretMode())
      .WillRepeatedly(Return(CaretMode::Cursor));

  EXPECT_CALL(mManager, HasNonEmptyTextContent(_))
      .WillRepeatedly(Return(false));

  MockFunction<void(std::string aCheckPointName)> check;
  {
    InSequence dummy;

    EXPECT_CALL(mManager, DispatchCaretStateChangedEvent(
                              CaretChangedReason::Updateposition, nullptr));
    EXPECT_CALL(check, Call("singletap updatecarets"));

    EXPECT_CALL(mManager, DispatchCaretStateChangedEvent(
                              CaretChangedReason::Updateposition, nullptr));
    EXPECT_CALL(check, Call("longtap updatecarets"));

    EXPECT_CALL(mManager, DispatchCaretStateChangedEvent(
                              CaretChangedReason::Scroll, nullptr));
    EXPECT_CALL(check, Call("longtap scrollstart1"));

    EXPECT_CALL(mManager.FirstCaret(), SetPosition(_, _))
        .WillOnce(Return(PositionChangedResult::Invisible));
    EXPECT_CALL(mManager, DispatchCaretStateChangedEvent(
                              CaretChangedReason::Updateposition, nullptr));
    EXPECT_CALL(check, Call("longtap scrollend1"));

    EXPECT_CALL(mManager, DispatchCaretStateChangedEvent(
                              CaretChangedReason::Scroll, nullptr));
    EXPECT_CALL(check, Call("longtap scrollstart2"));

    EXPECT_CALL(mManager, DispatchCaretStateChangedEvent(
                              CaretChangedReason::Updateposition, nullptr));
    EXPECT_CALL(check, Call("longtap scrollend2"));

    EXPECT_CALL(mManager, DispatchCaretStateChangedEvent(
                              CaretChangedReason::Scroll, nullptr));
    EXPECT_CALL(check, Call("longtap scrollstart3"));

    EXPECT_CALL(mManager, DispatchCaretStateChangedEvent(
                              CaretChangedReason::Updateposition, nullptr));
    EXPECT_CALL(check, Call("longtap scrollend3"));
  }

  // Simulate a single tap on an empty input.
  mManager.FirstCaret().SetAppearance(Appearance::None);
  mManager.UpdateCarets();
  EXPECT_EQ(FirstCaretAppearance(), Appearance::None);
  check.Call("singletap updatecarets");

  // Scroll the caret within the viewport.
  mManager.OnScrollStart();
  mManager.OnScrollEnd();
  EXPECT_EQ(FirstCaretAppearance(), Appearance::None);

  // Simulate a long tap on an empty input.
  mManager.FirstCaret().SetAppearance(Appearance::Normal);
  mManager.UpdateCarets();
  EXPECT_EQ(FirstCaretAppearance(), Appearance::Normal);
  check.Call("longtap updatecarets");

  // Scroll the caret to be out of the viewport.
  mManager.OnScrollStart();
  check.Call("longtap scrollstart1");
  mManager.OnScrollEnd();
  EXPECT_EQ(FirstCaretAppearance(), Appearance::NormalNotShown);
  check.Call("longtap scrollend1");

  // Scroll the caret into the viewport.
  mManager.OnScrollStart();
  check.Call("longtap scrollstart2");
  mManager.OnScrollPositionChanged();
  mManager.OnScrollEnd();
  EXPECT_EQ(FirstCaretAppearance(), Appearance::Normal);
  check.Call("longtap scrollend2");

  // Scroll the caret within the viewport.
  mManager.OnScrollStart();
  check.Call("longtap scrollstart3");
  mManager.OnScrollPositionChanged();
  mManager.OnScrollEnd();
  EXPECT_EQ(FirstCaretAppearance(), Appearance::Normal);
  check.Call("longtap scrollend3");
}

}  // namespace mozilla

Messung V0.5
C=94 H=98 G=95

¤ Dauer der Verarbeitung: 0.15 Sekunden  (vorverarbeitet)  ¤

*© Formatika GbR, Deutschland






Wurzel

Suchen

Beweissystem der NASA

Beweissystem Isabelle

NIST Cobol Testsuite

Cephes Mathematical Library

Wiener Entwicklungsmethode

Haftungshinweis

Die Informationen auf dieser Webseite wurden nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit, noch Qualität der bereit gestellten Informationen zugesichert.

Bemerkung:

Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.