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

Side by Side Diff: components/ntp_snippets/offline_pages/recent_tab_suggestions_provider_unittest.cc

Issue 2684973014: Only show Last N Pages in the UI when the corresponding tab is visible. (Closed)
Patch Set: Address comments. Created 3 years, 10 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
1 // Copyright 2016 The Chromium Authors. All rights reserved. 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 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "components/ntp_snippets/offline_pages/recent_tab_suggestions_provider. h" 5 #include "components/ntp_snippets/offline_pages/recent_tab_suggestions_provider. h"
6 6
7 #include <string> 7 #include <string>
8 #include <vector> 8 #include <vector>
9 9
10 #include "base/bind.h" 10 #include "base/bind.h"
11 #include "base/files/file_path.h" 11 #include "base/files/file_path.h"
12 #include "base/strings/string_number_conversions.h" 12 #include "base/strings/string_number_conversions.h"
13 #include "base/test/test_simple_task_runner.h"
14 #include "base/threading/thread_task_runner_handle.h"
13 #include "base/time/time.h" 15 #include "base/time/time.h"
14 #include "components/ntp_snippets/category.h" 16 #include "components/ntp_snippets/category.h"
15 #include "components/ntp_snippets/content_suggestions_provider.h" 17 #include "components/ntp_snippets/content_suggestions_provider.h"
16 #include "components/ntp_snippets/mock_content_suggestions_provider_observer.h" 18 #include "components/ntp_snippets/mock_content_suggestions_provider_observer.h"
17 #include "components/ntp_snippets/offline_pages/offline_pages_test_utils.h" 19 #include "components/ntp_snippets/offline_pages/offline_pages_test_utils.h"
20 #include "components/offline_pages/core/background/request_coordinator_stub_taco .h"
18 #include "components/offline_pages/core/client_namespace_constants.h" 21 #include "components/offline_pages/core/client_namespace_constants.h"
22 #include "components/offline_pages/core/downloads/download_ui_adapter.h"
19 #include "components/offline_pages/core/offline_page_item.h" 23 #include "components/offline_pages/core/offline_page_item.h"
20 #include "components/offline_pages/core/stub_offline_page_model.h" 24 #include "components/offline_pages/core/recent_tabs/recent_tabs_ui_adapter_deleg ate.h"
21 #include "components/prefs/testing_pref_service.h" 25 #include "components/prefs/testing_pref_service.h"
22 #include "testing/gmock/include/gmock/gmock.h" 26 #include "testing/gmock/include/gmock/gmock.h"
23 #include "testing/gtest/include/gtest/gtest.h" 27 #include "testing/gtest/include/gtest/gtest.h"
24 28
25 using ntp_snippets::test::CaptureDismissedSuggestions; 29 using ntp_snippets::test::CaptureDismissedSuggestions;
26 using ntp_snippets::test::FakeOfflinePageModel; 30 using ntp_snippets::test::FakeOfflinePageModel;
27 using offline_pages::ClientId; 31 using offline_pages::ClientId;
28 using offline_pages::MultipleOfflinePageItemCallback; 32 using offline_pages::MultipleOfflinePageItemCallback;
29 using offline_pages::OfflinePageItem; 33 using offline_pages::OfflinePageItem;
30 using offline_pages::StubOfflinePageModel;
31 using testing::_; 34 using testing::_;
32 using testing::IsEmpty; 35 using testing::IsEmpty;
33 using testing::Mock; 36 using testing::Mock;
34 using testing::Property; 37 using testing::Property;
35 using testing::SizeIs; 38 using testing::SizeIs;
36 39
37 namespace ntp_snippets { 40 namespace ntp_snippets {
38 41
39 namespace { 42 namespace {
40 43
41 OfflinePageItem CreateDummyRecentTab(int id) { 44 OfflinePageItem CreateDummyRecentTab(int offline_id) {
42 OfflinePageItem item = 45 // This is used to assign unique tab IDs to pages. Since offline IDs are
43 test::CreateDummyOfflinePageItem(id, offline_pages::kLastNNamespace); 46 // typically small integers like 1, 2, 3 etc, we start at 1001 to ensure that
44 item.client_id.id = base::IntToString(id); 47 // they are different, and can catch bugs where offline page ID is used in
45 return item; 48 // place of tab ID and vice versa.
49 std::string tab_id = base::IntToString(offline_id + 1000);
50 ClientId client_id(offline_pages::kLastNNamespace, tab_id);
51 return test::CreateDummyOfflinePageItem(offline_id, client_id);
46 } 52 }
47 53
48 std::vector<OfflinePageItem> CreateDummyRecentTabs( 54 std::vector<OfflinePageItem> CreateDummyRecentTabs(
49 const std::vector<int>& ids) { 55 const std::vector<int>& ids) {
50 std::vector<OfflinePageItem> result; 56 std::vector<OfflinePageItem> result;
51 for (int id : ids) { 57 for (int id : ids) {
52 result.push_back(CreateDummyRecentTab(id)); 58 result.push_back(CreateDummyRecentTab(id));
53 } 59 }
54 return result; 60 return result;
55 } 61 }
56 62
57 OfflinePageItem CreateDummyRecentTab(int id, base::Time time) { 63 OfflinePageItem CreateDummyRecentTab(int id, base::Time time) {
58 OfflinePageItem item = CreateDummyRecentTab(id); 64 OfflinePageItem item = CreateDummyRecentTab(id);
59 item.creation_time = time; 65 item.creation_time = time;
60 item.last_access_time = time; 66 item.last_access_time = time;
61 return item; 67 return item;
62 } 68 }
63 69
64 } // namespace 70 } // namespace
65 71
66 class RecentTabSuggestionsProviderTest : public testing::Test { 72 class RecentTabSuggestionsProviderTestNoLoad : public testing::Test {
67 public: 73 public:
68 RecentTabSuggestionsProviderTest() 74 RecentTabSuggestionsProviderTestNoLoad()
69 : pref_service_(new TestingPrefServiceSimple()) { 75 : task_runner_(new base::TestSimpleTaskRunner()),
76 task_runner_handle_(task_runner_),
77 pref_service_(new TestingPrefServiceSimple()) {
70 RecentTabSuggestionsProvider::RegisterProfilePrefs( 78 RecentTabSuggestionsProvider::RegisterProfilePrefs(
71 pref_service()->registry()); 79 pref_service()->registry());
72 80
73 provider_.reset( 81 taco_ = base::MakeUnique<offline_pages::RequestCoordinatorStubTaco>();
74 new RecentTabSuggestionsProvider(&observer_, &model_, pref_service())); 82 taco_->CreateRequestCoordinator();
83
84 ui_adapter_ = offline_pages::RecentTabsUIAdapterDelegate::
85 GetOrCreateRecentTabsUIAdapter(&model_, taco_->request_coordinator());
86 delegate_ =
87 offline_pages::RecentTabsUIAdapterDelegate::FromDownloadUIAdapter(
88 ui_adapter_);
89 provider_ = base::MakeUnique<RecentTabSuggestionsProvider>(
90 &observer_, ui_adapter_, pref_service());
75 } 91 }
76 92
77 Category recent_tabs_category() { 93 Category recent_tabs_category() {
78 return Category::FromKnownCategory(KnownCategories::RECENT_TABS); 94 return Category::FromKnownCategory(KnownCategories::RECENT_TABS);
79 } 95 }
80 96
81 ContentSuggestion::ID GetDummySuggestionId(int id) { 97 ContentSuggestion::ID GetDummySuggestionId(int id) {
82 return ContentSuggestion::ID(recent_tabs_category(), base::IntToString(id)); 98 return ContentSuggestion::ID(recent_tabs_category(), base::IntToString(id));
83 } 99 }
84 100
101 void AddTabAndOfflinePageToModel(const OfflinePageItem& item) {
102 AddTab(offline_pages::RecentTabsUIAdapterDelegate::TabIdFromClientId(
103 item.client_id));
104 AddOfflinePageToModel(item);
105 }
106
107 void AddTab(int tab_id) { delegate_->RegisterTab(tab_id); }
108
109 void RemoveTab(int tab_id) { delegate_->UnregisterTab(tab_id); }
110
85 void AddOfflinePageToModel(const OfflinePageItem& item) { 111 void AddOfflinePageToModel(const OfflinePageItem& item) {
86 model_.mutable_items()->push_back(item); 112 ui_adapter_->OfflinePageAdded(&model_, item);
87 provider_->OfflinePageAdded(&model_, item);
88 } 113 }
89 114
90 void FireOfflinePageDeleted(const OfflinePageItem& item) { 115 void FireOfflinePageDeleted(const OfflinePageItem& item) {
91 auto iter = std::remove(model_.mutable_items()->begin(), 116 int tab_id = offline_pages::RecentTabsUIAdapterDelegate::TabIdFromClientId(
92 model_.mutable_items()->end(), item); 117 item.client_id);
93 auto end = model_.mutable_items()->end(); 118 RemoveTab(tab_id);
94 model_.mutable_items()->erase(iter, end); 119 ui_adapter_->OfflinePageDeleted(item.offline_id, item.client_id);
95
96 provider_->OfflinePageDeleted(item.offline_id, item.client_id);
97 } 120 }
98 121
99 std::set<std::string> ReadDismissedIDsFromPrefs() { 122 std::set<std::string> ReadDismissedIDsFromPrefs() {
100 return provider_->ReadDismissedIDsFromPrefs(); 123 return provider_->ReadDismissedIDsFromPrefs();
101 } 124 }
102 125
103 RecentTabSuggestionsProvider* provider() { return provider_.get(); } 126 RecentTabSuggestionsProvider* provider() { return provider_.get(); }
104 FakeOfflinePageModel* model() { return &model_; }
105 MockContentSuggestionsProviderObserver* observer() { return &observer_; } 127 MockContentSuggestionsProviderObserver* observer() { return &observer_; }
106 TestingPrefServiceSimple* pref_service() { return pref_service_.get(); } 128 TestingPrefServiceSimple* pref_service() { return pref_service_.get(); }
129 base::TestSimpleTaskRunner* task_runner() { return task_runner_.get(); }
107 130
108 private: 131 private:
109 FakeOfflinePageModel model_; 132 FakeOfflinePageModel model_;
133 offline_pages::DownloadUIAdapter* ui_adapter_;
134 offline_pages::RecentTabsUIAdapterDelegate* delegate_;
135 scoped_refptr<base::TestSimpleTaskRunner> task_runner_;
136 base::ThreadTaskRunnerHandle task_runner_handle_;
137 std::unique_ptr<offline_pages::RequestCoordinatorStubTaco> taco_;
110 MockContentSuggestionsProviderObserver observer_; 138 MockContentSuggestionsProviderObserver observer_;
111 std::unique_ptr<TestingPrefServiceSimple> pref_service_; 139 std::unique_ptr<TestingPrefServiceSimple> pref_service_;
112 // Last so that the dependencies are deleted after the provider. 140 // Last so that the dependencies are deleted after the provider.
113 std::unique_ptr<RecentTabSuggestionsProvider> provider_; 141 std::unique_ptr<RecentTabSuggestionsProvider> provider_;
114 142
143 DISALLOW_COPY_AND_ASSIGN(RecentTabSuggestionsProviderTestNoLoad);
144 };
145
146 // Test that always loads the model before the start of the test.
147 class RecentTabSuggestionsProviderTest
148 : public RecentTabSuggestionsProviderTestNoLoad {
149 public:
150 RecentTabSuggestionsProviderTest() = default;
151
152 void SetUp() override {
153 // The UI adapter always fires asynchronously upon loading, so we want to
154 // run past that moment before each test. Expect a call to hide warnings.
155 EXPECT_CALL(*observer(), OnNewSuggestions(_, _, _)).Times(1);
156 task_runner()->RunUntilIdle();
157 Mock::VerifyAndClearExpectations(observer());
158 }
159
160 private:
115 DISALLOW_COPY_AND_ASSIGN(RecentTabSuggestionsProviderTest); 161 DISALLOW_COPY_AND_ASSIGN(RecentTabSuggestionsProviderTest);
116 }; 162 };
117 163
118 TEST_F(RecentTabSuggestionsProviderTest, ShouldConvertToSuggestions) { 164 TEST_F(RecentTabSuggestionsProviderTest, ShouldConvertToSuggestions) {
119 auto recent_tabs_list = CreateDummyRecentTabs({1, 2});
120 EXPECT_CALL(*observer(), OnNewSuggestions(_, _, _)).Times(2); 165 EXPECT_CALL(*observer(), OnNewSuggestions(_, _, _)).Times(2);
121 for (OfflinePageItem& recent_tab : recent_tabs_list)
122 AddOfflinePageToModel(recent_tab);
123
124 EXPECT_CALL( 166 EXPECT_CALL(
125 *observer(), 167 *observer(),
126 OnNewSuggestions(_, recent_tabs_category(), 168 OnNewSuggestions(_, recent_tabs_category(),
127 UnorderedElementsAre( 169 UnorderedElementsAre(
128 Property(&ContentSuggestion::url, 170 Property(&ContentSuggestion::url,
129 GURL("http://dummy.com/1")), 171 GURL("http://dummy.com/1")),
130 Property(&ContentSuggestion::url, 172 Property(&ContentSuggestion::url,
131 GURL("http://dummy.com/2")), 173 GURL("http://dummy.com/2")),
132 Property(&ContentSuggestion::url, 174 Property(&ContentSuggestion::url,
133 GURL("http://dummy.com/3"))))); 175 GURL("http://dummy.com/3")))));
134 AddOfflinePageToModel(CreateDummyRecentTab(3)); 176
177 auto recent_tabs_list = CreateDummyRecentTabs({1, 2, 3});
178 for (OfflinePageItem& recent_tab : recent_tabs_list) {
179 AddTabAndOfflinePageToModel(recent_tab);
180 }
135 } 181 }
136 182
137 TEST_F(RecentTabSuggestionsProviderTest, ShouldSortByCreationTime) { 183 TEST_F(RecentTabSuggestionsProviderTest, ShouldSortByCreationTime) {
138 base::Time now = base::Time::Now(); 184 base::Time now = base::Time::Now();
139 base::Time yesterday = now - base::TimeDelta::FromDays(1); 185 base::Time yesterday = now - base::TimeDelta::FromDays(1);
140 base::Time tomorrow = now + base::TimeDelta::FromDays(1); 186 base::Time tomorrow = now + base::TimeDelta::FromDays(1);
141 187
142 std::vector<OfflinePageItem> offline_pages = { 188 std::vector<OfflinePageItem> offline_pages = {
143 CreateDummyRecentTab(1, now), CreateDummyRecentTab(2, yesterday), 189 CreateDummyRecentTab(1, now), CreateDummyRecentTab(2, yesterday),
144 CreateDummyRecentTab(3, tomorrow)}; 190 CreateDummyRecentTab(3, tomorrow)};
145 191
146 EXPECT_CALL( 192 EXPECT_CALL(
147 *observer(), 193 *observer(),
148 OnNewSuggestions(_, recent_tabs_category(), 194 OnNewSuggestions(_, recent_tabs_category(),
149 ElementsAre(Property(&ContentSuggestion::url, 195 ElementsAre(Property(&ContentSuggestion::url,
150 GURL("http://dummy.com/1"))))); 196 GURL("http://dummy.com/1")))));
151 AddOfflinePageToModel(CreateDummyRecentTab(1, now)); 197 AddTabAndOfflinePageToModel(CreateDummyRecentTab(1, now));
152 198
153 EXPECT_CALL( 199 EXPECT_CALL(
154 *observer(), 200 *observer(),
155 OnNewSuggestions( 201 OnNewSuggestions(
156 _, recent_tabs_category(), 202 _, recent_tabs_category(),
157 ElementsAre( 203 ElementsAre(
158 Property(&ContentSuggestion::url, GURL("http://dummy.com/1")), 204 Property(&ContentSuggestion::url, GURL("http://dummy.com/1")),
159 Property(&ContentSuggestion::url, GURL("http://dummy.com/2"))))); 205 Property(&ContentSuggestion::url, GURL("http://dummy.com/2")))));
160 AddOfflinePageToModel(CreateDummyRecentTab(2, yesterday)); 206 AddTabAndOfflinePageToModel(CreateDummyRecentTab(2, yesterday));
161 207
162 offline_pages[1].last_access_time = 208 offline_pages[1].last_access_time =
163 offline_pages[0].last_access_time + base::TimeDelta::FromHours(1); 209 offline_pages[0].last_access_time + base::TimeDelta::FromHours(1);
164 210
165 EXPECT_CALL( 211 EXPECT_CALL(
166 *observer(), 212 *observer(),
167 OnNewSuggestions( 213 OnNewSuggestions(
168 _, recent_tabs_category(), 214 _, recent_tabs_category(),
169 ElementsAre(Property(&ContentSuggestion::url, 215 ElementsAre(Property(&ContentSuggestion::url,
170 GURL("http://dummy.com/3")), 216 GURL("http://dummy.com/3")),
171 Property(&ContentSuggestion::url, 217 Property(&ContentSuggestion::url,
172 GURL("http://dummy.com/1")), 218 GURL("http://dummy.com/1")),
173 Property(&ContentSuggestion::url, 219 Property(&ContentSuggestion::url,
174 GURL("http://dummy.com/2"))))); 220 GURL("http://dummy.com/2")))));
175 AddOfflinePageToModel(CreateDummyRecentTab(3, tomorrow)); 221 AddTabAndOfflinePageToModel(CreateDummyRecentTab(3, tomorrow));
176 } 222 }
177 223
178 TEST_F(RecentTabSuggestionsProviderTest, ShouldDeliverCorrectCategoryInfo) { 224 TEST_F(RecentTabSuggestionsProviderTest, ShouldDeliverCorrectCategoryInfo) {
179 EXPECT_FALSE( 225 EXPECT_FALSE(
180 provider()->GetCategoryInfo(recent_tabs_category()).has_fetch_action()); 226 provider()->GetCategoryInfo(recent_tabs_category()).has_fetch_action());
181 EXPECT_FALSE(provider() 227 EXPECT_FALSE(provider()
182 ->GetCategoryInfo(recent_tabs_category()) 228 ->GetCategoryInfo(recent_tabs_category())
183 .has_view_all_action()); 229 .has_view_all_action());
184 } 230 }
185 231
186 // TODO(vitaliii): Break this test into multiple tests. Currently if it fails, 232 // TODO(vitaliii): Break this test into multiple tests. Currently if it fails,
187 // it takes long time to find which part of it actually fails. 233 // it takes long time to find which part of it actually fails.
188 TEST_F(RecentTabSuggestionsProviderTest, ShouldDismiss) { 234 TEST_F(RecentTabSuggestionsProviderTest, ShouldDismiss) {
189 EXPECT_CALL(*observer(), OnNewSuggestions(_, _, _)).Times(3); 235 EXPECT_CALL(*observer(), OnNewSuggestions(_, _, _)).Times(3);
190 auto recent_tabs_list = CreateDummyRecentTabs({1, 2, 3}); 236 auto recent_tabs_list = CreateDummyRecentTabs({1, 2, 3});
191 for (OfflinePageItem& recent_tab : recent_tabs_list) { 237 for (OfflinePageItem& recent_tab : recent_tabs_list) {
192 AddOfflinePageToModel(recent_tab); 238 AddTabAndOfflinePageToModel(recent_tab);
193 } 239 }
194 240
195 // Dismiss 2 and 3. 241 // Dismiss 2 and 3.
196 EXPECT_CALL(*observer(), OnNewSuggestions(_, _, _)).Times(0); 242 EXPECT_CALL(*observer(), OnNewSuggestions(_, _, _)).Times(0);
197 provider()->DismissSuggestion(GetDummySuggestionId(2)); 243 provider()->DismissSuggestion(GetDummySuggestionId(2));
198 provider()->DismissSuggestion(GetDummySuggestionId(3)); 244 provider()->DismissSuggestion(GetDummySuggestionId(3));
199 Mock::VerifyAndClearExpectations(observer()); 245 Mock::VerifyAndClearExpectations(observer());
200 246
201 // They should disappear from the reported suggestions. 247 // They should disappear from the reported suggestions.
202 EXPECT_CALL( 248 EXPECT_CALL(
203 *observer(), 249 *observer(),
204 OnNewSuggestions( 250 OnNewSuggestions(
205 _, recent_tabs_category(), 251 _, recent_tabs_category(),
206 UnorderedElementsAre( 252 UnorderedElementsAre(
207 Property(&ContentSuggestion::url, GURL("http://dummy.com/1")), 253 Property(&ContentSuggestion::url, GURL("http://dummy.com/1")),
208 Property(&ContentSuggestion::url, GURL("http://dummy.com/4"))))); 254 Property(&ContentSuggestion::url, GURL("http://dummy.com/4")))));
209 255
210 AddOfflinePageToModel(CreateDummyRecentTab(4)); 256 AddTabAndOfflinePageToModel(CreateDummyRecentTab(4));
211 Mock::VerifyAndClearExpectations(observer()); 257 Mock::VerifyAndClearExpectations(observer());
212 258
213 // And appear in the dismissed suggestions. 259 // And appear in the dismissed suggestions.
214 std::vector<ContentSuggestion> dismissed_suggestions; 260 std::vector<ContentSuggestion> dismissed_suggestions;
215 provider()->GetDismissedSuggestionsForDebugging( 261 provider()->GetDismissedSuggestionsForDebugging(
216 recent_tabs_category(), 262 recent_tabs_category(),
217 base::Bind(&CaptureDismissedSuggestions, &dismissed_suggestions)); 263 base::Bind(&CaptureDismissedSuggestions, &dismissed_suggestions));
218 EXPECT_THAT( 264 EXPECT_THAT(
219 dismissed_suggestions, 265 dismissed_suggestions,
220 UnorderedElementsAre(Property(&ContentSuggestion::url, 266 UnorderedElementsAre(Property(&ContentSuggestion::url,
221 GURL("http://dummy.com/2")), 267 GURL("http://dummy.com/2")),
222 Property(&ContentSuggestion::url, 268 Property(&ContentSuggestion::url,
223 GURL("http://dummy.com/3")))); 269 GURL("http://dummy.com/3"))));
224 270
225 // Clear dismissed suggestions. 271 // Clear dismissed suggestions.
226 provider()->ClearDismissedSuggestionsForDebugging(recent_tabs_category()); 272 provider()->ClearDismissedSuggestionsForDebugging(recent_tabs_category());
227 273
228 // They should be gone from the dismissed suggestions. 274 // They should be gone from the dismissed suggestions.
229 dismissed_suggestions.clear(); 275 dismissed_suggestions.clear();
230 provider()->GetDismissedSuggestionsForDebugging( 276 provider()->GetDismissedSuggestionsForDebugging(
231 recent_tabs_category(), 277 recent_tabs_category(),
232 base::Bind(&CaptureDismissedSuggestions, &dismissed_suggestions)); 278 base::Bind(&CaptureDismissedSuggestions, &dismissed_suggestions));
233 EXPECT_THAT(dismissed_suggestions, IsEmpty()); 279 EXPECT_THAT(dismissed_suggestions, IsEmpty());
234 280
235 // And appear in the reported suggestions for the category again. 281 // And appear in the reported suggestions for the category again.
236 EXPECT_CALL(*observer(), 282 EXPECT_CALL(*observer(),
237 OnNewSuggestions(_, recent_tabs_category(), SizeIs(5))); 283 OnNewSuggestions(_, recent_tabs_category(), SizeIs(5)));
238 AddOfflinePageToModel(CreateDummyRecentTab(5)); 284 AddTabAndOfflinePageToModel(CreateDummyRecentTab(5));
239 Mock::VerifyAndClearExpectations(observer()); 285 Mock::VerifyAndClearExpectations(observer());
240 } 286 }
241 287
242 TEST_F(RecentTabSuggestionsProviderTest, 288 TEST_F(RecentTabSuggestionsProviderTest,
243 ShouldInvalidateWhenOfflinePageDeleted) { 289 ShouldInvalidateWhenOfflinePageDeleted) {
244 EXPECT_CALL(*observer(), OnNewSuggestions(_, _, _)).Times(3); 290 EXPECT_CALL(*observer(), OnNewSuggestions(_, _, _)).Times(3);
245 std::vector<OfflinePageItem> offline_pages = CreateDummyRecentTabs({1, 2, 3}); 291 std::vector<OfflinePageItem> offline_pages = CreateDummyRecentTabs({1, 2, 3});
246 for (OfflinePageItem& recent_tab : offline_pages) 292 for (OfflinePageItem& recent_tab : offline_pages)
247 AddOfflinePageToModel(recent_tab); 293 AddTabAndOfflinePageToModel(recent_tab);
248 294
249 // Invalidation of suggestion 2 should be forwarded. 295 // Invalidation of suggestion 2 should be forwarded.
250 EXPECT_CALL(*observer(), OnSuggestionInvalidated(_, GetDummySuggestionId(2))); 296 EXPECT_CALL(*observer(), OnSuggestionInvalidated(_, GetDummySuggestionId(2)));
251 FireOfflinePageDeleted(offline_pages[1]); 297 FireOfflinePageDeleted(offline_pages[1]);
252 } 298 }
253 299
254 TEST_F(RecentTabSuggestionsProviderTest, ShouldClearDismissedOnInvalidate) { 300 TEST_F(RecentTabSuggestionsProviderTest, ShouldClearDismissedOnInvalidate) {
255 EXPECT_CALL(*observer(), OnNewSuggestions(_, _, _)).Times(3); 301 EXPECT_CALL(*observer(), OnNewSuggestions(_, _, _)).Times(3);
256 std::vector<OfflinePageItem> offline_pages = CreateDummyRecentTabs({1, 2, 3}); 302 std::vector<OfflinePageItem> offline_pages = CreateDummyRecentTabs({1, 2, 3});
257 for (OfflinePageItem& recent_tab : offline_pages) 303 for (OfflinePageItem& recent_tab : offline_pages)
258 AddOfflinePageToModel(recent_tab); 304 AddTabAndOfflinePageToModel(recent_tab);
259 EXPECT_THAT(ReadDismissedIDsFromPrefs(), IsEmpty()); 305 EXPECT_THAT(ReadDismissedIDsFromPrefs(), IsEmpty());
260 306
261 provider()->DismissSuggestion(GetDummySuggestionId(2)); 307 provider()->DismissSuggestion(GetDummySuggestionId(2));
262 EXPECT_THAT(ReadDismissedIDsFromPrefs(), SizeIs(1)); 308 EXPECT_THAT(ReadDismissedIDsFromPrefs(), SizeIs(1));
263 309
264 FireOfflinePageDeleted(offline_pages[1]); 310 FireOfflinePageDeleted(offline_pages[1]);
265 EXPECT_THAT(ReadDismissedIDsFromPrefs(), IsEmpty()); 311 EXPECT_THAT(ReadDismissedIDsFromPrefs(), IsEmpty());
266 } 312 }
267 313
268 TEST_F(RecentTabSuggestionsProviderTest, ShouldClearDismissedOnFetch) { 314 TEST_F(RecentTabSuggestionsProviderTest, ShouldClearDismissedOnFetch) {
269 EXPECT_CALL(*observer(), OnNewSuggestions(_, _, _)).Times(3); 315 EXPECT_CALL(*observer(), OnNewSuggestions(_, _, _)).Times(3);
270 std::vector<OfflinePageItem> offline_pages = CreateDummyRecentTabs({1, 2, 3}); 316 std::vector<OfflinePageItem> offline_pages = CreateDummyRecentTabs({1, 2, 3});
271 for (OfflinePageItem& recent_tab : offline_pages) 317 for (OfflinePageItem& recent_tab : offline_pages)
272 AddOfflinePageToModel(recent_tab); 318 AddTabAndOfflinePageToModel(recent_tab);
273 319
274 provider()->DismissSuggestion(GetDummySuggestionId(2)); 320 provider()->DismissSuggestion(GetDummySuggestionId(2));
275 provider()->DismissSuggestion(GetDummySuggestionId(3)); 321 provider()->DismissSuggestion(GetDummySuggestionId(3));
276 EXPECT_THAT(ReadDismissedIDsFromPrefs(), SizeIs(2)); 322 EXPECT_THAT(ReadDismissedIDsFromPrefs(), SizeIs(2));
277 323
278 FireOfflinePageDeleted(offline_pages[0]); 324 FireOfflinePageDeleted(offline_pages[0]);
279 FireOfflinePageDeleted(offline_pages[2]); 325 FireOfflinePageDeleted(offline_pages[2]);
280 EXPECT_THAT(ReadDismissedIDsFromPrefs(), SizeIs(1)); 326 EXPECT_THAT(ReadDismissedIDsFromPrefs(), SizeIs(1));
281 327
282 FireOfflinePageDeleted(offline_pages[1]); 328 FireOfflinePageDeleted(offline_pages[1]);
283 EXPECT_THAT(ReadDismissedIDsFromPrefs(), IsEmpty()); 329 EXPECT_THAT(ReadDismissedIDsFromPrefs(), IsEmpty());
284 } 330 }
285 331
286 TEST_F(RecentTabSuggestionsProviderTest, ShouldNotShowSameUrlMutlipleTimes) { 332 TEST_F(RecentTabSuggestionsProviderTest, ShouldNotShowSameUrlMutlipleTimes) {
287 base::Time now = base::Time::Now(); 333 base::Time now = base::Time::Now();
288 base::Time yesterday = now - base::TimeDelta::FromDays(1); 334 base::Time yesterday = now - base::TimeDelta::FromDays(1);
289 base::Time tomorrow = now + base::TimeDelta::FromDays(1); 335 base::Time tomorrow = now + base::TimeDelta::FromDays(1);
290 std::vector<OfflinePageItem> offline_pages = { 336 std::vector<OfflinePageItem> offline_pages = {
291 CreateDummyRecentTab(1, yesterday), CreateDummyRecentTab(2, now), 337 CreateDummyRecentTab(1, yesterday), CreateDummyRecentTab(2, now),
292 CreateDummyRecentTab(3, tomorrow)}; 338 CreateDummyRecentTab(3, tomorrow)};
293 339
294 // We leave IDs different, but make the URLs the same. 340 // We leave IDs different, but make the URLs the same.
295 offline_pages[2].url = offline_pages[0].url; 341 offline_pages[2].url = offline_pages[0].url;
296 342
297 AddOfflinePageToModel(offline_pages[0]); 343 AddTabAndOfflinePageToModel(offline_pages[0]);
298 AddOfflinePageToModel(offline_pages[1]); 344 AddTabAndOfflinePageToModel(offline_pages[1]);
299 Mock::VerifyAndClearExpectations(observer()); 345 Mock::VerifyAndClearExpectations(observer());
300 EXPECT_CALL(*observer(), 346 EXPECT_CALL(*observer(),
301 OnNewSuggestions( 347 OnNewSuggestions(
302 _, recent_tabs_category(), 348 _, recent_tabs_category(),
303 UnorderedElementsAre( 349 UnorderedElementsAre(
304 Property(&ContentSuggestion::publish_date, now), 350 Property(&ContentSuggestion::publish_date, now),
305 Property(&ContentSuggestion::publish_date, tomorrow)))); 351 Property(&ContentSuggestion::publish_date, tomorrow))));
306 352
307 AddOfflinePageToModel(offline_pages[2]); 353 AddTabAndOfflinePageToModel(offline_pages[2]);
308 } 354 }
309 355
310 TEST_F(RecentTabSuggestionsProviderTest, 356 TEST_F(RecentTabSuggestionsProviderTest,
311 ShouldNotFetchIfAddedOfflinePageIsNotRecentTab) { 357 ShouldNotFetchIfAddedOfflinePageIsNotRecentTab) {
312 // The provider is not notified about the first recent tab yet.
313 model()->mutable_items()->push_back(CreateDummyRecentTab(1));
314 // It should not fetch when not a recent tab is added, thus, it should not 358 // It should not fetch when not a recent tab is added, thus, it should not
315 // report the first recent tab (which it is not aware about). 359 // report the first recent tab (which it is not aware about).
316 EXPECT_CALL(*observer(), OnNewSuggestions(_, _, _)).Times(0); 360 EXPECT_CALL(*observer(), OnNewSuggestions(_, _, _)).Times(0);
317 AddOfflinePageToModel(ntp_snippets::test::CreateDummyOfflinePageItem( 361 AddOfflinePageToModel(ntp_snippets::test::CreateDummyOfflinePageItem(
318 2, offline_pages::kDefaultNamespace)); 362 2, offline_pages::kDefaultNamespace));
319 } 363 }
320 364
321 TEST_F(RecentTabSuggestionsProviderTest, 365 TEST_F(RecentTabSuggestionsProviderTestNoLoad, ShouldFetchOnLoad) {
vitaliii 2017/02/16 08:11:04 Could you please add a comment saying that this te
dewittj 2017/02/17 22:33:38 Done. Also moved to the bottom to separate the two
322 ShouldFetchIfAddedOfflinePageIsRecentTab) { 366 // We should only fetch once, when the adapter is loaded.
vitaliii 2017/02/16 08:11:04 s/ We should/ On startup we should
dewittj 2017/02/17 22:33:38 Reworded.
323 // The provider is not notified about the first recent tab yet.
324 model()->mutable_items()->push_back(CreateDummyRecentTab(1));
325 // However, it must return the first recent tab (i.e. manually fetch it) even
326 // when notified about a different recent tab.
327 EXPECT_CALL( 367 EXPECT_CALL(
328 *observer(), 368 *observer(),
329 OnNewSuggestions( 369 OnNewSuggestions(
370 _, recent_tabs_category(),
371 UnorderedElementsAre(
372 Property(&ContentSuggestion::url, GURL("http://dummy.com/1")),
373 Property(&ContentSuggestion::url, GURL("http://dummy.com/2")))));
374
375 AddTabAndOfflinePageToModel(CreateDummyRecentTab(1));
vitaliii 2017/02/16 08:11:04 Could you please add recent tabs before EXPECT_CAL
dewittj 2017/02/17 22:33:38 In this top location, it catches improper |OnNewSu
376 AddTabAndOfflinePageToModel(CreateDummyRecentTab(2));
377 // The provider is not notified about the recent tabs yet.
378 task_runner()->RunUntilIdle();
379 // However, it must return both tabs when the model is loaded.
380 }
381
382 TEST_F(RecentTabSuggestionsProviderTest,
383 ShouldInvalidateSuggestionWhenTabGone) {
384 OfflinePageItem first_tab = CreateDummyRecentTab(1);
385 AddTabAndOfflinePageToModel(first_tab);
386 Mock::VerifyAndClearExpectations(observer());
387
388 EXPECT_CALL(*observer(), OnSuggestionInvalidated(_, GetDummySuggestionId(1)))
389 .Times(1);
390 RemoveTab(offline_pages::RecentTabsUIAdapterDelegate::TabIdFromClientId(
391 first_tab.client_id));
392 // Removing an unknown tab should not cause extra invalidations.
393 RemoveTab(42);
394 }
395
396 TEST_F(RecentTabSuggestionsProviderTest, ShouldNotShowPagesWithoutTab) {
397 EXPECT_CALL(*observer(), OnNewSuggestions(_, _, _)).Times(0);
398 // The provider is not notified about the first recent tab yet (no tab).
399 OfflinePageItem first_tab = CreateDummyRecentTab(1);
400 AddOfflinePageToModel(first_tab);
401
402 Mock::VerifyAndClearExpectations(observer());
403 EXPECT_CALL(*observer(), OnNewSuggestions(_, _, _)).Times(1);
404 EXPECT_CALL(
405 *observer(),
406 OnNewSuggestions(
330 _, recent_tabs_category(), 407 _, recent_tabs_category(),
331 UnorderedElementsAre( 408 UnorderedElementsAre(
332 Property(&ContentSuggestion::url, GURL("http://dummy.com/1")), 409 Property(&ContentSuggestion::url, GURL("http://dummy.com/1")),
333 Property(&ContentSuggestion::url, GURL("http://dummy.com/2"))))); 410 Property(&ContentSuggestion::url, GURL("http://dummy.com/2")))));
334 AddOfflinePageToModel(CreateDummyRecentTab(2)); 411
412 AddTab(offline_pages::RecentTabsUIAdapterDelegate::TabIdFromClientId(
413 first_tab.client_id));
414 OfflinePageItem second_tab = CreateDummyRecentTab(2);
415 AddTabAndOfflinePageToModel(second_tab);
416
417 Mock::VerifyAndClearExpectations(observer());
418
419 EXPECT_CALL(*observer(), OnNewSuggestions(_, _, _)).Times(0);
420 // |RemoveTab| by itself doesn't cause OnNewSuggestions to be called.
421 RemoveTab(offline_pages::RecentTabsUIAdapterDelegate::TabIdFromClientId(
422 second_tab.client_id));
423 Mock::VerifyAndClearExpectations(observer());
424
425 // But when we get another tab, OnNewSuggestions will be called.
426 EXPECT_CALL(
427 *observer(),
428 OnNewSuggestions(
429 _, recent_tabs_category(),
430 UnorderedElementsAre(
431 Property(&ContentSuggestion::url, GURL("http://dummy.com/1")),
432 Property(&ContentSuggestion::url, GURL("http://dummy.com/3")))));
433
434 AddTabAndOfflinePageToModel(CreateDummyRecentTab(3));
335 } 435 }
336 436
337 } // namespace ntp_snippets 437 } // namespace ntp_snippets
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698