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

Side by Side Diff: components/omnibox/browser/physical_web_provider_unittest.cc

Issue 2319033006: Include a page title in the Physical Web omnibox overflow item (Closed)
Patch Set: changes for mpearson@, refactor unit tests 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 unified diff | Download patch
OLDNEW
1 // Copyright 2016 The Chromium Authors. All rights reserved. 1 // Copyright 2016 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "components/omnibox/browser/physical_web_provider.h" 5 #include "components/omnibox/browser/physical_web_provider.h"
6 6
7 #include <memory> 7 #include <memory>
8 #include <string> 8 #include <string>
9 9
10 #include "base/memory/ptr_util.h" 10 #include "base/memory/ptr_util.h"
11 #include "base/strings/string_number_conversions.h" 11 #include "base/strings/string_number_conversions.h"
12 #include "base/strings/utf_string_conversions.h" 12 #include "base/strings/utf_string_conversions.h"
13 #include "base/values.h" 13 #include "base/values.h"
14 #include "components/metrics/proto/omnibox_event.pb.h" 14 #include "components/metrics/proto/omnibox_event.pb.h"
15 #include "components/omnibox/browser/mock_autocomplete_provider_client.h" 15 #include "components/omnibox/browser/mock_autocomplete_provider_client.h"
16 #include "components/omnibox/browser/test_scheme_classifier.h" 16 #include "components/omnibox/browser/test_scheme_classifier.h"
17 #include "components/physical_web/data_source/physical_web_data_source.h" 17 #include "components/physical_web/data_source/physical_web_data_source.h"
18 #include "components/physical_web/data_source/physical_web_listener.h" 18 #include "components/physical_web/data_source/physical_web_listener.h"
19 #include "grit/components_strings.h" 19 #include "grit/components_strings.h"
20 #include "testing/gmock/include/gmock/gmock.h" 20 #include "testing/gmock/include/gmock/gmock.h"
21 #include "testing/gtest/include/gtest/gtest.h" 21 #include "testing/gtest/include/gtest/gtest.h"
22 #include "ui/base/l10n/l10n_util.h" 22 #include "ui/base/l10n/l10n_util.h"
23 #include "ui/gfx/text_elider.h"
23 #include "url/gurl.h" 24 #include "url/gurl.h"
24 25
25 namespace { 26 namespace {
26 27
27 // A mock implementation of the Physical Web data source that allows setting 28 // A mock implementation of the Physical Web data source that allows setting
28 // metadata for nearby URLs directly. 29 // metadata for nearby URLs directly.
29 class MockPhysicalWebDataSource : public PhysicalWebDataSource { 30 class MockPhysicalWebDataSource : public PhysicalWebDataSource {
30 public: 31 public:
31 MockPhysicalWebDataSource() : metadata_(new base::ListValue()) {} 32 MockPhysicalWebDataSource() : metadata_(new base::ListValue()) {}
32 ~MockPhysicalWebDataSource() override {} 33 ~MockPhysicalWebDataSource() override {}
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after
77 // Convenience method to avoid downcasts when accessing the mock data source. 78 // Convenience method to avoid downcasts when accessing the mock data source.
78 MockPhysicalWebDataSource* GetMockPhysicalWebDataSource() { 79 MockPhysicalWebDataSource* GetMockPhysicalWebDataSource() {
79 return physical_web_data_source_.get(); 80 return physical_web_data_source_.get();
80 } 81 }
81 82
82 private: 83 private:
83 std::unique_ptr<MockPhysicalWebDataSource> physical_web_data_source_; 84 std::unique_ptr<MockPhysicalWebDataSource> physical_web_data_source_;
84 TestSchemeClassifier scheme_classifier_; 85 TestSchemeClassifier scheme_classifier_;
85 }; 86 };
86 87
88 } // namespace
89
87 class PhysicalWebProviderTest : public testing::Test { 90 class PhysicalWebProviderTest : public testing::Test {
88 protected: 91 protected:
89 PhysicalWebProviderTest() : provider_(NULL) {} 92 PhysicalWebProviderTest() : provider_(NULL) {}
90 ~PhysicalWebProviderTest() override {} 93 ~PhysicalWebProviderTest() override {}
91 94
92 void SetUp() override { 95 void SetUp() override {
93 client_.reset(new FakeAutocompleteProviderClient()); 96 client_.reset(new FakeAutocompleteProviderClient());
94 provider_ = PhysicalWebProvider::Create(client_.get(), nullptr); 97 provider_ = PhysicalWebProvider::Create(client_.get(), nullptr);
95 } 98 }
96 99
(...skipping 25 matching lines...) Expand all
122 static AutocompleteInput CreateInputForNTP() { 125 static AutocompleteInput CreateInputForNTP() {
123 return AutocompleteInput( 126 return AutocompleteInput(
124 base::string16(), base::string16::npos, std::string(), GURL(), 127 base::string16(), base::string16::npos, std::string(), GURL(),
125 metrics::OmniboxEventProto::INSTANT_NTP_WITH_OMNIBOX_AS_STARTING_FOCUS, 128 metrics::OmniboxEventProto::INSTANT_NTP_WITH_OMNIBOX_AS_STARTING_FOCUS,
126 false, false, true, true, true, TestSchemeClassifier()); 129 false, false, true, true, true, TestSchemeClassifier());
127 } 130 }
128 131
129 // Construct an AutocompleteInput to represent tapping the omnibox with |url| 132 // Construct an AutocompleteInput to represent tapping the omnibox with |url|
130 // as the current web page. 133 // as the current web page.
131 static AutocompleteInput CreateInputWithCurrentUrl(const std::string& url) { 134 static AutocompleteInput CreateInputWithCurrentUrl(const std::string& url) {
132 return AutocompleteInput(base::ASCIIToUTF16(url), base::string16::npos, 135 return AutocompleteInput(base::UTF8ToUTF16(url), base::string16::npos,
Mark P 2016/09/13 23:34:43 side comment: URLs are in ASCII as far as I know.
mattreynolds 2016/09/14 19:04:41 Acknowledged.
133 std::string(), GURL(url), 136 std::string(), GURL(url),
134 metrics::OmniboxEventProto::OTHER, false, false, 137 metrics::OmniboxEventProto::OTHER, false, false,
135 true, true, true, TestSchemeClassifier()); 138 true, true, true, TestSchemeClassifier());
136 } 139 }
137 140
141 // For a given |match|, check that the destination URL, contents string,
142 // description string, and default match state agree with the values specified
143 // in |url|, |contents|, |description|, and |allowed_to_be_default_match|.
144 static void ValidateMatch(const AutocompleteMatch& match,
145 const std::string& url,
146 const std::string& contents,
147 const std::string& description,
148 bool allowed_to_be_default_match) {
149 EXPECT_EQ(url, match.destination_url.spec());
150 EXPECT_EQ(contents, base::UTF16ToUTF8(match.contents));
151 EXPECT_EQ(description, base::UTF16ToUTF8(match.description));
152 EXPECT_EQ(allowed_to_be_default_match, match.allowed_to_be_default_match);
153 }
154
155 // Construct the contents string for an overflow item. Use |truncated_title|
Mark P 2016/09/13 23:34:43 nit: Constructs -> Returns
mattreynolds 2016/09/14 19:04:41 Done.
156 // as the title of the first match, |match_count_without_default| as the
157 // total number of matches (not counting the default match), and
158 // |metadata_count| as the number of nearby Physical Web URLs for which we
159 // have metadata.
160 static std::string ConstructOverflowItemContents(
161 const std::string& truncated_title,
162 size_t match_count_without_default,
163 size_t metadata_count) {
164 // Don't treat the overflow item as a metadata match.
165 const size_t metadata_match_count = match_count_without_default - 1;
166 // Determine how many URLs we didn't create match items for.
167 const size_t additional_url_count = metadata_count - metadata_match_count;
168
169 // Build the contents string.
170 if (truncated_title.empty()) {
171 return l10n_util::GetPluralStringFUTF8(
172 IDS_PHYSICAL_WEB_OVERFLOW_EMPTY_TITLE, additional_url_count);
173 } else {
174 // Subtract one from the additional URL count because the first item is
175 // represented by its title.
176 std::string contents_suffix = l10n_util::GetPluralStringFUTF8(
177 IDS_PHYSICAL_WEB_OVERFLOW, additional_url_count - 1);
178 return truncated_title + " " + contents_suffix;
179 }
180 }
181
182 // Run a test case using |input| as the simulated state of the omnibox input
183 // field, |metadata_list| as the list of simulated Physical Web metadata,
184 // and |title_truncated| as the truncated title of the first match. This will
185 // check for the presence of default matches and overflow items, as well as
186 // checking the fields of the overflow item. Metadata matches are not checked.
187 void OverflowItemTestCase(const AutocompleteInput& input,
Mark P 2016/09/13 23:34:43 I'm a bit nervous about this function. Rather tha
mattreynolds 2016/09/14 19:04:41 I removed the logic for computing the number of ma
188 std::unique_ptr<base::ListValue> metadata_list,
189 const std::string& title_truncated) {
190 const size_t metadata_count = metadata_list->GetSize();
191
192 const bool should_expect_default_match = !input.text().empty();
193
194 // The actual threshold for creating an overflow item may be lower than
195 // kMaxMatches, but for testing we always create enough metadata items to
196 // exceed the AutocompleteProvider's limit to ensure the overflow item is
197 // created.
198 const bool should_expect_overflow_item =
199 (metadata_count > AutocompleteProvider::kMaxMatches);
200
201 MockPhysicalWebDataSource* data_source =
202 client_->GetMockPhysicalWebDataSource();
203 EXPECT_TRUE(data_source);
204
205 data_source->SetMetadata(std::move(metadata_list));
206
207 provider_->Start(input, false);
208
209 const size_t match_count = provider_->matches().size();
210 const size_t match_count_without_default =
211 should_expect_default_match ? match_count - 1 : match_count;
212
213 if (should_expect_overflow_item) {
214 EXPECT_LT(match_count_without_default, metadata_count);
215 } else {
216 EXPECT_EQ(match_count_without_default, metadata_count);
217 }
218
219 size_t overflow_match_count = 0;
220 size_t default_match_count = 0;
221 for (const auto& match : provider_->matches()) {
222 if (match.type == AutocompleteMatchType::PHYSICAL_WEB_OVERFLOW) {
223 std::string contents = ConstructOverflowItemContents(
224 title_truncated, match_count_without_default, metadata_count);
225 ValidateMatch(
226 match, "chrome://physical-web/", contents,
227 l10n_util::GetStringUTF8(IDS_PHYSICAL_WEB_OVERFLOW_DESCRIPTION),
228 false);
229 ++overflow_match_count;
230 } else if (match.allowed_to_be_default_match) {
231 ++default_match_count;
232 }
233 }
234 EXPECT_EQ(should_expect_overflow_item ? 1U : 0U, overflow_match_count);
235 EXPECT_EQ(should_expect_default_match ? 1U : 0U, default_match_count);
236 }
237
138 std::unique_ptr<FakeAutocompleteProviderClient> client_; 238 std::unique_ptr<FakeAutocompleteProviderClient> client_;
139 scoped_refptr<PhysicalWebProvider> provider_; 239 scoped_refptr<PhysicalWebProvider> provider_;
140 240
141 private: 241 private:
142 DISALLOW_COPY_AND_ASSIGN(PhysicalWebProviderTest); 242 DISALLOW_COPY_AND_ASSIGN(PhysicalWebProviderTest);
143 }; 243 };
144 244
145 TEST_F(PhysicalWebProviderTest, TestEmptyMetadataListCreatesNoMatches) { 245 TEST_F(PhysicalWebProviderTest, TestEmptyMetadataListCreatesNoMatches) {
146 MockPhysicalWebDataSource* data_source = 246 MockPhysicalWebDataSource* data_source =
147 client_->GetMockPhysicalWebDataSource(); 247 client_->GetMockPhysicalWebDataSource();
(...skipping 27 matching lines...) Expand all
175 275
176 data_source->SetMetadata(std::move(metadata_list)); 276 data_source->SetMetadata(std::move(metadata_list));
177 277
178 // Run the test with no text in the omnibox input to simulate NTP. 278 // Run the test with no text in the omnibox input to simulate NTP.
179 provider_->Start(CreateInputForNTP(), false); 279 provider_->Start(CreateInputForNTP(), false);
180 280
181 // Check that there is only one match item and its fields are correct. 281 // Check that there is only one match item and its fields are correct.
182 EXPECT_EQ(1U, provider_->matches().size()); 282 EXPECT_EQ(1U, provider_->matches().size());
183 const AutocompleteMatch& metadata_match = provider_->matches().front(); 283 const AutocompleteMatch& metadata_match = provider_->matches().front();
184 EXPECT_EQ(AutocompleteMatchType::PHYSICAL_WEB, metadata_match.type); 284 EXPECT_EQ(AutocompleteMatchType::PHYSICAL_WEB, metadata_match.type);
185 EXPECT_EQ(resolved_url, metadata_match.destination_url.spec()); 285 ValidateMatch(metadata_match, resolved_url, resolved_url, title, false);
186 EXPECT_EQ(resolved_url, base::UTF16ToASCII(metadata_match.contents));
187 EXPECT_EQ(title, base::UTF16ToASCII(metadata_match.description));
188 EXPECT_FALSE(metadata_match.allowed_to_be_default_match);
189 286
190 // Run the test again with a URL in the omnibox input. An additional match 287 // Run the test again with a URL in the omnibox input. An additional match
191 // should be added as a default match. 288 // should be added as a default match.
192 provider_->Start(CreateInputWithCurrentUrl("http://www.cnn.com"), false); 289 provider_->Start(CreateInputWithCurrentUrl("http://www.cnn.com"), false);
193 290
194 size_t metadata_match_count = 0; 291 size_t metadata_match_count = 0;
195 size_t default_match_count = 0; 292 size_t default_match_count = 0;
196 for (const auto& match : provider_->matches()) { 293 for (const auto& match : provider_->matches()) {
197 if (match.type == AutocompleteMatchType::PHYSICAL_WEB) { 294 if (match.type == AutocompleteMatchType::PHYSICAL_WEB) {
198 EXPECT_EQ(resolved_url, match.destination_url.spec()); 295 ValidateMatch(match, resolved_url, resolved_url, title, false);
199 EXPECT_EQ(resolved_url, base::UTF16ToASCII(match.contents));
200 EXPECT_EQ(title, base::UTF16ToASCII(match.description));
201 EXPECT_FALSE(match.allowed_to_be_default_match);
202 ++metadata_match_count; 296 ++metadata_match_count;
203 } else { 297 } else {
204 EXPECT_TRUE(match.allowed_to_be_default_match); 298 EXPECT_TRUE(match.allowed_to_be_default_match);
205 ++default_match_count; 299 ++default_match_count;
206 } 300 }
207 } 301 }
208 EXPECT_EQ(2U, provider_->matches().size()); 302 EXPECT_EQ(2U, provider_->matches().size());
209 EXPECT_EQ(1U, metadata_match_count); 303 EXPECT_EQ(1U, metadata_match_count);
210 EXPECT_EQ(1U, default_match_count); 304 EXPECT_EQ(1U, default_match_count);
211 } 305 }
212 306
213 TEST_F(PhysicalWebProviderTest, TestManyMetadataItemsCreatesOverflowItem) {
214 // This test is intended to verify that an overflow item is created when the
215 // number of nearby Physical Web URLs exceeds the maximum allowable matches
216 // for this provider. The actual limit for the PhysicalWebProvider may be
217 // changed in the future, so create enough metadata to exceed the
218 // AutocompleteProvider's limit.
219 const size_t metadata_count = AutocompleteProvider::kMaxMatches + 1;
220
221 MockPhysicalWebDataSource* data_source =
222 client_->GetMockPhysicalWebDataSource();
223 EXPECT_TRUE(data_source);
224
225 data_source->SetMetadata(CreateMetadata(metadata_count));
226
227 {
228 // Run the test with no text in the omnibox input to simulate NTP.
229 provider_->Start(CreateInputForNTP(), false);
230
231 const size_t match_count = provider_->matches().size();
232 EXPECT_LT(match_count, metadata_count);
233
234 // Check that the overflow item is present and its fields are correct. There
235 // may be additional match items, but none should be marked as default.
236 size_t overflow_match_count = 0;
237 for (const auto& match : provider_->matches()) {
238 if (match.type == AutocompleteMatchType::PHYSICAL_WEB_OVERFLOW) {
239 EXPECT_EQ("chrome://physical-web/", match.destination_url.spec());
240 EXPECT_EQ("chrome://physical-web/", base::UTF16ToASCII(match.contents));
241 const size_t metadata_matches = match_count - 1;
242 std::string description = l10n_util::GetPluralStringFUTF8(
243 IDS_PHYSICAL_WEB_OVERFLOW, metadata_count - metadata_matches);
244 EXPECT_EQ(description, base::UTF16ToASCII(match.description));
245 ++overflow_match_count;
246 }
247 EXPECT_FALSE(match.allowed_to_be_default_match);
248 }
249 EXPECT_EQ(1U, overflow_match_count);
250 }
251
252 {
253 // Run the test again with a URL in the omnibox input. An additional match
254 // should be added as a default match.
255 provider_->Start(CreateInputWithCurrentUrl("http://www.cnn.com"), false);
256
257 const size_t match_count = provider_->matches().size();
258 EXPECT_LT(match_count - 1, metadata_count);
259
260 // Check that the overflow item and default match are present and their
261 // fields are correct.
262 size_t overflow_match_count = 0;
263 size_t default_match_count = 0;
264 for (const auto& match : provider_->matches()) {
265 if (match.type == AutocompleteMatchType::PHYSICAL_WEB_OVERFLOW) {
266 EXPECT_EQ("chrome://physical-web/", match.destination_url.spec());
267 EXPECT_EQ("chrome://physical-web/", base::UTF16ToASCII(match.contents));
268 const size_t metadata_matches = match_count - 2;
269 std::string description = l10n_util::GetPluralStringFUTF8(
270 IDS_PHYSICAL_WEB_OVERFLOW, metadata_count - metadata_matches);
271 EXPECT_EQ(description, base::UTF16ToASCII(match.description));
272 EXPECT_FALSE(match.allowed_to_be_default_match);
273 ++overflow_match_count;
274 } else if (match.allowed_to_be_default_match) {
275 ++default_match_count;
276 }
277 }
278 EXPECT_EQ(1U, overflow_match_count);
279 EXPECT_EQ(1U, default_match_count);
280 }
281 }
282
283 TEST_F(PhysicalWebProviderTest, TestNoMatchesWithUserInput) { 307 TEST_F(PhysicalWebProviderTest, TestNoMatchesWithUserInput) {
284 MockPhysicalWebDataSource* data_source = 308 MockPhysicalWebDataSource* data_source =
285 client_->GetMockPhysicalWebDataSource(); 309 client_->GetMockPhysicalWebDataSource();
286 EXPECT_TRUE(data_source); 310 EXPECT_TRUE(data_source);
287 311
288 data_source->SetMetadata(CreateMetadata(1)); 312 data_source->SetMetadata(CreateMetadata(1));
289 313
290 // Construct an AutocompleteInput to simulate user input in the omnibox input 314 // Construct an AutocompleteInput to simulate user input in the omnibox input
291 // field. The provider should not generate any matches. 315 // field. The provider should not generate any matches.
292 std::string text("user input"); 316 std::string text("user input");
293 const AutocompleteInput input(base::ASCIIToUTF16(text), text.length(), 317 const AutocompleteInput input(
294 std::string(), GURL(), 318 base::UTF8ToUTF16(text), text.length(), std::string(), GURL(),
295 metrics::OmniboxEventProto::INSTANT_NTP_WITH_OMNIBOX_AS_STARTING_FOCUS, 319 metrics::OmniboxEventProto::INSTANT_NTP_WITH_OMNIBOX_AS_STARTING_FOCUS,
296 true, false, true, true, false, TestSchemeClassifier()); 320 true, false, true, true, false, TestSchemeClassifier());
297 provider_->Start(input, false); 321 provider_->Start(input, false);
298 322
299 EXPECT_TRUE(provider_->matches().empty()); 323 EXPECT_TRUE(provider_->matches().empty());
300 } 324 }
301 325
326 TEST_F(PhysicalWebProviderTest, TestManyMetadataItemsCreatesOverflowItem) {
327 // Create enough metadata to guarantee an overflow item will be created.
328 const size_t metadata_count = AutocompleteProvider::kMaxMatches + 1;
329
330 // Run the test with no text in the omnibox input to simulate NTP.
331 OverflowItemTestCase(CreateInputForNTP(), CreateMetadata(metadata_count),
332 "Example title 0");
333
334 // Run the test again with a URL in the omnibox input. An additional match
335 // should be added as a default match.
336 OverflowItemTestCase(CreateInputWithCurrentUrl("http://www.cnn.com"),
337 CreateMetadata(metadata_count), "Example title 0");
302 } 338 }
339
340 TEST_F(PhysicalWebProviderTest, TestLongPageTitleIsTruncatedInOverflowItem) {
341 // Set a long title for the first item. The page title for this item will
342 // appear in the overflow item's content string.
343 auto metadata_list = CreateMetadata(AutocompleteProvider::kMaxMatches + 1);
344 base::DictionaryValue* metadata_item;
345 EXPECT_TRUE(metadata_list->GetDictionary(0, &metadata_item));
346 metadata_item->SetString("title", "Extra long example title 0");
347
348 OverflowItemTestCase(CreateInputForNTP(), std::move(metadata_list),
349 "Extra long exa" + std::string(gfx::kEllipsis));
350 }
351
352 TEST_F(PhysicalWebProviderTest, TestEmptyPageTitleInOverflowItem) {
353 // Set an empty title for the first item. Because the title is empty, we will
354 // display an alternate string in the overflow item's contents.
355 auto metadata_list = CreateMetadata(AutocompleteProvider::kMaxMatches + 1);
356 base::DictionaryValue* metadata_item;
357 EXPECT_TRUE(metadata_list->GetDictionary(0, &metadata_item));
358 metadata_item->SetString("title", "");
359
360 OverflowItemTestCase(CreateInputForNTP(), std::move(metadata_list), "");
361 }
362
363 TEST_F(PhysicalWebProviderTest, TestRTLPageTitleInOverflowItem) {
364 // Set a Hebrew title for the first item.
365 auto metadata_list = CreateMetadata(AutocompleteProvider::kMaxMatches + 1);
366 base::DictionaryValue* metadata_item;
367 EXPECT_TRUE(metadata_list->GetDictionary(0, &metadata_item));
368 metadata_item->SetString("title", "ויקיפדיה");
369
370 OverflowItemTestCase(CreateInputForNTP(), std::move(metadata_list),
371 "ויקיפדיה");
372 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698