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

Side by Side Diff: components/ntp_snippets/sessions/foreign_sessions_suggestions_provider_unittest.cc

Issue 2279123002: [Sync] Initial implementation of foreign sessions suggestions provider. (Closed)
Patch Set: Adding sessions deps to BUILD.gn Created 4 years, 3 months 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 2016 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 "components/ntp_snippets/sessions/foreign_sessions_suggestions_provider .h"
6
7 #include <map>
8 #include <utility>
9
10 #include "base/memory/ptr_util.h"
11 #include "components/ntp_snippets/category.h"
12 #include "components/ntp_snippets/category_factory.h"
13 #include "components/ntp_snippets/content_suggestions_provider.h"
14 #include "components/ntp_snippets/mock_content_suggestions_provider_observer.h"
15 #include "components/prefs/testing_pref_service.h"
16 #include "components/sessions/core/serialized_navigation_entry.h"
17 #include "components/sessions/core/serialized_navigation_entry_test_helper.h"
18 #include "components/sessions/core/session_types.h"
19 #include "components/sync_sessions/open_tabs_ui_delegate.h"
20 #include "components/sync_sessions/synced_session.h"
21 #include "testing/gmock/include/gmock/gmock.h"
22 #include "testing/gtest/include/gtest/gtest.h"
23
24 using base::Time;
25 using base::TimeDelta;
26 using sessions::SerializedNavigationEntry;
27 using sessions::SessionTab;
28 using sessions::SessionWindow;
29 using sync_driver::SyncedSession;
30 using testing::IsEmpty;
31 using testing::Property;
32 using testing::ElementsAre;
33 using testing::UnorderedElementsAre;
34 using testing::_;
35
36 namespace ntp_snippets {
37 namespace {
38
39 const char kUrl1[] = "http://www.fake1.com/";
40 const char kUrl2[] = "http://www.fake2.com/";
41 const char kUrl3[] = "http://www.fake3.com/";
42 const char kUrl4[] = "http://www.fake4.com/";
43 const char kUrl5[] = "http://www.fake5.com/";
44 const char kUrl6[] = "http://www.fake6.com/";
45 const char kUrl7[] = "http://www.fake7.com/";
46 const char kUrl8[] = "http://www.fake8.com/";
47 const char kUrl9[] = "http://www.fake9.com/";
48 const char kUrl10[] = "http://www.fake10.com/";
49 const char kUrl11[] = "http://www.fake11.com/";
50 const char kTitle[] = "title is ignored";
51
52 SessionWindow* GetWindow(SyncedSession* session, int window_id) {
Marc Treib 2016/09/16 12:26:49 GetOrCreateWindow?
skym 2016/09/16 18:18:49 Done.
53 if (session->windows.find(window_id) == session->windows.end()) {
54 // The session deletes the windows it points at upon destruction.
55 session->windows[window_id] = new SessionWindow();
56 }
57 return session->windows[window_id];
58 }
59
60 void AddTabToSession(SyncedSession* session,
61 int window_id,
62 const std::string& url,
63 TimeDelta age) {
64 SerializedNavigationEntry navigation =
65 sessions::SerializedNavigationEntryTestHelper::CreateNavigation(url,
66 kTitle);
67
68 std::unique_ptr<SessionTab> tab = base::MakeUnique<SessionTab>();
69 tab->timestamp = Time::Now() - age;
70 tab->navigations.push_back(navigation);
71
72 SessionWindow* window = GetWindow(session, window_id);
73 // The window deletes the tabs it points at upon destruction.
74 window->tabs.push_back(tab.release());
75 }
76
77 class FakeTabsDelegate
78 : public sync_driver::OpenTabsUIDelegate,
tschumann 2016/09/16 13:33:20 do we actually need to implement this interface?
skym 2016/09/16 18:18:49 Done. Ended up removing OpenTabsUIDelegate from th
tschumann 2016/09/17 15:52:56 :-) I think so too!
79 public ForeignSessionsSuggestionsProvider::OpenTabsUIDelegateProvider {
80 public:
81 ~FakeTabsDelegate() override {}
82 void SetAllForeignSessions(std::vector<const SyncedSession*> sessions) {
83 sessions_ = sessions;
84 change_callback_.Run(this);
85 }
86
87 // OpenTabsUIDelegate implementation.
88 bool GetSyncedFaviconForPageURL(
89 const std::string& pageurl,
90 scoped_refptr<base::RefCountedMemory>* favicon_png) const override {
91 return false;
92 }
93 bool GetAllForeignSessions(
94 std::vector<const SyncedSession*>* sessions) override {
95 *sessions = sessions_;
96 return !sessions->empty();
97 }
98 bool GetForeignTab(const std::string& tag,
99 const SessionID::id_type tab_id,
100 const sessions::SessionTab** tab) override {
101 return false;
102 }
103 void DeleteForeignSession(const std::string& tag) override {}
104 bool GetForeignSession(
105 const std::string& tag,
106 std::vector<const sessions::SessionWindow*>* windows) override {
107 return false;
108 }
109 bool GetForeignSessionTabs(
110 const std::string& tag,
111 std::vector<const sessions::SessionTab*>* tabs) override {
112 return false;
113 }
114 bool GetLocalSession(const SyncedSession** local) override { return false; }
115
116 // OpenTabsUIDelegateProvider implementation.
117 sync_driver::OpenTabsUIDelegate* GetOpenTabsUIDelegate() override {
118 return this;
119 }
120 void SubscribeForForeignTabChange(
121 const OnChangeWithDelegate& change_callback) override {
122 change_callback_ = change_callback;
123 }
124
125 private:
126 std::vector<const SyncedSession*> sessions_;
127 OnChangeWithDelegate change_callback_;
128 };
129 } // namespace
130
131 class ForeignSessionsSuggestionsProviderTest : public testing::Test {
132 public:
133 ForeignSessionsSuggestionsProviderTest()
134 : pref_service_(base::MakeUnique<TestingPrefServiceSimple>()) {
135 ForeignSessionsSuggestionsProvider::RegisterProfilePrefs(
136 pref_service_->registry());
137
138 std::unique_ptr<FakeTabsDelegate> delegate =
139 base::MakeUnique<FakeTabsDelegate>();
140 fake_tabs_delegate_ = delegate.get();
141
142 // During the provider's construction the follow mock calls occur.
Marc Treib 2016/09/16 12:26:48 nit: s/follow/following/
skym 2016/09/16 18:18:49 Done.
143 EXPECT_CALL(*observer(),
144 OnNewSuggestions(_, category(), testing::IsEmpty()));
Marc Treib 2016/09/16 12:26:49 nit: "testing::" not required, there's a "using" a
skym 2016/09/16 18:18:49 Done.
145 EXPECT_CALL(*observer(), OnCategoryStatusChanged(
146 _, category(), CategoryStatus::AVAILABLE));
147
148 provider_ = base::MakeUnique<ForeignSessionsSuggestionsProvider>(
149 &observer_, &category_factory_, std::move(delegate),
150 pref_service_.get());
151 }
152
153 protected:
154 SyncedSession* GetSession(int session_id) {
Marc Treib 2016/09/16 12:26:48 GotOrCreateSession?
skym 2016/09/16 18:18:49 Done.
155 if (sessions_map_.find(session_id) == sessions_map_.end()) {
156 std::string id_as_string = std::to_string(session_id);
Marc Treib 2016/09/16 12:26:48 Per https://chromium-cpp.appspot.com/, std::to_str
skym 2016/09/16 18:18:49 :( Done.
157 std::unique_ptr<SyncedSession> owned_session =
158 base::MakeUnique<SyncedSession>();
159 owned_session->session_tag = id_as_string;
160 owned_session->session_name = id_as_string;
161 sessions_map_[session_id] = std::move(owned_session);
162 }
163 return sessions_map_[session_id].get();
164 }
165
166 void AddTab(int session_id,
167 int window_id,
168 const std::string& url,
169 TimeDelta age) {
170 AddTabToSession(GetSession(session_id), window_id, url, age);
171 }
172
173 void TriggerOnChange() {
174 std::vector<const SyncedSession*> sessions;
175 for (const auto& kv : sessions_map_) {
176 sessions.push_back(kv.second.get());
177 }
178 fake_tabs_delegate_->SetAllForeignSessions(sessions);
179 }
180
181 void Dismiss(const std::string& url) {
Marc Treib 2016/09/16 12:26:48 s/url/id/ ?
skym 2016/09/16 18:18:49 So someone has to decide that to create a within_c
182 provider_->DismissSuggestion(provider_->MakeUniqueID(category(), url));
183 }
184
185 Category category() {
186 return category_factory_.FromKnownCategory(KnownCategories::FOREIGN_TABS);
187 }
188
189 MockContentSuggestionsProviderObserver* observer() { return &observer_; }
190
191 private:
192 FakeTabsDelegate* fake_tabs_delegate_;
193 MockContentSuggestionsProviderObserver observer_;
194 CategoryFactory category_factory_;
195 std::unique_ptr<TestingPrefServiceSimple> pref_service_;
Marc Treib 2016/09/16 12:26:48 I think this could just be an instance rather than
skym 2016/09/16 18:18:49 Done.
196 std::unique_ptr<ForeignSessionsSuggestionsProvider> provider_;
197 std::map<int, std::unique_ptr<SyncedSession>> sessions_map_;
198
199 DISALLOW_COPY_AND_ASSIGN(ForeignSessionsSuggestionsProviderTest);
200 };
201
202 TEST_F(ForeignSessionsSuggestionsProviderTest, Empty) {
203 EXPECT_CALL(*observer(), OnNewSuggestions(_, category(), testing::IsEmpty()));
204 TriggerOnChange();
205 }
206
207 TEST_F(ForeignSessionsSuggestionsProviderTest, Single) {
208 EXPECT_CALL(*observer(),
209 OnNewSuggestions(
210 _, category(),
211 ElementsAre(Property(&ContentSuggestion::url, GURL(kUrl1)))));
212 AddTab(0, 0, kUrl1, TimeDelta::FromMinutes(1));
213 TriggerOnChange();
214 }
215
216 TEST_F(ForeignSessionsSuggestionsProviderTest, Old) {
217 EXPECT_CALL(*observer(), OnNewSuggestions(_, category(), testing::IsEmpty()));
218 AddTab(0, 0, kUrl1, TimeDelta::FromHours(4));
219 TriggerOnChange();
220 }
221
222 TEST_F(ForeignSessionsSuggestionsProviderTest, Ordered) {
223 EXPECT_CALL(*observer(),
224 OnNewSuggestions(
225 _, category(),
226 ElementsAre(Property(&ContentSuggestion::url, GURL(kUrl1)),
227 Property(&ContentSuggestion::url, GURL(kUrl2)),
228 Property(&ContentSuggestion::url, GURL(kUrl3)),
229 Property(&ContentSuggestion::url, GURL(kUrl4)))));
230 AddTab(0, 0, kUrl2, TimeDelta::FromMinutes(2));
231 AddTab(0, 0, kUrl4, TimeDelta::FromMinutes(4));
232 AddTab(0, 1, kUrl3, TimeDelta::FromMinutes(3));
233 AddTab(1, 0, kUrl1, TimeDelta::FromMinutes(1));
234 TriggerOnChange();
235 }
236
237 TEST_F(ForeignSessionsSuggestionsProviderTest, MaxPerDevice) {
238 EXPECT_CALL(*observer(),
239 OnNewSuggestions(
240 _, category(),
241 ElementsAre(Property(&ContentSuggestion::url, GURL(kUrl1)),
242 Property(&ContentSuggestion::url, GURL(kUrl2)),
243 Property(&ContentSuggestion::url, GURL(kUrl3)))));
244 AddTab(0, 0, kUrl1, TimeDelta::FromMinutes(1));
245 AddTab(0, 0, kUrl2, TimeDelta::FromMinutes(2));
246 AddTab(0, 0, kUrl3, TimeDelta::FromMinutes(3));
247 AddTab(0, 0, kUrl4, TimeDelta::FromMinutes(4));
248 TriggerOnChange();
249 }
250
251 TEST_F(ForeignSessionsSuggestionsProviderTest, MaxTotal) {
252 EXPECT_CALL(
Marc Treib 2016/09/16 12:26:49 nit: I think all of these tests deserve a one-line
skym 2016/09/16 18:18:49 Done.
253 *observer(),
254 OnNewSuggestions(
255 _, category(),
256 ElementsAre(Property(&ContentSuggestion::url, GURL(kUrl1)),
257 Property(&ContentSuggestion::url, GURL(kUrl2)),
258 Property(&ContentSuggestion::url, GURL(kUrl3)),
259 Property(&ContentSuggestion::url, GURL(kUrl4)),
260 Property(&ContentSuggestion::url, GURL(kUrl5)),
261 Property(&ContentSuggestion::url, GURL(kUrl6)),
262 Property(&ContentSuggestion::url, GURL(kUrl7)),
263 Property(&ContentSuggestion::url, GURL(kUrl8)),
264 Property(&ContentSuggestion::url, GURL(kUrl9)),
265 Property(&ContentSuggestion::url, GURL(kUrl10)))));
266 AddTab(0, 0, kUrl1, TimeDelta::FromMinutes(1));
267 AddTab(0, 0, kUrl2, TimeDelta::FromMinutes(2));
268 AddTab(0, 0, kUrl3, TimeDelta::FromMinutes(3));
269 AddTab(1, 0, kUrl4, TimeDelta::FromMinutes(4));
270 AddTab(1, 0, kUrl5, TimeDelta::FromMinutes(5));
271 AddTab(1, 0, kUrl6, TimeDelta::FromMinutes(6));
272 AddTab(2, 0, kUrl7, TimeDelta::FromMinutes(7));
273 AddTab(2, 0, kUrl8, TimeDelta::FromMinutes(8));
274 AddTab(2, 0, kUrl9, TimeDelta::FromMinutes(9));
275 AddTab(3, 0, kUrl10, TimeDelta::FromMinutes(10));
276 AddTab(3, 0, kUrl11, TimeDelta::FromMinutes(11));
277 TriggerOnChange();
278 }
279
280 TEST_F(ForeignSessionsSuggestionsProviderTest, Duplicates) {
281 EXPECT_CALL(*observer(),
282 OnNewSuggestions(
283 _, category(),
284 ElementsAre(Property(&ContentSuggestion::url, GURL(kUrl1)))));
285 AddTab(0, 0, kUrl1, TimeDelta::FromMinutes(1));
286 AddTab(0, 1, kUrl1, TimeDelta::FromMinutes(2));
287 AddTab(1, 1, kUrl1, TimeDelta::FromMinutes(3));
288 TriggerOnChange();
289 }
290
291 TEST_F(ForeignSessionsSuggestionsProviderTest, DuplicatesChangingOtherSession) {
292 EXPECT_CALL(*observer(),
293 OnNewSuggestions(
294 _, category(),
295 ElementsAre(Property(&ContentSuggestion::url, GURL(kUrl3)),
296 Property(&ContentSuggestion::url, GURL(kUrl1)),
297 Property(&ContentSuggestion::url, GURL(kUrl2)),
298 Property(&ContentSuggestion::url, GURL(kUrl4)))));
299 AddTab(0, 0, kUrl1, TimeDelta::FromMinutes(1));
300 AddTab(0, 0, kUrl2, TimeDelta::FromMinutes(2));
301 AddTab(0, 0, kUrl3, TimeDelta::FromMinutes(3));
302 // Normally |kUrl4| wouldn't show up, because session_id=0 already has 3
303 // younger tabs, but session_id=1 has a younger |kUrl3| which gives |kUrl4| a
304 // spot.
305 AddTab(0, 0, kUrl4, TimeDelta::FromMinutes(4));
306 AddTab(1, 0, kUrl3, TimeDelta::FromMinutes(0));
307 TriggerOnChange();
308 }
309
310 TEST_F(ForeignSessionsSuggestionsProviderTest, Dismissed) {
311 EXPECT_CALL(*observer(), OnNewSuggestions(_, category(), testing::IsEmpty()));
312 Dismiss(kUrl1);
313 AddTab(0, 0, kUrl1, TimeDelta::FromMinutes(1));
314 TriggerOnChange();
315 }
316
317 TEST_F(ForeignSessionsSuggestionsProviderTest, DismissedChangingOwnSession) {
318 EXPECT_CALL(*observer(),
319 OnNewSuggestions(
320 _, category(),
321 ElementsAre(Property(&ContentSuggestion::url, GURL(kUrl2)),
322 Property(&ContentSuggestion::url, GURL(kUrl3)),
323 Property(&ContentSuggestion::url, GURL(kUrl5)))));
324 Dismiss(kUrl1);
325 Dismiss(kUrl4);
326 AddTab(0, 0, kUrl1, TimeDelta::FromMinutes(1));
327 AddTab(0, 0, kUrl2, TimeDelta::FromMinutes(2));
328 AddTab(0, 0, kUrl3, TimeDelta::FromMinutes(3));
329 AddTab(0, 0, kUrl4, TimeDelta::FromMinutes(4));
330 AddTab(0, 0, kUrl5, TimeDelta::FromMinutes(5));
331 AddTab(0, 0, kUrl6, TimeDelta::FromMinutes(6));
332 TriggerOnChange();
333 }
334
335 } // namespace ntp_snippets
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698