| // Copyright 2017 The Chromium Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #include "chrome/browser/search/one_google_bar/one_google_bar_service.h" |
| |
| #include <memory> |
| #include <utility> |
| #include <vector> |
| |
| #include "base/macros.h" |
| #include "base/memory/ptr_util.h" |
| #include "base/optional.h" |
| #include "chrome/browser/search/one_google_bar/one_google_bar_data.h" |
| #include "chrome/browser/search/one_google_bar/one_google_bar_fetcher.h" |
| #include "components/signin/core/browser/account_tracker_service.h" |
| #include "components/signin/core/browser/fake_profile_oauth2_token_service.h" |
| #include "components/signin/core/browser/fake_signin_manager.h" |
| #include "components/signin/core/browser/test_signin_client.h" |
| #include "components/sync_preferences/testing_pref_service_syncable.h" |
| #include "testing/gmock/include/gmock/gmock.h" |
| #include "testing/gtest/include/gtest/gtest.h" |
| |
| using testing::Eq; |
| using testing::InSequence; |
| using testing::StrictMock; |
| |
| class FakeOneGoogleBarFetcher : public OneGoogleBarFetcher { |
| public: |
| void Fetch(OneGoogleCallback callback) override { |
| callbacks_.push_back(std::move(callback)); |
| } |
| |
| size_t GetCallbackCount() const { return callbacks_.size(); } |
| |
| void RespondToAllCallbacks(const base::Optional<OneGoogleBarData>& data) { |
| for (OneGoogleCallback& callback : callbacks_) { |
| std::move(callback).Run(data); |
| } |
| callbacks_.clear(); |
| } |
| |
| private: |
| std::vector<OneGoogleCallback> callbacks_; |
| }; |
| |
| class MockOneGoogleBarServiceObserver : public OneGoogleBarServiceObserver { |
| public: |
| MOCK_METHOD0(OnOneGoogleBarDataChanged, void()); |
| MOCK_METHOD0(OnOneGoogleBarFetchFailed, void()); |
| }; |
| |
| class OneGoogleBarServiceTest : public testing::Test { |
| public: |
| OneGoogleBarServiceTest() |
| : signin_client_(&pref_service_), |
| signin_manager_(&signin_client_, &account_tracker_) { |
| SigninManagerBase::RegisterProfilePrefs(pref_service_.registry()); |
| SigninManagerBase::RegisterPrefs(pref_service_.registry()); |
| |
| auto fetcher = base::MakeUnique<FakeOneGoogleBarFetcher>(); |
| fetcher_ = fetcher.get(); |
| service_ = base::MakeUnique<OneGoogleBarService>(&signin_manager_, |
| std::move(fetcher)); |
| } |
| |
| FakeOneGoogleBarFetcher* fetcher() { return fetcher_; } |
| OneGoogleBarService* service() { return service_.get(); } |
| |
| private: |
| sync_preferences::TestingPrefServiceSyncable pref_service_; |
| TestSigninClient signin_client_; |
| AccountTrackerService account_tracker_; |
| FakeSigninManagerBase signin_manager_; |
| |
| // Owned by the service. |
| FakeOneGoogleBarFetcher* fetcher_; |
| |
| std::unique_ptr<OneGoogleBarService> service_; |
| }; |
| |
| TEST_F(OneGoogleBarServiceTest, RefreshesOnRequest) { |
| ASSERT_THAT(service()->one_google_bar_data(), Eq(base::nullopt)); |
| |
| // Request a refresh. That should arrive at the fetcher. |
| service()->Refresh(); |
| EXPECT_THAT(fetcher()->GetCallbackCount(), Eq(1u)); |
| |
| // Fulfill it. |
| OneGoogleBarData data; |
| data.bar_html = "<div></div>"; |
| fetcher()->RespondToAllCallbacks(data); |
| EXPECT_THAT(service()->one_google_bar_data(), Eq(data)); |
| |
| // Request another refresh. |
| service()->Refresh(); |
| EXPECT_THAT(fetcher()->GetCallbackCount(), Eq(1u)); |
| |
| // For now, the old data should still be there. |
| EXPECT_THAT(service()->one_google_bar_data(), Eq(data)); |
| |
| // Fulfill the second request. |
| OneGoogleBarData other_data; |
| other_data.bar_html = "<div>Different!</div>"; |
| fetcher()->RespondToAllCallbacks(other_data); |
| EXPECT_THAT(service()->one_google_bar_data(), Eq(other_data)); |
| } |
| |
| TEST_F(OneGoogleBarServiceTest, NotifiesObserverOnChanges) { |
| InSequence s; |
| |
| ASSERT_THAT(service()->one_google_bar_data(), Eq(base::nullopt)); |
| |
| StrictMock<MockOneGoogleBarServiceObserver> observer; |
| service()->AddObserver(&observer); |
| |
| // Empty result from a fetch should result in a "fetch failed" notification. |
| // However, the actual data doesn't change anything (it's already empty), so |
| // it should not result in a "data changed". |
| service()->Refresh(); |
| EXPECT_CALL(observer, OnOneGoogleBarFetchFailed()); |
| fetcher()->RespondToAllCallbacks(base::nullopt); |
| |
| // Non-empty response should result in a notification. |
| service()->Refresh(); |
| OneGoogleBarData data; |
| data.bar_html = "<div></div>"; |
| EXPECT_CALL(observer, OnOneGoogleBarDataChanged()); |
| fetcher()->RespondToAllCallbacks(data); |
| EXPECT_THAT(service()->one_google_bar_data(), Eq(data)); |
| |
| // Non-empty but identical response should not result in another notification. |
| service()->Refresh(); |
| OneGoogleBarData identical_data = data; |
| fetcher()->RespondToAllCallbacks(identical_data); |
| |
| // Different response should result in a notification. |
| service()->Refresh(); |
| OneGoogleBarData other_data; |
| data.bar_html = "<div>Different</div>"; |
| EXPECT_CALL(observer, OnOneGoogleBarDataChanged()); |
| fetcher()->RespondToAllCallbacks(other_data); |
| EXPECT_THAT(service()->one_google_bar_data(), Eq(other_data)); |
| |
| // Finally, an empty response should result in a notification now. |
| service()->Refresh(); |
| EXPECT_CALL(observer, OnOneGoogleBarDataChanged()); |
| EXPECT_CALL(observer, OnOneGoogleBarFetchFailed()); |
| fetcher()->RespondToAllCallbacks(base::nullopt); |
| EXPECT_THAT(service()->one_google_bar_data(), Eq(base::nullopt)); |
| |
| service()->RemoveObserver(&observer); |
| } |
| |
| #if !defined(OS_CHROMEOS) |
| |
| // Like OneGoogleBarServiceTest, but it has a FakeSigninManager (rather than |
| // FakeSigninManagerBase), so it can simulate sign-in and sign-out. |
| class OneGoogleBarServiceSignInTest : public testing::Test { |
| public: |
| OneGoogleBarServiceSignInTest() |
| : signin_client_(&pref_service_), |
| signin_manager_(&signin_client_, |
| &token_service_, |
| &account_tracker_, |
| nullptr) { |
| SigninManagerBase::RegisterProfilePrefs(pref_service_.registry()); |
| SigninManagerBase::RegisterPrefs(pref_service_.registry()); |
| AccountTrackerService::RegisterPrefs(pref_service_.registry()); |
| |
| account_tracker_.Initialize(&signin_client_); |
| |
| auto fetcher = base::MakeUnique<FakeOneGoogleBarFetcher>(); |
| fetcher_ = fetcher.get(); |
| service_ = base::MakeUnique<OneGoogleBarService>(&signin_manager_, |
| std::move(fetcher)); |
| } |
| |
| void SignIn() { signin_manager_.SignIn("account", "username", "pass"); } |
| void SignOut() { signin_manager_.ForceSignOut(); } |
| |
| FakeOneGoogleBarFetcher* fetcher() { return fetcher_; } |
| OneGoogleBarService* service() { return service_.get(); } |
| |
| private: |
| sync_preferences::TestingPrefServiceSyncable pref_service_; |
| TestSigninClient signin_client_; |
| FakeProfileOAuth2TokenService token_service_; |
| AccountTrackerService account_tracker_; |
| FakeSigninManager signin_manager_; |
| |
| // Owned by the service. |
| FakeOneGoogleBarFetcher* fetcher_; |
| |
| std::unique_ptr<OneGoogleBarService> service_; |
| }; |
| |
| TEST_F(OneGoogleBarServiceSignInTest, ResetsOnSignIn) { |
| // Load some data. |
| service()->Refresh(); |
| OneGoogleBarData data; |
| data.bar_html = "<div></div>"; |
| fetcher()->RespondToAllCallbacks(data); |
| ASSERT_THAT(service()->one_google_bar_data(), Eq(data)); |
| |
| // Sign in. This should clear the cached data. |
| SignIn(); |
| EXPECT_THAT(service()->one_google_bar_data(), Eq(base::nullopt)); |
| } |
| |
| TEST_F(OneGoogleBarServiceSignInTest, ResetsOnSignOut) { |
| SignIn(); |
| |
| // Load some data. |
| service()->Refresh(); |
| OneGoogleBarData data; |
| data.bar_html = "<div></div>"; |
| fetcher()->RespondToAllCallbacks(data); |
| ASSERT_THAT(service()->one_google_bar_data(), Eq(data)); |
| |
| // Sign out. This should clear the cached data. |
| SignOut(); |
| EXPECT_THAT(service()->one_google_bar_data(), Eq(base::nullopt)); |
| } |
| |
| #endif // OS_CHROMEOS |