Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(78)

Side by Side Diff: content/browser/android/overscroll_refresh_unittest.cc

Issue 679493002: [Android] Add a native pull-to-refresh overscroll effect (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Code review Created 6 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
1 // Copyright 2014 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
5 #include "cc/layers/layer.h"
6 #include "content/browser/android/overscroll_refresh.h"
7 #include "testing/gtest/include/gtest/gtest.h"
8 #include "ui/base/android/system_ui_resource_manager.h"
9
10 namespace content {
11
12 gfx::SizeF DefaultViewportSize() {
13 return gfx::SizeF(512, 512);
14 }
15
16 OverscrollRefresh::ActivationAllowance kAllowActivation =
17 OverscrollRefresh::ALLOW_ACTIVATION;
18
19 OverscrollRefresh::ActivationAllowance kPreventActivation =
20 OverscrollRefresh::PREVENT_ACTIVATION;
21
22 class OverscrollRefreshTest : public OverscrollRefreshClient,
23 public ui::SystemUIResourceManager,
24 public testing::Test {
25 public:
26 OverscrollRefreshTest() : refresh_triggered_(false) {}
27
28 // OverscrollRefreshClient implementation.
29 void TriggerRefresh() override {
30 refresh_triggered_ = true;
31 triggered_refresh_active_ = true;
32 }
33
34 bool IsTriggeredRefreshActive() const override {
35 return triggered_refresh_active_;
36 }
37
38 // SystemUIResoruceManager implementation.
39 void PreloadResource(ui::SystemUIResourceType) override {}
40
41 bool GetAndResetRefreshTriggered() {
42 bool triggered = refresh_triggered_;
43 refresh_triggered_ = false;
44 return triggered;
45 }
46
47 protected:
48 void ResetTriggeredRefreshActive() { triggered_refresh_active_ = false; }
49
50 cc::UIResourceId GetUIResourceId(ui::SystemUIResourceType) override {
51 return 0;
52 }
53
54 private:
55 bool refresh_triggered_;
56 bool triggered_refresh_active_;
57 };
58
59 TEST_F(OverscrollRefreshTest, Basic) {
60 OverscrollRefresh effect(this, this);
61
62 gfx::Vector2dF origin_scroll_offset;
63 effect.UpdateDisplay(DefaultViewportSize(), origin_scroll_offset);
64 EXPECT_FALSE(effect.IsActive());
65 EXPECT_FALSE(effect.IsPendingScrollUpdateAck());
66
67 effect.OnScrollBegin();
68 EXPECT_FALSE(effect.IsActive());
69 EXPECT_TRUE(effect.IsPendingScrollUpdateAck());
70
71 // The initial scroll should not be consumed, as it should first be offered
72 // to content.
73 gfx::Vector2dF scroll_up(0, 10);
74 EXPECT_FALSE(effect.WillHandleScrollUpdate(scroll_up));
75 EXPECT_FALSE(effect.IsActive());
76 EXPECT_TRUE(effect.IsPendingScrollUpdateAck());
77
78 // The unconsumed, overscrolling scroll will trigger the effect.
79 effect.OnScrollUpdateAck(kAllowActivation);
80 EXPECT_TRUE(effect.IsActive());
81 EXPECT_FALSE(effect.IsPendingScrollUpdateAck());
82
83 // Further scrolls will be consumed.
84 EXPECT_TRUE(effect.WillHandleScrollUpdate(gfx::Vector2dF(0, 50)));
85 EXPECT_TRUE(effect.IsActive());
86
87 // Even scrolls in the down direction should be consumed.
88 EXPECT_TRUE(effect.WillHandleScrollUpdate(gfx::Vector2dF(0, -50)));
89 EXPECT_TRUE(effect.IsActive());
90
91 // Feed enough scrolls to the effect to exceeds tht threshold.
92 EXPECT_TRUE(effect.WillHandleScrollUpdate(gfx::Vector2dF(0, 100)));
93 EXPECT_TRUE(effect.WillHandleScrollUpdate(gfx::Vector2dF(0, 100)));
94 EXPECT_TRUE(effect.WillHandleScrollUpdate(gfx::Vector2dF(0, 100)));
95 EXPECT_TRUE(effect.WillHandleScrollUpdate(gfx::Vector2dF(0, 100)));
96 EXPECT_TRUE(effect.WillHandleScrollUpdate(gfx::Vector2dF(0, 100)));
97 EXPECT_TRUE(effect.IsActive());
98
99 // Ending the scroll while beyond the threshold should trigger a refresh.
100 gfx::Vector2dF zero_velocity;
101 EXPECT_FALSE(GetAndResetRefreshTriggered());
102 effect.OnScrollEnd(zero_velocity);
103 EXPECT_TRUE(effect.IsActive());
104 EXPECT_TRUE(GetAndResetRefreshTriggered());
105 ResetTriggeredRefreshActive();
106
107 // Ensure animation doesn't explode.
108 base::TimeTicks initial_time = base::TimeTicks::Now();
109 base::TimeTicks current_time = initial_time;
110 scoped_refptr<cc::Layer> layer = cc::Layer::Create();
111 while (effect.Animate(current_time, layer.get()))
112 current_time += base::TimeDelta::FromMilliseconds(16);
113
114 // The effect should terminate in a timely fashion.
115 EXPECT_GT(current_time.ToInternalValue(), initial_time.ToInternalValue());
116 EXPECT_LE(
117 current_time.ToInternalValue(),
118 (initial_time + base::TimeDelta::FromSeconds(10)).ToInternalValue());
119 EXPECT_FALSE(effect.IsActive());
120 }
121
122 TEST_F(OverscrollRefreshTest, AnimationTerminatesEvenIfRefreshNeverTerminates) {
123 OverscrollRefresh effect(this, this);
124 effect.UpdateDisplay(DefaultViewportSize(), gfx::Vector2dF());
125 effect.OnScrollBegin();
126 ASSERT_FALSE(effect.WillHandleScrollUpdate(gfx::Vector2dF(0, 10)));
127 ASSERT_TRUE(effect.IsPendingScrollUpdateAck());
128 effect.OnScrollUpdateAck(kAllowActivation);
129 ASSERT_TRUE(effect.IsActive());
130 EXPECT_TRUE(effect.WillHandleScrollUpdate(gfx::Vector2dF(0, 50)));
131 EXPECT_TRUE(effect.WillHandleScrollUpdate(gfx::Vector2dF(0, 50)));
132 EXPECT_TRUE(effect.WillHandleScrollUpdate(gfx::Vector2dF(0, 50)));
133 EXPECT_TRUE(effect.WillHandleScrollUpdate(gfx::Vector2dF(0, 50)));
134 EXPECT_TRUE(effect.WillHandleScrollUpdate(gfx::Vector2dF(0, 50)));
135 EXPECT_TRUE(effect.WillHandleScrollUpdate(gfx::Vector2dF(0, 50)));
136 effect.OnScrollEnd(gfx::Vector2dF(0, 0));
137 ASSERT_TRUE(GetAndResetRefreshTriggered());
138
139 // Verify that the animation terminates even if the triggered refresh
140 // action never terminates (i.e., |triggered_refresh_active_| is always true).
141 base::TimeTicks initial_time = base::TimeTicks::Now();
142 base::TimeTicks current_time = initial_time;
143 scoped_refptr<cc::Layer> layer = cc::Layer::Create();
144 while (effect.Animate(current_time, layer.get()))
145 current_time += base::TimeDelta::FromMilliseconds(16);
146
147 EXPECT_GT(current_time.ToInternalValue(), initial_time.ToInternalValue());
148 EXPECT_LE(
149 current_time.ToInternalValue(),
150 (initial_time + base::TimeDelta::FromSeconds(10)).ToInternalValue());
151 EXPECT_FALSE(effect.IsActive());
152 }
153
154 TEST_F(OverscrollRefreshTest, NotTriggeredIfBelowThreshold) {
155 OverscrollRefresh effect(this, this);
156 effect.UpdateDisplay(DefaultViewportSize(), gfx::Vector2dF());
157 effect.OnScrollBegin();
158 ASSERT_FALSE(effect.WillHandleScrollUpdate(gfx::Vector2dF(0, 10)));
159 ASSERT_TRUE(effect.IsPendingScrollUpdateAck());
160 effect.OnScrollUpdateAck(kAllowActivation);
161 ASSERT_TRUE(effect.IsActive());
162
163 // Terminating the pull before it exceeds the threshold will prevent refresh.
164 EXPECT_TRUE(effect.WillHandleScrollUpdate(gfx::Vector2dF(0, 10)));
165 effect.OnScrollEnd(gfx::Vector2dF());
166 EXPECT_FALSE(GetAndResetRefreshTriggered());
167 }
168
169 TEST_F(OverscrollRefreshTest, NotTriggeredIfInitialYOffsetIsZero) {
170 OverscrollRefresh effect(this, this);
171
172 // A positive y scroll offset at the start of scroll will prevent activation,
173 // even if the subsequent scroll overscrolls upward.
174 gfx::Vector2dF nonzero_offset(0, 10);
175 effect.UpdateDisplay(DefaultViewportSize(), nonzero_offset);
176 effect.OnScrollBegin();
177
178 effect.UpdateDisplay(DefaultViewportSize(), gfx::Vector2dF());
179 ASSERT_FALSE(effect.WillHandleScrollUpdate(gfx::Vector2dF(0, 10)));
180 EXPECT_FALSE(effect.IsActive());
181 EXPECT_FALSE(effect.IsPendingScrollUpdateAck());
182 effect.OnScrollUpdateAck(kAllowActivation);
183 EXPECT_FALSE(effect.IsActive());
184 EXPECT_FALSE(effect.IsPendingScrollUpdateAck());
185 EXPECT_FALSE(effect.WillHandleScrollUpdate(gfx::Vector2dF(0, 500)));
186 effect.OnScrollEnd(gfx::Vector2dF());
187 EXPECT_FALSE(GetAndResetRefreshTriggered());
188 }
189
190 TEST_F(OverscrollRefreshTest, NotTriggeredIfInitialScrollDownward) {
191 OverscrollRefresh effect(this, this);
192 effect.UpdateDisplay(DefaultViewportSize(), gfx::Vector2dF());
193 effect.OnScrollBegin();
194
195 // A downward initial scroll will prevent activation, even if the subsequent
196 // scroll overscrolls upward.
197 ASSERT_FALSE(effect.WillHandleScrollUpdate(gfx::Vector2dF(0, -10)));
198 EXPECT_FALSE(effect.IsActive());
199 EXPECT_FALSE(effect.IsPendingScrollUpdateAck());
200
201 effect.OnScrollUpdateAck(kAllowActivation);
202 EXPECT_FALSE(effect.IsActive());
203 EXPECT_FALSE(effect.IsPendingScrollUpdateAck());
204 EXPECT_FALSE(effect.WillHandleScrollUpdate(gfx::Vector2dF(0, 500)));
205 effect.OnScrollEnd(gfx::Vector2dF());
206 EXPECT_FALSE(GetAndResetRefreshTriggered());
207 }
208
209 TEST_F(OverscrollRefreshTest, NotTriggeredIfInitialScrollOrTouchConsumed) {
210 OverscrollRefresh effect(this, this);
211 effect.UpdateDisplay(DefaultViewportSize(), gfx::Vector2dF());
212 effect.OnScrollBegin();
213 ASSERT_FALSE(effect.WillHandleScrollUpdate(gfx::Vector2dF(0, 10)));
214 ASSERT_TRUE(effect.IsPendingScrollUpdateAck());
215
216 // Consumption of the initial touchmove or scroll should prevent future
217 // activation.
218 effect.OnScrollUpdateAck(kPreventActivation);
219 EXPECT_FALSE(effect.IsActive());
220 EXPECT_FALSE(effect.IsPendingScrollUpdateAck());
221 EXPECT_FALSE(effect.WillHandleScrollUpdate(gfx::Vector2dF(0, 500)));
222 effect.OnScrollUpdateAck(kAllowActivation);
223 EXPECT_FALSE(effect.IsActive());
224 EXPECT_FALSE(effect.IsPendingScrollUpdateAck());
225 EXPECT_FALSE(effect.WillHandleScrollUpdate(gfx::Vector2dF(0, 500)));
226 effect.OnScrollEnd(gfx::Vector2dF());
227 EXPECT_FALSE(GetAndResetRefreshTriggered());
228 }
229
230 TEST_F(OverscrollRefreshTest, NotTriggeredIfInitialScrollsJanked) {
231 OverscrollRefresh effect(this, this);
232 effect.UpdateDisplay(DefaultViewportSize(), gfx::Vector2dF());
233 effect.OnScrollBegin();
234 ASSERT_FALSE(effect.WillHandleScrollUpdate(gfx::Vector2dF(0, 10)));
235 ASSERT_TRUE(effect.IsPendingScrollUpdateAck());
236 effect.OnScrollUpdateAck(kAllowActivation);
237 ASSERT_TRUE(effect.IsActive());
238
239 // It should take more than just one or two large scrolls to trigger,
240 // mitigating likelihood of jank triggering the effect.
241 EXPECT_TRUE(effect.WillHandleScrollUpdate(gfx::Vector2dF(0, 500)));
242 EXPECT_TRUE(effect.WillHandleScrollUpdate(gfx::Vector2dF(0, 500)));
243 effect.OnScrollEnd(gfx::Vector2dF());
244 EXPECT_FALSE(GetAndResetRefreshTriggered());
245 }
246
247 TEST_F(OverscrollRefreshTest, NotTriggeredIfFlungDownward) {
248 OverscrollRefresh effect(this, this);
249 effect.UpdateDisplay(DefaultViewportSize(), gfx::Vector2dF());
250 effect.OnScrollBegin();
251 ASSERT_FALSE(effect.WillHandleScrollUpdate(gfx::Vector2dF(0, 10)));
252 ASSERT_TRUE(effect.IsPendingScrollUpdateAck());
253 effect.OnScrollUpdateAck(kAllowActivation);
254 ASSERT_TRUE(effect.IsActive());
255
256 // Ensure the pull exceeds the necessary threshold.
257 EXPECT_TRUE(effect.WillHandleScrollUpdate(gfx::Vector2dF(0, 50)));
258 EXPECT_TRUE(effect.WillHandleScrollUpdate(gfx::Vector2dF(0, 50)));
259 EXPECT_TRUE(effect.WillHandleScrollUpdate(gfx::Vector2dF(0, 50)));
260 EXPECT_TRUE(effect.WillHandleScrollUpdate(gfx::Vector2dF(0, 50)));
261 EXPECT_TRUE(effect.WillHandleScrollUpdate(gfx::Vector2dF(0, 50)));
262 EXPECT_TRUE(effect.WillHandleScrollUpdate(gfx::Vector2dF(0, 50)));
263
264 // Terminating the pull with a down-directed fling should prevent triggering.
265 effect.OnScrollEnd(gfx::Vector2dF(0, -1000));
266 EXPECT_FALSE(GetAndResetRefreshTriggered());
267 }
268
269 } // namespace content
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698