blob: a4cfe20003fdac2fca1e7ad180cabe818efc5fe2 [file] [log] [blame]
// 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::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());
};
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) {
ASSERT_THAT(service()->one_google_bar_data(), Eq(base::nullopt));
StrictMock<MockOneGoogleBarServiceObserver> observer;
service()->AddObserver(&observer);
// Empty result from a fetch doesn't change anything (it's already empty), so
// should not result in a notification.
service()->Refresh();
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());
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