Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(394)

Unified Diff: components/ntp_snippets/sessions/foreign_sessions_suggestions_provider_unittest.cc

Issue 2279123002: [Sync] Initial implementation of foreign sessions suggestions provider. (Closed)
Patch Set: Adding sessions deps to BUILD.gn Created 4 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: components/ntp_snippets/sessions/foreign_sessions_suggestions_provider_unittest.cc
diff --git a/components/ntp_snippets/sessions/foreign_sessions_suggestions_provider_unittest.cc b/components/ntp_snippets/sessions/foreign_sessions_suggestions_provider_unittest.cc
new file mode 100644
index 0000000000000000000000000000000000000000..b0bdda17e4bda8f432205df0ebca01d55d258bb9
--- /dev/null
+++ b/components/ntp_snippets/sessions/foreign_sessions_suggestions_provider_unittest.cc
@@ -0,0 +1,335 @@
+// Copyright 2016 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 "components/ntp_snippets/sessions/foreign_sessions_suggestions_provider.h"
+
+#include <map>
+#include <utility>
+
+#include "base/memory/ptr_util.h"
+#include "components/ntp_snippets/category.h"
+#include "components/ntp_snippets/category_factory.h"
+#include "components/ntp_snippets/content_suggestions_provider.h"
+#include "components/ntp_snippets/mock_content_suggestions_provider_observer.h"
+#include "components/prefs/testing_pref_service.h"
+#include "components/sessions/core/serialized_navigation_entry.h"
+#include "components/sessions/core/serialized_navigation_entry_test_helper.h"
+#include "components/sessions/core/session_types.h"
+#include "components/sync_sessions/open_tabs_ui_delegate.h"
+#include "components/sync_sessions/synced_session.h"
+#include "testing/gmock/include/gmock/gmock.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+using base::Time;
+using base::TimeDelta;
+using sessions::SerializedNavigationEntry;
+using sessions::SessionTab;
+using sessions::SessionWindow;
+using sync_driver::SyncedSession;
+using testing::IsEmpty;
+using testing::Property;
+using testing::ElementsAre;
+using testing::UnorderedElementsAre;
+using testing::_;
+
+namespace ntp_snippets {
+namespace {
+
+const char kUrl1[] = "http://www.fake1.com/";
+const char kUrl2[] = "http://www.fake2.com/";
+const char kUrl3[] = "http://www.fake3.com/";
+const char kUrl4[] = "http://www.fake4.com/";
+const char kUrl5[] = "http://www.fake5.com/";
+const char kUrl6[] = "http://www.fake6.com/";
+const char kUrl7[] = "http://www.fake7.com/";
+const char kUrl8[] = "http://www.fake8.com/";
+const char kUrl9[] = "http://www.fake9.com/";
+const char kUrl10[] = "http://www.fake10.com/";
+const char kUrl11[] = "http://www.fake11.com/";
+const char kTitle[] = "title is ignored";
+
+SessionWindow* GetWindow(SyncedSession* session, int window_id) {
Marc Treib 2016/09/16 12:26:49 GetOrCreateWindow?
skym 2016/09/16 18:18:49 Done.
+ if (session->windows.find(window_id) == session->windows.end()) {
+ // The session deletes the windows it points at upon destruction.
+ session->windows[window_id] = new SessionWindow();
+ }
+ return session->windows[window_id];
+}
+
+void AddTabToSession(SyncedSession* session,
+ int window_id,
+ const std::string& url,
+ TimeDelta age) {
+ SerializedNavigationEntry navigation =
+ sessions::SerializedNavigationEntryTestHelper::CreateNavigation(url,
+ kTitle);
+
+ std::unique_ptr<SessionTab> tab = base::MakeUnique<SessionTab>();
+ tab->timestamp = Time::Now() - age;
+ tab->navigations.push_back(navigation);
+
+ SessionWindow* window = GetWindow(session, window_id);
+ // The window deletes the tabs it points at upon destruction.
+ window->tabs.push_back(tab.release());
+}
+
+class FakeTabsDelegate
+ : public sync_driver::OpenTabsUIDelegate,
tschumann 2016/09/16 13:33:20 do we actually need to implement this interface?
skym 2016/09/16 18:18:49 Done. Ended up removing OpenTabsUIDelegate from th
tschumann 2016/09/17 15:52:56 :-) I think so too!
+ public ForeignSessionsSuggestionsProvider::OpenTabsUIDelegateProvider {
+ public:
+ ~FakeTabsDelegate() override {}
+ void SetAllForeignSessions(std::vector<const SyncedSession*> sessions) {
+ sessions_ = sessions;
+ change_callback_.Run(this);
+ }
+
+ // OpenTabsUIDelegate implementation.
+ bool GetSyncedFaviconForPageURL(
+ const std::string& pageurl,
+ scoped_refptr<base::RefCountedMemory>* favicon_png) const override {
+ return false;
+ }
+ bool GetAllForeignSessions(
+ std::vector<const SyncedSession*>* sessions) override {
+ *sessions = sessions_;
+ return !sessions->empty();
+ }
+ bool GetForeignTab(const std::string& tag,
+ const SessionID::id_type tab_id,
+ const sessions::SessionTab** tab) override {
+ return false;
+ }
+ void DeleteForeignSession(const std::string& tag) override {}
+ bool GetForeignSession(
+ const std::string& tag,
+ std::vector<const sessions::SessionWindow*>* windows) override {
+ return false;
+ }
+ bool GetForeignSessionTabs(
+ const std::string& tag,
+ std::vector<const sessions::SessionTab*>* tabs) override {
+ return false;
+ }
+ bool GetLocalSession(const SyncedSession** local) override { return false; }
+
+ // OpenTabsUIDelegateProvider implementation.
+ sync_driver::OpenTabsUIDelegate* GetOpenTabsUIDelegate() override {
+ return this;
+ }
+ void SubscribeForForeignTabChange(
+ const OnChangeWithDelegate& change_callback) override {
+ change_callback_ = change_callback;
+ }
+
+ private:
+ std::vector<const SyncedSession*> sessions_;
+ OnChangeWithDelegate change_callback_;
+};
+} // namespace
+
+class ForeignSessionsSuggestionsProviderTest : public testing::Test {
+ public:
+ ForeignSessionsSuggestionsProviderTest()
+ : pref_service_(base::MakeUnique<TestingPrefServiceSimple>()) {
+ ForeignSessionsSuggestionsProvider::RegisterProfilePrefs(
+ pref_service_->registry());
+
+ std::unique_ptr<FakeTabsDelegate> delegate =
+ base::MakeUnique<FakeTabsDelegate>();
+ fake_tabs_delegate_ = delegate.get();
+
+ // During the provider's construction the follow mock calls occur.
Marc Treib 2016/09/16 12:26:48 nit: s/follow/following/
skym 2016/09/16 18:18:49 Done.
+ EXPECT_CALL(*observer(),
+ OnNewSuggestions(_, category(), testing::IsEmpty()));
Marc Treib 2016/09/16 12:26:49 nit: "testing::" not required, there's a "using" a
skym 2016/09/16 18:18:49 Done.
+ EXPECT_CALL(*observer(), OnCategoryStatusChanged(
+ _, category(), CategoryStatus::AVAILABLE));
+
+ provider_ = base::MakeUnique<ForeignSessionsSuggestionsProvider>(
+ &observer_, &category_factory_, std::move(delegate),
+ pref_service_.get());
+ }
+
+ protected:
+ SyncedSession* GetSession(int session_id) {
Marc Treib 2016/09/16 12:26:48 GotOrCreateSession?
skym 2016/09/16 18:18:49 Done.
+ if (sessions_map_.find(session_id) == sessions_map_.end()) {
+ std::string id_as_string = std::to_string(session_id);
Marc Treib 2016/09/16 12:26:48 Per https://chromium-cpp.appspot.com/, std::to_str
skym 2016/09/16 18:18:49 :( Done.
+ std::unique_ptr<SyncedSession> owned_session =
+ base::MakeUnique<SyncedSession>();
+ owned_session->session_tag = id_as_string;
+ owned_session->session_name = id_as_string;
+ sessions_map_[session_id] = std::move(owned_session);
+ }
+ return sessions_map_[session_id].get();
+ }
+
+ void AddTab(int session_id,
+ int window_id,
+ const std::string& url,
+ TimeDelta age) {
+ AddTabToSession(GetSession(session_id), window_id, url, age);
+ }
+
+ void TriggerOnChange() {
+ std::vector<const SyncedSession*> sessions;
+ for (const auto& kv : sessions_map_) {
+ sessions.push_back(kv.second.get());
+ }
+ fake_tabs_delegate_->SetAllForeignSessions(sessions);
+ }
+
+ void Dismiss(const std::string& url) {
Marc Treib 2016/09/16 12:26:48 s/url/id/ ?
skym 2016/09/16 18:18:49 So someone has to decide that to create a within_c
+ provider_->DismissSuggestion(provider_->MakeUniqueID(category(), url));
+ }
+
+ Category category() {
+ return category_factory_.FromKnownCategory(KnownCategories::FOREIGN_TABS);
+ }
+
+ MockContentSuggestionsProviderObserver* observer() { return &observer_; }
+
+ private:
+ FakeTabsDelegate* fake_tabs_delegate_;
+ MockContentSuggestionsProviderObserver observer_;
+ CategoryFactory category_factory_;
+ std::unique_ptr<TestingPrefServiceSimple> pref_service_;
Marc Treib 2016/09/16 12:26:48 I think this could just be an instance rather than
skym 2016/09/16 18:18:49 Done.
+ std::unique_ptr<ForeignSessionsSuggestionsProvider> provider_;
+ std::map<int, std::unique_ptr<SyncedSession>> sessions_map_;
+
+ DISALLOW_COPY_AND_ASSIGN(ForeignSessionsSuggestionsProviderTest);
+};
+
+TEST_F(ForeignSessionsSuggestionsProviderTest, Empty) {
+ EXPECT_CALL(*observer(), OnNewSuggestions(_, category(), testing::IsEmpty()));
+ TriggerOnChange();
+}
+
+TEST_F(ForeignSessionsSuggestionsProviderTest, Single) {
+ EXPECT_CALL(*observer(),
+ OnNewSuggestions(
+ _, category(),
+ ElementsAre(Property(&ContentSuggestion::url, GURL(kUrl1)))));
+ AddTab(0, 0, kUrl1, TimeDelta::FromMinutes(1));
+ TriggerOnChange();
+}
+
+TEST_F(ForeignSessionsSuggestionsProviderTest, Old) {
+ EXPECT_CALL(*observer(), OnNewSuggestions(_, category(), testing::IsEmpty()));
+ AddTab(0, 0, kUrl1, TimeDelta::FromHours(4));
+ TriggerOnChange();
+}
+
+TEST_F(ForeignSessionsSuggestionsProviderTest, Ordered) {
+ EXPECT_CALL(*observer(),
+ OnNewSuggestions(
+ _, category(),
+ ElementsAre(Property(&ContentSuggestion::url, GURL(kUrl1)),
+ Property(&ContentSuggestion::url, GURL(kUrl2)),
+ Property(&ContentSuggestion::url, GURL(kUrl3)),
+ Property(&ContentSuggestion::url, GURL(kUrl4)))));
+ AddTab(0, 0, kUrl2, TimeDelta::FromMinutes(2));
+ AddTab(0, 0, kUrl4, TimeDelta::FromMinutes(4));
+ AddTab(0, 1, kUrl3, TimeDelta::FromMinutes(3));
+ AddTab(1, 0, kUrl1, TimeDelta::FromMinutes(1));
+ TriggerOnChange();
+}
+
+TEST_F(ForeignSessionsSuggestionsProviderTest, MaxPerDevice) {
+ EXPECT_CALL(*observer(),
+ OnNewSuggestions(
+ _, category(),
+ ElementsAre(Property(&ContentSuggestion::url, GURL(kUrl1)),
+ Property(&ContentSuggestion::url, GURL(kUrl2)),
+ Property(&ContentSuggestion::url, GURL(kUrl3)))));
+ AddTab(0, 0, kUrl1, TimeDelta::FromMinutes(1));
+ AddTab(0, 0, kUrl2, TimeDelta::FromMinutes(2));
+ AddTab(0, 0, kUrl3, TimeDelta::FromMinutes(3));
+ AddTab(0, 0, kUrl4, TimeDelta::FromMinutes(4));
+ TriggerOnChange();
+}
+
+TEST_F(ForeignSessionsSuggestionsProviderTest, MaxTotal) {
+ EXPECT_CALL(
Marc Treib 2016/09/16 12:26:49 nit: I think all of these tests deserve a one-line
skym 2016/09/16 18:18:49 Done.
+ *observer(),
+ OnNewSuggestions(
+ _, category(),
+ ElementsAre(Property(&ContentSuggestion::url, GURL(kUrl1)),
+ Property(&ContentSuggestion::url, GURL(kUrl2)),
+ Property(&ContentSuggestion::url, GURL(kUrl3)),
+ Property(&ContentSuggestion::url, GURL(kUrl4)),
+ Property(&ContentSuggestion::url, GURL(kUrl5)),
+ Property(&ContentSuggestion::url, GURL(kUrl6)),
+ Property(&ContentSuggestion::url, GURL(kUrl7)),
+ Property(&ContentSuggestion::url, GURL(kUrl8)),
+ Property(&ContentSuggestion::url, GURL(kUrl9)),
+ Property(&ContentSuggestion::url, GURL(kUrl10)))));
+ AddTab(0, 0, kUrl1, TimeDelta::FromMinutes(1));
+ AddTab(0, 0, kUrl2, TimeDelta::FromMinutes(2));
+ AddTab(0, 0, kUrl3, TimeDelta::FromMinutes(3));
+ AddTab(1, 0, kUrl4, TimeDelta::FromMinutes(4));
+ AddTab(1, 0, kUrl5, TimeDelta::FromMinutes(5));
+ AddTab(1, 0, kUrl6, TimeDelta::FromMinutes(6));
+ AddTab(2, 0, kUrl7, TimeDelta::FromMinutes(7));
+ AddTab(2, 0, kUrl8, TimeDelta::FromMinutes(8));
+ AddTab(2, 0, kUrl9, TimeDelta::FromMinutes(9));
+ AddTab(3, 0, kUrl10, TimeDelta::FromMinutes(10));
+ AddTab(3, 0, kUrl11, TimeDelta::FromMinutes(11));
+ TriggerOnChange();
+}
+
+TEST_F(ForeignSessionsSuggestionsProviderTest, Duplicates) {
+ EXPECT_CALL(*observer(),
+ OnNewSuggestions(
+ _, category(),
+ ElementsAre(Property(&ContentSuggestion::url, GURL(kUrl1)))));
+ AddTab(0, 0, kUrl1, TimeDelta::FromMinutes(1));
+ AddTab(0, 1, kUrl1, TimeDelta::FromMinutes(2));
+ AddTab(1, 1, kUrl1, TimeDelta::FromMinutes(3));
+ TriggerOnChange();
+}
+
+TEST_F(ForeignSessionsSuggestionsProviderTest, DuplicatesChangingOtherSession) {
+ EXPECT_CALL(*observer(),
+ OnNewSuggestions(
+ _, category(),
+ ElementsAre(Property(&ContentSuggestion::url, GURL(kUrl3)),
+ Property(&ContentSuggestion::url, GURL(kUrl1)),
+ Property(&ContentSuggestion::url, GURL(kUrl2)),
+ Property(&ContentSuggestion::url, GURL(kUrl4)))));
+ AddTab(0, 0, kUrl1, TimeDelta::FromMinutes(1));
+ AddTab(0, 0, kUrl2, TimeDelta::FromMinutes(2));
+ AddTab(0, 0, kUrl3, TimeDelta::FromMinutes(3));
+ // Normally |kUrl4| wouldn't show up, because session_id=0 already has 3
+ // younger tabs, but session_id=1 has a younger |kUrl3| which gives |kUrl4| a
+ // spot.
+ AddTab(0, 0, kUrl4, TimeDelta::FromMinutes(4));
+ AddTab(1, 0, kUrl3, TimeDelta::FromMinutes(0));
+ TriggerOnChange();
+}
+
+TEST_F(ForeignSessionsSuggestionsProviderTest, Dismissed) {
+ EXPECT_CALL(*observer(), OnNewSuggestions(_, category(), testing::IsEmpty()));
+ Dismiss(kUrl1);
+ AddTab(0, 0, kUrl1, TimeDelta::FromMinutes(1));
+ TriggerOnChange();
+}
+
+TEST_F(ForeignSessionsSuggestionsProviderTest, DismissedChangingOwnSession) {
+ EXPECT_CALL(*observer(),
+ OnNewSuggestions(
+ _, category(),
+ ElementsAre(Property(&ContentSuggestion::url, GURL(kUrl2)),
+ Property(&ContentSuggestion::url, GURL(kUrl3)),
+ Property(&ContentSuggestion::url, GURL(kUrl5)))));
+ Dismiss(kUrl1);
+ Dismiss(kUrl4);
+ AddTab(0, 0, kUrl1, TimeDelta::FromMinutes(1));
+ AddTab(0, 0, kUrl2, TimeDelta::FromMinutes(2));
+ AddTab(0, 0, kUrl3, TimeDelta::FromMinutes(3));
+ AddTab(0, 0, kUrl4, TimeDelta::FromMinutes(4));
+ AddTab(0, 0, kUrl5, TimeDelta::FromMinutes(5));
+ AddTab(0, 0, kUrl6, TimeDelta::FromMinutes(6));
+ TriggerOnChange();
+}
+
+} // namespace ntp_snippets

Powered by Google App Engine
This is Rietveld 408576698