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

Unified Diff: chrome/browser/ui/app_list/search/answer_card/answer_card_search_provider_unittest.cc

Issue 2947283002: Unit-testing AnswerCardSearchProvider. (Closed)
Patch Set: Created 3 years, 6 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: chrome/browser/ui/app_list/search/answer_card/answer_card_search_provider_unittest.cc
diff --git a/chrome/browser/ui/app_list/search/answer_card/answer_card_search_provider_unittest.cc b/chrome/browser/ui/app_list/search/answer_card/answer_card_search_provider_unittest.cc
new file mode 100644
index 0000000000000000000000000000000000000000..f375d217a5e5bfd9c9b25fb6466c6e7203acccb6
--- /dev/null
+++ b/chrome/browser/ui/app_list/search/answer_card/answer_card_search_provider_unittest.cc
@@ -0,0 +1,329 @@
+// Copyright 2013 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/ui/app_list/search/app_search_provider.h"
+
+#include <stddef.h>
+
+#include <memory>
+#include <string>
+#include <utility>
+
+#include "base/macros.h"
+#include "base/metrics/field_trial.h"
+#include "base/metrics/field_trial_params.h"
+#include "base/strings/utf_string_conversions.h"
+#include "base/test/scoped_feature_list.h"
+#include "chrome/browser/ui/app_list/app_list_test_util.h"
+#include "chrome/browser/ui/app_list/search/answer_card/answer_card_search_provider.h"
+#include "chrome/browser/ui/app_list/test/test_app_list_controller_delegate.h"
+#include "chrome/test/base/testing_profile.h"
+#include "content/test/mock_navigation_handle.h"
+#include "net/http/http_response_headers.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "ui/app_list/app_list_features.h"
+#include "ui/app_list/app_list_model.h"
+#include "ui/app_list/search_result.h"
+
+using ::testing::_;
+using ::testing::Return;
+using ::testing::ReturnRef;
+
+namespace app_list {
+namespace test {
+
+namespace {
+
+views::View* const kView = reinterpret_cast<views::View*>(123456);
xiyuan 2017/06/22 16:43:21 Can we create a real views::View owned by AnswerCa
vadimt 2017/06/22 19:48:03 Done.
+constexpr char kCatCardId[] = "http://meow.org/meow";
+constexpr char kCatCardTitle[] = "Cat is a furry beast.";
+
+class MockAnswerCardContents : public AnswerCardContents {
+ public:
+ MockAnswerCardContents() {}
+
+ // AnswerCardContents overrides:
+ MOCK_METHOD1(LoadURL, void(const GURL& url));
+ MOCK_CONST_METHOD0(IsLoading, bool());
+ MOCK_METHOD0(GetView, views::View*());
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(MockAnswerCardContents);
+};
+
+gfx::Size GetMaxValidCardSize() {
+ return gfx::Size(features::AnswerCardMaxWidth(),
+ features::AnswerCardMaxHeight());
+}
+
+} // namespace
+
+class AnswerCardSearchProviderTest : public AppListTestBase {
+ public:
+ AnswerCardSearchProviderTest() : field_trial_list_(nullptr) {}
+
+ void SetMockHeaders(std::string has_result,
+ std::string open_url,
+ std::string title) {
+ headers_->RemoveHeader("SearchAnswer-HasResult");
+ headers_->RemoveHeader("SearchAnswer-OpenResultUrl");
+ headers_->RemoveHeader("SearchAnswer-Title");
+
+ if (!has_result.empty())
+ headers_->AddHeader("SearchAnswer-HasResult: " + has_result);
+ if (!open_url.empty())
+ headers_->AddHeader("SearchAnswer-OpenResultUrl: " + open_url);
+ if (!title.empty())
+ headers_->AddHeader("SearchAnswer-Title: " + title);
+ }
+
+ void TestHeadersParsing(std::string has_result,
+ std::string open_url,
+ std::string title,
+ std::size_t expected_result_count) {
+ SetMockHeaders(has_result, open_url, title);
+
+ EXPECT_CALL(*contents(), LoadURL(GURL("http://beasts.org/search?q=cat")));
+ provider()->Start(false, base::UTF8ToUTF16("cat"));
+
+ GURL url("http://beasts.org/search?q=cat");
+ EXPECT_CALL(*navigation_handle_.get(), GetURL()).WillOnce(ReturnRef(url));
+ provider()->DidFinishNavigation(navigation_handle_.get());
+
+ provider()->DidStopLoading();
+ provider()->UpdatePreferredSize(GetMaxValidCardSize());
+
+ EXPECT_EQ(expected_result_count, results().size());
xiyuan 2017/06/22 16:43:21 We might need a testing::Mock::VerifyAndClearE
vadimt 2017/06/22 19:48:03 Done.
+ }
+
+ AppListModel* model() const { return model_.get(); }
+
+ const SearchProvider::Results& results() { return provider()->results(); }
+
+ MockAnswerCardContents* contents() const { return contents_; }
+
+ AnswerCardSearchProvider* provider() const { return provider_.get(); }
+
+ content::MockNavigationHandle* navigation_handle() const {
+ return navigation_handle_.get();
+ }
+
+ // AppListTestBase overrides:
+ void SetUp() override {
+ AppListTestBase::SetUp();
+
+ model_ = base::MakeUnique<app_list::AppListModel>();
+ model_->SetSearchEngineIsGoogle(true);
+
+ controller_ = base::MakeUnique<::test::TestAppListControllerDelegate>();
+
+ // Set up card server URL.
+ std::map<std::string, std::string> params;
+ params["ServerUrl"] = "http://beasts.org/search";
+ base::AssociateFieldTrialParams("TestTrial", "TestGroup", params);
+ scoped_refptr<base::FieldTrial> trial =
+ base::FieldTrialList::CreateFieldTrial("TestTrial", "TestGroup");
+ std::unique_ptr<base::FeatureList> feature_list =
+ base::MakeUnique<base::FeatureList>();
+ feature_list->RegisterFieldTrialOverride(
+ features::kEnableAnswerCard.name,
+ base::FeatureList::OVERRIDE_ENABLE_FEATURE, trial.get());
+ scoped_feature_list_.InitWithFeatureList(std::move(feature_list));
+
+ contents_ = new MockAnswerCardContents;
+ std::unique_ptr<AnswerCardContents> contents(contents_);
xiyuan 2017/06/22 16:43:22 Would presubmit script complains about using std::
vadimt 2017/06/22 19:48:03 No, presubmit is fine.
+ // Provider will own the MockAnswerCardContents instance.
+ provider_ = base::MakeUnique<AnswerCardSearchProvider>(
+ profile_.get(), model_.get(), nullptr, std::move(contents));
+
+ headers_ = new net::HttpResponseHeaders("");
+ SetMockHeaders("true", kCatCardId, kCatCardTitle);
+
+ navigation_handle_ = base::MakeUnique<content::MockNavigationHandle>();
+ ON_CALL(*navigation_handle_.get(), HasCommitted())
+ .WillByDefault(Return(true));
+ ON_CALL(*navigation_handle_.get(), IsErrorPage())
+ .WillByDefault(Return(false));
+ ON_CALL(*navigation_handle_.get(), IsInMainFrame())
+ .WillByDefault(Return(true));
+ ON_CALL(*navigation_handle_.get(), GetResponseHeaders())
+ .WillByDefault(Return(headers_.get()));
+
+ ON_CALL(*contents_, GetView()).WillByDefault(Return(kView));
+ }
+
+ private:
+ std::unique_ptr<app_list::AppListModel> model_;
+ std::unique_ptr<AnswerCardSearchProvider> provider_;
+ std::unique_ptr<::test::TestAppListControllerDelegate> controller_;
+ MockAnswerCardContents* contents_ = nullptr; // Unowned.
+ base::FieldTrialList field_trial_list_;
+ base::test::ScopedFeatureList scoped_feature_list_;
+ scoped_refptr<net::HttpResponseHeaders> headers_;
+ std::unique_ptr<content::MockNavigationHandle> navigation_handle_;
+
+ DISALLOW_COPY_AND_ASSIGN(AnswerCardSearchProviderTest);
+};
+
+// Basic event sequence.
+TEST_F(AnswerCardSearchProviderTest, Basic) {
+ EXPECT_CALL(*contents(), LoadURL(GURL("http://beasts.org/search?q=cat")));
+ provider()->Start(false, base::UTF8ToUTF16("cat"));
+ GURL url("http://beasts.org/search?q=cat");
+ EXPECT_CALL(*navigation_handle(), GetURL()).WillOnce(ReturnRef(url));
+ provider()->DidFinishNavigation(navigation_handle());
+ provider()->DidStopLoading();
+ provider()->UpdatePreferredSize(GetMaxValidCardSize());
+
+ EXPECT_EQ(1UL, results().size());
+ SearchResult* result = results()[0].get();
+ EXPECT_EQ(SearchResult::DISPLAY_CARD, result->display_type());
+ EXPECT_EQ(kCatCardId, result->id());
+ EXPECT_EQ(1, result->relevance());
+ EXPECT_EQ(kView, result->view());
+ EXPECT_EQ(base::UTF8ToUTF16(kCatCardTitle), result->title());
+}
+
+// Voice queries are ignored.
+TEST_F(AnswerCardSearchProviderTest, VoiceQuery) {
+ EXPECT_CALL(*contents(), LoadURL(_)).Times(0);
+ provider()->Start(true, base::UTF8ToUTF16("cat"));
+}
+
+// Queries to non-Google search engines are ignored.
+TEST_F(AnswerCardSearchProviderTest, NotGoogle) {
+ model()->SetSearchEngineIsGoogle(false);
+ EXPECT_CALL(*contents(), LoadURL(_)).Times(0);
+ provider()->Start(false, base::UTF8ToUTF16("cat"));
+}
+
+// Zero-query is ignored.
+TEST_F(AnswerCardSearchProviderTest, EmptyQuery) {
+ EXPECT_CALL(*contents(), LoadURL(_)).Times(0);
+ provider()->Start(false, base::UTF8ToUTF16(""));
+}
+
+// Two queries, the second produces a card of exactly same size, so
+// UpdatePreferredSize() doesn't come. The second query should still produce a
+// result.
+TEST_F(AnswerCardSearchProviderTest, TwoResultsSameSize) {
+ EXPECT_CALL(*contents(), LoadURL(GURL("http://beasts.org/search?q=cat")));
+ provider()->Start(false, base::UTF8ToUTF16("cat"));
+ GURL url("http://beasts.org/search?q=cat");
+ EXPECT_CALL(*navigation_handle(), GetURL()).WillOnce(ReturnRef(url));
+ provider()->DidFinishNavigation(navigation_handle());
+ provider()->DidStopLoading();
+ provider()->UpdatePreferredSize(GetMaxValidCardSize());
+
+ EXPECT_EQ(1UL, results().size());
+ SearchResult* result = results()[0].get();
+ EXPECT_EQ(SearchResult::DISPLAY_CARD, result->display_type());
+ EXPECT_EQ(kCatCardId, result->id());
+ EXPECT_EQ(1, result->relevance());
+ EXPECT_EQ(kView, result->view());
+ EXPECT_EQ(base::UTF8ToUTF16(kCatCardTitle), result->title());
+
+ EXPECT_CALL(*contents(), LoadURL(GURL("http://beasts.org/search?q=dog")));
+ provider()->Start(false, base::UTF8ToUTF16("dog"));
+ EXPECT_EQ(0UL, results().size());
+
+ url = GURL("http://beasts.org/search?q=dog");
+ EXPECT_CALL(*navigation_handle(), GetURL()).WillOnce(ReturnRef(url));
+ SetMockHeaders("true", "http://woof.org/woof", "Dog is a friendly beast.");
+ provider()->DidFinishNavigation(navigation_handle());
+ provider()->DidStopLoading();
+ // No UpdatePreferredSize().
+
+ EXPECT_EQ(1UL, results().size());
+ result = results()[0].get();
+ EXPECT_EQ(SearchResult::DISPLAY_CARD, result->display_type());
+ EXPECT_EQ("http://woof.org/woof", result->id());
+ EXPECT_EQ(1, result->relevance());
+ EXPECT_EQ(kView, result->view());
+ EXPECT_EQ(base::UTF8ToUTF16("Dog is a friendly beast."), result->title());
+}
+
+// User enters a query character by character, so that each next query generates
+// a web request while the previous one is still in progress. Only the last
+// query should produce a result.
+TEST_F(AnswerCardSearchProviderTest, InterruptedRequest) {
+ EXPECT_CALL(*contents(), LoadURL(GURL("http://beasts.org/search?q=c")));
+ provider()->Start(false, base::UTF8ToUTF16("c"));
+ EXPECT_EQ(0UL, results().size());
+
+ EXPECT_CALL(*contents(), LoadURL(GURL("http://beasts.org/search?q=ca")));
+ provider()->Start(false, base::UTF8ToUTF16("ca"));
+ EXPECT_EQ(0UL, results().size());
+
+ EXPECT_CALL(*contents(), LoadURL(GURL("http://beasts.org/search?q=cat")));
+ provider()->Start(false, base::UTF8ToUTF16("cat"));
+ EXPECT_EQ(0UL, results().size());
+
+ SetMockHeaders("true", "http://c-meow", "Title c");
+ GURL url = GURL("http://beasts.org/search?q=c");
+ EXPECT_CALL(*navigation_handle(), GetURL()).WillOnce(ReturnRef(url));
+ provider()->DidFinishNavigation(navigation_handle());
+ provider()->DidStopLoading();
+ EXPECT_EQ(0UL, results().size());
+
+ SetMockHeaders("true", "http://ca-meow", "Title ca");
+ url = GURL("http://beasts.org/search?q=ca");
+ EXPECT_CALL(*navigation_handle(), GetURL()).WillOnce(ReturnRef(url));
+ provider()->DidFinishNavigation(navigation_handle());
+ provider()->DidStopLoading();
+ provider()->UpdatePreferredSize(gfx::Size(1, 1));
+ EXPECT_EQ(0UL, results().size());
+
+ SetMockHeaders("true", kCatCardId, kCatCardTitle);
+ url = GURL("http://beasts.org/search?q=cat");
+ EXPECT_CALL(*navigation_handle(), GetURL()).WillOnce(ReturnRef(url));
+ provider()->DidFinishNavigation(navigation_handle());
+ provider()->DidStopLoading();
+ provider()->UpdatePreferredSize(GetMaxValidCardSize());
+ EXPECT_EQ(1UL, results().size());
+
+ SearchResult* result = results()[0].get();
+ EXPECT_EQ(SearchResult::DISPLAY_CARD, result->display_type());
+ EXPECT_EQ(kCatCardId, result->id());
+ EXPECT_EQ(base::UTF8ToUTF16(kCatCardTitle), result->title());
+}
+
+// Due to, for example, JS activity in the card, it can change its size after
+// loading. We should hide the result while its size if larger than the allowed
+// maximum.
+TEST_F(AnswerCardSearchProviderTest, ChangingSize) {
+ EXPECT_CALL(*contents(), LoadURL(GURL("http://beasts.org/search?q=cat")));
+ provider()->Start(false, base::UTF8ToUTF16("cat"));
+ GURL url("http://beasts.org/search?q=cat");
+ EXPECT_CALL(*navigation_handle(), GetURL()).WillOnce(ReturnRef(url));
+ provider()->DidFinishNavigation(navigation_handle());
+ provider()->UpdatePreferredSize(gfx::Size(features::AnswerCardMaxWidth() + 1,
+ features::AnswerCardMaxHeight()));
+ provider()->DidStopLoading();
+ EXPECT_EQ(0UL, results().size());
+
+ provider()->UpdatePreferredSize(GetMaxValidCardSize());
+ EXPECT_EQ(1UL, results().size());
+
+ provider()->UpdatePreferredSize(gfx::Size(
+ features::AnswerCardMaxWidth(), features::AnswerCardMaxHeight() + 1));
+ EXPECT_EQ(0UL, results().size());
+
+ provider()->UpdatePreferredSize(GetMaxValidCardSize());
+ EXPECT_EQ(1UL, results().size());
+}
+
+// The result is generated only when all headers exist, and indicate presence of
+// the result.
+TEST_F(AnswerCardSearchProviderTest, Headers) {
+ TestHeadersParsing("true", kCatCardId, kCatCardTitle, 1UL);
+ TestHeadersParsing("false", kCatCardId, kCatCardTitle, 0UL);
+ TestHeadersParsing("", kCatCardId, kCatCardTitle, 0UL);
+ TestHeadersParsing("true", "", kCatCardTitle, 0UL);
+ TestHeadersParsing("true", kCatCardId, "", 0UL);
+ TestHeadersParsing("true", kCatCardId, kCatCardTitle, 1UL);
+}
+
+} // namespace test
+} // namespace app_list

Powered by Google App Engine
This is Rietveld 408576698