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
5 #include "components/ntp_tiles/most_visited_sites.h"
6
7 #include <stddef.h>
8
9 #include <map>
10 #include <memory>
11 #include <ostream>
12 #include <string>
13 #include <tuple>
14 #include <utility>
15 #include <vector>
16
17 #include "base/bind.h"
18 #include "base/callback_list.h"
19 #include "base/command_line.h"
20 #include "base/macros.h"
21 #include "base/run_loop.h"
22 #include "base/strings/utf_string_conversions.h"
23 #include "base/task/cancelable_task_tracker.h"
24 #include "base/test/scoped_feature_list.h"
25 #include "base/test/task_environment.h"
26 #include "base/threading/thread_task_runner_handle.h"
27 #include "build/build_config.h"
28 #include "components/history/core/browser/top_sites.h"
29 #include "components/history/core/browser/top_sites_observer.h"
30 #include "components/ntp_tiles/custom_links_manager.h"
31 #include "components/ntp_tiles/features.h"
32 #include "components/ntp_tiles/icon_cacher.h"
33 #include "components/ntp_tiles/popular_sites_impl.h"
34 #include "components/ntp_tiles/pref_names.h"
35 #include "components/ntp_tiles/section_type.h"
36 #include "components/ntp_tiles/switches.h"
37 #include "components/sync_preferences/testing_pref_service_syncable.h"
38 #include "services/data_decoder/public/cpp/test_support/in_process_data_decoder.h"
39 #include "services/network/public/cpp/shared_url_loader_factory.h"
40 #include "services/network/public/cpp/weak_wrapper_shared_url_loader_factory.h"
41 #include "services/network/test/test_url_loader_factory.h"
42 #include "testing/gmock/include/gmock/gmock.h"
43 #include "testing/gtest/include/gtest/gtest.h"
44
45 namespace ntp_tiles {
46
47 // Defined for googletest. Must be defined in the same namespace.
PrintTo(const NTPTile & tile,std::ostream * os)48 void PrintTo(const NTPTile& tile, std::ostream* os) {
49 *os << "{\"" << tile.title << "\", \"" << tile.url << "\", "
50 << static_cast<int>(tile.source) << "}";
51 }
52
53 namespace {
54
55 using history::MostVisitedURL;
56 using history::MostVisitedURLList;
57 using history::TopSites;
58 using suggestions::ChromeSuggestion;
59 using suggestions::SuggestionsProfile;
60 using suggestions::SuggestionsService;
61 using testing::AtLeast;
62 using testing::AllOf;
63 using testing::AnyNumber;
64 using testing::ByMove;
65 using testing::Contains;
66 using testing::ElementsAre;
67 using testing::Eq;
68 using testing::Ge;
69 using testing::InSequence;
70 using testing::Invoke;
71 using testing::IsEmpty;
72 using testing::Key;
73 using testing::Mock;
74 using testing::Not;
75 using testing::Pair;
76 using testing::Return;
77 using testing::ReturnRef;
78 using testing::SaveArg;
79 using testing::SizeIs;
80 using testing::StrictMock;
81 using testing::_;
82
83 const char kHomepageUrl[] = "http://homepa.ge/";
84 const char kHomepageTitle[] = "Homepage";
85 const char kTestExploreUrl[] = "https://example.com/";
86 const char kTestExploreTitle[] = "Example";
87
PrintTile(const std::string & title,const std::string & url,TileSource source)88 std::string PrintTile(const std::string& title,
89 const std::string& url,
90 TileSource source) {
91 return std::string("has title \"") + title + std::string("\" and url \"") +
92 url + std::string("\" and source ") +
93 testing::PrintToString(static_cast<int>(source));
94 }
95
MATCHER_P3(MatchesTile,title,url,source,PrintTile (title,url,source))96 MATCHER_P3(MatchesTile, title, url, source, PrintTile(title, url, source)) {
97 return arg.title == base::ASCIIToUTF16(title) && arg.url == GURL(url) &&
98 arg.source == source;
99 }
100
PrintTileSource(TileSource source)101 std::string PrintTileSource(TileSource source) {
102 return std::string("has source ") +
103 testing::PrintToString(static_cast<int>(source));
104 }
105
MATCHER_P(TileWithSource,source,PrintTileSource (source))106 MATCHER_P(TileWithSource, source, PrintTileSource(source)) {
107 return arg.source == source;
108 }
109
110 MATCHER_P3(LastTileIs,
111 title,
112 url,
113 source,
114 std::string("last tile ") + PrintTile(title, url, source)) {
115 const NTPTilesVector& tiles = arg.at(SectionType::PERSONALIZED);
116 if (tiles.empty())
117 return false;
118
119 const NTPTile& last = tiles.back();
120 return last.title == base::ASCIIToUTF16(title) && last.url == GURL(url) &&
121 last.source == source;
122 }
123
124 MATCHER_P3(FirstPersonalizedTileIs,
125 title,
126 url,
127 source,
128 std::string("first tile ") + PrintTile(title, url, source)) {
129 if (arg.count(SectionType::PERSONALIZED) == 0) {
130 return false;
131 }
132 const NTPTilesVector& tiles = arg.at(SectionType::PERSONALIZED);
133 return !tiles.empty() && tiles[0].title == base::ASCIIToUTF16(title) &&
134 tiles[0].url == GURL(url) && tiles[0].source == source;
135 }
136
137 // testing::InvokeArgument<N> does not work with base::Callback, fortunately
138 // gmock makes it simple to create action templates that do for the various
139 // possible numbers of arguments.
ACTION_TEMPLATE(InvokeCallbackArgument,HAS_1_TEMPLATE_PARAMS (int,k),AND_1_VALUE_PARAMS (p0))140 ACTION_TEMPLATE(InvokeCallbackArgument,
141 HAS_1_TEMPLATE_PARAMS(int, k),
142 AND_1_VALUE_PARAMS(p0)) {
143 std::move(std::get<k>(args)).Run(p0);
144 }
145
MakeTile(const std::string & title,const std::string & url,TileSource source)146 NTPTile MakeTile(const std::string& title,
147 const std::string& url,
148 TileSource source) {
149 NTPTile tile;
150 tile.title = base::ASCIIToUTF16(title);
151 tile.url = GURL(url);
152 tile.source = source;
153 return tile;
154 }
155
MakeSuggestion(const std::string & title,const std::string & url)156 ChromeSuggestion MakeSuggestion(const std::string& title,
157 const std::string& url) {
158 ChromeSuggestion suggestion;
159 suggestion.set_title(title);
160 suggestion.set_url(url);
161 return suggestion;
162 }
163
MakeProfile(const std::vector<ChromeSuggestion> & suggestions)164 SuggestionsProfile MakeProfile(
165 const std::vector<ChromeSuggestion>& suggestions) {
166 SuggestionsProfile profile;
167 for (const ChromeSuggestion& suggestion : suggestions) {
168 *profile.add_suggestions() = suggestion;
169 }
170 return profile;
171 }
172
MakeMostVisitedURL(const std::string & title,const std::string & url)173 MostVisitedURL MakeMostVisitedURL(const std::string& title,
174 const std::string& url) {
175 MostVisitedURL result;
176 result.title = base::ASCIIToUTF16(title);
177 result.url = GURL(url);
178 return result;
179 }
180
181 class MockTopSites : public TopSites {
182 public:
183 MOCK_METHOD0(ShutdownOnUIThread, void());
GetMostVisitedURLs(GetMostVisitedURLsCallback callback)184 void GetMostVisitedURLs(GetMostVisitedURLsCallback callback) override {
185 GetMostVisitedURLs_(callback);
186 }
187 MOCK_METHOD1(GetMostVisitedURLs_, void(GetMostVisitedURLsCallback& callback));
188 MOCK_METHOD0(SyncWithHistory, void());
189 MOCK_CONST_METHOD0(HasBlacklistedItems, bool());
190 MOCK_METHOD1(AddBlacklistedURL, void(const GURL& url));
191 MOCK_METHOD1(RemoveBlacklistedURL, void(const GURL& url));
192 MOCK_METHOD1(IsBlacklisted, bool(const GURL& url));
193 MOCK_METHOD0(ClearBlacklistedURLs, void());
194 MOCK_METHOD0(StartQueryForMostVisited, base::CancelableTaskTracker::TaskId());
195 MOCK_METHOD1(IsKnownURL, bool(const GURL& url));
196 MOCK_CONST_METHOD1(GetCanonicalURLString,
197 const std::string&(const GURL& url));
198 MOCK_METHOD0(IsFull, bool());
199 MOCK_CONST_METHOD0(loaded, bool());
200 MOCK_METHOD0(GetPrepopulatedPages, history::PrepopulatedPageList());
201 MOCK_METHOD1(OnNavigationCommitted, void(const GURL& url));
202
203 // Publicly expose notification to observers, since the implementation cannot
204 // be overriden.
205 using TopSites::NotifyTopSitesChanged;
206
207 protected:
208 ~MockTopSites() override = default;
209 };
210
211 class MockSuggestionsService : public SuggestionsService {
212 public:
213 MOCK_METHOD0(FetchSuggestionsData, bool());
214 MOCK_CONST_METHOD0(GetSuggestionsDataFromCache,
215 base::Optional<SuggestionsProfile>());
216 MOCK_METHOD1(AddCallback,
217 std::unique_ptr<ResponseCallbackList::Subscription>(
218 const ResponseCallback& callback));
219 MOCK_METHOD1(BlacklistURL, bool(const GURL& candidate_url));
220 MOCK_METHOD1(UndoBlacklistURL, bool(const GURL& url));
221 MOCK_METHOD0(ClearBlacklist, void());
222 };
223
224 class MockMostVisitedSitesObserver : public MostVisitedSites::Observer {
225 public:
226 MOCK_METHOD1(OnURLsAvailable,
227 void(const std::map<SectionType, NTPTilesVector>& sections));
228 MOCK_METHOD1(OnIconMadeAvailable, void(const GURL& site_url));
229 };
230
231 class FakeHomepageClient : public MostVisitedSites::HomepageClient {
232 public:
FakeHomepageClient()233 FakeHomepageClient()
234 : homepage_tile_enabled_(false), homepage_url_(kHomepageUrl) {}
~FakeHomepageClient()235 ~FakeHomepageClient() override {}
236
IsHomepageTileEnabled() const237 bool IsHomepageTileEnabled() const override { return homepage_tile_enabled_; }
238
GetHomepageUrl() const239 GURL GetHomepageUrl() const override { return homepage_url_; }
240
QueryHomepageTitle(TitleCallback title_callback)241 void QueryHomepageTitle(TitleCallback title_callback) override {
242 std::move(title_callback).Run(homepage_title_);
243 }
244
SetHomepageTileEnabled(bool homepage_tile_enabled)245 void SetHomepageTileEnabled(bool homepage_tile_enabled) {
246 homepage_tile_enabled_ = homepage_tile_enabled;
247 }
248
SetHomepageUrl(GURL homepage_url)249 void SetHomepageUrl(GURL homepage_url) { homepage_url_ = homepage_url; }
250
SetHomepageTitle(const base::Optional<base::string16> & homepage_title)251 void SetHomepageTitle(const base::Optional<base::string16>& homepage_title) {
252 homepage_title_ = homepage_title;
253 }
254
255 private:
256 bool homepage_tile_enabled_;
257 GURL homepage_url_;
258 base::Optional<base::string16> homepage_title_;
259 };
260
261 class FakeExploreSitesClient : public MostVisitedSites::ExploreSitesClient {
262 public:
263 ~FakeExploreSitesClient() override = default;
264
GetExploreSitesUrl() const265 GURL GetExploreSitesUrl() const override { return GURL(kTestExploreUrl); }
266
GetExploreSitesTitle() const267 base::string16 GetExploreSitesTitle() const override {
268 return base::ASCIIToUTF16(kTestExploreTitle);
269 }
270 };
271
272 class MockIconCacher : public IconCacher {
273 public:
274 MOCK_METHOD3(StartFetchPopularSites,
275 void(PopularSites::Site site,
276 base::OnceClosure icon_available,
277 base::OnceClosure preliminary_icon_available));
278 MOCK_METHOD2(StartFetchMostLikely,
279 void(const GURL& page_url, base::OnceClosure icon_available));
280 };
281
282 class MockCustomLinksManager : public CustomLinksManager {
283 public:
284 MOCK_METHOD1(Initialize, bool(const NTPTilesVector& tiles));
285 MOCK_METHOD0(Uninitialize, void());
286 MOCK_CONST_METHOD0(IsInitialized, bool());
287 MOCK_CONST_METHOD0(GetLinks, const std::vector<CustomLinksManager::Link>&());
288 MOCK_METHOD2(AddLink, bool(const GURL& url, const base::string16& title));
289 MOCK_METHOD3(UpdateLink,
290 bool(const GURL& url,
291 const GURL& new_url,
292 const base::string16& new_title));
293 MOCK_METHOD2(ReorderLink, bool(const GURL& url, size_t new_pos));
294 MOCK_METHOD1(DeleteLink, bool(const GURL& url));
295 MOCK_METHOD0(UndoAction, bool());
296 MOCK_METHOD1(RegisterCallbackForOnChanged,
297 std::unique_ptr<base::CallbackList<void()>::Subscription>(
298 base::RepeatingClosure callback));
299 };
300
301 class PopularSitesFactoryForTest {
302 public:
PopularSitesFactoryForTest(sync_preferences::TestingPrefServiceSyncable * pref_service)303 PopularSitesFactoryForTest(
304 sync_preferences::TestingPrefServiceSyncable* pref_service)
305 : prefs_(pref_service) {
306 test_shared_loader_factory_ =
307 base::MakeRefCounted<network::WeakWrapperSharedURLLoaderFactory>(
308 &test_url_loader_factory_);
309 PopularSitesImpl::RegisterProfilePrefs(pref_service->registry());
310 }
311
SeedWithSampleData()312 void SeedWithSampleData() {
313 prefs_->SetString(prefs::kPopularSitesOverrideCountry, "IN");
314 prefs_->SetString(prefs::kPopularSitesOverrideVersion, "5");
315
316 test_url_loader_factory_.ClearResponses();
317 test_url_loader_factory_.AddResponse(
318 "https://www.gstatic.com/chrome/ntp/suggested_sites_IN_5.json",
319 R"([{
320 "title": "PopularSite1",
321 "url": "http://popularsite1/",
322 "favicon_url": "http://popularsite1/favicon.ico"
323 },
324 {
325 "title": "PopularSite2",
326 "url": "http://popularsite2/",
327 "favicon_url": "http://popularsite2/favicon.ico"
328 }
329 ])");
330
331 test_url_loader_factory_.AddResponse(
332 "https://www.gstatic.com/chrome/ntp/suggested_sites_US_5.json",
333 R"([{
334 "title": "ESPN",
335 "url": "http://www.espn.com",
336 "favicon_url": "http://www.espn.com/favicon.ico"
337 }, {
338 "title": "Mobile",
339 "url": "http://www.mobile.de",
340 "favicon_url": "http://www.mobile.de/favicon.ico"
341 }, {
342 "title": "Google News",
343 "url": "http://news.google.com",
344 "favicon_url": "http://news.google.com/favicon.ico"
345 }
346 ])");
347
348 test_url_loader_factory_.AddResponse(
349 "https://www.gstatic.com/chrome/ntp/suggested_sites_IN_6.json",
350 R"([{
351 "section": 1, // PERSONALIZED
352 "sites": [{
353 "title": "PopularSite1",
354 "url": "http://popularsite1/",
355 "favicon_url": "http://popularsite1/favicon.ico"
356 },
357 {
358 "title": "PopularSite2",
359 "url": "http://popularsite2/",
360 "favicon_url": "http://popularsite2/favicon.ico"
361 },
362 ]
363 },
364 {
365 "section": 4, // NEWS
366 "sites": [{
367 "large_icon_url": "https://news.google.com/icon.ico",
368 "title": "Google News",
369 "url": "https://news.google.com/"
370 },
371 {
372 "favicon_url": "https://news.google.com/icon.ico",
373 "title": "Google News Germany",
374 "url": "https://news.google.de/"
375 }]
376 },
377 {
378 "section": 2, // SOCIAL
379 "sites": [{
380 "large_icon_url": "https://ssl.gstatic.com/icon.png",
381 "title": "Google+",
382 "url": "https://plus.google.com/"
383 }]
384 },
385 {
386 "section": 3, // ENTERTAINMENT
387 "sites": [
388 // Intentionally empty site list.
389 ]
390 }
391 ])");
392 }
393
New()394 std::unique_ptr<PopularSites> New() {
395 return std::make_unique<PopularSitesImpl>(prefs_,
396 /*template_url_service=*/nullptr,
397 /*variations_service=*/nullptr,
398 test_shared_loader_factory_);
399 }
400
401 private:
402 PrefService* prefs_;
403 network::TestURLLoaderFactory test_url_loader_factory_;
404 scoped_refptr<network::SharedURLLoaderFactory> test_shared_loader_factory_;
405 };
406
407 // CallbackList-like container without Subscription, mimicking the
408 // implementation in TopSites (which doesn't use base::CallbackList).
409 class TopSitesCallbackList {
410 public:
411 void Add(TopSites::GetMostVisitedURLsCallback& callback) {
412 callbacks_.push_back(std::move(callback));
413 }
414
415 void ClearAndNotify(const MostVisitedURLList& list) {
416 std::vector<TopSites::GetMostVisitedURLsCallback> callbacks;
417 callbacks.swap(callbacks_);
418 for (auto& callback : callbacks)
419 std::move(callback).Run(list);
420 }
421
422 bool empty() const { return callbacks_.empty(); }
423
424 private:
425 std::vector<TopSites::GetMostVisitedURLsCallback> callbacks_;
426 };
427
428 } // namespace
429
430 // Param is a tuple with two components:
431 // * The first specifies whether Popular Sites is enabled via variations.
432 // * The second specifies whether Suggestions Service tiles are enabled via
433 // variations.
434 class MostVisitedSitesTest
435 : public ::testing::TestWithParam<std::tuple<bool, bool>> {
436 protected:
437 MostVisitedSitesTest()
438 : is_custom_links_enabled_(false),
439 popular_sites_factory_(&pref_service_),
440 mock_top_sites_(new StrictMock<MockTopSites>()) {
441 MostVisitedSites::RegisterProfilePrefs(pref_service_.registry());
442
443 std::vector<base::Feature> enabled_features;
444 // Disable FaviconServer in most tests and override in specific tests.
445 std::vector<base::Feature> disabled_features = {
446 kNtpMostLikelyFaviconsFromServerFeature};
447 if (IsPopularSitesFeatureEnabled()) {
448 enabled_features.push_back(kUsePopularSitesSuggestions);
449 } else {
450 disabled_features.push_back(kUsePopularSitesSuggestions);
451 }
452 if (IsDisplaySuggestionsServiceTilesEnabled()) {
453 enabled_features.push_back(kDisplaySuggestionsServiceTiles);
454 } else {
455 disabled_features.push_back(kDisplaySuggestionsServiceTiles);
456 }
457
458 feature_list_.InitWithFeatures(enabled_features, disabled_features);
459 if (IsPopularSitesFeatureEnabled())
460 popular_sites_factory_.SeedWithSampleData();
461
462 RecreateMostVisitedSites();
463 }
464
465 void RecreateMostVisitedSites() {
466 // We use StrictMock to make sure the object is not used unless Popular
467 // Sites is enabled.
468 auto icon_cacher = std::make_unique<StrictMock<MockIconCacher>>();
469 icon_cacher_ = icon_cacher.get();
470
471 // Custom links needs to be nullptr when MostVisitedSites is created, unless
472 // the custom links feature is enabled. Custom links is disabled for
473 // Android, iOS, and third-party NTPs.
474 std::unique_ptr<StrictMock<MockCustomLinksManager>> mock_custom_links;
475 if (is_custom_links_enabled_) {
476 mock_custom_links =
477 std::make_unique<StrictMock<MockCustomLinksManager>>();
478 mock_custom_links_ = mock_custom_links.get();
479 }
480
481 if (IsPopularSitesFeatureEnabled()) {
482 // Populate Popular Sites' internal cache by mimicking a past usage of
483 // PopularSitesImpl.
484 auto tmp_popular_sites = popular_sites_factory_.New();
485 base::RunLoop loop;
486 bool save_success = false;
487 tmp_popular_sites->MaybeStartFetch(
488 /*force_download=*/true,
489 base::BindOnce(
490 [](bool* save_success, base::RunLoop* loop, bool success) {
491 *save_success = success;
492 loop->Quit();
493 },
494 &save_success, &loop));
495 loop.Run();
496 EXPECT_TRUE(save_success);
497
498 // With PopularSites enabled, blacklist is exercised.
499 EXPECT_CALL(*mock_top_sites_, IsBlacklisted(_))
500 .WillRepeatedly(Return(false));
501 // Mock icon cacher never replies, and we also don't verify whether the
502 // code uses it correctly.
503 EXPECT_CALL(*icon_cacher, StartFetchPopularSites(_, _, _))
504 .Times(AtLeast(0));
505 }
506
507 EXPECT_CALL(*icon_cacher, StartFetchMostLikely(_, _)).Times(AtLeast(0));
508
509 most_visited_sites_ = std::make_unique<MostVisitedSites>(
510 &pref_service_, mock_top_sites_, &mock_suggestions_service_,
511 popular_sites_factory_.New(), std::move(mock_custom_links),
512 std::move(icon_cacher),
513 /*supervisor=*/nullptr);
514 }
515
516 bool IsPopularSitesFeatureEnabled() const { return std::get<0>(GetParam()); }
517 bool IsDisplaySuggestionsServiceTilesEnabled() const {
518 return std::get<1>(GetParam());
519 }
520
521 bool VerifyAndClearExpectations() {
522 base::RunLoop().RunUntilIdle();
523 const bool success =
524 Mock::VerifyAndClearExpectations(mock_top_sites_.get()) &&
525 Mock::VerifyAndClearExpectations(&mock_suggestions_service_) &&
526 Mock::VerifyAndClearExpectations(&mock_observer_);
527 // For convenience, restore the expectations for IsBlacklisted().
528 if (IsPopularSitesFeatureEnabled()) {
529 EXPECT_CALL(*mock_top_sites_, IsBlacklisted(_))
530 .WillRepeatedly(Return(false));
531 }
532 return success;
533 }
534
535 FakeHomepageClient* RegisterNewHomepageClient() {
536 auto homepage_client = std::make_unique<FakeHomepageClient>();
537 FakeHomepageClient* raw_client_ptr = homepage_client.get();
538 most_visited_sites_->SetHomepageClient(std::move(homepage_client));
539 return raw_client_ptr;
540 }
541
542 FakeExploreSitesClient* RegisterNewExploreSitesClient() {
543 auto explore_sites_client = std::make_unique<FakeExploreSitesClient>();
544 FakeExploreSitesClient* raw_client_ptr = explore_sites_client.get();
545 most_visited_sites_->SetExploreSitesClient(std::move(explore_sites_client));
546 return raw_client_ptr;
547 }
548
549 void DisableRemoteSuggestions() {
550 EXPECT_CALL(mock_suggestions_service_, AddCallback(_))
551 .Times(AnyNumber())
552 .WillRepeatedly(Invoke(&suggestions_service_callbacks_,
553 &SuggestionsService::ResponseCallbackList::Add));
554 EXPECT_CALL(mock_suggestions_service_, GetSuggestionsDataFromCache())
555 .Times(AnyNumber())
556 .WillRepeatedly(Return(SuggestionsProfile())); // Empty cache.
557 EXPECT_CALL(mock_suggestions_service_, FetchSuggestionsData())
558 .Times(AnyNumber())
559 .WillRepeatedly(Return(true));
560 }
561
562 void EnableCustomLinks() { is_custom_links_enabled_ = true; }
563
564 bool is_custom_links_enabled_;
565 base::CallbackList<SuggestionsService::ResponseCallback::RunType>
566 suggestions_service_callbacks_;
567 TopSitesCallbackList top_sites_callbacks_;
568
569 base::test::SingleThreadTaskEnvironment task_environment_;
570 data_decoder::test::InProcessDataDecoder in_process_data_decoder_;
571 sync_preferences::TestingPrefServiceSyncable pref_service_;
572 PopularSitesFactoryForTest popular_sites_factory_;
573 scoped_refptr<StrictMock<MockTopSites>> mock_top_sites_;
574 StrictMock<MockSuggestionsService> mock_suggestions_service_;
575 StrictMock<MockMostVisitedSitesObserver> mock_observer_;
576 std::unique_ptr<MostVisitedSites> most_visited_sites_;
577 base::test::ScopedFeatureList feature_list_;
578 MockCustomLinksManager* mock_custom_links_;
579 MockIconCacher* icon_cacher_;
580 };
581
582 TEST_P(MostVisitedSitesTest, ShouldStartNoCallInConstructor) {
583 // No call to mocks expected by the mere fact of instantiating
584 // MostVisitedSites.
585 base::RunLoop().RunUntilIdle();
586 }
587
588 TEST_P(MostVisitedSitesTest, ShouldRefreshBothBackends) {
589 EXPECT_CALL(*mock_top_sites_, SyncWithHistory());
590 EXPECT_CALL(mock_suggestions_service_, FetchSuggestionsData());
591 most_visited_sites_->Refresh();
592 }
593
594 TEST_P(MostVisitedSitesTest, ShouldIncludeTileForHomepage) {
595 FakeHomepageClient* homepage_client = RegisterNewHomepageClient();
596 homepage_client->SetHomepageTileEnabled(true);
597 DisableRemoteSuggestions();
598 EXPECT_CALL(*mock_top_sites_, GetMostVisitedURLs_(_))
599 .WillRepeatedly(InvokeCallbackArgument<0>(MostVisitedURLList{}));
600 EXPECT_CALL(*mock_top_sites_, SyncWithHistory());
601 EXPECT_CALL(*mock_top_sites_, IsBlacklisted(Eq(GURL(kHomepageUrl))))
602 .Times(AnyNumber())
603 .WillRepeatedly(Return(false));
604 EXPECT_CALL(mock_observer_, OnURLsAvailable(FirstPersonalizedTileIs(
605 "", kHomepageUrl, TileSource::HOMEPAGE)));
606 most_visited_sites_->SetMostVisitedURLsObserver(&mock_observer_,
607 /*num_sites=*/3);
608 base::RunLoop().RunUntilIdle();
609 }
610
611 TEST_P(MostVisitedSitesTest, ShouldNotIncludeHomepageWithoutClient) {
612 DisableRemoteSuggestions();
613 EXPECT_CALL(*mock_top_sites_, GetMostVisitedURLs_(_))
614 .WillRepeatedly(InvokeCallbackArgument<0>(MostVisitedURLList{}));
615 EXPECT_CALL(*mock_top_sites_, SyncWithHistory());
616 EXPECT_CALL(mock_observer_,
617 OnURLsAvailable(Contains(
618 Pair(SectionType::PERSONALIZED,
619 Not(Contains(MatchesTile("", kHomepageUrl,
620 TileSource::HOMEPAGE)))))));
621 most_visited_sites_->SetMostVisitedURLsObserver(&mock_observer_,
622 /*num_sites=*/3);
623 base::RunLoop().RunUntilIdle();
624 }
625
626 TEST_P(MostVisitedSitesTest, ShouldIncludeHomeTileWithUrlBeforeQueryingName) {
627 // Because the query time for the real name might take a while, provide the
628 // home tile with URL as title immediately and update the tiles as soon as the
629 // real title was found.
630 FakeHomepageClient* homepage_client = RegisterNewHomepageClient();
631 homepage_client->SetHomepageTileEnabled(true);
632 homepage_client->SetHomepageTitle(base::UTF8ToUTF16(kHomepageTitle));
633 DisableRemoteSuggestions();
634 EXPECT_CALL(*mock_top_sites_, GetMostVisitedURLs_(_))
635 .WillRepeatedly(InvokeCallbackArgument<0>(MostVisitedURLList{}));
636 EXPECT_CALL(*mock_top_sites_, SyncWithHistory());
637 EXPECT_CALL(*mock_top_sites_, IsBlacklisted(Eq(GURL(kHomepageUrl))))
638 .Times(AnyNumber())
639 .WillRepeatedly(Return(false));
640 {
641 testing::Sequence seq;
642 EXPECT_CALL(mock_observer_,
643 OnURLsAvailable(Contains(
644 Pair(SectionType::PERSONALIZED,
645 Not(Contains(MatchesTile("", kHomepageUrl,
646 TileSource::HOMEPAGE)))))));
647 EXPECT_CALL(mock_observer_,
648 OnURLsAvailable(Contains(
649 Pair(SectionType::PERSONALIZED,
650 Not(Contains(MatchesTile(kHomepageTitle, kHomepageUrl,
651 TileSource::HOMEPAGE)))))));
652 }
653 most_visited_sites_->SetMostVisitedURLsObserver(&mock_observer_,
654 /*num_sites=*/3);
655 base::RunLoop().RunUntilIdle();
656 }
657
658 TEST_P(MostVisitedSitesTest, ShouldUpdateHomepageTileWhenRefreshHomepageTile) {
659 FakeHomepageClient* homepage_client = RegisterNewHomepageClient();
660 homepage_client->SetHomepageTileEnabled(true);
661 DisableRemoteSuggestions();
662
663 // Ensure that home tile is available as usual.
664 EXPECT_CALL(*mock_top_sites_, GetMostVisitedURLs_(_))
665 .WillRepeatedly(InvokeCallbackArgument<0>(MostVisitedURLList{}));
666 EXPECT_CALL(*mock_top_sites_, SyncWithHistory());
667 EXPECT_CALL(*mock_top_sites_, IsBlacklisted(Eq(GURL(kHomepageUrl))))
668 .Times(AnyNumber())
669 .WillRepeatedly(Return(false));
670 EXPECT_CALL(mock_observer_, OnURLsAvailable(FirstPersonalizedTileIs(
671 "", kHomepageUrl, TileSource::HOMEPAGE)));
672 most_visited_sites_->SetMostVisitedURLsObserver(&mock_observer_,
673 /*num_sites=*/3);
674 base::RunLoop().RunUntilIdle();
675 VerifyAndClearExpectations();
676
677 // Disable home page and rebuild _without_ Resync. The tile should be gone.
678 homepage_client->SetHomepageTileEnabled(false);
679 DisableRemoteSuggestions();
680 EXPECT_CALL(*mock_top_sites_, GetMostVisitedURLs_(_))
681 .WillRepeatedly(InvokeCallbackArgument<0>(MostVisitedURLList{}));
682 EXPECT_CALL(*mock_top_sites_, SyncWithHistory()).Times(0);
683 EXPECT_CALL(mock_observer_, OnURLsAvailable(Not(FirstPersonalizedTileIs(
684 "", kHomepageUrl, TileSource::HOMEPAGE))));
685 most_visited_sites_->RefreshTiles();
686 base::RunLoop().RunUntilIdle();
687 }
688
689 TEST_P(MostVisitedSitesTest, ShouldNotIncludeHomepageIfNoTileRequested) {
690 FakeHomepageClient* homepage_client = RegisterNewHomepageClient();
691 homepage_client->SetHomepageTileEnabled(true);
692 DisableRemoteSuggestions();
693 EXPECT_CALL(*mock_top_sites_, GetMostVisitedURLs_(_))
694 .WillRepeatedly(InvokeCallbackArgument<0>(MostVisitedURLList{}));
695 EXPECT_CALL(*mock_top_sites_, SyncWithHistory());
696 EXPECT_CALL(*mock_top_sites_, IsBlacklisted(Eq(GURL(kHomepageUrl))))
697 .Times(AnyNumber())
698 .WillRepeatedly(Return(false));
699 EXPECT_CALL(
700 mock_observer_,
701 OnURLsAvailable(Contains(Pair(SectionType::PERSONALIZED, IsEmpty()))));
702 most_visited_sites_->SetMostVisitedURLsObserver(&mock_observer_,
703 /*num_sites=*/0);
704 base::RunLoop().RunUntilIdle();
705 }
706
707 TEST_P(MostVisitedSitesTest, ShouldReturnHomepageIfOneTileRequested) {
708 FakeHomepageClient* homepage_client = RegisterNewHomepageClient();
709 homepage_client->SetHomepageTileEnabled(true);
710 DisableRemoteSuggestions();
711 EXPECT_CALL(*mock_top_sites_, GetMostVisitedURLs_(_))
712 .WillRepeatedly(InvokeCallbackArgument<0>(
713 (MostVisitedURLList{MakeMostVisitedURL("Site 1", "http://site1/")})));
714 EXPECT_CALL(*mock_top_sites_, SyncWithHistory());
715 EXPECT_CALL(*mock_top_sites_, IsBlacklisted(Eq(GURL(kHomepageUrl))))
716 .Times(AnyNumber())
717 .WillRepeatedly(Return(false));
718 EXPECT_CALL(
719 mock_observer_,
720 OnURLsAvailable(Contains(Pair(
721 SectionType::PERSONALIZED,
722 ElementsAre(MatchesTile("", kHomepageUrl, TileSource::HOMEPAGE))))));
723 most_visited_sites_->SetMostVisitedURLsObserver(&mock_observer_,
724 /*num_sites=*/1);
725 base::RunLoop().RunUntilIdle();
726 }
727
TEST_P(MostVisitedSitesTest,ShouldHaveHomepageFirstInListWhenFull)728 TEST_P(MostVisitedSitesTest, ShouldHaveHomepageFirstInListWhenFull) {
729 FakeHomepageClient* homepage_client = RegisterNewHomepageClient();
730 homepage_client->SetHomepageTileEnabled(true);
731 DisableRemoteSuggestions();
732 EXPECT_CALL(*mock_top_sites_, GetMostVisitedURLs_(_))
733 .WillRepeatedly(InvokeCallbackArgument<0>((MostVisitedURLList{
734 MakeMostVisitedURL("Site 1", "http://site1/"),
735 MakeMostVisitedURL("Site 2", "http://site2/"),
736 MakeMostVisitedURL("Site 3", "http://site3/"),
737 MakeMostVisitedURL("Site 4", "http://site4/"),
738 MakeMostVisitedURL("Site 5", "http://site5/"),
739 })));
740 EXPECT_CALL(*mock_top_sites_, SyncWithHistory());
741 EXPECT_CALL(*mock_top_sites_, IsBlacklisted(Eq(GURL(kHomepageUrl))))
742 .Times(AnyNumber())
743 .WillRepeatedly(Return(false));
744 std::map<SectionType, NTPTilesVector> sections;
745 EXPECT_CALL(mock_observer_, OnURLsAvailable(_))
746 .WillOnce(SaveArg<0>(§ions));
747 most_visited_sites_->SetMostVisitedURLsObserver(&mock_observer_,
748 /*num_sites=*/4);
749 base::RunLoop().RunUntilIdle();
750 ASSERT_THAT(sections, Contains(Key(SectionType::PERSONALIZED)));
751 NTPTilesVector tiles = sections.at(SectionType::PERSONALIZED);
752 ASSERT_THAT(tiles.size(), Ge(4ul));
753 // Assert that the home page is appended as the final tile.
754 EXPECT_THAT(tiles[0], MatchesTile("", kHomepageUrl, TileSource::HOMEPAGE));
755 }
756
TEST_P(MostVisitedSitesTest,ShouldHaveHomepageFirstInListWhenNotFull)757 TEST_P(MostVisitedSitesTest, ShouldHaveHomepageFirstInListWhenNotFull) {
758 FakeHomepageClient* homepage_client = RegisterNewHomepageClient();
759 homepage_client->SetHomepageTileEnabled(true);
760 DisableRemoteSuggestions();
761 EXPECT_CALL(*mock_top_sites_, GetMostVisitedURLs_(_))
762 .WillRepeatedly(InvokeCallbackArgument<0>((MostVisitedURLList{
763 MakeMostVisitedURL("Site 1", "http://site1/"),
764 MakeMostVisitedURL("Site 2", "http://site2/"),
765 MakeMostVisitedURL("Site 3", "http://site3/"),
766 MakeMostVisitedURL("Site 4", "http://site4/"),
767 MakeMostVisitedURL("Site 5", "http://site5/"),
768 })));
769 EXPECT_CALL(*mock_top_sites_, SyncWithHistory());
770 EXPECT_CALL(*mock_top_sites_, IsBlacklisted(Eq(GURL(kHomepageUrl))))
771 .Times(AnyNumber())
772 .WillRepeatedly(Return(false));
773 std::map<SectionType, NTPTilesVector> sections;
774 EXPECT_CALL(mock_observer_, OnURLsAvailable(_))
775 .WillOnce(SaveArg<0>(§ions));
776 most_visited_sites_->SetMostVisitedURLsObserver(&mock_observer_,
777 /*num_sites=*/8);
778 base::RunLoop().RunUntilIdle();
779 ASSERT_THAT(sections, Contains(Key(SectionType::PERSONALIZED)));
780 NTPTilesVector tiles = sections.at(SectionType::PERSONALIZED);
781 ASSERT_THAT(tiles.size(), Ge(6ul));
782 // Assert that the home page is the first tile.
783 EXPECT_THAT(tiles[0], MatchesTile("", kHomepageUrl, TileSource::HOMEPAGE));
784 }
785
TEST_P(MostVisitedSitesTest,ShouldDeduplicateHomepageWithTopSites)786 TEST_P(MostVisitedSitesTest, ShouldDeduplicateHomepageWithTopSites) {
787 FakeHomepageClient* homepage_client = RegisterNewHomepageClient();
788 homepage_client->SetHomepageTileEnabled(true);
789 DisableRemoteSuggestions();
790 EXPECT_CALL(*mock_top_sites_, GetMostVisitedURLs_(_))
791 .WillRepeatedly(InvokeCallbackArgument<0>(
792 (MostVisitedURLList{MakeMostVisitedURL("Site 1", "http://site1/"),
793 MakeMostVisitedURL("", kHomepageUrl)})));
794 EXPECT_CALL(*mock_top_sites_, SyncWithHistory());
795 EXPECT_CALL(*mock_top_sites_, IsBlacklisted(Eq(GURL(kHomepageUrl))))
796 .Times(AnyNumber())
797 .WillRepeatedly(Return(false));
798 EXPECT_CALL(
799 mock_observer_,
800 OnURLsAvailable(Contains(Pair(
801 SectionType::PERSONALIZED,
802 AllOf(Contains(MatchesTile("", kHomepageUrl, TileSource::HOMEPAGE)),
803 Not(Contains(
804 MatchesTile("", kHomepageUrl, TileSource::TOP_SITES))))))));
805 most_visited_sites_->SetMostVisitedURLsObserver(&mock_observer_,
806 /*num_sites=*/3);
807 base::RunLoop().RunUntilIdle();
808 }
809
TEST_P(MostVisitedSitesTest,ShouldNotIncludeHomepageIfThereIsNone)810 TEST_P(MostVisitedSitesTest, ShouldNotIncludeHomepageIfThereIsNone) {
811 FakeHomepageClient* homepage_client = RegisterNewHomepageClient();
812 homepage_client->SetHomepageTileEnabled(false);
813 DisableRemoteSuggestions();
814 EXPECT_CALL(*mock_top_sites_, GetMostVisitedURLs_(_))
815 .WillRepeatedly(InvokeCallbackArgument<0>(MostVisitedURLList{}));
816 EXPECT_CALL(*mock_top_sites_, SyncWithHistory());
817 EXPECT_CALL(*mock_top_sites_, IsBlacklisted(Eq(GURL(kHomepageUrl))))
818 .Times(AnyNumber())
819 .WillRepeatedly(Return(false));
820 EXPECT_CALL(mock_observer_,
821 OnURLsAvailable(Contains(
822 Pair(SectionType::PERSONALIZED,
823 Not(Contains(MatchesTile("", kHomepageUrl,
824 TileSource::HOMEPAGE)))))));
825 most_visited_sites_->SetMostVisitedURLsObserver(&mock_observer_,
826 /*num_sites=*/3);
827 base::RunLoop().RunUntilIdle();
828 }
829
TEST_P(MostVisitedSitesTest,ShouldNotIncludeHomepageIfEmptyUrl)830 TEST_P(MostVisitedSitesTest, ShouldNotIncludeHomepageIfEmptyUrl) {
831 const std::string kEmptyHomepageUrl;
832 FakeHomepageClient* homepage_client = RegisterNewHomepageClient();
833 homepage_client->SetHomepageTileEnabled(true);
834 homepage_client->SetHomepageUrl(GURL(kEmptyHomepageUrl));
835 DisableRemoteSuggestions();
836 EXPECT_CALL(*mock_top_sites_, GetMostVisitedURLs_(_))
837 .WillRepeatedly(InvokeCallbackArgument<0>(MostVisitedURLList{}));
838 EXPECT_CALL(*mock_top_sites_, SyncWithHistory());
839 EXPECT_CALL(*mock_top_sites_, IsBlacklisted(Eq(kEmptyHomepageUrl)))
840 .Times(AnyNumber())
841 .WillRepeatedly(Return(false));
842 EXPECT_CALL(mock_observer_,
843 OnURLsAvailable(Not(FirstPersonalizedTileIs(
844 "", kEmptyHomepageUrl, TileSource::HOMEPAGE))));
845 most_visited_sites_->SetMostVisitedURLsObserver(&mock_observer_,
846 /*num_sites=*/3);
847 base::RunLoop().RunUntilIdle();
848 }
849
TEST_P(MostVisitedSitesTest,ShouldNotIncludeHomepageIfBlacklisted)850 TEST_P(MostVisitedSitesTest, ShouldNotIncludeHomepageIfBlacklisted) {
851 FakeHomepageClient* homepage_client = RegisterNewHomepageClient();
852 homepage_client->SetHomepageTileEnabled(true);
853 DisableRemoteSuggestions();
854 EXPECT_CALL(*mock_top_sites_, GetMostVisitedURLs_(_))
855 .WillRepeatedly(InvokeCallbackArgument<0>(
856 (MostVisitedURLList{MakeMostVisitedURL("", kHomepageUrl)})));
857 EXPECT_CALL(*mock_top_sites_, SyncWithHistory());
858 EXPECT_CALL(*mock_top_sites_, IsBlacklisted(Eq(GURL(kHomepageUrl))))
859 .Times(AnyNumber())
860 .WillRepeatedly(Return(false));
861
862 EXPECT_CALL(*mock_top_sites_, IsBlacklisted(Eq(GURL(kHomepageUrl))))
863 .Times(AtLeast(1))
864 .WillRepeatedly(Return(true));
865 EXPECT_CALL(mock_observer_,
866 OnURLsAvailable(Contains(
867 Pair(SectionType::PERSONALIZED,
868 Not(Contains(MatchesTile("", kHomepageUrl,
869 TileSource::HOMEPAGE)))))));
870
871 most_visited_sites_->SetMostVisitedURLsObserver(&mock_observer_,
872 /*num_sites=*/3);
873 base::RunLoop().RunUntilIdle();
874 }
875
TEST_P(MostVisitedSitesTest,ShouldPinHomepageAgainIfBlacklistingUndone)876 TEST_P(MostVisitedSitesTest, ShouldPinHomepageAgainIfBlacklistingUndone) {
877 FakeHomepageClient* homepage_client = RegisterNewHomepageClient();
878 homepage_client->SetHomepageTileEnabled(true);
879
880 DisableRemoteSuggestions();
881 EXPECT_CALL(*mock_top_sites_, GetMostVisitedURLs_(_))
882 .WillOnce(InvokeCallbackArgument<0>(
883 (MostVisitedURLList{MakeMostVisitedURL("", kHomepageUrl)})));
884 EXPECT_CALL(*mock_top_sites_, SyncWithHistory());
885 EXPECT_CALL(*mock_top_sites_, IsBlacklisted(Eq(GURL(kHomepageUrl))))
886 .Times(AtLeast(1))
887 .WillRepeatedly(Return(true));
888 EXPECT_CALL(mock_observer_,
889 OnURLsAvailable(Contains(
890 Pair(SectionType::PERSONALIZED,
891 Not(Contains(MatchesTile("", kHomepageUrl,
892 TileSource::HOMEPAGE)))))));
893
894 most_visited_sites_->SetMostVisitedURLsObserver(&mock_observer_,
895 /*num_sites=*/3);
896 base::RunLoop().RunUntilIdle();
897 VerifyAndClearExpectations();
898
899 DisableRemoteSuggestions();
900 EXPECT_CALL(*mock_top_sites_, GetMostVisitedURLs_(_))
901 .WillOnce(InvokeCallbackArgument<0>(MostVisitedURLList{}));
902 EXPECT_CALL(*mock_top_sites_, IsBlacklisted(Eq(GURL(kHomepageUrl))))
903 .Times(AtLeast(1))
904 .WillRepeatedly(Return(false));
905 EXPECT_CALL(
906 mock_observer_,
907 OnURLsAvailable(Contains(Pair(
908 SectionType::PERSONALIZED,
909 Contains(MatchesTile("", kHomepageUrl, TileSource::HOMEPAGE))))));
910
911 most_visited_sites_->OnBlockedSitesChanged();
912 base::RunLoop().RunUntilIdle();
913 }
914
TEST_P(MostVisitedSitesTest,ShouldNotIncludeTileForExploreSitesIfNoClient)915 TEST_P(MostVisitedSitesTest, ShouldNotIncludeTileForExploreSitesIfNoClient) {
916 // Does not register an explore sites client.
917
918 DisableRemoteSuggestions();
919 EXPECT_CALL(*mock_top_sites_, GetMostVisitedURLs_(_))
920 .WillRepeatedly(InvokeCallbackArgument<0>(MostVisitedURLList{
921 MakeMostVisitedURL("ESPN", "http://espn.com/"),
922 MakeMostVisitedURL("Mobile", "http://m.mobile.de/"),
923 MakeMostVisitedURL("Google", "http://www.google.com/")}));
924 EXPECT_CALL(*mock_top_sites_, SyncWithHistory());
925 EXPECT_CALL(mock_observer_,
926 OnURLsAvailable(Not(Contains(
927 Pair(SectionType::PERSONALIZED,
928 Contains(TileWithSource(TileSource::EXPLORE)))))));
929 // Note that 5 sites are requested, this means that there should be the 3 from
930 // top sites and two from popular sites.
931 most_visited_sites_->SetMostVisitedURLsObserver(&mock_observer_,
932 /*num_sites=*/5);
933 base::RunLoop().RunUntilIdle();
934 }
935
936 // Tests that the explore sites tile appears when there is a mix of top sites
937 // and popular sites.
TEST_P(MostVisitedSitesTest,ShouldIncludeTileForExploreSites)938 TEST_P(MostVisitedSitesTest, ShouldIncludeTileForExploreSites) {
939 RegisterNewExploreSitesClient();
940 DisableRemoteSuggestions();
941 EXPECT_CALL(*mock_top_sites_, GetMostVisitedURLs_(_))
942 .WillRepeatedly(InvokeCallbackArgument<0>(MostVisitedURLList{
943 MakeMostVisitedURL("ESPN", "http://espn.com/"),
944 MakeMostVisitedURL("Mobile", "http://m.mobile.de/"),
945 MakeMostVisitedURL("Google", "http://www.google.com/")}));
946 EXPECT_CALL(*mock_top_sites_, SyncWithHistory());
947 EXPECT_CALL(mock_observer_,
948 OnURLsAvailable(LastTileIs(kTestExploreTitle, kTestExploreUrl,
949 TileSource::EXPLORE)));
950 // Note that 5 sites are requested, this means that there should be the 3 from
951 // top sites, one from popular sites, and one explore tile.
952 most_visited_sites_->SetMostVisitedURLsObserver(&mock_observer_,
953 /*num_sites=*/5);
954 base::RunLoop().RunUntilIdle();
955 }
956
TEST_P(MostVisitedSitesTest,RemovesPersonalSiteIfExploreSitesTilePresent)957 TEST_P(MostVisitedSitesTest, RemovesPersonalSiteIfExploreSitesTilePresent) {
958 RegisterNewExploreSitesClient();
959 DisableRemoteSuggestions();
960 EXPECT_CALL(*mock_top_sites_, GetMostVisitedURLs_(_))
961 .WillRepeatedly(InvokeCallbackArgument<0>(MostVisitedURLList{
962 MakeMostVisitedURL("ESPN", "http://espn.com/"),
963 MakeMostVisitedURL("Mobile", "http://m.mobile.de/"),
964 MakeMostVisitedURL("Google", "http://www.google.com/")}));
965 EXPECT_CALL(*mock_top_sites_, SyncWithHistory());
966 EXPECT_CALL(mock_observer_,
967 OnURLsAvailable(Contains(Pair(
968 SectionType::PERSONALIZED,
969 ElementsAre(MatchesTile("ESPN", "http://espn.com/",
970 TileSource::TOP_SITES),
971 MatchesTile("Mobile", "http://m.mobile.de/",
972 TileSource::TOP_SITES),
973 MatchesTile(kTestExploreTitle, kTestExploreUrl,
974 TileSource::EXPLORE))))));
975 most_visited_sites_->SetMostVisitedURLsObserver(&mock_observer_,
976 /*num_sites=*/3);
977 base::RunLoop().RunUntilIdle();
978 }
979
TEST_P(MostVisitedSitesTest,ShouldInformSuggestionSourcesWhenBlacklisting)980 TEST_P(MostVisitedSitesTest, ShouldInformSuggestionSourcesWhenBlacklisting) {
981 EXPECT_CALL(*mock_top_sites_, AddBlacklistedURL(Eq(GURL(kHomepageUrl))))
982 .Times(1);
983 EXPECT_CALL(mock_suggestions_service_, BlacklistURL(Eq(GURL(kHomepageUrl))))
984 .Times(AnyNumber());
985 most_visited_sites_->AddOrRemoveBlacklistedUrl(GURL(kHomepageUrl),
986 /*add_url=*/true);
987 EXPECT_CALL(*mock_top_sites_, RemoveBlacklistedURL(Eq(GURL(kHomepageUrl))))
988 .Times(1);
989 EXPECT_CALL(mock_suggestions_service_,
990 UndoBlacklistURL(Eq(GURL(kHomepageUrl))))
991 .Times(AnyNumber());
992 most_visited_sites_->AddOrRemoveBlacklistedUrl(GURL(kHomepageUrl),
993 /*add_url=*/false);
994 }
995
TEST_P(MostVisitedSitesTest,ShouldDeduplicatePopularSitesWithMostVisitedIffHostAndTitleMatches)996 TEST_P(MostVisitedSitesTest,
997 ShouldDeduplicatePopularSitesWithMostVisitedIffHostAndTitleMatches) {
998 pref_service_.SetString(prefs::kPopularSitesOverrideCountry, "US");
999 RecreateMostVisitedSites(); // Refills cache with ESPN and Google News.
1000 DisableRemoteSuggestions();
1001 EXPECT_CALL(*mock_top_sites_, GetMostVisitedURLs_(_))
1002 .WillRepeatedly(InvokeCallbackArgument<0>(MostVisitedURLList{
1003 MakeMostVisitedURL("ESPN", "http://espn.com/"),
1004 MakeMostVisitedURL("Mobile", "http://m.mobile.de/"),
1005 MakeMostVisitedURL("Google", "http://www.google.com/")}));
1006 EXPECT_CALL(*mock_top_sites_, SyncWithHistory());
1007 std::map<SectionType, NTPTilesVector> sections;
1008 EXPECT_CALL(mock_observer_, OnURLsAvailable(_))
1009 .WillOnce(SaveArg<0>(§ions));
1010
1011 most_visited_sites_->SetMostVisitedURLsObserver(&mock_observer_,
1012 /*num_sites=*/6);
1013 base::RunLoop().RunUntilIdle();
1014 ASSERT_THAT(sections, Contains(Key(SectionType::PERSONALIZED)));
1015 EXPECT_THAT(sections.at(SectionType::PERSONALIZED),
1016 Contains(MatchesTile("Google", "http://www.google.com/",
1017 TileSource::TOP_SITES)));
1018 if (IsPopularSitesFeatureEnabled()) {
1019 EXPECT_THAT(sections.at(SectionType::PERSONALIZED),
1020 Contains(MatchesTile("Google News", "http://news.google.com/",
1021 TileSource::POPULAR)));
1022 }
1023 EXPECT_THAT(sections.at(SectionType::PERSONALIZED),
1024 AllOf(Contains(MatchesTile("ESPN", "http://espn.com/",
1025 TileSource::TOP_SITES)),
1026 Contains(MatchesTile("Mobile", "http://m.mobile.de/",
1027 TileSource::TOP_SITES)),
1028 Not(Contains(MatchesTile("ESPN", "http://www.espn.com/",
1029 TileSource::POPULAR))),
1030 Not(Contains(MatchesTile("Mobile", "http://www.mobile.de/",
1031 TileSource::POPULAR)))));
1032 }
1033
TEST_P(MostVisitedSitesTest,ShouldHandleTopSitesCacheHit)1034 TEST_P(MostVisitedSitesTest, ShouldHandleTopSitesCacheHit) {
1035 // If cached, TopSites returns the tiles synchronously, running the callback
1036 // even before the function returns.
1037 EXPECT_CALL(*mock_top_sites_, GetMostVisitedURLs_(_))
1038 .WillRepeatedly(InvokeCallbackArgument<0>(
1039 MostVisitedURLList{MakeMostVisitedURL("Site 1", "http://site1/")}));
1040
1041 InSequence seq;
1042 EXPECT_CALL(mock_suggestions_service_, AddCallback(_))
1043 .WillOnce(Invoke(&suggestions_service_callbacks_,
1044 &SuggestionsService::ResponseCallbackList::Add));
1045 EXPECT_CALL(mock_suggestions_service_, GetSuggestionsDataFromCache())
1046 .WillOnce(Return(SuggestionsProfile())); // Empty cache.
1047 if (IsPopularSitesFeatureEnabled()) {
1048 EXPECT_CALL(
1049 mock_observer_,
1050 OnURLsAvailable(Contains(Pair(
1051 SectionType::PERSONALIZED,
1052 ElementsAre(
1053 MatchesTile("Site 1", "http://site1/", TileSource::TOP_SITES),
1054 MatchesTile("PopularSite1", "http://popularsite1/",
1055 TileSource::POPULAR),
1056 MatchesTile("PopularSite2", "http://popularsite2/",
1057 TileSource::POPULAR))))));
1058 } else {
1059 EXPECT_CALL(mock_observer_,
1060 OnURLsAvailable(Contains(
1061 Pair(SectionType::PERSONALIZED,
1062 ElementsAre(MatchesTile("Site 1", "http://site1/",
1063 TileSource::TOP_SITES))))));
1064 }
1065 EXPECT_CALL(*mock_top_sites_, SyncWithHistory());
1066 EXPECT_CALL(mock_suggestions_service_, FetchSuggestionsData())
1067 .WillOnce(Return(true));
1068
1069 most_visited_sites_->SetMostVisitedURLsObserver(&mock_observer_,
1070 /*num_sites=*/3);
1071 VerifyAndClearExpectations();
1072 EXPECT_FALSE(suggestions_service_callbacks_.empty());
1073 CHECK(top_sites_callbacks_.empty());
1074
1075 // Update by TopSites is propagated.
1076 EXPECT_CALL(*mock_top_sites_, GetMostVisitedURLs_(_))
1077 .WillOnce(InvokeCallbackArgument<0>(
1078 MostVisitedURLList{MakeMostVisitedURL("Site 2", "http://site2/")}));
1079 if (IsPopularSitesFeatureEnabled()) {
1080 EXPECT_CALL(*mock_top_sites_, IsBlacklisted(_))
1081 .WillRepeatedly(Return(false));
1082 }
1083 EXPECT_CALL(mock_observer_, OnURLsAvailable(_));
1084 mock_top_sites_->NotifyTopSitesChanged(
1085 history::TopSitesObserver::ChangeReason::MOST_VISITED);
1086 base::RunLoop().RunUntilIdle();
1087 }
1088
1089 INSTANTIATE_TEST_SUITE_P(MostVisitedSitesTest,
1090 MostVisitedSitesTest,
1091 ::testing::Combine(::testing::Bool(),
1092 ::testing::Bool()));
1093
TEST(MostVisitedSitesTest,ShouldDeduplicateDomainWithNoWwwDomain)1094 TEST(MostVisitedSitesTest, ShouldDeduplicateDomainWithNoWwwDomain) {
1095 EXPECT_TRUE(MostVisitedSites::IsHostOrMobilePageKnown({"www.mobile.de"},
1096 "mobile.de"));
1097 EXPECT_TRUE(MostVisitedSites::IsHostOrMobilePageKnown({"mobile.de"},
1098 "www.mobile.de"));
1099 EXPECT_TRUE(MostVisitedSites::IsHostOrMobilePageKnown({"mobile.co.uk"},
1100 "www.mobile.co.uk"));
1101 }
1102
TEST(MostVisitedSitesTest,ShouldDeduplicateDomainByRemovingMobilePrefixes)1103 TEST(MostVisitedSitesTest, ShouldDeduplicateDomainByRemovingMobilePrefixes) {
1104 EXPECT_TRUE(
1105 MostVisitedSites::IsHostOrMobilePageKnown({"bbc.co.uk"}, "m.bbc.co.uk"));
1106 EXPECT_TRUE(
1107 MostVisitedSites::IsHostOrMobilePageKnown({"m.bbc.co.uk"}, "bbc.co.uk"));
1108 EXPECT_TRUE(MostVisitedSites::IsHostOrMobilePageKnown({"cnn.com"},
1109 "edition.cnn.com"));
1110 EXPECT_TRUE(MostVisitedSites::IsHostOrMobilePageKnown({"edition.cnn.com"},
1111 "cnn.com"));
1112 EXPECT_TRUE(
1113 MostVisitedSites::IsHostOrMobilePageKnown({"cnn.com"}, "mobile.cnn.com"));
1114 EXPECT_TRUE(
1115 MostVisitedSites::IsHostOrMobilePageKnown({"mobile.cnn.com"}, "cnn.com"));
1116 }
1117
TEST(MostVisitedSitesTest,ShouldDeduplicateDomainByReplacingMobilePrefixes)1118 TEST(MostVisitedSitesTest, ShouldDeduplicateDomainByReplacingMobilePrefixes) {
1119 EXPECT_TRUE(MostVisitedSites::IsHostOrMobilePageKnown({"www.bbc.co.uk"},
1120 "m.bbc.co.uk"));
1121 EXPECT_TRUE(MostVisitedSites::IsHostOrMobilePageKnown({"m.mobile.de"},
1122 "www.mobile.de"));
1123 EXPECT_TRUE(MostVisitedSites::IsHostOrMobilePageKnown({"www.cnn.com"},
1124 "edition.cnn.com"));
1125 EXPECT_TRUE(MostVisitedSites::IsHostOrMobilePageKnown({"mobile.cnn.com"},
1126 "www.cnn.com"));
1127 }
1128
1129 #if !defined(OS_ANDROID) && !defined(OS_IOS)
1130 class MostVisitedSitesWithCustomLinksTest : public MostVisitedSitesTest {
1131 public:
MostVisitedSitesWithCustomLinksTest()1132 MostVisitedSitesWithCustomLinksTest() {
1133 EnableCustomLinks();
1134 RecreateMostVisitedSites();
1135 }
1136
ExpectBuildWithTopSites(const MostVisitedURLList & expected_list,std::map<SectionType,NTPTilesVector> * sections)1137 void ExpectBuildWithTopSites(
1138 const MostVisitedURLList& expected_list,
1139 std::map<SectionType, NTPTilesVector>* sections) {
1140 EXPECT_CALL(*mock_top_sites_, GetMostVisitedURLs_(_))
1141 .WillRepeatedly(InvokeCallbackArgument<0>(expected_list));
1142 EXPECT_CALL(*mock_top_sites_, SyncWithHistory());
1143 EXPECT_CALL(*mock_custom_links_, IsInitialized())
1144 .WillRepeatedly(Return(false));
1145 EXPECT_CALL(mock_observer_, OnURLsAvailable(_))
1146 .WillOnce(SaveArg<0>(sections));
1147 }
1148
ExpectBuildWithSuggestions(const std::vector<ChromeSuggestion> & suggestions,std::map<SectionType,NTPTilesVector> * sections)1149 void ExpectBuildWithSuggestions(
1150 const std::vector<ChromeSuggestion>& suggestions,
1151 std::map<SectionType, NTPTilesVector>* sections) {
1152 EXPECT_CALL(mock_suggestions_service_, AddCallback(_))
1153 .WillOnce(Invoke(&suggestions_service_callbacks_,
1154 &SuggestionsService::ResponseCallbackList::Add));
1155 EXPECT_CALL(mock_suggestions_service_, GetSuggestionsDataFromCache())
1156 .WillOnce(Return(MakeProfile(suggestions)));
1157 EXPECT_CALL(*mock_top_sites_, SyncWithHistory());
1158 EXPECT_CALL(mock_suggestions_service_, FetchSuggestionsData())
1159 .WillOnce(Return(true));
1160 EXPECT_CALL(*mock_custom_links_, IsInitialized())
1161 .WillRepeatedly(Return(false));
1162 EXPECT_CALL(mock_observer_, OnURLsAvailable(_))
1163 .WillOnce(SaveArg<0>(sections));
1164 }
1165
ExpectBuildWithCustomLinks(const std::vector<CustomLinksManager::Link> & expected_links,std::map<SectionType,NTPTilesVector> * sections)1166 void ExpectBuildWithCustomLinks(
1167 const std::vector<CustomLinksManager::Link>& expected_links,
1168 std::map<SectionType, NTPTilesVector>* sections) {
1169 EXPECT_CALL(*mock_custom_links_, IsInitialized())
1170 .WillRepeatedly(Return(true));
1171 EXPECT_CALL(*mock_custom_links_, GetLinks())
1172 .WillOnce(ReturnRef(expected_links));
1173 EXPECT_CALL(mock_observer_, OnURLsAvailable(_))
1174 .WillOnce(SaveArg<0>(sections));
1175 }
1176 };
1177
TEST_P(MostVisitedSitesWithCustomLinksTest,ShouldOnlyBuildCustomLinksWhenInitialized)1178 TEST_P(MostVisitedSitesWithCustomLinksTest,
1179 ShouldOnlyBuildCustomLinksWhenInitialized) {
1180 const char kTestUrl[] = "http://site1/";
1181 const char kTestTitle[] = "Site 1";
1182 std::vector<CustomLinksManager::Link> expected_links(
1183 {CustomLinksManager::Link{GURL(kTestUrl),
1184 base::UTF8ToUTF16(kTestTitle)}});
1185 std::map<SectionType, NTPTilesVector> sections;
1186 DisableRemoteSuggestions();
1187
1188 // Build tiles when custom links is not initialized. Tiles should be Top
1189 // Sites.
1190 EXPECT_CALL(*mock_custom_links_, RegisterCallbackForOnChanged(_));
1191 ExpectBuildWithTopSites(
1192 MostVisitedURLList{MakeMostVisitedURL(kTestTitle, kTestUrl)}, §ions);
1193 most_visited_sites_->SetMostVisitedURLsObserver(&mock_observer_,
1194 /*num_sites=*/1);
1195 base::RunLoop().RunUntilIdle();
1196 EXPECT_THAT(
1197 sections.at(SectionType::PERSONALIZED),
1198 ElementsAre(MatchesTile(kTestTitle, kTestUrl, TileSource::TOP_SITES)));
1199
1200 // Initialize custom links and rebuild tiles. Tiles should be custom links.
1201 EXPECT_CALL(*mock_custom_links_, Initialize(_)).WillOnce(Return(true));
1202 ExpectBuildWithCustomLinks(expected_links, §ions);
1203 most_visited_sites_->InitializeCustomLinks();
1204 most_visited_sites_->RefreshTiles();
1205 base::RunLoop().RunUntilIdle();
1206 EXPECT_THAT(
1207 sections.at(SectionType::PERSONALIZED),
1208 ElementsAre(MatchesTile(kTestTitle, kTestUrl, TileSource::CUSTOM_LINKS)));
1209
1210 // Uninitialize custom links and rebuild tiles. Tiles should be Top Sites.
1211 EXPECT_CALL(*mock_custom_links_, Uninitialize());
1212 EXPECT_CALL(*mock_top_sites_, GetMostVisitedURLs_(_))
1213 .WillRepeatedly(InvokeCallbackArgument<0>(
1214 MostVisitedURLList{MakeMostVisitedURL(kTestTitle, kTestUrl)}));
1215 EXPECT_CALL(*mock_custom_links_, IsInitialized())
1216 .WillRepeatedly(Return(false));
1217 EXPECT_CALL(mock_observer_, OnURLsAvailable(_))
1218 .WillOnce(SaveArg<0>(§ions));
1219 most_visited_sites_->UninitializeCustomLinks();
1220 base::RunLoop().RunUntilIdle();
1221 EXPECT_THAT(
1222 sections.at(SectionType::PERSONALIZED),
1223 ElementsAre(MatchesTile(kTestTitle, kTestUrl, TileSource::TOP_SITES)));
1224 }
1225
TEST_P(MostVisitedSitesWithCustomLinksTest,ShouldFavorCustomLinksOverTopSites)1226 TEST_P(MostVisitedSitesWithCustomLinksTest,
1227 ShouldFavorCustomLinksOverTopSites) {
1228 const char kTestUrl[] = "http://site1/";
1229 const char kTestTitle[] = "Site 1";
1230 std::vector<CustomLinksManager::Link> expected_links(
1231 {CustomLinksManager::Link{GURL(kTestUrl),
1232 base::UTF8ToUTF16(kTestTitle)}});
1233 std::map<SectionType, NTPTilesVector> sections;
1234 DisableRemoteSuggestions();
1235
1236 // Build tiles when custom links is not initialized. Tiles should be Top
1237 // Sites.
1238 EXPECT_CALL(*mock_custom_links_, RegisterCallbackForOnChanged(_));
1239 ExpectBuildWithTopSites(
1240 MostVisitedURLList{MakeMostVisitedURL(kTestTitle, kTestUrl)}, §ions);
1241 most_visited_sites_->SetMostVisitedURLsObserver(&mock_observer_,
1242 /*num_sites=*/1);
1243 base::RunLoop().RunUntilIdle();
1244 ASSERT_THAT(
1245 sections.at(SectionType::PERSONALIZED),
1246 ElementsAre(MatchesTile(kTestTitle, kTestUrl, TileSource::TOP_SITES)));
1247
1248 // Initialize custom links and rebuild tiles. Tiles should be custom links.
1249 EXPECT_CALL(*mock_custom_links_, Initialize(_)).WillOnce(Return(true));
1250 ExpectBuildWithCustomLinks(expected_links, §ions);
1251 most_visited_sites_->InitializeCustomLinks();
1252 most_visited_sites_->RefreshTiles();
1253 base::RunLoop().RunUntilIdle();
1254 ASSERT_THAT(
1255 sections.at(SectionType::PERSONALIZED),
1256 ElementsAre(MatchesTile(kTestTitle, kTestUrl, TileSource::CUSTOM_LINKS)));
1257
1258 // Initiate notification for new Top Sites. This should be ignored.
1259 EXPECT_CALL(*mock_custom_links_, IsInitialized()).WillOnce(Return(true));
1260 // Notify with an empty SuggestionsProfile first to trigger a query for
1261 // TopSites.
1262 suggestions_service_callbacks_.Notify(SuggestionsProfile());
1263 VerifyAndClearExpectations();
1264 EXPECT_CALL(mock_observer_, OnURLsAvailable(_)).Times(0);
1265 top_sites_callbacks_.ClearAndNotify(
1266 {MakeMostVisitedURL("Site 2", "http://site2/")});
1267 base::RunLoop().RunUntilIdle();
1268 }
1269
TEST_P(MostVisitedSitesWithCustomLinksTest,ShouldFavorCustomLinksOverSuggestions)1270 TEST_P(MostVisitedSitesWithCustomLinksTest,
1271 ShouldFavorCustomLinksOverSuggestions) {
1272 const char kTestUrl[] = "http://site1/";
1273 const char kTestTitle[] = "Site 1";
1274 std::vector<CustomLinksManager::Link> expected_links(
1275 {CustomLinksManager::Link{GURL(kTestUrl),
1276 base::UTF8ToUTF16(kTestTitle)}});
1277 std::map<SectionType, NTPTilesVector> sections;
1278
1279 // Build tiles when custom links is not initialized. Tiles should be from
1280 // suggestions.
1281 EXPECT_CALL(*mock_custom_links_, RegisterCallbackForOnChanged(_));
1282 ExpectBuildWithSuggestions({MakeSuggestion(kTestTitle, kTestUrl)}, §ions);
1283 most_visited_sites_->SetMostVisitedURLsObserver(&mock_observer_,
1284 /*num_sites=*/1);
1285 base::RunLoop().RunUntilIdle();
1286 ASSERT_THAT(sections.at(SectionType::PERSONALIZED),
1287 ElementsAre(MatchesTile(kTestTitle, kTestUrl,
1288 TileSource::SUGGESTIONS_SERVICE)));
1289
1290 // Initialize custom links and rebuild tiles. Tiles should be custom links.
1291 EXPECT_CALL(*mock_custom_links_, Initialize(_)).WillOnce(Return(true));
1292 ExpectBuildWithCustomLinks(expected_links, §ions);
1293 most_visited_sites_->InitializeCustomLinks();
1294 most_visited_sites_->RefreshTiles();
1295 base::RunLoop().RunUntilIdle();
1296 ASSERT_THAT(
1297 sections.at(SectionType::PERSONALIZED),
1298 ElementsAre(MatchesTile(kTestTitle, kTestUrl, TileSource::CUSTOM_LINKS)));
1299
1300 // Initiate notification for new suggestions. This should be ignored.
1301 EXPECT_CALL(*mock_custom_links_, IsInitialized())
1302 .WillRepeatedly(Return(true));
1303 EXPECT_CALL(mock_observer_, OnURLsAvailable(_)).Times(0);
1304 suggestions_service_callbacks_.Notify(
1305 MakeProfile({MakeSuggestion("Site 2", "http://site2/")}));
1306 base::RunLoop().RunUntilIdle();
1307 }
1308
TEST_P(MostVisitedSitesWithCustomLinksTest,DisableCustomLinksWhenNotInitialized)1309 TEST_P(MostVisitedSitesWithCustomLinksTest,
1310 DisableCustomLinksWhenNotInitialized) {
1311 const char kTestUrl[] = "http://site1/";
1312 const char kTestTitle[] = "Site 1";
1313 std::vector<CustomLinksManager::Link> expected_links(
1314 {CustomLinksManager::Link{GURL(kTestUrl),
1315 base::UTF8ToUTF16(kTestTitle)}});
1316 std::map<SectionType, NTPTilesVector> sections;
1317
1318 // Build tiles when custom links is not initialized. Tiles should be from
1319 // suggestions.
1320 EXPECT_CALL(*mock_custom_links_, RegisterCallbackForOnChanged(_));
1321 ExpectBuildWithSuggestions({MakeSuggestion(kTestTitle, kTestUrl)}, §ions);
1322 most_visited_sites_->SetMostVisitedURLsObserver(&mock_observer_,
1323 /*num_sites=*/1);
1324 base::RunLoop().RunUntilIdle();
1325 ASSERT_THAT(sections.at(SectionType::PERSONALIZED),
1326 ElementsAre(MatchesTile(kTestTitle, kTestUrl,
1327 TileSource::SUGGESTIONS_SERVICE)));
1328
1329 // Disable custom links. Tiles should rebuild but not send an update.
1330 EXPECT_CALL(mock_suggestions_service_, GetSuggestionsDataFromCache())
1331 .WillOnce(Return(MakeProfile({MakeSuggestion(kTestTitle, kTestUrl)})));
1332 EXPECT_CALL(mock_observer_, OnURLsAvailable(_)).Times(0);
1333 most_visited_sites_->EnableCustomLinks(false);
1334 base::RunLoop().RunUntilIdle();
1335
1336 // Try to disable custom links again. This should not rebuild the tiles.
1337 EXPECT_CALL(mock_suggestions_service_, GetSuggestionsDataFromCache())
1338 .Times(0);
1339 EXPECT_CALL(*mock_custom_links_, GetLinks()).Times(0);
1340 most_visited_sites_->EnableCustomLinks(false);
1341 base::RunLoop().RunUntilIdle();
1342 }
1343
TEST_P(MostVisitedSitesWithCustomLinksTest,DisableCustomLinksWhenInitialized)1344 TEST_P(MostVisitedSitesWithCustomLinksTest, DisableCustomLinksWhenInitialized) {
1345 const char kTestUrl[] = "http://site1/";
1346 const char kTestTitle[] = "Site 1";
1347 std::vector<CustomLinksManager::Link> expected_links(
1348 {CustomLinksManager::Link{GURL(kTestUrl),
1349 base::UTF8ToUTF16(kTestTitle)}});
1350 std::map<SectionType, NTPTilesVector> sections;
1351
1352 // Build tiles when custom links is initialized and not disabled. Tiles should
1353 // be custom links.
1354 EXPECT_CALL(*mock_custom_links_, RegisterCallbackForOnChanged(_));
1355 EXPECT_CALL(mock_suggestions_service_, AddCallback(_))
1356 .WillOnce(Invoke(&suggestions_service_callbacks_,
1357 &SuggestionsService::ResponseCallbackList::Add));
1358 EXPECT_CALL(*mock_top_sites_, SyncWithHistory());
1359 EXPECT_CALL(mock_suggestions_service_, FetchSuggestionsData())
1360 .WillOnce(Return(false));
1361 ExpectBuildWithCustomLinks(expected_links, §ions);
1362 most_visited_sites_->SetMostVisitedURLsObserver(&mock_observer_,
1363 /*num_sites=*/1);
1364 base::RunLoop().RunUntilIdle();
1365 ASSERT_THAT(
1366 sections.at(SectionType::PERSONALIZED),
1367 ElementsAre(MatchesTile(kTestTitle, kTestUrl, TileSource::CUSTOM_LINKS)));
1368
1369 // Disable custom links. Tiles should rebuild and return suggestions.
1370 EXPECT_CALL(mock_suggestions_service_, GetSuggestionsDataFromCache())
1371 .WillOnce(Return(MakeProfile({MakeSuggestion(kTestTitle, kTestUrl)})));
1372 EXPECT_CALL(*mock_custom_links_, IsInitialized())
1373 .WillRepeatedly(Return(false));
1374 EXPECT_CALL(mock_observer_, OnURLsAvailable(_))
1375 .WillOnce(SaveArg<0>(§ions));
1376 most_visited_sites_->EnableCustomLinks(false);
1377 base::RunLoop().RunUntilIdle();
1378 EXPECT_THAT(sections.at(SectionType::PERSONALIZED),
1379 ElementsAre(MatchesTile(kTestTitle, kTestUrl,
1380 TileSource::SUGGESTIONS_SERVICE)));
1381
1382 // Re-enable custom links. Tiles should rebuild and return custom links.
1383 ExpectBuildWithCustomLinks(expected_links, §ions);
1384 most_visited_sites_->EnableCustomLinks(true);
1385 base::RunLoop().RunUntilIdle();
1386 ASSERT_THAT(
1387 sections.at(SectionType::PERSONALIZED),
1388 ElementsAre(MatchesTile(kTestTitle, kTestUrl, TileSource::CUSTOM_LINKS)));
1389 }
1390
TEST_P(MostVisitedSitesWithCustomLinksTest,ShouldGenerateShortTitleForTopSites)1391 TEST_P(MostVisitedSitesWithCustomLinksTest,
1392 ShouldGenerateShortTitleForTopSites) {
1393 std::string kTestUrl1 = "https://www.imdb.com/";
1394 std::string kTestTitle1 = "IMDb - Movies, TV and Celebrities - IMDb";
1395 std::string kTestUrl2 = "https://drive.google.com/";
1396 std::string kTestTitle2 =
1397 "Google Drive - Cloud Storage & File Backup for Photos, Docs & More";
1398 std::string kTestUrl3 = "https://amazon.com/";
1399 std::string kTestTitle3 =
1400 "Amazon.com: Online Shopping for Electronics, Apparel, Computers, Books, "
1401 "DVDs & more";
1402 std::map<SectionType, NTPTilesVector> sections;
1403 DisableRemoteSuggestions();
1404
1405 // Build tiles from Top Sites. The tiles should have short titles.
1406 EXPECT_CALL(*mock_custom_links_, RegisterCallbackForOnChanged(_));
1407 ExpectBuildWithTopSites(
1408 MostVisitedURLList{MakeMostVisitedURL(kTestTitle1, kTestUrl1),
1409 MakeMostVisitedURL(kTestTitle2, kTestUrl2),
1410 MakeMostVisitedURL(kTestTitle3, kTestUrl3)},
1411 §ions);
1412 most_visited_sites_->SetMostVisitedURLsObserver(&mock_observer_,
1413 /*num_sites=*/3);
1414 base::RunLoop().RunUntilIdle();
1415
1416 EXPECT_THAT(
1417 sections.at(SectionType::PERSONALIZED),
1418 ElementsAre(
1419 MatchesTile(/* The short title generated by the heuristic */ "IMDb",
1420 kTestUrl1, TileSource::TOP_SITES),
1421 MatchesTile(
1422 /* The short title generated by the heuristic */ "Google Drive",
1423 kTestUrl2, TileSource::TOP_SITES),
1424 MatchesTile(
1425 /* The short title generated by the heuristic */ "Amazon.com",
1426 kTestUrl3, TileSource::TOP_SITES)));
1427 }
1428
TEST_P(MostVisitedSitesWithCustomLinksTest,ShouldGenerateShortTitleForSuggestions)1429 TEST_P(MostVisitedSitesWithCustomLinksTest,
1430 ShouldGenerateShortTitleForSuggestions) {
1431 std::string kTestUrl1 = "https://www.imdb.com/";
1432 std::string kTestTitle1 = "IMDb - Movies, TV and Celebrities - IMDb";
1433 std::string kTestUrl2 = "https://drive.google.com/";
1434 std::string kTestTitle2 =
1435 "Google Drive - Cloud Storage & File Backup for Photos, Docs & More";
1436 std::string kTestUrl3 = "https://amazon.com/";
1437 std::string kTestTitle3 =
1438 "Amazon.com: Online Shopping for Electronics, Apparel, Computers, Books, "
1439 "DVDs & more";
1440 std::map<SectionType, NTPTilesVector> sections;
1441
1442 // Build tiles from Suggestions. The tiles should have short titles.
1443 EXPECT_CALL(*mock_custom_links_, RegisterCallbackForOnChanged(_));
1444 ExpectBuildWithSuggestions({MakeSuggestion(kTestTitle1, kTestUrl1),
1445 MakeSuggestion(kTestTitle2, kTestUrl2),
1446 MakeSuggestion(kTestTitle3, kTestUrl3)},
1447 §ions);
1448 most_visited_sites_->SetMostVisitedURLsObserver(&mock_observer_,
1449 /*num_sites=*/3);
1450 base::RunLoop().RunUntilIdle();
1451
1452 EXPECT_THAT(
1453 sections.at(SectionType::PERSONALIZED),
1454 ElementsAre(
1455 MatchesTile(/* The short title generated by the heuristic */ "IMDb",
1456 kTestUrl1, TileSource::SUGGESTIONS_SERVICE),
1457 MatchesTile(
1458 /* The short title generated by the heuristic */ "Google Drive",
1459 kTestUrl2, TileSource::SUGGESTIONS_SERVICE),
1460 MatchesTile(
1461 /* The short title generated by the heuristic */ "Amazon.com",
1462 kTestUrl3, TileSource::SUGGESTIONS_SERVICE)));
1463 }
1464
TEST_P(MostVisitedSitesWithCustomLinksTest,ShouldNotCrashIfReceiveAnEmptyTitle)1465 TEST_P(MostVisitedSitesWithCustomLinksTest,
1466 ShouldNotCrashIfReceiveAnEmptyTitle) {
1467 std::string kTestUrl1 = "https://site1/";
1468 std::string kTestTitle1 = ""; // Empty title
1469 std::string kTestUrl2 = "https://site2/";
1470 std::string kTestTitle2 = " "; // Title only contains spaces
1471 std::map<SectionType, NTPTilesVector> sections;
1472 DisableRemoteSuggestions();
1473
1474 // Build tiles from Top Sites. The tiles should have short titles.
1475 EXPECT_CALL(*mock_custom_links_, RegisterCallbackForOnChanged(_));
1476 ExpectBuildWithTopSites(
1477 MostVisitedURLList{MakeMostVisitedURL(kTestTitle1, kTestUrl1),
1478 MakeMostVisitedURL(kTestTitle2, kTestUrl2)},
1479 §ions);
1480 most_visited_sites_->SetMostVisitedURLsObserver(&mock_observer_,
1481 /*num_sites=*/2);
1482 base::RunLoop().RunUntilIdle();
1483
1484 // Both cases should not crash and generate an empty title tile.
1485 EXPECT_THAT(sections.at(SectionType::PERSONALIZED),
1486 ElementsAre(MatchesTile("", kTestUrl1, TileSource::TOP_SITES),
1487 MatchesTile("", kTestUrl2, TileSource::TOP_SITES)));
1488 }
1489
TEST_P(MostVisitedSitesWithCustomLinksTest,UninitializeCustomLinksOnUndoAfterFirstAction)1490 TEST_P(MostVisitedSitesWithCustomLinksTest,
1491 UninitializeCustomLinksOnUndoAfterFirstAction) {
1492 const char kTestUrl[] = "http://site1/";
1493 const char kTestTitle[] = "Site 1";
1494 std::vector<CustomLinksManager::Link> expected_links(
1495 {CustomLinksManager::Link{GURL(kTestUrl),
1496 base::UTF8ToUTF16(kTestTitle)}});
1497 std::map<SectionType, NTPTilesVector> sections;
1498 DisableRemoteSuggestions();
1499
1500 // Build initial tiles with Top Sites.
1501 EXPECT_CALL(*mock_custom_links_, RegisterCallbackForOnChanged(_));
1502 ExpectBuildWithTopSites(
1503 MostVisitedURLList{MakeMostVisitedURL(kTestTitle, kTestUrl)}, §ions);
1504 most_visited_sites_->SetMostVisitedURLsObserver(&mock_observer_,
1505 /*num_sites=*/1);
1506 base::RunLoop().RunUntilIdle();
1507 ASSERT_THAT(
1508 sections.at(SectionType::PERSONALIZED),
1509 ElementsAre(MatchesTile(kTestTitle, kTestUrl, TileSource::TOP_SITES)));
1510
1511 // Initialize custom links and complete a custom link action.
1512 EXPECT_CALL(*mock_custom_links_, Initialize(_)).WillOnce(Return(true));
1513 EXPECT_CALL(*mock_custom_links_, AddLink(_, _)).WillOnce(Return(true));
1514 EXPECT_CALL(*mock_custom_links_, IsInitialized())
1515 .WillRepeatedly(Return(true));
1516 EXPECT_CALL(*mock_custom_links_, GetLinks())
1517 .WillRepeatedly(ReturnRef(expected_links));
1518 EXPECT_CALL(mock_observer_, OnURLsAvailable(_))
1519 .WillOnce(SaveArg<0>(§ions));
1520 most_visited_sites_->AddCustomLink(GURL("test.com"),
1521 base::UTF8ToUTF16("test"));
1522 base::RunLoop().RunUntilIdle();
1523 ASSERT_THAT(
1524 sections.at(SectionType::PERSONALIZED),
1525 ElementsAre(MatchesTile(kTestTitle, kTestUrl, TileSource::CUSTOM_LINKS)));
1526
1527 // Undo the action. This should uninitialize custom links.
1528 EXPECT_CALL(*mock_custom_links_, UndoAction()).Times(0);
1529 EXPECT_CALL(*mock_custom_links_, Uninitialize());
1530 EXPECT_CALL(*mock_top_sites_, GetMostVisitedURLs_(_))
1531 .WillRepeatedly(InvokeCallbackArgument<0>(
1532 MostVisitedURLList{MakeMostVisitedURL(kTestTitle, kTestUrl)}));
1533 EXPECT_CALL(*mock_custom_links_, IsInitialized())
1534 .WillRepeatedly(Return(false));
1535 EXPECT_CALL(mock_observer_, OnURLsAvailable(_))
1536 .WillOnce(SaveArg<0>(§ions));
1537 most_visited_sites_->UndoCustomLinkAction();
1538 base::RunLoop().RunUntilIdle();
1539 ASSERT_THAT(
1540 sections.at(SectionType::PERSONALIZED),
1541 ElementsAre(MatchesTile(kTestTitle, kTestUrl, TileSource::TOP_SITES)));
1542 }
1543
TEST_P(MostVisitedSitesWithCustomLinksTest,DontUninitializeCustomLinksOnUndoAfterMultipleActions)1544 TEST_P(MostVisitedSitesWithCustomLinksTest,
1545 DontUninitializeCustomLinksOnUndoAfterMultipleActions) {
1546 const char kTestUrl[] = "http://site1/";
1547 const char kTestTitle[] = "Site 1";
1548 std::vector<CustomLinksManager::Link> expected_links(
1549 {CustomLinksManager::Link{GURL(kTestUrl),
1550 base::UTF8ToUTF16(kTestTitle)}});
1551 std::map<SectionType, NTPTilesVector> sections;
1552 DisableRemoteSuggestions();
1553
1554 // Build initial tiles with Top Sites.
1555 EXPECT_CALL(*mock_custom_links_, RegisterCallbackForOnChanged(_));
1556 ExpectBuildWithTopSites(
1557 MostVisitedURLList{MakeMostVisitedURL(kTestTitle, kTestUrl)}, §ions);
1558 most_visited_sites_->SetMostVisitedURLsObserver(&mock_observer_,
1559 /*num_sites=*/1);
1560 base::RunLoop().RunUntilIdle();
1561 ASSERT_THAT(
1562 sections.at(SectionType::PERSONALIZED),
1563 ElementsAre(MatchesTile(kTestTitle, kTestUrl, TileSource::TOP_SITES)));
1564
1565 // Initialize custom links and complete a custom link action.
1566 EXPECT_CALL(*mock_custom_links_, Initialize(_)).WillOnce(Return(true));
1567 EXPECT_CALL(*mock_custom_links_, UpdateLink(_, _, _)).WillOnce(Return(true));
1568 EXPECT_CALL(*mock_custom_links_, IsInitialized())
1569 .WillRepeatedly(Return(true));
1570 EXPECT_CALL(*mock_custom_links_, GetLinks())
1571 .WillRepeatedly(ReturnRef(expected_links));
1572 EXPECT_CALL(mock_observer_, OnURLsAvailable(_))
1573 .WillOnce(SaveArg<0>(§ions));
1574 most_visited_sites_->UpdateCustomLink(GURL("test.com"), GURL("test.com"),
1575 base::UTF8ToUTF16("test"));
1576 base::RunLoop().RunUntilIdle();
1577 ASSERT_THAT(
1578 sections.at(SectionType::PERSONALIZED),
1579 ElementsAre(MatchesTile(kTestTitle, kTestUrl, TileSource::CUSTOM_LINKS)));
1580
1581 // Complete a second custom link action.
1582 EXPECT_CALL(*mock_custom_links_, Initialize(_)).WillOnce(Return(false));
1583 EXPECT_CALL(*mock_custom_links_, DeleteLink(_)).WillOnce(Return(true));
1584 EXPECT_CALL(*mock_custom_links_, IsInitialized())
1585 .WillRepeatedly(Return(true));
1586 EXPECT_CALL(*mock_custom_links_, GetLinks())
1587 .WillOnce(ReturnRef(expected_links));
1588 most_visited_sites_->DeleteCustomLink(GURL("test.com"));
1589 base::RunLoop().RunUntilIdle();
1590
1591 // Undo the second action. This should not uninitialize custom links.
1592 EXPECT_CALL(*mock_custom_links_, UndoAction()).WillOnce(Return(true));
1593 EXPECT_CALL(*mock_custom_links_, Uninitialize()).Times(0);
1594 EXPECT_CALL(*mock_custom_links_, IsInitialized()).WillOnce(Return(true));
1595 EXPECT_CALL(*mock_custom_links_, GetLinks())
1596 .WillOnce(ReturnRef(expected_links));
1597 most_visited_sites_->UndoCustomLinkAction();
1598 base::RunLoop().RunUntilIdle();
1599 }
1600
TEST_P(MostVisitedSitesWithCustomLinksTest,UninitializeCustomLinksIfFirstActionFails)1601 TEST_P(MostVisitedSitesWithCustomLinksTest,
1602 UninitializeCustomLinksIfFirstActionFails) {
1603 const char kTestUrl[] = "http://site1/";
1604 const char kTestTitle[] = "Site 1";
1605 std::vector<CustomLinksManager::Link> expected_links(
1606 {CustomLinksManager::Link{GURL(kTestUrl),
1607 base::UTF8ToUTF16(kTestTitle)}});
1608 std::map<SectionType, NTPTilesVector> sections;
1609 DisableRemoteSuggestions();
1610
1611 // Build initial tiles with Top Sites.
1612 EXPECT_CALL(*mock_custom_links_, RegisterCallbackForOnChanged(_));
1613 ExpectBuildWithTopSites(
1614 MostVisitedURLList{MakeMostVisitedURL(kTestTitle, kTestUrl)}, §ions);
1615 most_visited_sites_->SetMostVisitedURLsObserver(&mock_observer_,
1616 /*num_sites=*/1);
1617 base::RunLoop().RunUntilIdle();
1618 ASSERT_THAT(
1619 sections.at(SectionType::PERSONALIZED),
1620 ElementsAre(MatchesTile(kTestTitle, kTestUrl, TileSource::TOP_SITES)));
1621
1622 // Fail to add a custom link. This should not initialize custom links nor
1623 // notify.
1624 EXPECT_CALL(*mock_custom_links_, Initialize(_)).WillOnce(Return(true));
1625 EXPECT_CALL(*mock_custom_links_, AddLink(_, _)).WillOnce(Return(false));
1626 EXPECT_CALL(*mock_custom_links_, IsInitialized())
1627 .WillRepeatedly(Return(false));
1628 EXPECT_CALL(*mock_custom_links_, Uninitialize());
1629 EXPECT_CALL(mock_observer_, OnURLsAvailable(_)).Times(0);
1630 most_visited_sites_->AddCustomLink(GURL(kTestUrl), base::UTF8ToUTF16("test"));
1631 base::RunLoop().RunUntilIdle();
1632
1633 // Fail to edit a custom link. This should not initialize custom links nor
1634 // notify.
1635 EXPECT_CALL(*mock_custom_links_, Initialize(_)).WillOnce(Return(true));
1636 EXPECT_CALL(*mock_custom_links_, UpdateLink(_, _, _)).WillOnce(Return(false));
1637 EXPECT_CALL(*mock_custom_links_, IsInitialized())
1638 .WillRepeatedly(Return(false));
1639 EXPECT_CALL(*mock_custom_links_, Uninitialize());
1640 EXPECT_CALL(mock_observer_, OnURLsAvailable(_)).Times(0);
1641 most_visited_sites_->UpdateCustomLink(GURL("test.com"), GURL("test2.com"),
1642 base::UTF8ToUTF16("test"));
1643 base::RunLoop().RunUntilIdle();
1644
1645 // Fail to reorder a custom link. This should not initialize custom links nor
1646 // notify.
1647 EXPECT_CALL(*mock_custom_links_, Initialize(_)).WillOnce(Return(true));
1648 EXPECT_CALL(*mock_custom_links_, ReorderLink(_, _)).WillOnce(Return(false));
1649 EXPECT_CALL(*mock_custom_links_, IsInitialized())
1650 .WillRepeatedly(Return(false));
1651 EXPECT_CALL(*mock_custom_links_, Uninitialize());
1652 EXPECT_CALL(mock_observer_, OnURLsAvailable(_)).Times(0);
1653 most_visited_sites_->ReorderCustomLink(GURL("test.com"), 1);
1654 base::RunLoop().RunUntilIdle();
1655
1656 // Fail to delete a custom link. This should not initialize custom links nor
1657 // notify.
1658 EXPECT_CALL(*mock_custom_links_, Initialize(_)).WillOnce(Return(true));
1659 EXPECT_CALL(*mock_custom_links_, DeleteLink(_)).WillOnce(Return(false));
1660 EXPECT_CALL(*mock_custom_links_, IsInitialized())
1661 .WillRepeatedly(Return(false));
1662 EXPECT_CALL(*mock_custom_links_, Uninitialize());
1663 EXPECT_CALL(mock_observer_, OnURLsAvailable(_)).Times(0);
1664 most_visited_sites_->DeleteCustomLink(GURL("test.com"));
1665 base::RunLoop().RunUntilIdle();
1666 }
1667
TEST_P(MostVisitedSitesWithCustomLinksTest,RebuildTilesOnCustomLinksChanged)1668 TEST_P(MostVisitedSitesWithCustomLinksTest, RebuildTilesOnCustomLinksChanged) {
1669 const char kTestUrl1[] = "http://site1/";
1670 const char kTestUrl2[] = "http://site2/";
1671 const char kTestTitle1[] = "Site 1";
1672 const char kTestTitle2[] = "Site 2";
1673 std::vector<CustomLinksManager::Link> expected_links(
1674 {CustomLinksManager::Link{GURL(kTestUrl2),
1675 base::UTF8ToUTF16(kTestTitle2)}});
1676 std::map<SectionType, NTPTilesVector> sections;
1677 DisableRemoteSuggestions();
1678
1679 // Build initial tiles with Top Sites.
1680 base::RepeatingClosure custom_links_callback;
1681 EXPECT_CALL(*mock_custom_links_, RegisterCallbackForOnChanged(_))
1682 .WillOnce(
1683 DoAll(SaveArg<0>(&custom_links_callback), Return(ByMove(nullptr))));
1684 ExpectBuildWithTopSites(
1685 MostVisitedURLList{MakeMostVisitedURL(kTestTitle1, kTestUrl1)},
1686 §ions);
1687 most_visited_sites_->SetMostVisitedURLsObserver(&mock_observer_,
1688 /*num_sites=*/1);
1689 base::RunLoop().RunUntilIdle();
1690 ASSERT_THAT(
1691 sections.at(SectionType::PERSONALIZED),
1692 ElementsAre(MatchesTile(kTestTitle1, kTestUrl1, TileSource::TOP_SITES)));
1693
1694 // Notify that there is a new set of custom links. This should replace the
1695 // current tiles with custom links.
1696 EXPECT_CALL(*mock_custom_links_, IsInitialized())
1697 .WillRepeatedly(Return(true));
1698 EXPECT_CALL(*mock_custom_links_, GetLinks())
1699 .WillRepeatedly(ReturnRef(expected_links));
1700 EXPECT_CALL(mock_observer_, OnURLsAvailable(_))
1701 .WillOnce(SaveArg<0>(§ions));
1702 custom_links_callback.Run();
1703 base::RunLoop().RunUntilIdle();
1704 EXPECT_THAT(sections.at(SectionType::PERSONALIZED),
1705 ElementsAre(MatchesTile(kTestTitle2, kTestUrl2,
1706 TileSource::CUSTOM_LINKS)));
1707
1708 // Notify that custom links have been uninitialized. This should rebuild the
1709 // tiles with Top Sites.
1710 EXPECT_CALL(*mock_custom_links_, IsInitialized())
1711 .WillRepeatedly(Return(false));
1712 EXPECT_CALL(*mock_top_sites_, GetMostVisitedURLs_(_))
1713 .WillRepeatedly(InvokeCallbackArgument<0>(
1714 MostVisitedURLList{MakeMostVisitedURL(kTestTitle1, kTestUrl1)}));
1715 EXPECT_CALL(*mock_custom_links_, IsInitialized())
1716 .WillRepeatedly(Return(false));
1717 EXPECT_CALL(mock_observer_, OnURLsAvailable(_))
1718 .WillOnce(SaveArg<0>(§ions));
1719 custom_links_callback.Run();
1720 base::RunLoop().RunUntilIdle();
1721 EXPECT_THAT(
1722 sections.at(SectionType::PERSONALIZED),
1723 ElementsAre(MatchesTile(kTestTitle1, kTestUrl1, TileSource::TOP_SITES)));
1724 }
1725
1726 // These tests expect Most Likely to be enabled, and exclude Android and iOS,
1727 // so this will continue to be the case.
1728 INSTANTIATE_TEST_SUITE_P(MostVisitedSitesWithCustomLinksTest,
1729 MostVisitedSitesWithCustomLinksTest,
1730 ::testing::Combine(::testing::Bool(),
1731 ::testing::Values(true)));
1732 #endif
1733
1734 class MostVisitedSitesWithCacheHitTest : public MostVisitedSitesTest {
1735 public:
1736 // Constructor sets the common expectations for the case where suggestions
1737 // service has cached results when the observer is registered.
MostVisitedSitesWithCacheHitTest()1738 MostVisitedSitesWithCacheHitTest() {
1739 InSequence seq;
1740 EXPECT_CALL(mock_suggestions_service_, AddCallback(_))
1741 .WillOnce(Invoke(&suggestions_service_callbacks_,
1742 &SuggestionsService::ResponseCallbackList::Add));
1743 EXPECT_CALL(mock_suggestions_service_, GetSuggestionsDataFromCache())
1744 .WillOnce(Return(MakeProfile({
1745 MakeSuggestion("Site 1", "http://site1/"),
1746 MakeSuggestion("Site 2", "http://site2/"),
1747 MakeSuggestion("Site 3", "http://site3/"),
1748 })));
1749
1750 if (IsPopularSitesFeatureEnabled()) {
1751 EXPECT_CALL(
1752 mock_observer_,
1753 OnURLsAvailable(Contains(Pair(
1754 SectionType::PERSONALIZED,
1755 ElementsAre(MatchesTile("Site 1", "http://site1/",
1756 TileSource::SUGGESTIONS_SERVICE),
1757 MatchesTile("Site 2", "http://site2/",
1758 TileSource::SUGGESTIONS_SERVICE),
1759 MatchesTile("Site 3", "http://site3/",
1760 TileSource::SUGGESTIONS_SERVICE),
1761 MatchesTile("PopularSite1", "http://popularsite1/",
1762 TileSource::POPULAR))))));
1763 } else {
1764 EXPECT_CALL(
1765 mock_observer_,
1766 OnURLsAvailable(Contains(Pair(
1767 SectionType::PERSONALIZED,
1768 ElementsAre(MatchesTile("Site 1", "http://site1/",
1769 TileSource::SUGGESTIONS_SERVICE),
1770 MatchesTile("Site 2", "http://site2/",
1771 TileSource::SUGGESTIONS_SERVICE),
1772 MatchesTile("Site 3", "http://site3/",
1773 TileSource::SUGGESTIONS_SERVICE))))));
1774 }
1775 EXPECT_CALL(*mock_top_sites_, SyncWithHistory());
1776 EXPECT_CALL(mock_suggestions_service_, FetchSuggestionsData())
1777 .WillOnce(Return(true));
1778
1779 most_visited_sites_->SetMostVisitedURLsObserver(&mock_observer_,
1780 /*num_sites=*/4);
1781 VerifyAndClearExpectations();
1782
1783 EXPECT_FALSE(suggestions_service_callbacks_.empty());
1784 EXPECT_TRUE(top_sites_callbacks_.empty());
1785 }
1786 };
1787
TEST_P(MostVisitedSitesWithCacheHitTest,ShouldFavorSuggestionsServiceCache)1788 TEST_P(MostVisitedSitesWithCacheHitTest, ShouldFavorSuggestionsServiceCache) {
1789 // Constructor sets basic expectations for a suggestions service cache hit.
1790 }
1791
TEST_P(MostVisitedSitesWithCacheHitTest,ShouldPropagateUpdateBySuggestionsService)1792 TEST_P(MostVisitedSitesWithCacheHitTest,
1793 ShouldPropagateUpdateBySuggestionsService) {
1794 EXPECT_CALL(mock_observer_,
1795 OnURLsAvailable(Contains(Pair(
1796 SectionType::PERSONALIZED,
1797 ElementsAre(MatchesTile("Site 4", "http://site4/",
1798 TileSource::SUGGESTIONS_SERVICE),
1799 MatchesTile("Site 5", "http://site5/",
1800 TileSource::SUGGESTIONS_SERVICE),
1801 MatchesTile("Site 6", "http://site6/",
1802 TileSource::SUGGESTIONS_SERVICE),
1803 MatchesTile("Site 7", "http://site7/",
1804 TileSource::SUGGESTIONS_SERVICE))))));
1805 suggestions_service_callbacks_.Notify(
1806 MakeProfile({MakeSuggestion("Site 4", "http://site4/"),
1807 MakeSuggestion("Site 5", "http://site5/"),
1808 MakeSuggestion("Site 6", "http://site6/"),
1809 MakeSuggestion("Site 7", "http://site7/")}));
1810 base::RunLoop().RunUntilIdle();
1811 }
1812
TEST_P(MostVisitedSitesWithCacheHitTest,ShouldTruncateList)1813 TEST_P(MostVisitedSitesWithCacheHitTest, ShouldTruncateList) {
1814 EXPECT_CALL(
1815 mock_observer_,
1816 OnURLsAvailable(Contains(Pair(SectionType::PERSONALIZED, SizeIs(4)))));
1817 suggestions_service_callbacks_.Notify(
1818 MakeProfile({MakeSuggestion("Site 4", "http://site4/"),
1819 MakeSuggestion("Site 5", "http://site5/"),
1820 MakeSuggestion("Site 6", "http://site6/"),
1821 MakeSuggestion("Site 7", "http://site7/"),
1822 MakeSuggestion("Site 8", "http://site8/")}));
1823 base::RunLoop().RunUntilIdle();
1824 }
1825
TEST_P(MostVisitedSitesWithCacheHitTest,ShouldCompleteWithPopularSitesIffEnabled)1826 TEST_P(MostVisitedSitesWithCacheHitTest,
1827 ShouldCompleteWithPopularSitesIffEnabled) {
1828 if (IsPopularSitesFeatureEnabled()) {
1829 EXPECT_CALL(
1830 mock_observer_,
1831 OnURLsAvailable(Contains(
1832 Pair(SectionType::PERSONALIZED,
1833 ElementsAre(MatchesTile("Site 4", "http://site4/",
1834 TileSource::SUGGESTIONS_SERVICE),
1835 MatchesTile("PopularSite1", "http://popularsite1/",
1836 TileSource::POPULAR),
1837 MatchesTile("PopularSite2", "http://popularsite2/",
1838 TileSource::POPULAR))))));
1839 } else {
1840 EXPECT_CALL(
1841 mock_observer_,
1842 OnURLsAvailable(Contains(
1843 Pair(SectionType::PERSONALIZED,
1844 ElementsAre(MatchesTile("Site 4", "http://site4/",
1845 TileSource::SUGGESTIONS_SERVICE))))));
1846 }
1847 suggestions_service_callbacks_.Notify(
1848 MakeProfile({MakeSuggestion("Site 4", "http://site4/")}));
1849 base::RunLoop().RunUntilIdle();
1850 }
1851
TEST_P(MostVisitedSitesWithCacheHitTest,ShouldSwitchToTopSitesIfEmptyUpdateBySuggestionsService)1852 TEST_P(MostVisitedSitesWithCacheHitTest,
1853 ShouldSwitchToTopSitesIfEmptyUpdateBySuggestionsService) {
1854 EXPECT_CALL(*mock_top_sites_, GetMostVisitedURLs_(_))
1855 .WillOnce(Invoke(&top_sites_callbacks_, &TopSitesCallbackList::Add));
1856 suggestions_service_callbacks_.Notify(SuggestionsProfile());
1857 VerifyAndClearExpectations();
1858
1859 EXPECT_CALL(
1860 mock_observer_,
1861 OnURLsAvailable(Contains(Pair(
1862 SectionType::PERSONALIZED,
1863 ElementsAre(
1864 MatchesTile("Site 4", "http://site4/", TileSource::TOP_SITES),
1865 MatchesTile("Site 5", "http://site5/", TileSource::TOP_SITES),
1866 MatchesTile("Site 6", "http://site6/", TileSource::TOP_SITES),
1867 MatchesTile("Site 7", "http://site7/",
1868 TileSource::TOP_SITES))))));
1869 top_sites_callbacks_.ClearAndNotify(
1870 {MakeMostVisitedURL("Site 4", "http://site4/"),
1871 MakeMostVisitedURL("Site 5", "http://site5/"),
1872 MakeMostVisitedURL("Site 6", "http://site6/"),
1873 MakeMostVisitedURL("Site 7", "http://site7/")});
1874 base::RunLoop().RunUntilIdle();
1875 }
1876
TEST_P(MostVisitedSitesWithCacheHitTest,ShouldFetchFaviconsIfEnabled)1877 TEST_P(MostVisitedSitesWithCacheHitTest, ShouldFetchFaviconsIfEnabled) {
1878 base::test::ScopedFeatureList feature_list;
1879 feature_list.InitAndEnableFeature(kNtpMostLikelyFaviconsFromServerFeature);
1880
1881 EXPECT_CALL(mock_observer_, OnURLsAvailable(_));
1882 EXPECT_CALL(*icon_cacher_, StartFetchMostLikely(GURL("http://site4/"), _));
1883
1884 suggestions_service_callbacks_.Notify(
1885 MakeProfile({MakeSuggestion("Site 4", "http://site4/")}));
1886 base::RunLoop().RunUntilIdle();
1887 }
1888
1889 // Tests only apply when the suggestions service is enabled.
1890 INSTANTIATE_TEST_SUITE_P(MostVisitedSitesWithCacheHitTest,
1891 MostVisitedSitesWithCacheHitTest,
1892 ::testing::Combine(::testing::Bool(),
1893 testing::Values(true)));
1894
1895 class MostVisitedSitesWithEmptyCacheTest : public MostVisitedSitesTest {
1896 public:
1897 // Constructor sets the common expectations for the case where suggestions
1898 // service doesn't have cached results when the observer is registered.
MostVisitedSitesWithEmptyCacheTest()1899 MostVisitedSitesWithEmptyCacheTest() {
1900 InSequence seq;
1901 EXPECT_CALL(mock_suggestions_service_, AddCallback(_))
1902 .WillOnce(Invoke(&suggestions_service_callbacks_,
1903 &SuggestionsService::ResponseCallbackList::Add));
1904 EXPECT_CALL(mock_suggestions_service_, GetSuggestionsDataFromCache())
1905 .WillOnce(Return(SuggestionsProfile())); // Empty cache.
1906 EXPECT_CALL(*mock_top_sites_, GetMostVisitedURLs_(_))
1907 .WillOnce(Invoke(&top_sites_callbacks_, &TopSitesCallbackList::Add));
1908 EXPECT_CALL(*mock_top_sites_, SyncWithHistory());
1909 EXPECT_CALL(mock_suggestions_service_, FetchSuggestionsData())
1910 .WillOnce(Return(true));
1911
1912 most_visited_sites_->SetMostVisitedURLsObserver(&mock_observer_,
1913 /*num_sites=*/3);
1914 VerifyAndClearExpectations();
1915
1916 EXPECT_FALSE(suggestions_service_callbacks_.empty());
1917 EXPECT_FALSE(top_sites_callbacks_.empty());
1918 }
1919 };
1920
TEST_P(MostVisitedSitesWithEmptyCacheTest,ShouldQueryTopSitesAndSuggestionsService)1921 TEST_P(MostVisitedSitesWithEmptyCacheTest,
1922 ShouldQueryTopSitesAndSuggestionsService) {
1923 // Constructor sets basic expectations for a suggestions service cache miss.
1924 }
1925
TEST_P(MostVisitedSitesWithEmptyCacheTest,ShouldCompleteWithPopularSitesIffEnabled)1926 TEST_P(MostVisitedSitesWithEmptyCacheTest,
1927 ShouldCompleteWithPopularSitesIffEnabled) {
1928 if (IsPopularSitesFeatureEnabled()) {
1929 EXPECT_CALL(
1930 mock_observer_,
1931 OnURLsAvailable(Contains(
1932 Pair(SectionType::PERSONALIZED,
1933 ElementsAre(MatchesTile("Site 4", "http://site4/",
1934 TileSource::SUGGESTIONS_SERVICE),
1935 MatchesTile("PopularSite1", "http://popularsite1/",
1936 TileSource::POPULAR),
1937 MatchesTile("PopularSite2", "http://popularsite2/",
1938 TileSource::POPULAR))))));
1939 } else {
1940 EXPECT_CALL(
1941 mock_observer_,
1942 OnURLsAvailable(Contains(
1943 Pair(SectionType::PERSONALIZED,
1944 ElementsAre(MatchesTile("Site 4", "http://site4/",
1945 TileSource::SUGGESTIONS_SERVICE))))));
1946 }
1947 suggestions_service_callbacks_.Notify(
1948 MakeProfile({MakeSuggestion("Site 4", "http://site4/")}));
1949 base::RunLoop().RunUntilIdle();
1950 }
1951
TEST_P(MostVisitedSitesWithEmptyCacheTest,ShouldIgnoreTopSitesIfSuggestionsServiceFaster)1952 TEST_P(MostVisitedSitesWithEmptyCacheTest,
1953 ShouldIgnoreTopSitesIfSuggestionsServiceFaster) {
1954 // Reply from suggestions service triggers and update to our observer.
1955 EXPECT_CALL(mock_observer_,
1956 OnURLsAvailable(Contains(Pair(
1957 SectionType::PERSONALIZED,
1958 ElementsAre(MatchesTile("Site 1", "http://site1/",
1959 TileSource::SUGGESTIONS_SERVICE),
1960 MatchesTile("Site 2", "http://site2/",
1961 TileSource::SUGGESTIONS_SERVICE),
1962 MatchesTile("Site 3", "http://site3/",
1963 TileSource::SUGGESTIONS_SERVICE))))));
1964 suggestions_service_callbacks_.Notify(
1965 MakeProfile({MakeSuggestion("Site 1", "http://site1/"),
1966 MakeSuggestion("Site 2", "http://site2/"),
1967 MakeSuggestion("Site 3", "http://site3/")}));
1968 VerifyAndClearExpectations();
1969
1970 // Reply from top sites is ignored (i.e. not reported to observer).
1971 top_sites_callbacks_.ClearAndNotify(
1972 {MakeMostVisitedURL("Site 4", "http://site4/")});
1973 VerifyAndClearExpectations();
1974
1975 // Update by TopSites is also ignored.
1976 mock_top_sites_->NotifyTopSitesChanged(
1977 history::TopSitesObserver::ChangeReason::MOST_VISITED);
1978 base::RunLoop().RunUntilIdle();
1979 }
1980
TEST_P(MostVisitedSitesWithEmptyCacheTest,ShouldExposeTopSitesIfSuggestionsServiceFasterButEmpty)1981 TEST_P(MostVisitedSitesWithEmptyCacheTest,
1982 ShouldExposeTopSitesIfSuggestionsServiceFasterButEmpty) {
1983 // Empty reply from suggestions service causes no update to our observer.
1984 suggestions_service_callbacks_.Notify(SuggestionsProfile());
1985 VerifyAndClearExpectations();
1986
1987 // Reply from top sites is propagated to observer.
1988 EXPECT_CALL(
1989 mock_observer_,
1990 OnURLsAvailable(Contains(Pair(
1991 SectionType::PERSONALIZED,
1992 ElementsAre(
1993 MatchesTile("Site 1", "http://site1/", TileSource::TOP_SITES),
1994 MatchesTile("Site 2", "http://site2/", TileSource::TOP_SITES),
1995 MatchesTile("Site 3", "http://site3/",
1996 TileSource::TOP_SITES))))));
1997 top_sites_callbacks_.ClearAndNotify(
1998 {MakeMostVisitedURL("Site 1", "http://site1/"),
1999 MakeMostVisitedURL("Site 2", "http://site2/"),
2000 MakeMostVisitedURL("Site 3", "http://site3/")});
2001 base::RunLoop().RunUntilIdle();
2002 }
2003
TEST_P(MostVisitedSitesWithEmptyCacheTest,ShouldFavorSuggestionsServiceAlthoughSlower)2004 TEST_P(MostVisitedSitesWithEmptyCacheTest,
2005 ShouldFavorSuggestionsServiceAlthoughSlower) {
2006 // Reply from top sites is propagated to observer.
2007 EXPECT_CALL(
2008 mock_observer_,
2009 OnURLsAvailable(Contains(Pair(
2010 SectionType::PERSONALIZED,
2011 ElementsAre(
2012 MatchesTile("Site 1", "http://site1/", TileSource::TOP_SITES),
2013 MatchesTile("Site 2", "http://site2/", TileSource::TOP_SITES),
2014 MatchesTile("Site 3", "http://site3/",
2015 TileSource::TOP_SITES))))));
2016 top_sites_callbacks_.ClearAndNotify(
2017 {MakeMostVisitedURL("Site 1", "http://site1/"),
2018 MakeMostVisitedURL("Site 2", "http://site2/"),
2019 MakeMostVisitedURL("Site 3", "http://site3/")});
2020 VerifyAndClearExpectations();
2021
2022 // Reply from suggestions service overrides top sites.
2023 InSequence seq;
2024 EXPECT_CALL(mock_observer_,
2025 OnURLsAvailable(Contains(Pair(
2026 SectionType::PERSONALIZED,
2027 ElementsAre(MatchesTile("Site 4", "http://site4/",
2028 TileSource::SUGGESTIONS_SERVICE),
2029 MatchesTile("Site 5", "http://site5/",
2030 TileSource::SUGGESTIONS_SERVICE),
2031 MatchesTile("Site 6", "http://site6/",
2032 TileSource::SUGGESTIONS_SERVICE))))));
2033 suggestions_service_callbacks_.Notify(
2034 MakeProfile({MakeSuggestion("Site 4", "http://site4/"),
2035 MakeSuggestion("Site 5", "http://site5/"),
2036 MakeSuggestion("Site 6", "http://site6/")}));
2037 base::RunLoop().RunUntilIdle();
2038 }
2039
TEST_P(MostVisitedSitesWithEmptyCacheTest,ShouldIgnoreSuggestionsServiceIfSlowerAndEmpty)2040 TEST_P(MostVisitedSitesWithEmptyCacheTest,
2041 ShouldIgnoreSuggestionsServiceIfSlowerAndEmpty) {
2042 // Reply from top sites is propagated to observer.
2043 EXPECT_CALL(
2044 mock_observer_,
2045 OnURLsAvailable(Contains(Pair(
2046 SectionType::PERSONALIZED,
2047 ElementsAre(
2048 MatchesTile("Site 1", "http://site1/", TileSource::TOP_SITES),
2049 MatchesTile("Site 2", "http://site2/", TileSource::TOP_SITES),
2050 MatchesTile("Site 3", "http://site3/",
2051 TileSource::TOP_SITES))))));
2052 top_sites_callbacks_.ClearAndNotify(
2053 {MakeMostVisitedURL("Site 1", "http://site1/"),
2054 MakeMostVisitedURL("Site 2", "http://site2/"),
2055 MakeMostVisitedURL("Site 3", "http://site3/")});
2056 VerifyAndClearExpectations();
2057
2058 // Reply from suggestions service is empty and thus ignored.
2059 suggestions_service_callbacks_.Notify(SuggestionsProfile());
2060 base::RunLoop().RunUntilIdle();
2061 }
2062
TEST_P(MostVisitedSitesWithEmptyCacheTest,ShouldPropagateUpdateByTopSites)2063 TEST_P(MostVisitedSitesWithEmptyCacheTest, ShouldPropagateUpdateByTopSites) {
2064 // Reply from top sites is propagated to observer.
2065 EXPECT_CALL(
2066 mock_observer_,
2067 OnURLsAvailable(Contains(Pair(
2068 SectionType::PERSONALIZED,
2069 ElementsAre(
2070 MatchesTile("Site 1", "http://site1/", TileSource::TOP_SITES),
2071 MatchesTile("Site 2", "http://site2/", TileSource::TOP_SITES),
2072 MatchesTile("Site 3", "http://site3/",
2073 TileSource::TOP_SITES))))));
2074 top_sites_callbacks_.ClearAndNotify(
2075 {MakeMostVisitedURL("Site 1", "http://site1/"),
2076 MakeMostVisitedURL("Site 2", "http://site2/"),
2077 MakeMostVisitedURL("Site 3", "http://site3/")});
2078 VerifyAndClearExpectations();
2079
2080 // Reply from suggestions service is empty and thus ignored.
2081 suggestions_service_callbacks_.Notify(SuggestionsProfile());
2082 VerifyAndClearExpectations();
2083 EXPECT_TRUE(top_sites_callbacks_.empty());
2084
2085 // Update from top sites is propagated to observer.
2086 EXPECT_CALL(*mock_top_sites_, GetMostVisitedURLs_(_))
2087 .WillOnce(InvokeCallbackArgument<0>(
2088 MostVisitedURLList{MakeMostVisitedURL("Site 4", "http://site4/"),
2089 MakeMostVisitedURL("Site 5", "http://site5/"),
2090 MakeMostVisitedURL("Site 6", "http://site6/")}));
2091 EXPECT_CALL(
2092 mock_observer_,
2093 OnURLsAvailable(Contains(Pair(
2094 SectionType::PERSONALIZED,
2095 ElementsAre(
2096 MatchesTile("Site 4", "http://site4/", TileSource::TOP_SITES),
2097 MatchesTile("Site 5", "http://site5/", TileSource::TOP_SITES),
2098 MatchesTile("Site 6", "http://site6/",
2099 TileSource::TOP_SITES))))));
2100 mock_top_sites_->NotifyTopSitesChanged(
2101 history::TopSitesObserver::ChangeReason::MOST_VISITED);
2102 base::RunLoop().RunUntilIdle();
2103 }
2104
TEST_P(MostVisitedSitesWithEmptyCacheTest,ShouldSendEmptyListIfBothTopSitesAndSuggestionsServiceEmpty)2105 TEST_P(MostVisitedSitesWithEmptyCacheTest,
2106 ShouldSendEmptyListIfBothTopSitesAndSuggestionsServiceEmpty) {
2107 if (IsPopularSitesFeatureEnabled()) {
2108 EXPECT_CALL(
2109 mock_observer_,
2110 OnURLsAvailable(Contains(
2111 Pair(SectionType::PERSONALIZED,
2112 ElementsAre(MatchesTile("PopularSite1", "http://popularsite1/",
2113 TileSource::POPULAR),
2114 MatchesTile("PopularSite2", "http://popularsite2/",
2115 TileSource::POPULAR))))));
2116 } else {
2117 // The Android NTP doesn't finish initialization until it gets tiles, so a
2118 // 0-tile notification is always needed.
2119 EXPECT_CALL(mock_observer_, OnURLsAvailable(ElementsAre(Pair(
2120 SectionType::PERSONALIZED, IsEmpty()))));
2121 }
2122 suggestions_service_callbacks_.Notify(SuggestionsProfile());
2123 top_sites_callbacks_.ClearAndNotify(MostVisitedURLList{});
2124
2125 base::RunLoop().RunUntilIdle();
2126 }
2127
TEST_P(MostVisitedSitesWithEmptyCacheTest,ShouldNotifyOnceIfTopSitesUnchanged)2128 TEST_P(MostVisitedSitesWithEmptyCacheTest,
2129 ShouldNotifyOnceIfTopSitesUnchanged) {
2130 EXPECT_CALL(
2131 mock_observer_,
2132 OnURLsAvailable(Contains(Pair(
2133 SectionType::PERSONALIZED,
2134 ElementsAre(
2135 MatchesTile("Site 1", "http://site1/", TileSource::TOP_SITES),
2136 MatchesTile("Site 2", "http://site2/", TileSource::TOP_SITES),
2137 MatchesTile("Site 3", "http://site3/",
2138 TileSource::TOP_SITES))))));
2139
2140 suggestions_service_callbacks_.Notify(SuggestionsProfile());
2141
2142 top_sites_callbacks_.ClearAndNotify(
2143 {MakeMostVisitedURL("Site 1", "http://site1/"),
2144 MakeMostVisitedURL("Site 2", "http://site2/"),
2145 MakeMostVisitedURL("Site 3", "http://site3/")});
2146 base::RunLoop().RunUntilIdle();
2147
2148 for (int i = 0; i < 4; ++i) {
2149 EXPECT_CALL(*mock_top_sites_, GetMostVisitedURLs_(_))
2150 .WillOnce(Invoke(&top_sites_callbacks_, &TopSitesCallbackList::Add));
2151 mock_top_sites_->NotifyTopSitesChanged(
2152 history::TopSitesObserver::ChangeReason::MOST_VISITED);
2153 EXPECT_FALSE(top_sites_callbacks_.empty());
2154 top_sites_callbacks_.ClearAndNotify(
2155 {MakeMostVisitedURL("Site 1", "http://site1/"),
2156 MakeMostVisitedURL("Site 2", "http://site2/"),
2157 MakeMostVisitedURL("Site 3", "http://site3/")});
2158 base::RunLoop().RunUntilIdle();
2159 }
2160 }
2161
TEST_P(MostVisitedSitesWithEmptyCacheTest,ShouldNotifyOnceIfSuggestionsUnchanged)2162 TEST_P(MostVisitedSitesWithEmptyCacheTest,
2163 ShouldNotifyOnceIfSuggestionsUnchanged) {
2164 EXPECT_CALL(mock_observer_,
2165 OnURLsAvailable(Contains(Pair(
2166 SectionType::PERSONALIZED,
2167 ElementsAre(MatchesTile("Site 1", "http://site1/",
2168 TileSource::SUGGESTIONS_SERVICE),
2169 MatchesTile("Site 2", "http://site2/",
2170 TileSource::SUGGESTIONS_SERVICE),
2171 MatchesTile("Site 3", "http://site3/",
2172 TileSource::SUGGESTIONS_SERVICE))))));
2173
2174 for (int i = 0; i < 5; ++i) {
2175 suggestions_service_callbacks_.Notify(
2176 MakeProfile({MakeSuggestion("Site 1", "http://site1/"),
2177 MakeSuggestion("Site 2", "http://site2/"),
2178 MakeSuggestion("Site 3", "http://site3/")}));
2179 }
2180 }
2181
2182 // Tests only apply when the suggestions service is enabled.
2183 INSTANTIATE_TEST_SUITE_P(MostVisitedSitesWithEmptyCacheTest,
2184 MostVisitedSitesWithEmptyCacheTest,
2185 ::testing::Combine(::testing::Bool(),
2186 testing::Values(true)));
2187
2188 // This a test for MostVisitedSites::MergeTiles(...) method, and thus has the
2189 // same scope as the method itself. This tests merging popular sites with
2190 // personal tiles.
2191 // More important things out of the scope of testing presently:
2192 // - Removing blacklisted tiles.
2193 // - Correct host extraction from the URL.
2194 // - Ensuring personal tiles are not duplicated in popular tiles.
TEST(MostVisitedSitesMergeTest,ShouldMergeTilesWithPersonalOnly)2195 TEST(MostVisitedSitesMergeTest, ShouldMergeTilesWithPersonalOnly) {
2196 std::vector<NTPTile> personal_tiles{
2197 MakeTile("Site 1", "https://www.site1.com/", TileSource::TOP_SITES),
2198 MakeTile("Site 2", "https://www.site2.com/", TileSource::TOP_SITES),
2199 MakeTile("Site 3", "https://www.site3.com/", TileSource::TOP_SITES),
2200 MakeTile("Site 4", "https://www.site4.com/", TileSource::TOP_SITES),
2201 };
2202 // Without any popular tiles, the result after merge should be the personal
2203 // tiles.
2204 EXPECT_THAT(MostVisitedSites::MergeTiles(std::move(personal_tiles),
2205 /*whitelist_tiles=*/NTPTilesVector(),
2206 /*popular_tiles=*/NTPTilesVector(),
2207 /*explore_tile=*/base::nullopt),
2208 ElementsAre(MatchesTile("Site 1", "https://www.site1.com/",
2209 TileSource::TOP_SITES),
2210 MatchesTile("Site 2", "https://www.site2.com/",
2211 TileSource::TOP_SITES),
2212 MatchesTile("Site 3", "https://www.site3.com/",
2213 TileSource::TOP_SITES),
2214 MatchesTile("Site 4", "https://www.site4.com/",
2215 TileSource::TOP_SITES)));
2216 }
2217
TEST(MostVisitedSitesMergeTest,ShouldMergeTilesWithPopularOnly)2218 TEST(MostVisitedSitesMergeTest, ShouldMergeTilesWithPopularOnly) {
2219 std::vector<NTPTile> popular_tiles{
2220 MakeTile("Site 1", "https://www.site1.com/", TileSource::POPULAR),
2221 MakeTile("Site 2", "https://www.site2.com/", TileSource::POPULAR),
2222 MakeTile("Site 3", "https://www.site3.com/", TileSource::POPULAR),
2223 MakeTile("Site 4", "https://www.site4.com/", TileSource::POPULAR),
2224 };
2225 // Without any personal tiles, the result after merge should be the popular
2226 // tiles.
2227 EXPECT_THAT(
2228 MostVisitedSites::MergeTiles(/*personal_tiles=*/NTPTilesVector(),
2229 /*whitelist_tiles=*/NTPTilesVector(),
2230 /*popular_tiles=*/std::move(popular_tiles),
2231 /*explore_tile=*/base::nullopt),
2232 ElementsAre(
2233 MatchesTile("Site 1", "https://www.site1.com/", TileSource::POPULAR),
2234 MatchesTile("Site 2", "https://www.site2.com/", TileSource::POPULAR),
2235 MatchesTile("Site 3", "https://www.site3.com/", TileSource::POPULAR),
2236 MatchesTile("Site 4", "https://www.site4.com/",
2237 TileSource::POPULAR)));
2238 }
2239
TEST(MostVisitedSitesMergeTest,ShouldMergeTilesFavoringPersonalOverPopular)2240 TEST(MostVisitedSitesMergeTest, ShouldMergeTilesFavoringPersonalOverPopular) {
2241 std::vector<NTPTile> popular_tiles{
2242 MakeTile("Site 1", "https://www.site1.com/", TileSource::POPULAR),
2243 MakeTile("Site 2", "https://www.site2.com/", TileSource::POPULAR),
2244 };
2245 std::vector<NTPTile> personal_tiles{
2246 MakeTile("Site 3", "https://www.site3.com/", TileSource::TOP_SITES),
2247 MakeTile("Site 4", "https://www.site4.com/", TileSource::TOP_SITES),
2248 };
2249 base::Optional<NTPTile> explore_tile{
2250 MakeTile("Explore", "https://explore.example.com/", TileSource::EXPLORE),
2251 };
2252 EXPECT_THAT(
2253 MostVisitedSites::MergeTiles(std::move(personal_tiles),
2254 /*whitelist_tiles=*/NTPTilesVector(),
2255 /*popular_tiles=*/std::move(popular_tiles),
2256 /*explore_tiles=*/explore_tile),
2257 ElementsAre(
2258 MatchesTile("Site 3", "https://www.site3.com/",
2259 TileSource::TOP_SITES),
2260 MatchesTile("Site 4", "https://www.site4.com/",
2261 TileSource::TOP_SITES),
2262 MatchesTile("Site 1", "https://www.site1.com/", TileSource::POPULAR),
2263 MatchesTile("Site 2", "https://www.site2.com/", TileSource::POPULAR),
2264 MatchesTile("Explore", "https://explore.example.com/",
2265 TileSource::EXPLORE)));
2266 }
2267
2268 } // namespace ntp_tiles
2269