Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright 2015 The Chromium Authors. All rights reserved. | 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 | 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/ntp_snippets_service.h" | 5 #include "components/ntp_snippets/ntp_snippets_service.h" |
| 6 | 6 |
| 7 #include <memory> | 7 #include <memory> |
| 8 #include <vector> | 8 #include <vector> |
| 9 | 9 |
| 10 #include "base/command_line.h" | 10 #include "base/command_line.h" |
| (...skipping 23 matching lines...) Expand all Loading... | |
| 34 #include "components/signin/core/browser/fake_profile_oauth2_token_service.h" | 34 #include "components/signin/core/browser/fake_profile_oauth2_token_service.h" |
| 35 #include "components/signin/core/browser/fake_signin_manager.h" | 35 #include "components/signin/core/browser/fake_signin_manager.h" |
| 36 #include "google_apis/google_api_keys.h" | 36 #include "google_apis/google_api_keys.h" |
| 37 #include "net/url_request/test_url_fetcher_factory.h" | 37 #include "net/url_request/test_url_fetcher_factory.h" |
| 38 #include "net/url_request/url_request_test_util.h" | 38 #include "net/url_request/url_request_test_util.h" |
| 39 #include "testing/gmock/include/gmock/gmock.h" | 39 #include "testing/gmock/include/gmock/gmock.h" |
| 40 #include "testing/gtest/include/gtest/gtest.h" | 40 #include "testing/gtest/include/gtest/gtest.h" |
| 41 | 41 |
| 42 using testing::ElementsAre; | 42 using testing::ElementsAre; |
| 43 using testing::Eq; | 43 using testing::Eq; |
| 44 using testing::Invoke; | |
| 45 using testing::IsEmpty; | |
| 46 using testing::Mock; | |
| 44 using testing::Return; | 47 using testing::Return; |
| 45 using testing::IsEmpty; | |
| 46 using testing::SizeIs; | 48 using testing::SizeIs; |
| 47 using testing::StartsWith; | 49 using testing::StartsWith; |
| 48 using testing::_; | 50 using testing::_; |
| 49 | 51 |
| 50 namespace ntp_snippets { | 52 namespace ntp_snippets { |
| 51 | 53 |
| 52 namespace { | 54 namespace { |
| 53 | 55 |
| 54 MATCHER_P(IdEq, value, "") { | 56 MATCHER_P(IdEq, value, "") { |
| 55 return arg->id() == value; | 57 return arg->id() == value; |
| (...skipping 161 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 217 class MockScheduler : public NTPSnippetsScheduler { | 219 class MockScheduler : public NTPSnippetsScheduler { |
| 218 public: | 220 public: |
| 219 MOCK_METHOD4(Schedule, | 221 MOCK_METHOD4(Schedule, |
| 220 bool(base::TimeDelta period_wifi_charging, | 222 bool(base::TimeDelta period_wifi_charging, |
| 221 base::TimeDelta period_wifi, | 223 base::TimeDelta period_wifi, |
| 222 base::TimeDelta period_fallback, | 224 base::TimeDelta period_fallback, |
| 223 base::Time reschedule_time)); | 225 base::Time reschedule_time)); |
| 224 MOCK_METHOD0(Unschedule, bool()); | 226 MOCK_METHOD0(Unschedule, bool()); |
| 225 }; | 227 }; |
| 226 | 228 |
| 227 class MockServiceObserver : public NTPSnippetsServiceObserver { | 229 class MockProviderObserver : public ContentSuggestionsProvider::Observer { |
| 228 public: | 230 public: |
| 229 MOCK_METHOD0(NTPSnippetsServiceLoaded, void()); | 231 void OnNewSuggestions(ContentSuggestionsProvider* provider, |
| 230 MOCK_METHOD0(NTPSnippetsServiceShutdown, void()); | 232 Category category, |
| 231 MOCK_METHOD1(NTPSnippetsServiceDisabledReasonChanged, | 233 std::vector<ContentSuggestion> suggestions) {} |
|
Marc Treib
2016/08/03 11:53:23
Shouldn't this be marked override? Or maybe just d
Philipp Keck
2016/08/03 12:57:23
Done.
| |
| 232 void(DisabledReason disabled_reason)); | 234 MOCK_METHOD3(OnCategoryStatusChanged, |
| 235 void(ContentSuggestionsProvider* provider, | |
| 236 Category category, | |
| 237 CategoryStatus new_status)); | |
| 233 }; | 238 }; |
| 234 | 239 |
| 235 class WaitForDBLoad : public NTPSnippetsServiceObserver { | 240 class WaitForDBLoad { |
| 236 public: | 241 public: |
| 237 WaitForDBLoad(NTPSnippetsService* service) : service_(service) { | 242 WaitForDBLoad(MockProviderObserver* observer, NTPSnippetsService* service) |
| 238 service_->AddObserver(this); | 243 : observer_(observer) { |
| 239 if (!service_->ready()) | 244 ON_CALL(*observer_, OnCategoryStatusChanged(_, _, _)) |
| 245 .WillByDefault(Invoke(this, &WaitForDBLoad::OnCategoryStatusChanged)); | |
|
Marc Treib
2016/08/03 11:53:23
WillOnce?
Philipp Keck
2016/08/03 12:28:25
Not available for ON_CALL, unfortunately. That's a
Marc Treib
2016/08/03 12:37:56
EXPECT_CALL then?
Philipp Keck
2016/08/03 12:57:23
Ok, using EXPECT_CALL now. It's not really what it
| |
| 246 if (!service->ready()) | |
| 240 run_loop_.Run(); | 247 run_loop_.Run(); |
| 241 } | 248 } |
| 242 | 249 |
| 243 ~WaitForDBLoad() override { | 250 ~WaitForDBLoad() { Mock::VerifyAndClear(observer_); } |
| 244 service_->RemoveObserver(this); | |
| 245 } | |
| 246 | 251 |
| 247 private: | 252 private: |
| 248 void NTPSnippetsServiceLoaded() override { | 253 void OnCategoryStatusChanged(ContentSuggestionsProvider* provider, |
| 249 EXPECT_TRUE(service_->ready()); | 254 Category category, |
| 255 CategoryStatus new_status) { | |
| 256 EXPECT_EQ(new_status, CategoryStatus::AVAILABLE_LOADING); | |
| 250 run_loop_.Quit(); | 257 run_loop_.Quit(); |
| 251 } | 258 } |
| 252 | 259 |
| 253 void NTPSnippetsServiceShutdown() override {} | 260 MockProviderObserver* observer_; |
| 254 void NTPSnippetsServiceDisabledReasonChanged( | |
| 255 DisabledReason disabled_reason) override {} | |
| 256 | |
| 257 NTPSnippetsService* service_; | |
| 258 base::RunLoop run_loop_; | 261 base::RunLoop run_loop_; |
| 259 | 262 |
| 260 DISALLOW_COPY_AND_ASSIGN(WaitForDBLoad); | 263 DISALLOW_COPY_AND_ASSIGN(WaitForDBLoad); |
| 261 }; | 264 }; |
| 262 | 265 |
| 263 } // namespace | 266 } // namespace |
| 264 | 267 |
| 265 class NTPSnippetsServiceTest : public test::NTPSnippetsTestBase { | 268 class NTPSnippetsServiceTest : public test::NTPSnippetsTestBase { |
| 266 public: | 269 public: |
| 267 NTPSnippetsServiceTest() | 270 NTPSnippetsServiceTest() |
| 268 : fake_url_fetcher_factory_( | 271 : fake_url_fetcher_factory_( |
| 269 /*default_factory=*/&failing_url_fetcher_factory_), | 272 /*default_factory=*/&failing_url_fetcher_factory_), |
| 270 test_url_(base::StringPrintf(kTestContentSnippetsServerFormat, | 273 test_url_(base::StringPrintf(kTestContentSnippetsServerFormat, |
| 271 google_apis::GetAPIKey().c_str())) { | 274 google_apis::GetAPIKey().c_str())) { |
| 272 NTPSnippetsService::RegisterProfilePrefs(pref_service()->registry()); | 275 NTPSnippetsService::RegisterProfilePrefs(pref_service()->registry()); |
| 273 RequestThrottler::RegisterProfilePrefs(pref_service()->registry()); | 276 RequestThrottler::RegisterProfilePrefs(pref_service()->registry()); |
| 274 | 277 |
| 275 // Since no SuggestionsService is injected in tests, we need to force the | 278 // Since no SuggestionsService is injected in tests, we need to force the |
| 276 // service to fetch from all hosts. | 279 // service to fetch from all hosts. |
| 277 base::CommandLine::ForCurrentProcess()->AppendSwitch( | 280 base::CommandLine::ForCurrentProcess()->AppendSwitch( |
| 278 switches::kDontRestrict); | 281 switches::kDontRestrict); |
| 279 EXPECT_TRUE(database_dir_.CreateUniqueTempDir()); | 282 EXPECT_TRUE(database_dir_.CreateUniqueTempDir()); |
| 280 } | 283 } |
| 281 | 284 |
| 282 ~NTPSnippetsServiceTest() override { | 285 ~NTPSnippetsServiceTest() override { |
| 283 if (service_) | |
| 284 service_->Shutdown(); | |
| 285 | |
| 286 // We need to run the message loop after deleting the database, because | 286 // We need to run the message loop after deleting the database, because |
| 287 // ProtoDatabaseImpl deletes the actual LevelDB asynchronously on the task | 287 // ProtoDatabaseImpl deletes the actual LevelDB asynchronously on the task |
| 288 // runner. Without this, we'd get reports of memory leaks. | 288 // runner. Without this, we'd get reports of memory leaks. |
| 289 Mock::VerifyAndClear(&mock_scheduler()); | |
| 289 service_.reset(); | 290 service_.reset(); |
| 290 base::RunLoop().RunUntilIdle(); | 291 base::RunLoop().RunUntilIdle(); |
| 291 } | 292 } |
| 292 | 293 |
| 293 void SetUp() override { | 294 void SetUp() override { |
| 294 test::NTPSnippetsTestBase::SetUp(); | 295 test::NTPSnippetsTestBase::SetUp(); |
| 295 EXPECT_CALL(mock_scheduler(), Schedule(_, _, _, _)).Times(1); | 296 EXPECT_CALL(mock_scheduler(), Schedule(_, _, _, _)).Times(1); |
| 296 CreateSnippetsService(/*enabled=*/true); | 297 CreateSnippetsService(); |
| 297 } | 298 } |
| 298 | 299 |
| 299 void CreateSnippetsService(bool enabled) { | 300 void RecreateSnippetsService() { |
| 300 if (service_) | 301 Mock::VerifyAndClear(&mock_scheduler()); |
| 301 service_->Shutdown(); | 302 service_.reset(); |
| 303 base::RunLoop().RunUntilIdle(); | |
| 304 EXPECT_CALL(mock_scheduler(), Schedule(_, _, _, _)).Times(1); | |
| 305 CreateSnippetsService(); | |
| 306 } | |
| 302 | 307 |
| 308 void CreateSnippetsService() { | |
| 303 scoped_refptr<base::SingleThreadTaskRunner> task_runner( | 309 scoped_refptr<base::SingleThreadTaskRunner> task_runner( |
| 304 base::ThreadTaskRunnerHandle::Get()); | 310 base::ThreadTaskRunnerHandle::Get()); |
| 305 scoped_refptr<net::TestURLRequestContextGetter> request_context_getter = | 311 scoped_refptr<net::TestURLRequestContextGetter> request_context_getter = |
| 306 new net::TestURLRequestContextGetter(task_runner.get()); | 312 new net::TestURLRequestContextGetter(task_runner.get()); |
| 307 | 313 |
| 308 // Delete the current service, so that the database is destroyed before we | 314 // Delete the current service, so that the database is destroyed before we |
| 309 // create the new one, otherwise opening the new database will fail. | 315 // create the new one, otherwise opening the new database will fail. |
| 310 service_.reset(); | 316 service_.reset(); |
|
Marc Treib
2016/08/03 11:53:23
Is this still required now that there is an explic
Philipp Keck
2016/08/03 12:28:25
Right. Done.
| |
| 311 | 317 |
| 312 ResetSigninManager(); | 318 ResetSigninManager(); |
| 313 std::unique_ptr<NTPSnippetsFetcher> snippets_fetcher = | 319 std::unique_ptr<NTPSnippetsFetcher> snippets_fetcher = |
| 314 base::MakeUnique<NTPSnippetsFetcher>( | 320 base::MakeUnique<NTPSnippetsFetcher>( |
| 315 fake_signin_manager(), fake_token_service_.get(), | 321 fake_signin_manager(), fake_token_service_.get(), |
| 316 std::move(request_context_getter), pref_service(), | 322 std::move(request_context_getter), pref_service(), |
| 317 base::Bind(&ParseJson), | 323 base::Bind(&ParseJson), |
| 318 /*is_stable_channel=*/true); | 324 /*is_stable_channel=*/true); |
| 319 | 325 |
| 320 fake_signin_manager()->SignIn("foo@bar.com"); | 326 fake_signin_manager()->SignIn("foo@bar.com"); |
| 321 snippets_fetcher->SetPersonalizationForTesting( | 327 snippets_fetcher->SetPersonalizationForTesting( |
| 322 NTPSnippetsFetcher::Personalization::kNonPersonal); | 328 NTPSnippetsFetcher::Personalization::kNonPersonal); |
| 323 | 329 |
| 324 // Add an initial fetch response, as the service tries to fetch when there | 330 // Add an initial fetch response, as the service tries to fetch when there |
| 325 // is nothing in the DB. | 331 // is nothing in the DB. |
| 326 SetUpFetchResponse(GetTestJson({GetSnippet()})); | 332 SetUpFetchResponse(GetTestJson({GetSnippet()})); |
| 327 | 333 |
| 328 service_.reset(new NTPSnippetsService( | 334 service_.reset(new NTPSnippetsService( |
| 329 enabled, pref_service(), nullptr, &category_factory_, "fr", &scheduler_, | 335 &observer_, &category_factory_, pref_service(), nullptr, "fr", |
| 330 std::move(snippets_fetcher), /*image_fetcher=*/nullptr, | 336 &scheduler_, std::move(snippets_fetcher), /*image_fetcher=*/nullptr, |
| 331 /*image_fetcher=*/nullptr, base::MakeUnique<NTPSnippetsDatabase>( | 337 /*image_fetcher=*/nullptr, base::MakeUnique<NTPSnippetsDatabase>( |
| 332 database_dir_.path(), task_runner), | 338 database_dir_.path(), task_runner), |
| 333 base::MakeUnique<NTPSnippetsStatusService>(fake_signin_manager(), | 339 base::MakeUnique<NTPSnippetsStatusService>(fake_signin_manager(), |
| 334 pref_service()))); | 340 pref_service()))); |
| 335 | 341 |
| 336 if (enabled) | 342 WaitForDBLoad(&observer_, service_.get()); |
| 337 WaitForDBLoad(service_.get()); | |
| 338 } | 343 } |
| 339 | 344 |
| 340 std::string MakeUniqueID(const std::string& within_category_id) { | 345 std::string MakeUniqueID(const std::string& within_category_id) { |
| 341 return service()->MakeUniqueID( | 346 return service()->MakeUniqueID( |
| 342 category_factory_.FromKnownCategory(KnownCategories::ARTICLES), | 347 category_factory_.FromKnownCategory(KnownCategories::ARTICLES), |
| 343 within_category_id); | 348 within_category_id); |
| 344 } | 349 } |
| 345 | 350 |
| 346 protected: | 351 protected: |
| 347 const GURL& test_url() { return test_url_; } | 352 const GURL& test_url() { return test_url_; } |
| 348 NTPSnippetsService* service() { return service_.get(); } | 353 NTPSnippetsService* service() { return service_.get(); } |
| 349 MockScheduler& mock_scheduler() { return scheduler_; } | 354 MockProviderObserver& observer() { return observer_; } |
| 355 MockScheduler& mock_scheduler() { return scheduler_; } | |
| 350 | 356 |
| 351 // Provide the json to be returned by the fake fetcher. | 357 // Provide the json to be returned by the fake fetcher. |
| 352 void SetUpFetchResponse(const std::string& json) { | 358 void SetUpFetchResponse(const std::string& json) { |
| 353 fake_url_fetcher_factory_.SetFakeResponse(test_url_, json, net::HTTP_OK, | 359 fake_url_fetcher_factory_.SetFakeResponse(test_url_, json, net::HTTP_OK, |
| 354 net::URLRequestStatus::SUCCESS); | 360 net::URLRequestStatus::SUCCESS); |
| 355 } | 361 } |
| 356 | 362 |
| 357 void LoadFromJSONString(const std::string& json) { | 363 void LoadFromJSONString(const std::string& json) { |
| 358 SetUpFetchResponse(json); | 364 SetUpFetchResponse(json); |
| 359 service()->FetchSnippets(true); | 365 service()->FetchSnippets(true); |
| 360 base::RunLoop().RunUntilIdle(); | 366 base::RunLoop().RunUntilIdle(); |
| 361 } | 367 } |
| 362 | 368 |
| 363 private: | 369 private: |
| 364 base::MessageLoop message_loop_; | 370 base::MessageLoop message_loop_; |
| 365 FailingFakeURLFetcherFactory failing_url_fetcher_factory_; | 371 FailingFakeURLFetcherFactory failing_url_fetcher_factory_; |
| 366 // Instantiation of factory automatically sets itself as URLFetcher's factory. | 372 // Instantiation of factory automatically sets itself as URLFetcher's factory. |
| 367 net::FakeURLFetcherFactory fake_url_fetcher_factory_; | 373 net::FakeURLFetcherFactory fake_url_fetcher_factory_; |
| 368 const GURL test_url_; | 374 const GURL test_url_; |
| 369 std::unique_ptr<OAuth2TokenService> fake_token_service_; | 375 std::unique_ptr<OAuth2TokenService> fake_token_service_; |
| 370 MockScheduler scheduler_; | 376 MockScheduler scheduler_; |
| 377 MockProviderObserver observer_; | |
| 371 CategoryFactory category_factory_; | 378 CategoryFactory category_factory_; |
| 372 // Last so that the dependencies are deleted after the service. | 379 // Last so that the dependencies are deleted after the service. |
| 373 std::unique_ptr<NTPSnippetsService> service_; | 380 std::unique_ptr<NTPSnippetsService> service_; |
| 374 | 381 |
| 375 base::ScopedTempDir database_dir_; | 382 base::ScopedTempDir database_dir_; |
| 376 | 383 |
| 377 DISALLOW_COPY_AND_ASSIGN(NTPSnippetsServiceTest); | 384 DISALLOW_COPY_AND_ASSIGN(NTPSnippetsServiceTest); |
| 378 }; | 385 }; |
| 379 | 386 |
| 380 class NTPSnippetsServiceDisabledTest : public NTPSnippetsServiceTest { | 387 TEST_F(NTPSnippetsServiceTest, ScheduleOnStart) { |
| 381 public: | |
| 382 void SetUp() override { | |
| 383 test::NTPSnippetsTestBase::SetUp(); | |
| 384 EXPECT_CALL(mock_scheduler(), Unschedule()).Times(1); | |
| 385 CreateSnippetsService(/*enabled=*/false); | |
| 386 } | |
| 387 }; | |
| 388 | |
| 389 TEST_F(NTPSnippetsServiceTest, ScheduleIfEnabled) { | |
| 390 // SetUp() checks that Schedule is called. | 388 // SetUp() checks that Schedule is called. |
| 391 | 389 |
| 392 // When we have no snippets are all, loading the service initiates a fetch. | 390 // When we have no snippets are all, loading the service initiates a fetch. |
| 393 base::RunLoop().RunUntilIdle(); | 391 base::RunLoop().RunUntilIdle(); |
| 394 ASSERT_EQ("OK", service()->snippets_fetcher()->last_status()); | 392 ASSERT_EQ("OK", service()->snippets_fetcher()->last_status()); |
| 395 } | 393 } |
| 396 | 394 |
| 397 TEST_F(NTPSnippetsServiceDisabledTest, Unschedule) { | |
| 398 // SetUp() checks that Unschedule is called. | |
| 399 | |
| 400 // Make sure we don't fetch anything. | |
| 401 base::RunLoop().RunUntilIdle(); | |
| 402 EXPECT_THAT(service()->snippets_fetcher()->last_status(), IsEmpty()); | |
| 403 } | |
| 404 | |
| 405 TEST_F(NTPSnippetsServiceTest, Full) { | 395 TEST_F(NTPSnippetsServiceTest, Full) { |
| 406 std::string json_str(GetTestJson({GetSnippet()})); | 396 std::string json_str(GetTestJson({GetSnippet()})); |
| 407 | 397 |
| 408 LoadFromJSONString(json_str); | 398 LoadFromJSONString(json_str); |
| 409 ASSERT_THAT(service()->snippets(), SizeIs(1)); | 399 ASSERT_THAT(service()->snippets(), SizeIs(1)); |
| 410 const NTPSnippet& snippet = *service()->snippets().front(); | 400 const NTPSnippet& snippet = *service()->snippets().front(); |
| 411 | 401 |
| 412 EXPECT_EQ(snippet.id(), kSnippetUrl); | 402 EXPECT_EQ(snippet.id(), kSnippetUrl); |
| 413 EXPECT_EQ(snippet.title(), kSnippetTitle); | 403 EXPECT_EQ(snippet.title(), kSnippetTitle); |
| 414 EXPECT_EQ(snippet.snippet(), kSnippetText); | 404 EXPECT_EQ(snippet.snippet(), kSnippetText); |
| (...skipping 99 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 514 | 504 |
| 515 // Dismiss the snippet. | 505 // Dismiss the snippet. |
| 516 service()->DismissSuggestion(MakeUniqueID(kSnippetUrl)); | 506 service()->DismissSuggestion(MakeUniqueID(kSnippetUrl)); |
| 517 EXPECT_THAT(service()->snippets(), IsEmpty()); | 507 EXPECT_THAT(service()->snippets(), IsEmpty()); |
| 518 | 508 |
| 519 // Make sure that fetching the same snippet again does not re-add it. | 509 // Make sure that fetching the same snippet again does not re-add it. |
| 520 LoadFromJSONString(json_str); | 510 LoadFromJSONString(json_str); |
| 521 EXPECT_THAT(service()->snippets(), IsEmpty()); | 511 EXPECT_THAT(service()->snippets(), IsEmpty()); |
| 522 | 512 |
| 523 // The snippet should stay dismissed even after re-creating the service. | 513 // The snippet should stay dismissed even after re-creating the service. |
| 524 EXPECT_CALL(mock_scheduler(), Schedule(_, _, _, _)).Times(1); | 514 RecreateSnippetsService(); |
| 525 CreateSnippetsService(/*enabled=*/true); | |
| 526 LoadFromJSONString(json_str); | 515 LoadFromJSONString(json_str); |
| 527 EXPECT_THAT(service()->snippets(), IsEmpty()); | 516 EXPECT_THAT(service()->snippets(), IsEmpty()); |
| 528 | 517 |
| 529 // The snippet can be added again after clearing dismissed snippets. | 518 // The snippet can be added again after clearing dismissed snippets. |
| 530 service()->ClearDismissedSuggestionsForDebugging(); | 519 service()->ClearDismissedSuggestionsForDebugging(); |
| 531 EXPECT_THAT(service()->snippets(), IsEmpty()); | 520 EXPECT_THAT(service()->snippets(), IsEmpty()); |
| 532 LoadFromJSONString(json_str); | 521 LoadFromJSONString(json_str); |
| 533 EXPECT_THAT(service()->snippets(), SizeIs(1)); | 522 EXPECT_THAT(service()->snippets(), SizeIs(1)); |
| 534 } | 523 } |
| 535 | 524 |
| (...skipping 293 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 829 base::Bucket(/*min=*/1, /*count=*/2))); | 818 base::Bucket(/*min=*/1, /*count=*/2))); |
| 830 // Dismissed snippets shouldn't influence NumArticlesFetched. | 819 // Dismissed snippets shouldn't influence NumArticlesFetched. |
| 831 EXPECT_THAT(tester.GetAllSamples("NewTabPage.Snippets.NumArticlesFetched"), | 820 EXPECT_THAT(tester.GetAllSamples("NewTabPage.Snippets.NumArticlesFetched"), |
| 832 ElementsAre(base::Bucket(/*min=*/0, /*count=*/1), | 821 ElementsAre(base::Bucket(/*min=*/0, /*count=*/1), |
| 833 base::Bucket(/*min=*/1, /*count=*/3))); | 822 base::Bucket(/*min=*/1, /*count=*/3))); |
| 834 EXPECT_THAT( | 823 EXPECT_THAT( |
| 835 tester.GetAllSamples("NewTabPage.Snippets.NumArticlesZeroDueToDiscarded"), | 824 tester.GetAllSamples("NewTabPage.Snippets.NumArticlesZeroDueToDiscarded"), |
| 836 ElementsAre(base::Bucket(/*min=*/1, /*count=*/1))); | 825 ElementsAre(base::Bucket(/*min=*/1, /*count=*/1))); |
| 837 // Recreating the service and loading from prefs shouldn't count as fetched | 826 // Recreating the service and loading from prefs shouldn't count as fetched |
| 838 // articles. | 827 // articles. |
| 839 EXPECT_CALL(mock_scheduler(), Schedule(_, _, _, _)).Times(1); | 828 RecreateSnippetsService(); |
| 840 CreateSnippetsService(/*enabled=*/true); | |
| 841 tester.ExpectTotalCount("NewTabPage.Snippets.NumArticlesFetched", 4); | 829 tester.ExpectTotalCount("NewTabPage.Snippets.NumArticlesFetched", 4); |
| 842 } | 830 } |
| 843 | 831 |
| 844 TEST_F(NTPSnippetsServiceTest, DismissShouldRespectAllKnownUrls) { | 832 TEST_F(NTPSnippetsServiceTest, DismissShouldRespectAllKnownUrls) { |
| 845 const std::string creation = | 833 const std::string creation = |
| 846 NTPSnippet::TimeToJsonString(GetDefaultCreationTime()); | 834 NTPSnippet::TimeToJsonString(GetDefaultCreationTime()); |
| 847 const std::string expiry = | 835 const std::string expiry = |
| 848 NTPSnippet::TimeToJsonString(GetDefaultExpirationTime()); | 836 NTPSnippet::TimeToJsonString(GetDefaultExpirationTime()); |
| 849 const std::vector<std::string> source_urls = { | 837 const std::vector<std::string> source_urls = { |
| 850 "http://mashable.com/2016/05/11/stolen", | 838 "http://mashable.com/2016/05/11/stolen", |
| (...skipping 13 matching lines...) Expand all Loading... | |
| 864 service()->DismissSuggestion(MakeUniqueID(source_urls[0])); | 852 service()->DismissSuggestion(MakeUniqueID(source_urls[0])); |
| 865 EXPECT_THAT(service()->snippets(), IsEmpty()); | 853 EXPECT_THAT(service()->snippets(), IsEmpty()); |
| 866 | 854 |
| 867 // The same article from the AOL domain should now be detected as dismissed. | 855 // The same article from the AOL domain should now be detected as dismissed. |
| 868 LoadFromJSONString(GetTestJson({GetSnippetWithUrlAndTimesAndSources( | 856 LoadFromJSONString(GetTestJson({GetSnippetWithUrlAndTimesAndSources( |
| 869 source_urls[1], creation, expiry, source_urls, publishers, amp_urls)})); | 857 source_urls[1], creation, expiry, source_urls, publishers, amp_urls)})); |
| 870 ASSERT_THAT(service()->snippets(), IsEmpty()); | 858 ASSERT_THAT(service()->snippets(), IsEmpty()); |
| 871 } | 859 } |
| 872 | 860 |
| 873 TEST_F(NTPSnippetsServiceTest, StatusChanges) { | 861 TEST_F(NTPSnippetsServiceTest, StatusChanges) { |
| 874 MockServiceObserver mock_observer; | |
| 875 service()->AddObserver(&mock_observer); | |
| 876 | |
| 877 // Simulate user signed out | 862 // Simulate user signed out |
| 878 SetUpFetchResponse(GetTestJson({GetSnippet()})); | 863 SetUpFetchResponse(GetTestJson({GetSnippet()})); |
| 879 EXPECT_CALL(mock_observer, NTPSnippetsServiceDisabledReasonChanged( | 864 EXPECT_CALL(observer(), |
| 880 DisabledReason::SIGNED_OUT)); | 865 OnCategoryStatusChanged(_, _, CategoryStatus::SIGNED_OUT)); |
| 881 service()->OnDisabledReasonChanged(DisabledReason::SIGNED_OUT); | 866 service()->OnDisabledReasonChanged(DisabledReason::SIGNED_OUT); |
| 882 base::RunLoop().RunUntilIdle(); | 867 base::RunLoop().RunUntilIdle(); |
| 883 EXPECT_EQ(NTPSnippetsService::State::DISABLED, service()->state_); | 868 EXPECT_EQ(NTPSnippetsService::State::DISABLED, service()->state_); |
| 884 EXPECT_THAT(service()->snippets(), IsEmpty()); // No fetch should be made. | 869 EXPECT_THAT(service()->snippets(), IsEmpty()); // No fetch should be made. |
| 885 | 870 |
| 886 // Simulate user sign in. The service should be ready again and load snippets. | 871 // Simulate user sign in. The service should be ready again and load snippets. |
| 887 SetUpFetchResponse(GetTestJson({GetSnippet()})); | 872 SetUpFetchResponse(GetTestJson({GetSnippet()})); |
| 888 EXPECT_CALL(mock_observer, | 873 EXPECT_CALL(observer(), |
| 889 NTPSnippetsServiceDisabledReasonChanged(DisabledReason::NONE)); | 874 OnCategoryStatusChanged(_, _, CategoryStatus::AVAILABLE_LOADING)); |
| 890 EXPECT_CALL(mock_scheduler(), Schedule(_, _, _, _)).Times(1); | 875 EXPECT_CALL(mock_scheduler(), Schedule(_, _, _, _)).Times(1); |
| 891 service()->OnDisabledReasonChanged(DisabledReason::NONE); | 876 service()->OnDisabledReasonChanged(DisabledReason::NONE); |
| 877 EXPECT_CALL(observer(), | |
| 878 OnCategoryStatusChanged(_, _, CategoryStatus::AVAILABLE)); | |
| 892 base::RunLoop().RunUntilIdle(); | 879 base::RunLoop().RunUntilIdle(); |
| 893 EXPECT_EQ(NTPSnippetsService::State::READY, service()->state_); | 880 EXPECT_EQ(NTPSnippetsService::State::READY, service()->state_); |
| 894 EXPECT_FALSE(service()->snippets().empty()); | 881 EXPECT_FALSE(service()->snippets().empty()); |
| 895 | |
| 896 service()->RemoveObserver(&mock_observer); | |
| 897 } | 882 } |
| 898 | 883 |
| 899 } // namespace ntp_snippets | 884 } // namespace ntp_snippets |
| OLD | NEW |