Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright 2016 The Chromium Authors. All rights reserved. | 1 // Copyright 2016 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "components/ntp_snippets/content_suggestions_service.h" | 5 #include "components/ntp_snippets/content_suggestions_service.h" |
| 6 | 6 |
| 7 #include <memory> | 7 #include <memory> |
| 8 #include <utility> | |
| 8 #include <vector> | 9 #include <vector> |
| 9 | 10 |
| 10 #include "base/bind.h" | 11 #include "base/bind.h" |
| 11 #include "base/macros.h" | 12 #include "base/macros.h" |
| 12 #include "base/memory/ptr_util.h" | 13 #include "base/memory/ptr_util.h" |
| 13 #include "base/message_loop/message_loop.h" | 14 #include "base/message_loop/message_loop.h" |
| 14 #include "base/run_loop.h" | 15 #include "base/run_loop.h" |
| 15 #include "base/strings/string_number_conversions.h" | 16 #include "base/strings/string_number_conversions.h" |
| 16 #include "base/strings/utf_string_conversions.h" | 17 #include "base/strings/utf_string_conversions.h" |
| 17 #include "components/ntp_snippets/category_info.h" | 18 #include "components/ntp_snippets/category_info.h" |
| (...skipping 13 matching lines...) Expand all Loading... | |
| 31 using testing::IsNull; | 32 using testing::IsNull; |
| 32 using testing::Mock; | 33 using testing::Mock; |
| 33 using testing::NotNull; | 34 using testing::NotNull; |
| 34 using testing::Property; | 35 using testing::Property; |
| 35 using testing::_; | 36 using testing::_; |
| 36 | 37 |
| 37 namespace ntp_snippets { | 38 namespace ntp_snippets { |
| 38 | 39 |
| 39 namespace { | 40 namespace { |
| 40 | 41 |
| 41 // Returns a suggestion instance for testing. | |
| 42 ContentSuggestion CreateSuggestion(int number) { | |
| 43 return ContentSuggestion( | |
| 44 base::IntToString(number), | |
| 45 GURL("http://testsuggestion/" + base::IntToString(number))); | |
| 46 } | |
| 47 | |
| 48 std::vector<ContentSuggestion> CreateSuggestions( | |
| 49 const std::vector<int>& numbers) { | |
| 50 std::vector<ContentSuggestion> result; | |
| 51 for (int number : numbers) { | |
| 52 result.emplace_back(CreateSuggestion(number)); | |
| 53 } | |
| 54 return result; | |
| 55 } | |
| 56 | |
| 57 class MockProvider : public ContentSuggestionsProvider { | 42 class MockProvider : public ContentSuggestionsProvider { |
| 58 public: | 43 public: |
| 59 MockProvider(Observer* observer, | 44 MockProvider(Observer* observer, |
| 60 CategoryFactory* category_factory, | 45 CategoryFactory* category_factory, |
| 61 const std::vector<Category>& provided_categories) | 46 const std::vector<Category>& provided_categories) |
| 62 : ContentSuggestionsProvider(observer, category_factory) { | 47 : ContentSuggestionsProvider(observer, category_factory) { |
| 63 SetProvidedCategories(provided_categories); | 48 SetProvidedCategories(provided_categories); |
| 64 } | 49 } |
| 65 | 50 |
| 66 void SetProvidedCategories(const std::vector<Category>& provided_categories) { | 51 void SetProvidedCategories(const std::vector<Category>& provided_categories) { |
| 67 statuses_.clear(); | 52 statuses_.clear(); |
| 68 provided_categories_ = provided_categories; | 53 provided_categories_ = provided_categories; |
| 69 for (Category category : provided_categories) { | 54 for (Category category : provided_categories) { |
| 70 statuses_[category.id()] = CategoryStatus::AVAILABLE; | 55 statuses_[category.id()] = CategoryStatus::AVAILABLE; |
| 71 } | 56 } |
| 72 } | 57 } |
| 73 | 58 |
| 74 CategoryStatus GetCategoryStatus(Category category) { | 59 CategoryStatus GetCategoryStatus(Category category) { |
| 75 return statuses_[category.id()]; | 60 return statuses_[category.id()]; |
| 76 } | 61 } |
| 77 | 62 |
| 78 CategoryInfo GetCategoryInfo(Category category) { | 63 CategoryInfo GetCategoryInfo(Category category) { |
| 79 return CategoryInfo(base::ASCIIToUTF16("Section title"), | 64 return CategoryInfo(base::ASCIIToUTF16("Section title"), |
| 80 ContentSuggestionsCardLayout::FULL_CARD, true, true); | 65 ContentSuggestionsCardLayout::FULL_CARD, true, true); |
| 81 } | 66 } |
| 82 | 67 |
| 83 void FireSuggestionsChanged(Category category, | 68 void FireSuggestionsChanged( |
| 84 const std::vector<int>& numbers) { | 69 Category category, |
| 85 observer()->OnNewSuggestions(this, category, CreateSuggestions(numbers)); | 70 std::vector<ContentSuggestion> suggestions) { |
| 71 observer()->OnNewSuggestions(this, category, std::move(suggestions)); | |
| 86 } | 72 } |
| 87 | 73 |
| 88 void FireCategoryStatusChanged(Category category, CategoryStatus new_status) { | 74 void FireCategoryStatusChanged(Category category, CategoryStatus new_status) { |
| 89 statuses_[category.id()] = new_status; | 75 statuses_[category.id()] = new_status; |
| 90 observer()->OnCategoryStatusChanged(this, category, new_status); | 76 observer()->OnCategoryStatusChanged(this, category, new_status); |
| 91 } | 77 } |
| 92 | 78 |
| 93 void FireCategoryStatusChangedWithCurrentStatus(Category category) { | 79 void FireCategoryStatusChangedWithCurrentStatus(Category category) { |
| 94 observer()->OnCategoryStatusChanged(this, category, | 80 observer()->OnCategoryStatusChanged(this, category, |
| 95 statuses_[category.id()]); | 81 statuses_[category.id()]); |
| (...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 149 // returned by the service for the given |category|. | 135 // returned by the service for the given |category|. |
| 150 void ExpectThatSuggestionsAre(Category category, std::vector<int> numbers) { | 136 void ExpectThatSuggestionsAre(Category category, std::vector<int> numbers) { |
| 151 std::vector<Category> categories = service()->GetCategories(); | 137 std::vector<Category> categories = service()->GetCategories(); |
| 152 auto position = std::find(categories.begin(), categories.end(), category); | 138 auto position = std::find(categories.begin(), categories.end(), category); |
| 153 if (!numbers.empty()) { | 139 if (!numbers.empty()) { |
| 154 EXPECT_NE(categories.end(), position); | 140 EXPECT_NE(categories.end(), position); |
| 155 } | 141 } |
| 156 | 142 |
| 157 for (const auto& suggestion : | 143 for (const auto& suggestion : |
| 158 service()->GetSuggestionsForCategory(category)) { | 144 service()->GetSuggestionsForCategory(category)) { |
| 145 std::string id_string = | |
|
Marc Treib
2016/09/23 13:31:29
within_category_id ?
jkrcal
2016/09/23 16:11:48
Done.
| |
| 146 service()->category_factory()->GetWithinCategoryIDFromUniqueID( | |
| 147 suggestion.id()); | |
| 159 int id; | 148 int id; |
| 160 ASSERT_TRUE(base::StringToInt(suggestion.id(), &id)); | 149 ASSERT_TRUE(base::StringToInt(id_string, &id)); |
| 161 auto position = std::find(numbers.begin(), numbers.end(), id); | 150 auto position = std::find(numbers.begin(), numbers.end(), id); |
| 162 if (position == numbers.end()) { | 151 if (position == numbers.end()) { |
| 163 ADD_FAILURE() << "Unexpected suggestion with ID " << id; | 152 ADD_FAILURE() << "Unexpected suggestion with ID " << id; |
| 164 } else { | 153 } else { |
| 165 numbers.erase(position); | 154 numbers.erase(position); |
| 166 } | 155 } |
| 167 } | 156 } |
| 168 for (int number : numbers) { | 157 for (int number : numbers) { |
| 169 ADD_FAILURE() << "Suggestion number " << number | 158 ADD_FAILURE() << "Suggestion number " << number |
| 170 << " not present, though expected"; | 159 << " not present, though expected"; |
| (...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 205 void CreateContentSuggestionsService( | 194 void CreateContentSuggestionsService( |
| 206 ContentSuggestionsService::State enabled) { | 195 ContentSuggestionsService::State enabled) { |
| 207 ASSERT_FALSE(service_); | 196 ASSERT_FALSE(service_); |
| 208 service_.reset(new ContentSuggestionsService(enabled, | 197 service_.reset(new ContentSuggestionsService(enabled, |
| 209 nullptr /* history_service */, | 198 nullptr /* history_service */, |
| 210 nullptr /* pref_service */)); | 199 nullptr /* pref_service */)); |
| 211 } | 200 } |
| 212 | 201 |
| 213 ContentSuggestionsService* service() { return service_.get(); } | 202 ContentSuggestionsService* service() { return service_.get(); } |
| 214 | 203 |
| 204 // Returns a suggestion instance for testing. | |
| 205 ContentSuggestion CreateSuggestion(Category category, int number) { | |
| 206 return ContentSuggestion( | |
| 207 service()->category_factory()->MakeUniqueID(category, | |
| 208 base::IntToString(number)), | |
| 209 GURL("http://testsuggestion/" + base::IntToString(number))); | |
| 210 } | |
| 211 | |
| 212 std::vector<ContentSuggestion> CreateSuggestions( | |
| 213 Category category, | |
| 214 const std::vector<int>& numbers) { | |
| 215 std::vector<ContentSuggestion> result; | |
| 216 for (int number : numbers) { | |
| 217 result.emplace_back(CreateSuggestion(category, number)); | |
|
Marc Treib
2016/09/23 13:31:29
nit: push_back will do the exact same thing here I
jkrcal
2016/09/23 16:11:48
Done, thanks!
| |
| 218 } | |
| 219 return result; | |
| 220 } | |
| 221 | |
| 215 private: | 222 private: |
| 216 std::unique_ptr<ContentSuggestionsService> service_; | 223 std::unique_ptr<ContentSuggestionsService> service_; |
| 217 | 224 |
| 218 DISALLOW_COPY_AND_ASSIGN(ContentSuggestionsServiceTest); | 225 DISALLOW_COPY_AND_ASSIGN(ContentSuggestionsServiceTest); |
| 219 }; | 226 }; |
| 220 | 227 |
| 221 class ContentSuggestionsServiceDisabledTest | 228 class ContentSuggestionsServiceDisabledTest |
| 222 : public ContentSuggestionsServiceTest { | 229 : public ContentSuggestionsServiceTest { |
| 223 public: | 230 public: |
| 224 void SetUp() override { | 231 void SetUp() override { |
| (...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 282 IsEmpty()); | 289 IsEmpty()); |
| 283 } | 290 } |
| 284 | 291 |
| 285 TEST_F(ContentSuggestionsServiceTest, ShouldRedirectFetchSuggestionImage) { | 292 TEST_F(ContentSuggestionsServiceTest, ShouldRedirectFetchSuggestionImage) { |
| 286 Category articles_category = FromKnownCategory(KnownCategories::ARTICLES); | 293 Category articles_category = FromKnownCategory(KnownCategories::ARTICLES); |
| 287 Category offline_pages_category = | 294 Category offline_pages_category = |
| 288 FromKnownCategory(KnownCategories::DOWNLOADS); | 295 FromKnownCategory(KnownCategories::DOWNLOADS); |
| 289 MockProvider* provider1 = RegisterProvider(articles_category); | 296 MockProvider* provider1 = RegisterProvider(articles_category); |
| 290 MockProvider* provider2 = RegisterProvider(offline_pages_category); | 297 MockProvider* provider2 = RegisterProvider(offline_pages_category); |
| 291 | 298 |
| 292 provider1->FireSuggestionsChanged(articles_category, {1}); | 299 provider1->FireSuggestionsChanged(articles_category, |
| 293 std::string suggestion_id = CreateSuggestion(1).id(); | 300 CreateSuggestions(articles_category, {1})); |
| 301 std::string suggestion_id = CreateSuggestion(articles_category, 1).id(); | |
| 294 | 302 |
| 295 EXPECT_CALL(*provider1, FetchSuggestionImage(suggestion_id, _)); | 303 EXPECT_CALL(*provider1, FetchSuggestionImage(suggestion_id, _)); |
| 296 EXPECT_CALL(*provider2, FetchSuggestionImage(_, _)).Times(0); | 304 EXPECT_CALL(*provider2, FetchSuggestionImage(_, _)).Times(0); |
| 297 service()->FetchSuggestionImage( | 305 service()->FetchSuggestionImage( |
| 298 suggestion_id, base::Bind(&ContentSuggestionsServiceTest::OnImageFetched, | 306 suggestion_id, base::Bind(&ContentSuggestionsServiceTest::OnImageFetched, |
| 299 base::Unretained(this))); | 307 base::Unretained(this))); |
| 300 } | 308 } |
| 301 | 309 |
| 302 TEST_F(ContentSuggestionsServiceTest, | 310 TEST_F(ContentSuggestionsServiceTest, |
| 303 ShouldCallbackEmptyImageForUnavailableProvider) { | 311 ShouldCallbackEmptyImageForUnavailableProvider) { |
| 304 // Setup the current thread's MessageLoop. | 312 // Setup the current thread's MessageLoop. |
| 305 base::MessageLoop message_loop; | 313 base::MessageLoop message_loop; |
| 306 | 314 |
| 307 base::RunLoop run_loop; | 315 base::RunLoop run_loop; |
| 308 std::string suggestion_id = "TestID"; | 316 // Assuming there will never be a category with the randomly-picked id below. |
|
Marc Treib
2016/09/23 13:31:29
https://xkcd.com/221/ :)
(Not an actual complaint)
jkrcal
2016/09/23 16:11:48
:)
| |
| 317 std::string suggestion_id = "21563|TestID"; | |
| 309 EXPECT_CALL(*this, OnImageFetched(Property(&gfx::Image::IsEmpty, Eq(true)))) | 318 EXPECT_CALL(*this, OnImageFetched(Property(&gfx::Image::IsEmpty, Eq(true)))) |
| 310 .WillOnce(InvokeWithoutArgs(&run_loop, &base::RunLoop::Quit)); | 319 .WillOnce(InvokeWithoutArgs(&run_loop, &base::RunLoop::Quit)); |
| 311 service()->FetchSuggestionImage( | 320 service()->FetchSuggestionImage( |
| 312 suggestion_id, base::Bind(&ContentSuggestionsServiceTest::OnImageFetched, | 321 suggestion_id, base::Bind(&ContentSuggestionsServiceTest::OnImageFetched, |
| 313 base::Unretained(this))); | 322 base::Unretained(this))); |
| 314 run_loop.Run(); | 323 run_loop.Run(); |
| 315 } | 324 } |
| 316 | 325 |
| 317 TEST_F(ContentSuggestionsServiceTest, ShouldRedirectDismissSuggestion) { | 326 TEST_F(ContentSuggestionsServiceTest, ShouldRedirectDismissSuggestion) { |
| 318 Category articles_category = FromKnownCategory(KnownCategories::ARTICLES); | 327 Category articles_category = FromKnownCategory(KnownCategories::ARTICLES); |
| 319 Category offline_pages_category = | 328 Category offline_pages_category = |
| 320 FromKnownCategory(KnownCategories::DOWNLOADS); | 329 FromKnownCategory(KnownCategories::DOWNLOADS); |
| 321 MockProvider* provider1 = RegisterProvider(articles_category); | 330 MockProvider* provider1 = RegisterProvider(articles_category); |
| 322 MockProvider* provider2 = RegisterProvider(offline_pages_category); | 331 MockProvider* provider2 = RegisterProvider(offline_pages_category); |
| 323 | 332 |
| 324 provider2->FireSuggestionsChanged(offline_pages_category, {11}); | 333 provider2->FireSuggestionsChanged( |
| 325 std::string suggestion_id = CreateSuggestion(11).id(); | 334 offline_pages_category, CreateSuggestions(offline_pages_category, {11})); |
| 335 std::string suggestion_id = CreateSuggestion(offline_pages_category, 11).id(); | |
| 326 | 336 |
| 327 EXPECT_CALL(*provider1, DismissSuggestion(_)).Times(0); | 337 EXPECT_CALL(*provider1, DismissSuggestion(_)).Times(0); |
| 328 EXPECT_CALL(*provider2, DismissSuggestion(suggestion_id)); | 338 EXPECT_CALL(*provider2, DismissSuggestion(suggestion_id)); |
| 329 service()->DismissSuggestion(suggestion_id); | 339 service()->DismissSuggestion(suggestion_id); |
| 330 } | 340 } |
| 331 | 341 |
| 332 TEST_F(ContentSuggestionsServiceTest, ShouldRedirectSuggestionInvalidated) { | 342 TEST_F(ContentSuggestionsServiceTest, ShouldRedirectSuggestionInvalidated) { |
| 333 Category articles_category = FromKnownCategory(KnownCategories::ARTICLES); | 343 Category articles_category = FromKnownCategory(KnownCategories::ARTICLES); |
| 334 | 344 |
| 335 MockProvider* provider = RegisterProvider(articles_category); | 345 MockProvider* provider = RegisterProvider(articles_category); |
| 336 MockServiceObserver observer; | 346 MockServiceObserver observer; |
| 337 service()->AddObserver(&observer); | 347 service()->AddObserver(&observer); |
| 338 | 348 |
| 339 provider->FireSuggestionsChanged(articles_category, {11, 12, 13}); | 349 provider->FireSuggestionsChanged( |
| 350 articles_category, CreateSuggestions(articles_category, {11, 12, 13})); | |
| 340 ExpectThatSuggestionsAre(articles_category, {11, 12, 13}); | 351 ExpectThatSuggestionsAre(articles_category, {11, 12, 13}); |
| 341 | 352 |
| 342 std::string suggestion_id = CreateSuggestion(12).id(); | 353 std::string suggestion_id = CreateSuggestion(articles_category, 12).id(); |
| 343 EXPECT_CALL(observer, | 354 EXPECT_CALL(observer, |
| 344 OnSuggestionInvalidated(articles_category, suggestion_id)); | 355 OnSuggestionInvalidated(articles_category, suggestion_id)); |
| 345 provider->FireSuggestionInvalidated(articles_category, suggestion_id); | 356 provider->FireSuggestionInvalidated(articles_category, suggestion_id); |
| 346 ExpectThatSuggestionsAre(articles_category, {11, 13}); | 357 ExpectThatSuggestionsAre(articles_category, {11, 13}); |
| 347 Mock::VerifyAndClearExpectations(&observer); | 358 Mock::VerifyAndClearExpectations(&observer); |
| 348 | 359 |
| 349 // Unknown IDs must be forwarded (though no change happens to the service's | 360 // Unknown IDs must be forwarded (though no change happens to the service's |
| 350 // internal data structures) because previously opened UIs, which can still | 361 // internal data structures) because previously opened UIs, which can still |
| 351 // show the invalidated suggestion, must be notified. | 362 // show the invalidated suggestion, must be notified. |
| 352 std::string unknown_id = CreateSuggestion(1234).id(); | 363 std::string unknown_id = CreateSuggestion(articles_category, 1234).id(); |
| 353 EXPECT_CALL(observer, OnSuggestionInvalidated(articles_category, unknown_id)); | 364 EXPECT_CALL(observer, OnSuggestionInvalidated(articles_category, unknown_id)); |
| 354 provider->FireSuggestionInvalidated(articles_category, unknown_id); | 365 provider->FireSuggestionInvalidated(articles_category, unknown_id); |
| 355 ExpectThatSuggestionsAre(articles_category, {11, 13}); | 366 ExpectThatSuggestionsAre(articles_category, {11, 13}); |
| 356 Mock::VerifyAndClearExpectations(&observer); | 367 Mock::VerifyAndClearExpectations(&observer); |
| 357 | 368 |
| 358 service()->RemoveObserver(&observer); | 369 service()->RemoveObserver(&observer); |
| 359 } | 370 } |
| 360 | 371 |
| 361 TEST_F(ContentSuggestionsServiceTest, ShouldForwardSuggestions) { | 372 TEST_F(ContentSuggestionsServiceTest, ShouldForwardSuggestions) { |
| 362 Category articles_category = FromKnownCategory(KnownCategories::ARTICLES); | 373 Category articles_category = FromKnownCategory(KnownCategories::ARTICLES); |
| 363 Category offline_pages_category = | 374 Category offline_pages_category = |
| 364 FromKnownCategory(KnownCategories::DOWNLOADS); | 375 FromKnownCategory(KnownCategories::DOWNLOADS); |
| 365 | 376 |
| 366 // Create and register providers | 377 // Create and register providers |
| 367 MockProvider* provider1 = RegisterProvider(articles_category); | 378 MockProvider* provider1 = RegisterProvider(articles_category); |
| 368 provider1->FireCategoryStatusChangedWithCurrentStatus(articles_category); | 379 provider1->FireCategoryStatusChangedWithCurrentStatus(articles_category); |
| 369 MockProvider* provider2 = RegisterProvider(offline_pages_category); | 380 MockProvider* provider2 = RegisterProvider(offline_pages_category); |
| 370 provider2->FireCategoryStatusChangedWithCurrentStatus(offline_pages_category); | 381 provider2->FireCategoryStatusChangedWithCurrentStatus(offline_pages_category); |
| 371 ASSERT_THAT(providers().count(articles_category), Eq(1ul)); | 382 ASSERT_THAT(providers().count(articles_category), Eq(1ul)); |
| 372 EXPECT_THAT(providers().at(articles_category), Eq(provider1)); | 383 EXPECT_THAT(providers().at(articles_category), Eq(provider1)); |
| 373 ASSERT_THAT(providers().count(offline_pages_category), Eq(1ul)); | 384 ASSERT_THAT(providers().count(offline_pages_category), Eq(1ul)); |
| 374 EXPECT_THAT(providers().at(offline_pages_category), Eq(provider2)); | 385 EXPECT_THAT(providers().at(offline_pages_category), Eq(provider2)); |
| 375 | 386 |
| 376 // Create and register observer | 387 // Create and register observer |
| 377 MockServiceObserver observer; | 388 MockServiceObserver observer; |
| 378 service()->AddObserver(&observer); | 389 service()->AddObserver(&observer); |
| 379 | 390 |
| 380 // Send suggestions 1 and 2 | 391 // Send suggestions 1 and 2 |
| 381 EXPECT_CALL(observer, OnNewSuggestions(articles_category)); | 392 EXPECT_CALL(observer, OnNewSuggestions(articles_category)); |
| 382 provider1->FireSuggestionsChanged(articles_category, {1, 2}); | 393 provider1->FireSuggestionsChanged( |
| 394 articles_category, CreateSuggestions(articles_category, {1, 2})); | |
| 383 ExpectThatSuggestionsAre(articles_category, {1, 2}); | 395 ExpectThatSuggestionsAre(articles_category, {1, 2}); |
| 384 Mock::VerifyAndClearExpectations(&observer); | 396 Mock::VerifyAndClearExpectations(&observer); |
| 385 | 397 |
| 386 // Send them again, make sure they're not reported twice | 398 // Send them again, make sure they're not reported twice |
| 387 EXPECT_CALL(observer, OnNewSuggestions(articles_category)); | 399 EXPECT_CALL(observer, OnNewSuggestions(articles_category)); |
| 388 provider1->FireSuggestionsChanged(articles_category, {1, 2}); | 400 provider1->FireSuggestionsChanged( |
| 401 articles_category, CreateSuggestions(articles_category, {1, 2})); | |
| 389 ExpectThatSuggestionsAre(articles_category, {1, 2}); | 402 ExpectThatSuggestionsAre(articles_category, {1, 2}); |
| 390 ExpectThatSuggestionsAre(offline_pages_category, std::vector<int>()); | 403 ExpectThatSuggestionsAre(offline_pages_category, std::vector<int>()); |
| 391 Mock::VerifyAndClearExpectations(&observer); | 404 Mock::VerifyAndClearExpectations(&observer); |
| 392 | 405 |
| 393 // Send suggestions 13 and 14 | 406 // Send suggestions 13 and 14 |
| 394 EXPECT_CALL(observer, OnNewSuggestions(offline_pages_category)); | 407 EXPECT_CALL(observer, OnNewSuggestions(offline_pages_category)); |
| 395 provider2->FireSuggestionsChanged(offline_pages_category, {13, 14}); | 408 provider2->FireSuggestionsChanged( |
| 409 offline_pages_category, CreateSuggestions(articles_category, {13, 14})); | |
| 396 ExpectThatSuggestionsAre(articles_category, {1, 2}); | 410 ExpectThatSuggestionsAre(articles_category, {1, 2}); |
| 397 ExpectThatSuggestionsAre(offline_pages_category, {13, 14}); | 411 ExpectThatSuggestionsAre(offline_pages_category, {13, 14}); |
| 398 Mock::VerifyAndClearExpectations(&observer); | 412 Mock::VerifyAndClearExpectations(&observer); |
| 399 | 413 |
| 400 // Send suggestion 1 only | 414 // Send suggestion 1 only |
| 401 EXPECT_CALL(observer, OnNewSuggestions(articles_category)); | 415 EXPECT_CALL(observer, OnNewSuggestions(articles_category)); |
| 402 provider1->FireSuggestionsChanged(articles_category, {1}); | 416 provider1->FireSuggestionsChanged(articles_category, |
| 417 CreateSuggestions(articles_category, {1})); | |
| 403 ExpectThatSuggestionsAre(articles_category, {1}); | 418 ExpectThatSuggestionsAre(articles_category, {1}); |
| 404 ExpectThatSuggestionsAre(offline_pages_category, {13, 14}); | 419 ExpectThatSuggestionsAre(offline_pages_category, {13, 14}); |
| 405 Mock::VerifyAndClearExpectations(&observer); | 420 Mock::VerifyAndClearExpectations(&observer); |
| 406 | 421 |
| 407 // provider2 reports BOOKMARKS as unavailable | 422 // provider2 reports BOOKMARKS as unavailable |
| 408 EXPECT_CALL(observer, OnCategoryStatusChanged( | 423 EXPECT_CALL(observer, OnCategoryStatusChanged( |
| 409 offline_pages_category, | 424 offline_pages_category, |
| 410 CategoryStatus::CATEGORY_EXPLICITLY_DISABLED)); | 425 CategoryStatus::CATEGORY_EXPLICITLY_DISABLED)); |
| 411 provider2->FireCategoryStatusChanged( | 426 provider2->FireCategoryStatusChanged( |
| 412 offline_pages_category, CategoryStatus::CATEGORY_EXPLICITLY_DISABLED); | 427 offline_pages_category, CategoryStatus::CATEGORY_EXPLICITLY_DISABLED); |
| (...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 456 // Provider starts providing |new_category| without calling | 471 // Provider starts providing |new_category| without calling |
| 457 // |OnCategoryStatusChanged|. This is supported for now until further | 472 // |OnCategoryStatusChanged|. This is supported for now until further |
| 458 // reconsideration. | 473 // reconsideration. |
| 459 Category new_category = FromKnownCategory(KnownCategories::ARTICLES); | 474 Category new_category = FromKnownCategory(KnownCategories::ARTICLES); |
| 460 provider->SetProvidedCategories( | 475 provider->SetProvidedCategories( |
| 461 std::vector<Category>({category, new_category})); | 476 std::vector<Category>({category, new_category})); |
| 462 | 477 |
| 463 EXPECT_CALL(observer, OnNewSuggestions(new_category)); | 478 EXPECT_CALL(observer, OnNewSuggestions(new_category)); |
| 464 EXPECT_CALL(observer, | 479 EXPECT_CALL(observer, |
| 465 OnCategoryStatusChanged(new_category, CategoryStatus::AVAILABLE)); | 480 OnCategoryStatusChanged(new_category, CategoryStatus::AVAILABLE)); |
| 466 provider->FireSuggestionsChanged(new_category, {1, 2}); | 481 provider->FireSuggestionsChanged(new_category, |
| 482 CreateSuggestions(new_category, {1, 2})); | |
| 467 | 483 |
| 468 ExpectThatSuggestionsAre(new_category, {1, 2}); | 484 ExpectThatSuggestionsAre(new_category, {1, 2}); |
| 469 ASSERT_THAT(providers().count(category), Eq(1ul)); | 485 ASSERT_THAT(providers().count(category), Eq(1ul)); |
| 470 EXPECT_THAT(providers().at(category), Eq(provider)); | 486 EXPECT_THAT(providers().at(category), Eq(provider)); |
| 471 EXPECT_THAT(service()->GetCategoryStatus(category), | 487 EXPECT_THAT(service()->GetCategoryStatus(category), |
| 472 Eq(CategoryStatus::AVAILABLE)); | 488 Eq(CategoryStatus::AVAILABLE)); |
| 473 ASSERT_THAT(providers().count(new_category), Eq(1ul)); | 489 ASSERT_THAT(providers().count(new_category), Eq(1ul)); |
| 474 EXPECT_THAT(providers().at(new_category), Eq(provider)); | 490 EXPECT_THAT(providers().at(new_category), Eq(provider)); |
| 475 EXPECT_THAT(service()->GetCategoryStatus(new_category), | 491 EXPECT_THAT(service()->GetCategoryStatus(new_category), |
| 476 Eq(CategoryStatus::AVAILABLE)); | 492 Eq(CategoryStatus::AVAILABLE)); |
| (...skipping 29 matching lines...) Expand all Loading... | |
| 506 | 522 |
| 507 service()->RemoveObserver(&observer); | 523 service()->RemoveObserver(&observer); |
| 508 } | 524 } |
| 509 | 525 |
| 510 TEST_F(ContentSuggestionsServiceTest, ShouldRemoveCategoryWhenNotProvided) { | 526 TEST_F(ContentSuggestionsServiceTest, ShouldRemoveCategoryWhenNotProvided) { |
| 511 Category category = FromKnownCategory(KnownCategories::DOWNLOADS); | 527 Category category = FromKnownCategory(KnownCategories::DOWNLOADS); |
| 512 MockProvider* provider = RegisterProvider(category); | 528 MockProvider* provider = RegisterProvider(category); |
| 513 MockServiceObserver observer; | 529 MockServiceObserver observer; |
| 514 service()->AddObserver(&observer); | 530 service()->AddObserver(&observer); |
| 515 | 531 |
| 516 provider->FireSuggestionsChanged(category, {1, 2}); | 532 provider->FireSuggestionsChanged(category, |
| 533 CreateSuggestions(category, {1, 2})); | |
| 517 ExpectThatSuggestionsAre(category, {1, 2}); | 534 ExpectThatSuggestionsAre(category, {1, 2}); |
| 518 | 535 |
| 519 EXPECT_CALL(observer, | 536 EXPECT_CALL(observer, |
| 520 OnCategoryStatusChanged(category, CategoryStatus::NOT_PROVIDED)); | 537 OnCategoryStatusChanged(category, CategoryStatus::NOT_PROVIDED)); |
| 521 provider->FireCategoryStatusChanged(category, CategoryStatus::NOT_PROVIDED); | 538 provider->FireCategoryStatusChanged(category, CategoryStatus::NOT_PROVIDED); |
| 522 | 539 |
| 523 EXPECT_THAT(service()->GetCategoryStatus(category), | 540 EXPECT_THAT(service()->GetCategoryStatus(category), |
| 524 Eq(CategoryStatus::NOT_PROVIDED)); | 541 Eq(CategoryStatus::NOT_PROVIDED)); |
| 525 EXPECT_TRUE(service()->GetCategories().empty()); | 542 EXPECT_TRUE(service()->GetCategories().empty()); |
| 526 ExpectThatSuggestionsAre(category, std::vector<int>()); | 543 ExpectThatSuggestionsAre(category, std::vector<int>()); |
| 527 | 544 |
| 528 service()->RemoveObserver(&observer); | 545 service()->RemoveObserver(&observer); |
| 529 } | 546 } |
| 530 | 547 |
| 531 // This tests the temporary special-casing of the bookmarks section: If it is | 548 // This tests the temporary special-casing of the bookmarks section: If it is |
| 532 // empty, it should appear at the end; see crbug.com/640568. | 549 // empty, it should appear at the end; see crbug.com/640568. |
| 533 TEST_F(ContentSuggestionsServiceTest, ShouldPutBookmarksAtEndIfEmpty) { | 550 TEST_F(ContentSuggestionsServiceTest, ShouldPutBookmarksAtEndIfEmpty) { |
| 534 // Register a bookmarks provider and an arbitrary remote provider. | 551 // Register a bookmarks provider and an arbitrary remote provider. |
| 535 Category bookmarks = FromKnownCategory(KnownCategories::BOOKMARKS); | 552 Category bookmarks = FromKnownCategory(KnownCategories::BOOKMARKS); |
| 536 MockProvider* bookmarks_provider = RegisterProvider(bookmarks); | 553 MockProvider* bookmarks_provider = RegisterProvider(bookmarks); |
| 537 bookmarks_provider->FireCategoryStatusChangedWithCurrentStatus(bookmarks); | 554 bookmarks_provider->FireCategoryStatusChangedWithCurrentStatus(bookmarks); |
| 538 Category remote = FromRemoteCategory(123); | 555 Category remote = FromRemoteCategory(123); |
| 539 MockProvider* remote_provider = RegisterProvider(remote); | 556 MockProvider* remote_provider = RegisterProvider(remote); |
| 540 remote_provider->FireCategoryStatusChangedWithCurrentStatus(remote); | 557 remote_provider->FireCategoryStatusChangedWithCurrentStatus(remote); |
| 541 | 558 |
| 542 // By default, the bookmarks category is empty, so it should be at the end. | 559 // By default, the bookmarks category is empty, so it should be at the end. |
| 543 EXPECT_THAT(service()->GetCategories(), ElementsAre(remote, bookmarks)); | 560 EXPECT_THAT(service()->GetCategories(), ElementsAre(remote, bookmarks)); |
| 544 | 561 |
| 545 // Add two bookmark suggestions; now bookmarks should be in the front. | 562 // Add two bookmark suggestions; now bookmarks should be in the front. |
| 546 bookmarks_provider->FireSuggestionsChanged(bookmarks, {1, 2}); | 563 bookmarks_provider->FireSuggestionsChanged( |
| 564 bookmarks, CreateSuggestions(bookmarks, {1, 2})); | |
| 547 EXPECT_THAT(service()->GetCategories(), ElementsAre(bookmarks, remote)); | 565 EXPECT_THAT(service()->GetCategories(), ElementsAre(bookmarks, remote)); |
| 548 // Dismiss the first suggestion; bookmarks should stay in the front. | 566 // Dismiss the first suggestion; bookmarks should stay in the front. |
| 549 service()->DismissSuggestion(CreateSuggestion(1).id()); | 567 service()->DismissSuggestion(CreateSuggestion(bookmarks, 1).id()); |
| 550 EXPECT_THAT(service()->GetCategories(), ElementsAre(bookmarks, remote)); | 568 EXPECT_THAT(service()->GetCategories(), ElementsAre(bookmarks, remote)); |
| 551 // Dismiss the second suggestion; now bookmarks should go back to the end. | 569 // Dismiss the second suggestion; now bookmarks should go back to the end. |
| 552 service()->DismissSuggestion(CreateSuggestion(2).id()); | 570 service()->DismissSuggestion(CreateSuggestion(bookmarks, 2).id()); |
| 553 EXPECT_THAT(service()->GetCategories(), ElementsAre(remote, bookmarks)); | 571 EXPECT_THAT(service()->GetCategories(), ElementsAre(remote, bookmarks)); |
| 554 | 572 |
| 555 // Same thing, but invalidate instead of dismissing. | 573 // Same thing, but invalidate instead of dismissing. |
| 556 bookmarks_provider->FireSuggestionsChanged(bookmarks, {1, 2}); | 574 bookmarks_provider->FireSuggestionsChanged( |
| 575 bookmarks, CreateSuggestions(bookmarks, {1, 2})); | |
| 557 EXPECT_THAT(service()->GetCategories(), ElementsAre(bookmarks, remote)); | 576 EXPECT_THAT(service()->GetCategories(), ElementsAre(bookmarks, remote)); |
| 558 bookmarks_provider->FireSuggestionInvalidated(bookmarks, | 577 bookmarks_provider->FireSuggestionInvalidated( |
| 559 CreateSuggestion(1).id()); | 578 bookmarks, CreateSuggestion(bookmarks, 1).id()); |
| 560 EXPECT_THAT(service()->GetCategories(), ElementsAre(bookmarks, remote)); | 579 EXPECT_THAT(service()->GetCategories(), ElementsAre(bookmarks, remote)); |
| 561 bookmarks_provider->FireSuggestionInvalidated(bookmarks, | 580 bookmarks_provider->FireSuggestionInvalidated( |
| 562 CreateSuggestion(2).id()); | 581 bookmarks, CreateSuggestion(bookmarks, 2).id()); |
| 563 EXPECT_THAT(service()->GetCategories(), ElementsAre(remote, bookmarks)); | 582 EXPECT_THAT(service()->GetCategories(), ElementsAre(remote, bookmarks)); |
| 564 | 583 |
| 565 // Same thing, but now the bookmarks category updates "naturally". | 584 // Same thing, but now the bookmarks category updates "naturally". |
| 566 bookmarks_provider->FireSuggestionsChanged(bookmarks, {1, 2}); | 585 bookmarks_provider->FireSuggestionsChanged( |
| 586 bookmarks, CreateSuggestions(bookmarks, {1, 2})); | |
| 567 EXPECT_THAT(service()->GetCategories(), ElementsAre(bookmarks, remote)); | 587 EXPECT_THAT(service()->GetCategories(), ElementsAre(bookmarks, remote)); |
| 568 bookmarks_provider->FireSuggestionsChanged(bookmarks, {1}); | 588 bookmarks_provider->FireSuggestionsChanged(bookmarks, |
| 589 CreateSuggestions(bookmarks, {1})); | |
| 569 EXPECT_THAT(service()->GetCategories(), ElementsAre(bookmarks, remote)); | 590 EXPECT_THAT(service()->GetCategories(), ElementsAre(bookmarks, remote)); |
| 570 bookmarks_provider->FireSuggestionsChanged(bookmarks, std::vector<int>()); | 591 bookmarks_provider->FireSuggestionsChanged( |
| 592 bookmarks, CreateSuggestions(bookmarks, std::vector<int>())); | |
| 571 EXPECT_THAT(service()->GetCategories(), ElementsAre(remote, bookmarks)); | 593 EXPECT_THAT(service()->GetCategories(), ElementsAre(remote, bookmarks)); |
| 572 } | 594 } |
| 573 | 595 |
| 574 TEST_F(ContentSuggestionsServiceTest, ShouldForwardClearHistory) { | 596 TEST_F(ContentSuggestionsServiceTest, ShouldForwardClearHistory) { |
| 575 Category category = FromKnownCategory(KnownCategories::DOWNLOADS); | 597 Category category = FromKnownCategory(KnownCategories::DOWNLOADS); |
| 576 MockProvider* provider = RegisterProvider(category); | 598 MockProvider* provider = RegisterProvider(category); |
| 577 base::Time begin = base::Time::FromTimeT(123), | 599 base::Time begin = base::Time::FromTimeT(123), |
| 578 end = base::Time::FromTimeT(456); | 600 end = base::Time::FromTimeT(456); |
| 579 EXPECT_CALL(*provider, ClearHistory(begin, end, _)); | 601 EXPECT_CALL(*provider, ClearHistory(begin, end, _)); |
| 580 base::Callback<bool(const GURL& url)> filter; | 602 base::Callback<bool(const GURL& url)> filter; |
| 581 service()->ClearHistory(begin, end, filter); | 603 service()->ClearHistory(begin, end, filter); |
| 582 } | 604 } |
| 583 | 605 |
| 584 } // namespace ntp_snippets | 606 } // namespace ntp_snippets |
| OLD | NEW |