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

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

Powered by Google App Engine
This is Rietveld 408576698