ink_drop_highlight_unittest.cc 8.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238
  1. // Copyright 2015 The Chromium Authors. All rights reserved.
  2. // Use of this source code is governed by a BSD-style license that can be
  3. // found in the LICENSE file.
  4. #include "ui/views/animation/ink_drop_highlight.h"
  5. #include <cmath>
  6. #include <memory>
  7. #include <utility>
  8. #include "base/time/time.h"
  9. #include "testing/gtest/include/gtest/gtest.h"
  10. #include "ui/compositor/layer.h"
  11. #include "ui/compositor/scoped_animation_duration_scale_mode.h"
  12. #include "ui/gfx/animation/animation.h"
  13. #include "ui/gfx/animation/animation_test_api.h"
  14. #include "ui/gfx/geometry/size.h"
  15. #include "ui/gfx/geometry/transform.h"
  16. #include "ui/views/animation/test/ink_drop_highlight_test_api.h"
  17. #include "ui/views/animation/test/test_ink_drop_highlight_observer.h"
  18. namespace views {
  19. namespace test {
  20. class InkDropHighlightTest : public testing::Test {
  21. public:
  22. InkDropHighlightTest();
  23. InkDropHighlightTest(const InkDropHighlightTest&) = delete;
  24. InkDropHighlightTest& operator=(const InkDropHighlightTest&) = delete;
  25. ~InkDropHighlightTest() override;
  26. protected:
  27. InkDropHighlight* ink_drop_highlight() { return ink_drop_highlight_.get(); }
  28. InkDropHighlightTestApi* test_api() { return test_api_.get(); }
  29. // Observer of the test target.
  30. TestInkDropHighlightObserver* observer() { return &observer_; }
  31. // Initializes |ink_drop_highlight_| and attaches |test_api_| and |observer_|
  32. // to the new instance.
  33. void InitHighlight(std::unique_ptr<InkDropHighlight> new_highlight);
  34. // Destroys the |ink_drop_highlight_| and the attached |test_api_|.
  35. void DestroyHighlight();
  36. private:
  37. // The test target.
  38. std::unique_ptr<InkDropHighlight> ink_drop_highlight_;
  39. // Allows privileged access to the the |ink_drop_highlight_|.
  40. std::unique_ptr<InkDropHighlightTestApi> test_api_;
  41. // Observer of the test target.
  42. TestInkDropHighlightObserver observer_;
  43. std::unique_ptr<base::AutoReset<gfx::Animation::RichAnimationRenderMode>>
  44. animation_mode_reset_;
  45. };
  46. InkDropHighlightTest::InkDropHighlightTest()
  47. : animation_mode_reset_(gfx::AnimationTestApi::SetRichAnimationRenderMode(
  48. gfx::Animation::RichAnimationRenderMode::FORCE_DISABLED)) {
  49. InitHighlight(std::make_unique<InkDropHighlight>(
  50. gfx::Size(10, 10), 3, gfx::PointF(), SK_ColorBLACK));
  51. }
  52. InkDropHighlightTest::~InkDropHighlightTest() {
  53. // Destory highlight to make sure it is destroyed before the observer.
  54. DestroyHighlight();
  55. }
  56. void InkDropHighlightTest::InitHighlight(
  57. std::unique_ptr<InkDropHighlight> new_highlight) {
  58. ink_drop_highlight_ = std::move(new_highlight);
  59. test_api_ =
  60. std::make_unique<InkDropHighlightTestApi>(ink_drop_highlight_.get());
  61. test_api()->SetDisableAnimationTimers(true);
  62. ink_drop_highlight()->set_observer(&observer_);
  63. }
  64. void InkDropHighlightTest::DestroyHighlight() {
  65. test_api_.reset();
  66. ink_drop_highlight_.reset();
  67. }
  68. TEST_F(InkDropHighlightTest, InitialStateAfterConstruction) {
  69. EXPECT_FALSE(ink_drop_highlight()->IsFadingInOrVisible());
  70. }
  71. TEST_F(InkDropHighlightTest, IsHighlightedStateTransitions) {
  72. ink_drop_highlight()->FadeIn(base::Seconds(1));
  73. EXPECT_TRUE(ink_drop_highlight()->IsFadingInOrVisible());
  74. test_api()->CompleteAnimations();
  75. EXPECT_TRUE(ink_drop_highlight()->IsFadingInOrVisible());
  76. ink_drop_highlight()->FadeOut(base::Seconds(1));
  77. EXPECT_FALSE(ink_drop_highlight()->IsFadingInOrVisible());
  78. test_api()->CompleteAnimations();
  79. EXPECT_FALSE(ink_drop_highlight()->IsFadingInOrVisible());
  80. }
  81. TEST_F(InkDropHighlightTest, VerifyObserversAreNotified) {
  82. // TODO(bruthig): Re-enable! For some reason these tests fail on some win
  83. // trunk builds. See crbug.com/731811.
  84. if (!gfx::Animation::ShouldRenderRichAnimation())
  85. return;
  86. ink_drop_highlight()->FadeIn(base::Seconds(1));
  87. EXPECT_EQ(1, observer()->last_animation_started_ordinal());
  88. EXPECT_FALSE(observer()->AnimationHasEnded());
  89. test_api()->CompleteAnimations();
  90. EXPECT_TRUE(observer()->AnimationHasEnded());
  91. EXPECT_EQ(2, observer()->last_animation_ended_ordinal());
  92. }
  93. TEST_F(InkDropHighlightTest,
  94. VerifyObserversAreNotifiedWithCorrectAnimationType) {
  95. ink_drop_highlight()->FadeIn(base::Seconds(1));
  96. EXPECT_TRUE(observer()->AnimationHasStarted());
  97. EXPECT_EQ(InkDropHighlight::AnimationType::kFadeIn,
  98. observer()->last_animation_started_context());
  99. test_api()->CompleteAnimations();
  100. EXPECT_TRUE(observer()->AnimationHasEnded());
  101. EXPECT_EQ(InkDropHighlight::AnimationType::kFadeIn,
  102. observer()->last_animation_started_context());
  103. ink_drop_highlight()->FadeOut(base::Seconds(1));
  104. EXPECT_EQ(InkDropHighlight::AnimationType::kFadeOut,
  105. observer()->last_animation_started_context());
  106. test_api()->CompleteAnimations();
  107. EXPECT_EQ(InkDropHighlight::AnimationType::kFadeOut,
  108. observer()->last_animation_started_context());
  109. }
  110. TEST_F(InkDropHighlightTest, VerifyObserversAreNotifiedOfSuccessfulAnimations) {
  111. ink_drop_highlight()->FadeIn(base::Seconds(1));
  112. test_api()->CompleteAnimations();
  113. EXPECT_EQ(2, observer()->last_animation_ended_ordinal());
  114. EXPECT_EQ(InkDropAnimationEndedReason::SUCCESS,
  115. observer()->last_animation_ended_reason());
  116. }
  117. TEST_F(InkDropHighlightTest, VerifyObserversAreNotifiedOfPreemptedAnimations) {
  118. // TODO(bruthig): Re-enable! For some reason these tests fail on some win
  119. // trunk builds. See crbug.com/731811.
  120. if (!gfx::Animation::ShouldRenderRichAnimation())
  121. return;
  122. ink_drop_highlight()->FadeIn(base::Seconds(1));
  123. ink_drop_highlight()->FadeOut(base::Seconds(1));
  124. EXPECT_EQ(2, observer()->last_animation_ended_ordinal());
  125. EXPECT_EQ(InkDropHighlight::AnimationType::kFadeIn,
  126. observer()->last_animation_ended_context());
  127. EXPECT_EQ(InkDropAnimationEndedReason::PRE_EMPTED,
  128. observer()->last_animation_ended_reason());
  129. }
  130. // Confirms there is no crash.
  131. TEST_F(InkDropHighlightTest, NullObserverIsSafe) {
  132. ink_drop_highlight()->set_observer(nullptr);
  133. ink_drop_highlight()->FadeIn(base::Seconds(1));
  134. test_api()->CompleteAnimations();
  135. ink_drop_highlight()->FadeOut(base::Milliseconds(0));
  136. test_api()->CompleteAnimations();
  137. EXPECT_FALSE(ink_drop_highlight()->IsFadingInOrVisible());
  138. }
  139. // Verify animations are aborted during deletion and the
  140. // InkDropHighlightObservers are notified.
  141. TEST_F(InkDropHighlightTest, AnimationsAbortedDuringDeletion) {
  142. // TODO(bruthig): Re-enable! For some reason these tests fail on some win
  143. // trunk builds. See crbug.com/731811.
  144. if (!gfx::Animation::ShouldRenderRichAnimation())
  145. return;
  146. ink_drop_highlight()->FadeIn(base::Seconds(1));
  147. DestroyHighlight();
  148. EXPECT_EQ(1, observer()->last_animation_started_ordinal());
  149. EXPECT_EQ(2, observer()->last_animation_ended_ordinal());
  150. EXPECT_EQ(InkDropHighlight::AnimationType::kFadeIn,
  151. observer()->last_animation_ended_context());
  152. EXPECT_EQ(InkDropAnimationEndedReason::PRE_EMPTED,
  153. observer()->last_animation_ended_reason());
  154. }
  155. // Confirms a zero sized highlight doesn't crash.
  156. TEST_F(InkDropHighlightTest, AnimatingAZeroSizeHighlight) {
  157. InitHighlight(std::make_unique<InkDropHighlight>(
  158. gfx::Size(0, 0), 3, gfx::PointF(), SK_ColorBLACK));
  159. ink_drop_highlight()->FadeOut(base::Milliseconds(0));
  160. }
  161. TEST_F(InkDropHighlightTest, TransformIsPixelAligned) {
  162. constexpr float kEpsilon = 0.001f;
  163. constexpr gfx::Size kHighlightSize(10, 10);
  164. InitHighlight(std::make_unique<InkDropHighlight>(
  165. kHighlightSize, 3, gfx::PointF(3.5f, 3.5f), SK_ColorYELLOW));
  166. const gfx::PointF layer_origin(
  167. ink_drop_highlight()->layer()->bounds().origin());
  168. for (auto dsf : {1.25, 1.33, 1.5, 1.6, 1.75, 1.8, 2.25}) {
  169. SCOPED_TRACE(testing::Message()
  170. << std::endl
  171. << "Device Scale Factor: " << dsf << std::endl);
  172. ink_drop_highlight()->layer()->OnDeviceScaleFactorChanged(dsf);
  173. gfx::Transform transform = test_api()->CalculateTransform();
  174. gfx::Point3F transformed_layer_origin(layer_origin.x(), layer_origin.y(),
  175. 0);
  176. transform.TransformPoint(&transformed_layer_origin);
  177. // Apply device scale factor to get the final offset.
  178. gfx::Transform dsf_transform;
  179. dsf_transform.Scale(dsf, dsf);
  180. dsf_transform.TransformPoint(&transformed_layer_origin);
  181. EXPECT_NEAR(transformed_layer_origin.x(),
  182. std::round(transformed_layer_origin.x()), kEpsilon);
  183. EXPECT_NEAR(transformed_layer_origin.y(),
  184. std::round(transformed_layer_origin.y()), kEpsilon);
  185. }
  186. }
  187. } // namespace test
  188. } // namespace views