1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146
|
// 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/bookmarks/bookmark_suggestions_provider.h"
#include <memory>
#include <string>
#include <utility>
#include "base/bind.h"
#include "base/macros.h"
#include "base/memory/ptr_util.h"
#include "base/strings/utf_string_conversions.h"
#include "components/bookmarks/browser/bookmark_model.h"
#include "components/bookmarks/browser/bookmark_node.h"
#include "components/bookmarks/test/test_bookmark_client.h"
#include "components/ntp_snippets/bookmarks/bookmark_last_visit_utils.h"
#include "components/ntp_snippets/category.h"
#include "components/ntp_snippets/mock_content_suggestions_provider_observer.h"
#include "components/prefs/testing_pref_service.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "url/gurl.h"
namespace ntp_snippets {
namespace {
using ::testing::StrictMock;
using ::testing::_;
using ::testing::Eq;
using ::testing::IsEmpty;
using ::testing::Property;
using ::testing::UnorderedElementsAre;
class BookmarkSuggestionsProviderTest : public ::testing::Test {
public:
BookmarkSuggestionsProviderTest()
: model_(bookmarks::TestBookmarkClient::CreateModel()) {
EXPECT_CALL(observer_, OnNewSuggestions(_, Category::FromKnownCategory(
KnownCategories::BOOKMARKS),
IsEmpty()))
.RetiresOnSaturation();
EXPECT_CALL(observer_,
OnCategoryStatusChanged(
_, Category::FromKnownCategory(KnownCategories::BOOKMARKS),
CategoryStatus::AVAILABLE_LOADING))
.RetiresOnSaturation();
EXPECT_CALL(observer_,
OnCategoryStatusChanged(
_, Category::FromKnownCategory(KnownCategories::BOOKMARKS),
CategoryStatus::AVAILABLE))
.RetiresOnSaturation();
BookmarkSuggestionsProvider::RegisterProfilePrefs(test_prefs_.registry());
provider_ = base::MakeUnique<BookmarkSuggestionsProvider>(
&observer_, model_.get(), &test_prefs_);
}
protected:
std::unique_ptr<bookmarks::BookmarkModel> model_;
StrictMock<MockContentSuggestionsProviderObserver> observer_;
TestingPrefServiceSimple test_prefs_;
std::unique_ptr<BookmarkSuggestionsProvider> provider_;
};
TEST_F(BookmarkSuggestionsProviderTest,
ShouldProvideBookmarkSuggestions) {
GURL url("http://my-new-bookmarked.url");
// Note, this update to the model does not trigger OnNewSuggestions() on the
// observer as the provider realizes no new nodes were added.
// don't have new data.
model_->AddURL(model_->bookmark_bar_node(), 0,
base::ASCIIToUTF16("cool page's title"), url);
// Once we provided the last-visited meta information, an update with the
// suggestion containing the bookmark should follow.
EXPECT_CALL(
observer_,
OnNewSuggestions(
_, Category::FromKnownCategory(KnownCategories::BOOKMARKS),
UnorderedElementsAre(Property(&ContentSuggestion::url, GURL(url)))));
UpdateBookmarkOnURLVisitedInMainFrame(model_.get(), url,
/*is_mobile_platform=*/true);
}
TEST_F(BookmarkSuggestionsProviderTest,
ShouldEnsureToBeClearedBookmarksDontAppearAfterClear) {
// Set up the provider with 2 entries: one dismissed and one active.
// Add one bookmark (the one to be not dismissed) -- this will trigger a
// notification.
GURL active_bookmark("http://my-active-bookmarked.url");
EXPECT_CALL(observer_,
OnNewSuggestions(
_, Category::FromKnownCategory(KnownCategories::BOOKMARKS),
UnorderedElementsAre(Property(&ContentSuggestion::url,
GURL(active_bookmark)))));
model_->AddURL(model_->bookmark_bar_node(), 0,
base::ASCIIToUTF16("cool page's title"), active_bookmark);
UpdateBookmarkOnURLVisitedInMainFrame(model_.get(), active_bookmark,
/*is_mobile_platform=*/true);
// Add the other bookmark -- this will trigger another notification. Then
// marks it was dismissed.
GURL dismissed_bookmark("http://my-dismissed-bookmark.url");
EXPECT_CALL(
observer_,
OnNewSuggestions(
_, Category::FromKnownCategory(KnownCategories::BOOKMARKS),
UnorderedElementsAre(
Property(&ContentSuggestion::url, GURL(active_bookmark)),
Property(&ContentSuggestion::url, GURL(dismissed_bookmark)))));
const bookmarks::BookmarkNode* dismissed_node = model_->AddURL(
model_->bookmark_bar_node(), 1, base::ASCIIToUTF16("cool page's title"),
dismissed_bookmark);
UpdateBookmarkOnURLVisitedInMainFrame(model_.get(), dismissed_bookmark,
/*is_mobile_platform=*/true);
// According to the ContentSugestionsProvider contract, solely dismissing an
// item should not result in another OnNewSuggestions() call.
static_cast<ContentSuggestionsProvider*>(provider_.get())
->DismissSuggestion(ContentSuggestion::ID(
Category::FromKnownCategory(KnownCategories::BOOKMARKS),
dismissed_bookmark.spec()));
EXPECT_THAT(IsDismissedFromNTPForBookmark(*dismissed_node), Eq(true));
// Clear history and make sure the suggestions actually get removed.
EXPECT_CALL(observer_, OnNewSuggestions(_, Category::FromKnownCategory(
KnownCategories::BOOKMARKS),
IsEmpty()));
static_cast<ContentSuggestionsProvider*>(provider_.get())
->ClearHistory(base::Time(), base::Time::Max(),
base::Bind([] (const GURL& url) { return true; }));
// Verify the dismissed marker is gone.
EXPECT_THAT(IsDismissedFromNTPForBookmark(*dismissed_node), Eq(false));
}
// TODO(tschumann): There are plenty of test cases missing. Most importantly:
// -- Remove a bookmark from the model
// -- verifying handling of threshold time
// -- dealing with fetches before the model is loaded.
} // namespace
} // namespace ntp_snippets
|