| 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..421a9f545571ba8c9f37e44e46ba9cf7bf3a8091
|
| --- /dev/null
|
| +++ b/chrome/browser/ui/app_list/search/answer_card/answer_card_search_provider_unittest.cc
|
| @@ -0,0 +1,333 @@
|
| +// 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 <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"
|
| +#include "ui/views/view.h"
|
| +
|
| +using ::testing::_;
|
| +using ::testing::Return;
|
| +using ::testing::ReturnRef;
|
| +
|
| +namespace app_list {
|
| +namespace test {
|
| +
|
| +namespace {
|
| +
|
| +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());
|
| +
|
| + testing::Mock::VerifyAndClearExpectations(contents());
|
| + testing::Mock::VerifyAndClearExpectations(navigation_handle());
|
| + }
|
| +
|
| + 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();
|
| + }
|
| +
|
| + views::View* view() { return &view_; }
|
| +
|
| + // 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_);
|
| + // 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(view()));
|
| + }
|
| +
|
| + 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_;
|
| + views::View view_;
|
| +
|
| + 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(view(), 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(view(), 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(view(), 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
|
|
|