Cleanup and IWYU-ify CocoaProfileTest and related tests.
[chromium-blink-merge.git] / chrome / browser / ui / cocoa / omnibox / omnibox_popup_view_mac_unittest.mm
blobc78d63aeec639974a21ad5dc47a890c73cf7b89f
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #import "chrome/browser/ui/cocoa/omnibox/omnibox_popup_view_mac.h"
7 #include "base/memory/scoped_ptr.h"
8 #include "base/strings/sys_string_conversions.h"
9 #include "base/strings/utf_string_conversions.h"
10 #include "chrome/browser/ui/cocoa/cocoa_profile_test.h"
11 #import "chrome/browser/ui/cocoa/omnibox/omnibox_view_mac.h"
12 #include "chrome/test/base/testing_profile.h"
13 #include "ui/gfx/rect.h"
14 #include "ui/gfx/text_elider.h"
16 namespace {
18 const float kLargeWidth = 10000;
20 // Returns the length of the run starting at |location| for which
21 // |attributeName| remains the same.
22 NSUInteger RunLengthForAttribute(NSAttributedString* string,
23                                  NSUInteger location,
24                                  NSString* attributeName) {
25   const NSRange full_range = NSMakeRange(0, [string length]);
26   NSRange range;
27   [string attribute:attributeName
28             atIndex:location longestEffectiveRange:&range inRange:full_range];
30   // In order to signal when the run doesn't start exactly at location, return
31   // a weirdo length.  This causes the incorrect expectation to manifest at the
32   // calling location, which is more useful than an EXPECT_EQ() would be here.
33   if (range.location != location) {
34     return -1;
35   }
37   return range.length;
40 // Return true if the run starting at |location| has |color| for attribute
41 // NSForegroundColorAttributeName.
42 bool RunHasColor(NSAttributedString* string,
43                  NSUInteger location,
44                  NSColor* color) {
45   const NSRange full_range = NSMakeRange(0, [string length]);
46   NSRange range;
47   NSColor* run_color = [string attribute:NSForegroundColorAttributeName
48                                  atIndex:location
49                    longestEffectiveRange:&range
50                                  inRange:full_range];
52   // According to one "Ali Ozer", you can compare objects within the same color
53   // space using -isEqual:.  Converting color spaces seems too heavyweight for
54   // these tests.
55   // http://lists.apple.com/archives/cocoa-dev/2005/May/msg00186.html
56   return [run_color isEqual:color] ? true : false;
59 // Return true if the run starting at |location| has the font trait(s) in |mask|
60 // font in NSFontAttributeName.
61 bool RunHasFontTrait(NSAttributedString* string,
62                      NSUInteger location,
63                      NSFontTraitMask mask) {
64   const NSRange full_range = NSMakeRange(0, [string length]);
65   NSRange range;
66   NSFont* run_font = [string attribute:NSFontAttributeName
67                                atIndex:location
68                  longestEffectiveRange:&range
69                                inRange:full_range];
70   NSFontManager* fontManager = [NSFontManager sharedFontManager];
71   if (run_font && (mask == ([fontManager traitsOfFont:run_font] & mask))) {
72     return true;
73   }
74   return false;
77 // AutocompleteMatch doesn't really have the right constructor for our
78 // needs.  Fake one for us to use.
79 AutocompleteMatch MakeMatch(const string16& contents,
80                             const string16& description) {
81   AutocompleteMatch m(NULL, 1, true, AutocompleteMatchType::URL_WHAT_YOU_TYPED);
82   m.contents = contents;
83   m.description = description;
84   return m;
87 class MockOmniboxPopupViewMac : public OmniboxPopupViewMac {
88  public:
89   MockOmniboxPopupViewMac(OmniboxView* omnibox_view,
90                           OmniboxEditModel* edit_model,
91                           NSTextField* field)
92       : OmniboxPopupViewMac(omnibox_view, edit_model, field) {
93   }
95   void SetResultCount(size_t count) {
96     ACMatches matches;
97     for (size_t i = 0; i < count; ++i)
98       matches.push_back(AutocompleteMatch());
99     result_.Reset();
100     result_.AppendMatches(matches);
101   }
103  protected:
104   virtual const AutocompleteResult& GetResult() const OVERRIDE {
105     return result_;
106   }
108  private:
109   AutocompleteResult result_;
112 class OmniboxPopupViewMacTest : public CocoaProfileTest {
113  public:
114   OmniboxPopupViewMacTest() {
115     color_ = [NSColor blackColor];
116     dim_color_ = [NSColor darkGrayColor];
117     font_ = gfx::Font(
118         base::SysNSStringToUTF8([[NSFont userFontOfSize:12] fontName]), 12);
119   }
121  protected:
122   NSColor* color_;  // weak
123   NSColor* dim_color_;  // weak
124   gfx::Font font_;
126  private:
127   DISALLOW_COPY_AND_ASSIGN(OmniboxPopupViewMacTest);
130 // Simple inputs with no matches should result in styled output who's text
131 // matches the input string, with the passed-in color, and nothing bolded.
132 TEST_F(OmniboxPopupViewMacTest, DecorateMatchedStringNoMatch) {
133   NSString* const string = @"This is a test";
134   AutocompleteMatch::ACMatchClassifications classifications;
136   NSAttributedString* decorated =
137       OmniboxPopupViewMac::DecorateMatchedString(
138           base::SysNSStringToUTF16(string), classifications,
139           color_, dim_color_, font_);
141   // Result has same characters as the input.
142   EXPECT_EQ([decorated length], [string length]);
143   EXPECT_TRUE([[decorated string] isEqualToString:string]);
145   // Our passed-in color for the entire string.
146   EXPECT_EQ(RunLengthForAttribute(decorated, 0U,
147                                   NSForegroundColorAttributeName),
148             [string length]);
149   EXPECT_TRUE(RunHasColor(decorated, 0U, color_));
151   // An unbolded font for the entire string.
152   EXPECT_EQ(RunLengthForAttribute(decorated, 0U, NSFontAttributeName),
153             [string length]);
154   EXPECT_FALSE(RunHasFontTrait(decorated, 0U, NSBoldFontMask));
157 // Identical to DecorateMatchedStringNoMatch, except test that URL style gets a
158 // different color than we passed in.
159 TEST_F(OmniboxPopupViewMacTest, DecorateMatchedStringURLNoMatch) {
160   NSString* const string = @"This is a test";
161   AutocompleteMatch::ACMatchClassifications classifications;
163   classifications.push_back(
164       ACMatchClassification(0, ACMatchClassification::URL));
166   NSAttributedString* decorated =
167       OmniboxPopupViewMac::DecorateMatchedString(
168           base::SysNSStringToUTF16(string), classifications,
169           color_, dim_color_, font_);
171   // Result has same characters as the input.
172   EXPECT_EQ([decorated length], [string length]);
173   EXPECT_TRUE([[decorated string] isEqualToString:string]);
175   // One color for the entire string, and it's not the one we passed in.
176   EXPECT_EQ(RunLengthForAttribute(decorated, 0U,
177                                   NSForegroundColorAttributeName),
178             [string length]);
179   EXPECT_FALSE(RunHasColor(decorated, 0U, color_));
181   // An unbolded font for the entire string.
182   EXPECT_EQ(RunLengthForAttribute(decorated, 0U,
183                                   NSFontAttributeName), [string length]);
184   EXPECT_FALSE(RunHasFontTrait(decorated, 0U, NSBoldFontMask));
187 // Test that DIM works as expected.
188 TEST_F(OmniboxPopupViewMacTest, DecorateMatchedStringDimNoMatch) {
189   NSString* const string = @"This is a test";
190   // Dim "is".
191   const NSUInteger run_length_1 = 5, run_length_2 = 2, run_length_3 = 7;
192   // Make sure nobody messed up the inputs.
193   EXPECT_EQ(run_length_1 + run_length_2 + run_length_3, [string length]);
195   // Push each run onto classifications.
196   AutocompleteMatch::ACMatchClassifications classifications;
197   classifications.push_back(
198       ACMatchClassification(0, ACMatchClassification::NONE));
199   classifications.push_back(
200       ACMatchClassification(run_length_1, ACMatchClassification::DIM));
201   classifications.push_back(
202       ACMatchClassification(run_length_1 + run_length_2,
203                             ACMatchClassification::NONE));
205   NSAttributedString* decorated =
206       OmniboxPopupViewMac::DecorateMatchedString(
207           base::SysNSStringToUTF16(string), classifications,
208           color_, dim_color_, font_);
210   // Result has same characters as the input.
211   EXPECT_EQ([decorated length], [string length]);
212   EXPECT_TRUE([[decorated string] isEqualToString:string]);
214   // Should have three font runs, normal, dim, normal.
215   EXPECT_EQ(RunLengthForAttribute(decorated, 0U,
216                                   NSForegroundColorAttributeName),
217             run_length_1);
218   EXPECT_TRUE(RunHasColor(decorated, 0U, color_));
220   EXPECT_EQ(RunLengthForAttribute(decorated, run_length_1,
221                                   NSForegroundColorAttributeName),
222             run_length_2);
223   EXPECT_TRUE(RunHasColor(decorated, run_length_1, dim_color_));
225   EXPECT_EQ(RunLengthForAttribute(decorated, run_length_1 + run_length_2,
226                                   NSForegroundColorAttributeName),
227             run_length_3);
228   EXPECT_TRUE(RunHasColor(decorated, run_length_1 + run_length_2, color_));
230   // An unbolded font for the entire string.
231   EXPECT_EQ(RunLengthForAttribute(decorated, 0U,
232                                   NSFontAttributeName), [string length]);
233   EXPECT_FALSE(RunHasFontTrait(decorated, 0U, NSBoldFontMask));
236 // Test that the matched run gets bold-faced, but keeps the same color.
237 TEST_F(OmniboxPopupViewMacTest, DecorateMatchedStringMatch) {
238   NSString* const string = @"This is a test";
239   // Match "is".
240   const NSUInteger run_length_1 = 5, run_length_2 = 2, run_length_3 = 7;
241   // Make sure nobody messed up the inputs.
242   EXPECT_EQ(run_length_1 + run_length_2 + run_length_3, [string length]);
244   // Push each run onto classifications.
245   AutocompleteMatch::ACMatchClassifications classifications;
246   classifications.push_back(
247       ACMatchClassification(0, ACMatchClassification::NONE));
248   classifications.push_back(
249       ACMatchClassification(run_length_1, ACMatchClassification::MATCH));
250   classifications.push_back(
251       ACMatchClassification(run_length_1 + run_length_2,
252                             ACMatchClassification::NONE));
254   NSAttributedString* decorated =
255       OmniboxPopupViewMac::DecorateMatchedString(
256           base::SysNSStringToUTF16(string), classifications,
257           color_, dim_color_, font_);
259   // Result has same characters as the input.
260   EXPECT_EQ([decorated length], [string length]);
261   EXPECT_TRUE([[decorated string] isEqualToString:string]);
263   // Our passed-in color for the entire string.
264   EXPECT_EQ(RunLengthForAttribute(decorated, 0U,
265                                   NSForegroundColorAttributeName),
266             [string length]);
267   EXPECT_TRUE(RunHasColor(decorated, 0U, color_));
269   // Should have three font runs, not bold, bold, then not bold again.
270   EXPECT_EQ(RunLengthForAttribute(decorated, 0U,
271                                   NSFontAttributeName), run_length_1);
272   EXPECT_FALSE(RunHasFontTrait(decorated, 0U, NSBoldFontMask));
274   EXPECT_EQ(RunLengthForAttribute(decorated, run_length_1,
275                                   NSFontAttributeName), run_length_2);
276   EXPECT_TRUE(RunHasFontTrait(decorated, run_length_1, NSBoldFontMask));
278   EXPECT_EQ(RunLengthForAttribute(decorated, run_length_1 + run_length_2,
279                                   NSFontAttributeName), run_length_3);
280   EXPECT_FALSE(RunHasFontTrait(decorated, run_length_1 + run_length_2,
281                                NSBoldFontMask));
284 // Just like DecorateMatchedStringURLMatch, this time with URL style.
285 TEST_F(OmniboxPopupViewMacTest, DecorateMatchedStringURLMatch) {
286   NSString* const string = @"http://hello.world/";
287   // Match "hello".
288   const NSUInteger run_length_1 = 7, run_length_2 = 5, run_length_3 = 7;
289   // Make sure nobody messed up the inputs.
290   EXPECT_EQ(run_length_1 + run_length_2 + run_length_3, [string length]);
292   // Push each run onto classifications.
293   AutocompleteMatch::ACMatchClassifications classifications;
294   classifications.push_back(
295       ACMatchClassification(0, ACMatchClassification::URL));
296   const int kURLMatch = ACMatchClassification::URL|ACMatchClassification::MATCH;
297   classifications.push_back(ACMatchClassification(run_length_1, kURLMatch));
298   classifications.push_back(
299       ACMatchClassification(run_length_1 + run_length_2,
300                             ACMatchClassification::URL));
302   NSAttributedString* decorated =
303       OmniboxPopupViewMac::DecorateMatchedString(
304           base::SysNSStringToUTF16(string), classifications,
305           color_, dim_color_, font_);
307   // Result has same characters as the input.
308   EXPECT_EQ([decorated length], [string length]);
309   EXPECT_TRUE([[decorated string] isEqualToString:string]);
311   // One color for the entire string, and it's not the one we passed in.
312   EXPECT_EQ(RunLengthForAttribute(decorated, 0U,
313                                   NSForegroundColorAttributeName),
314             [string length]);
315   EXPECT_FALSE(RunHasColor(decorated, 0U, color_));
317   // Should have three font runs, not bold, bold, then not bold again.
318   EXPECT_EQ(RunLengthForAttribute(decorated, 0U,
319                                   NSFontAttributeName), run_length_1);
320   EXPECT_FALSE(RunHasFontTrait(decorated, 0U, NSBoldFontMask));
322   EXPECT_EQ(RunLengthForAttribute(decorated, run_length_1,
323                                   NSFontAttributeName), run_length_2);
324   EXPECT_TRUE(RunHasFontTrait(decorated, run_length_1, NSBoldFontMask));
326   EXPECT_EQ(RunLengthForAttribute(decorated, run_length_1 + run_length_2,
327                                   NSFontAttributeName), run_length_3);
328   EXPECT_FALSE(RunHasFontTrait(decorated, run_length_1 + run_length_2,
329                                NSBoldFontMask));
332 TEST_F(OmniboxPopupViewMacTest, UpdatePopupAppearance) {
333   base::scoped_nsobject<NSTextField> field(
334       [[NSTextField alloc] initWithFrame:NSMakeRect(0, 0, 100, 20)]);
335   [[test_window() contentView] addSubview:field];
337   OmniboxViewMac view(NULL, profile(), NULL, NULL);
338   MockOmniboxPopupViewMac popup_view(&view, view.model(), field);
340   popup_view.UpdatePopupAppearance();
341   EXPECT_FALSE(popup_view.IsOpen());
342   EXPECT_EQ(0, [popup_view.matrix() numberOfRows]);
344   popup_view.SetResultCount(3);
345   popup_view.UpdatePopupAppearance();
346   EXPECT_TRUE(popup_view.IsOpen());
347   EXPECT_EQ(3, [popup_view.matrix() numberOfRows]);
349   int old_height = popup_view.GetTargetBounds().height();
350   popup_view.SetResultCount(5);
351   popup_view.UpdatePopupAppearance();
352   EXPECT_GT(popup_view.GetTargetBounds().height(), old_height);
353   EXPECT_EQ(5, [popup_view.matrix() numberOfRows]);
355   popup_view.SetResultCount(0);
356   popup_view.UpdatePopupAppearance();
357   EXPECT_FALSE(popup_view.IsOpen());
358   EXPECT_EQ(0, [popup_view.matrix() numberOfRows]);
361 }  // namespace