Upstream version 5.34.92.0
[platform/framework/web/crosswalk.git] / src / ui / views / controls / styled_label_unittest.cc
1 // Copyright 2013 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.
4
5 #include <string>
6
7 #include "base/basictypes.h"
8 #include "base/memory/scoped_ptr.h"
9 #include "base/strings/utf_string_conversions.h"
10 #include "testing/gtest/include/gtest/gtest.h"
11 #include "third_party/skia/include/core/SkColor.h"
12 #include "ui/gfx/font_list.h"
13 #include "ui/views/border.h"
14 #include "ui/views/controls/link.h"
15 #include "ui/views/controls/styled_label.h"
16 #include "ui/views/controls/styled_label_listener.h"
17
18 using base::ASCIIToUTF16;
19
20 namespace views {
21
22 class StyledLabelTest : public testing::Test, public StyledLabelListener {
23  public:
24   StyledLabelTest() {}
25   virtual ~StyledLabelTest() {}
26
27   // StyledLabelListener implementation.
28   virtual void StyledLabelLinkClicked(const gfx::Range& range,
29                                       int event_flags) OVERRIDE {}
30
31  protected:
32   StyledLabel* styled() { return styled_.get(); }
33
34   void InitStyledLabel(const std::string& ascii_text) {
35     styled_.reset(new StyledLabel(ASCIIToUTF16(ascii_text), this));
36     styled_->set_owned_by_client();
37   }
38
39   int StyledLabelContentHeightForWidth(int w) {
40     return styled_->GetHeightForWidth(w) - styled_->GetInsets().height();
41   }
42
43  private:
44   scoped_ptr<StyledLabel> styled_;
45
46   DISALLOW_COPY_AND_ASSIGN(StyledLabelTest);
47 };
48
49 TEST_F(StyledLabelTest, NoWrapping) {
50   const std::string text("This is a test block of text");
51   InitStyledLabel(text);
52   Label label(ASCIIToUTF16(text));
53   const gfx::Size label_preferred_size = label.GetPreferredSize();
54   EXPECT_EQ(label_preferred_size.height(),
55             StyledLabelContentHeightForWidth(label_preferred_size.width() * 2));
56 }
57
58 TEST_F(StyledLabelTest, TrailingWhitespaceiIgnored) {
59   const std::string text("This is a test block of text   ");
60   InitStyledLabel(text);
61
62   styled()->SetBounds(0, 0, 1000, 1000);
63   styled()->Layout();
64
65   ASSERT_EQ(1, styled()->child_count());
66   ASSERT_EQ(std::string(Label::kViewClassName),
67             styled()->child_at(0)->GetClassName());
68   EXPECT_EQ(ASCIIToUTF16("This is a test block of text"),
69             static_cast<Label*>(styled()->child_at(0))->text());
70 }
71
72 TEST_F(StyledLabelTest, RespectLeadingWhitespace) {
73   const std::string text("   This is a test block of text");
74   InitStyledLabel(text);
75
76   styled()->SetBounds(0, 0, 1000, 1000);
77   styled()->Layout();
78
79   ASSERT_EQ(1, styled()->child_count());
80   ASSERT_EQ(std::string(Label::kViewClassName),
81             styled()->child_at(0)->GetClassName());
82   EXPECT_EQ(ASCIIToUTF16("   This is a test block of text"),
83             static_cast<Label*>(styled()->child_at(0))->text());
84 }
85
86 TEST_F(StyledLabelTest, FirstLineNotEmptyWhenLeadingWhitespaceTooLong) {
87   const std::string text("                                     a");
88   InitStyledLabel(text);
89
90   Label label(ASCIIToUTF16(text));
91   gfx::Size label_preferred_size = label.GetPreferredSize();
92
93   styled()->SetBounds(0, 0, label_preferred_size.width() / 2, 1000);
94   styled()->Layout();
95
96   ASSERT_EQ(1, styled()->child_count());
97   ASSERT_EQ(std::string(Label::kViewClassName),
98             styled()->child_at(0)->GetClassName());
99   EXPECT_EQ(ASCIIToUTF16("a"),
100             static_cast<Label*>(styled()->child_at(0))->text());
101 }
102
103 TEST_F(StyledLabelTest, BasicWrapping) {
104   const std::string text("This is a test block of text");
105   InitStyledLabel(text);
106   Label label(ASCIIToUTF16(text.substr(0, text.size() * 2 / 3)));
107   gfx::Size label_preferred_size = label.GetPreferredSize();
108   EXPECT_EQ(label_preferred_size.height() * 2,
109             StyledLabelContentHeightForWidth(label_preferred_size.width()));
110
111   // Also respect the border.
112   styled()->SetBorder(Border::CreateEmptyBorder(3, 3, 3, 3));
113   styled()->SetBounds(
114       0,
115       0,
116       styled()->GetInsets().width() + label_preferred_size.width(),
117       styled()->GetInsets().height() + 2 * label_preferred_size.height());
118   styled()->Layout();
119   ASSERT_EQ(2, styled()->child_count());
120   EXPECT_EQ(3, styled()->child_at(0)->x());
121   EXPECT_EQ(3, styled()->child_at(0)->y());
122   EXPECT_EQ(styled()->height() - 3, styled()->child_at(1)->bounds().bottom());
123 }
124
125 TEST_F(StyledLabelTest, CreateLinks) {
126   const std::string text("This is a test block of text.");
127   InitStyledLabel(text);
128
129   // Without links, there should be no focus border.
130   EXPECT_TRUE(styled()->GetInsets().empty());
131
132   // Now let's add some links.
133   styled()->AddStyleRange(gfx::Range(0, 1),
134                           StyledLabel::RangeStyleInfo::CreateForLink());
135   styled()->AddStyleRange(gfx::Range(1, 2),
136                           StyledLabel::RangeStyleInfo::CreateForLink());
137   styled()->AddStyleRange(gfx::Range(10, 11),
138                           StyledLabel::RangeStyleInfo::CreateForLink());
139   styled()->AddStyleRange(gfx::Range(12, 13),
140                           StyledLabel::RangeStyleInfo::CreateForLink());
141
142   // Now there should be a focus border because there are non-empty Links.
143   EXPECT_FALSE(styled()->GetInsets().empty());
144
145   // Verify layout creates the right number of children.
146   styled()->SetBounds(0, 0, 1000, 1000);
147   styled()->Layout();
148   EXPECT_EQ(7, styled()->child_count());
149 }
150
151 TEST_F(StyledLabelTest, DontBreakLinks) {
152   const std::string text("This is a test block of text, ");
153   const std::string link_text("and this should be a link");
154   InitStyledLabel(text + link_text);
155   styled()->AddStyleRange(
156       gfx::Range(text.size(), text.size() + link_text.size()),
157       StyledLabel::RangeStyleInfo::CreateForLink());
158
159   Label label(ASCIIToUTF16(text + link_text.substr(0, link_text.size() / 2)));
160   gfx::Size label_preferred_size = label.GetPreferredSize();
161   int pref_height = styled()->GetHeightForWidth(label_preferred_size.width());
162   EXPECT_EQ(label_preferred_size.height() * 2,
163             pref_height - styled()->GetInsets().height());
164
165   styled()->SetBounds(0, 0, label_preferred_size.width(), pref_height);
166   styled()->Layout();
167   ASSERT_EQ(2, styled()->child_count());
168   // The label has no focus border while the link (and thus overall styled
169   // label) does, so the label should be inset by the width of the focus border.
170   EXPECT_EQ(Label::kFocusBorderPadding, styled()->child_at(0)->x());
171   EXPECT_EQ(0, styled()->child_at(1)->x());
172 }
173
174 TEST_F(StyledLabelTest, StyledRangeWithDisabledLineWrapping) {
175   const std::string text("This is a test block of text, ");
176   const std::string unbreakable_text("and this should not be broken");
177   InitStyledLabel(text + unbreakable_text);
178   StyledLabel::RangeStyleInfo style_info;
179   style_info.disable_line_wrapping = true;
180   styled()->AddStyleRange(
181       gfx::Range(text.size(), text.size() + unbreakable_text.size()),
182       style_info);
183
184   Label label(ASCIIToUTF16(
185       text + unbreakable_text.substr(0, unbreakable_text.size() / 2)));
186   gfx::Size label_preferred_size = label.GetPreferredSize();
187   int pref_height = styled()->GetHeightForWidth(label_preferred_size.width());
188   EXPECT_EQ(label_preferred_size.height() * 2,
189             pref_height - styled()->GetInsets().height());
190
191   styled()->SetBounds(0, 0, label_preferred_size.width(), pref_height);
192   styled()->Layout();
193   ASSERT_EQ(2, styled()->child_count());
194   EXPECT_EQ(0, styled()->child_at(0)->x());
195   EXPECT_EQ(0, styled()->child_at(1)->x());
196 }
197
198 TEST_F(StyledLabelTest, StyledRangeUnderlined) {
199   const std::string text("This is a test block of text, ");
200   const std::string underlined_text("and this should be undelined");
201   InitStyledLabel(text + underlined_text);
202   StyledLabel::RangeStyleInfo style_info;
203   style_info.font_style = gfx::Font::UNDERLINE;
204   styled()->AddStyleRange(
205       gfx::Range(text.size(), text.size() + underlined_text.size()),
206       style_info);
207
208   styled()->SetBounds(0, 0, 1000, 1000);
209   styled()->Layout();
210
211   ASSERT_EQ(2, styled()->child_count());
212   ASSERT_EQ(std::string(Label::kViewClassName),
213             styled()->child_at(1)->GetClassName());
214   EXPECT_EQ(
215       gfx::Font::UNDERLINE,
216       static_cast<Label*>(styled()->child_at(1))->font_list().GetFontStyle());
217 }
218
219 TEST_F(StyledLabelTest, StyledRangeBold) {
220   const std::string bold_text(
221       "This is a block of text whose style will be set to BOLD in the test");
222   const std::string text(" normal text");
223   InitStyledLabel(bold_text + text);
224
225   StyledLabel::RangeStyleInfo style_info;
226   style_info.font_style = gfx::Font::BOLD;
227   styled()->AddStyleRange(gfx::Range(0, bold_text.size()), style_info);
228
229   // Calculate the bold text width if it were a pure label view, both with bold
230   // and normal style.
231   Label label(ASCIIToUTF16(bold_text));
232   const gfx::Size normal_label_size = label.GetPreferredSize();
233   label.SetFontList(label.font_list().DeriveFontListWithSizeDeltaAndStyle(
234       0, gfx::Font::BOLD));
235   const gfx::Size bold_label_size = label.GetPreferredSize();
236
237   ASSERT_GE(bold_label_size.width(), normal_label_size.width());
238
239   // Set the width so |bold_text| doesn't fit on a single line with bold style,
240   // but does with normal font style.
241   int styled_width = (normal_label_size.width() + bold_label_size.width()) / 2;
242   int pref_height = styled()->GetHeightForWidth(styled_width);
243
244   // Sanity check that |bold_text| with normal font style would fit on a single
245   // line in a styled label with width |styled_width|.
246   StyledLabel unstyled(ASCIIToUTF16(bold_text), this);
247   unstyled.SetBounds(0, 0, styled_width, pref_height);
248   unstyled.Layout();
249   EXPECT_EQ(1, unstyled.child_count());
250
251   styled()->SetBounds(0, 0, styled_width, pref_height);
252   styled()->Layout();
253
254   ASSERT_EQ(3, styled()->child_count());
255
256   // The bold text should be broken up into two parts.
257   ASSERT_EQ(std::string(Label::kViewClassName),
258             styled()->child_at(0)->GetClassName());
259   EXPECT_EQ(
260       gfx::Font::BOLD,
261       static_cast<Label*>(styled()->child_at(0))->font_list().GetFontStyle());
262   ASSERT_EQ(std::string(Label::kViewClassName),
263             styled()->child_at(1)->GetClassName());
264   EXPECT_EQ(
265       gfx::Font::BOLD,
266       static_cast<Label*>(styled()->child_at(1))->font_list().GetFontStyle());
267   ASSERT_EQ(std::string(Label::kViewClassName),
268             styled()->child_at(2)->GetClassName());
269   EXPECT_EQ(
270       gfx::Font::NORMAL,
271       static_cast<Label*>(styled()->child_at(2))->font_list().GetFontStyle());
272
273   // The second bold part should start on a new line.
274   EXPECT_EQ(0, styled()->child_at(0)->x());
275   EXPECT_EQ(0, styled()->child_at(1)->x());
276   EXPECT_EQ(styled()->child_at(1)->bounds().right(),
277             styled()->child_at(2)->x());
278 }
279
280 TEST_F(StyledLabelTest, Color) {
281   const std::string text_red("RED");
282   const std::string text_link("link");
283   const std::string text("word");
284   InitStyledLabel(text_red + text_link + text);
285
286   StyledLabel::RangeStyleInfo style_info_red;
287   style_info_red.color = SK_ColorRED;
288   styled()->AddStyleRange(gfx::Range(0, text_red.size()), style_info_red);
289
290   StyledLabel::RangeStyleInfo style_info_link =
291       StyledLabel::RangeStyleInfo::CreateForLink();
292   styled()->AddStyleRange(gfx::Range(text_red.size(),
293                                     text_red.size() + text_link.size()),
294                           style_info_link);
295
296   // Obtain the default text color for a label.
297   Label label(ASCIIToUTF16(text));
298   const SkColor kDefaultTextColor = label.enabled_color();
299
300   // Obtain the default text color for a link;
301   Link link(ASCIIToUTF16(text_link));
302   const SkColor kDefaultLinkColor = link.enabled_color();
303
304   styled()->SetBounds(0, 0, 1000, 1000);
305   styled()->Layout();
306
307   EXPECT_EQ(SK_ColorRED,
308             static_cast<Label*>(styled()->child_at(0))->enabled_color());
309   EXPECT_EQ(kDefaultLinkColor,
310             static_cast<Label*>(styled()->child_at(1))->enabled_color());
311   EXPECT_EQ(kDefaultTextColor,
312             static_cast<Label*>(styled()->child_at(2))->enabled_color());
313 }
314
315 TEST_F(StyledLabelTest, ColorReadability) {
316   const std::string text(
317       "This is a block of text that needs color adjustment.");
318   InitStyledLabel(text);
319   styled()->SetDisplayedOnBackgroundColor(SK_ColorBLACK);
320
321   // Obtain the text color if it were a pure label.
322   Label label(ASCIIToUTF16(text));
323   label.SetBackgroundColor(SK_ColorBLACK);
324
325   styled()->SetBounds(0, 0, 1000, 1000);
326   styled()->Layout();
327
328   EXPECT_EQ(label.enabled_color(),
329             static_cast<Label*>(styled()->child_at(0))->enabled_color());
330 }
331
332 TEST_F(StyledLabelTest, StyledRangeWithTooltip) {
333   const std::string text("This is a test block of text, ");
334   const std::string tooltip_text("this should have a tooltip,");
335   const std::string normal_text(" this should not have a tooltip, ");
336   const std::string link_text("and this should be a link");
337
338   const size_t tooltip_start = text.size();
339   const size_t link_start =
340       text.size() + tooltip_text.size() + normal_text.size();
341
342   InitStyledLabel(text + tooltip_text + normal_text + link_text);
343   StyledLabel::RangeStyleInfo tooltip_style;
344   tooltip_style.tooltip = ASCIIToUTF16("tooltip");
345   styled()->AddStyleRange(
346       gfx::Range(tooltip_start, tooltip_start + tooltip_text.size()),
347       tooltip_style);
348   styled()->AddStyleRange(gfx::Range(link_start, link_start + link_text.size()),
349                           StyledLabel::RangeStyleInfo::CreateForLink());
350
351   // Break line inside the range with the tooltip.
352   Label label(ASCIIToUTF16(
353        text + tooltip_text.substr(0, tooltip_text.size() - 3)));
354   gfx::Size label_preferred_size = label.GetPreferredSize();
355   int pref_height = styled()->GetHeightForWidth(label_preferred_size.width());
356   EXPECT_EQ(label_preferred_size.height() * 3,
357             pref_height - styled()->GetInsets().height());
358
359   styled()->SetBounds(0, 0, label_preferred_size.width(), pref_height);
360   styled()->Layout();
361
362   EXPECT_EQ(label_preferred_size.width(), styled()->width());
363
364   ASSERT_EQ(5, styled()->child_count());
365   // The labels have no focus border while the link (and thus overall styled
366   // label) does, so the labels should be inset by the width of the focus
367   // border.
368   EXPECT_EQ(Label::kFocusBorderPadding, styled()->child_at(0)->x());
369   EXPECT_EQ(styled()->child_at(0)->bounds().right(),
370             styled()->child_at(1)->x());
371   EXPECT_EQ(Label::kFocusBorderPadding, styled()->child_at(2)->x());
372   EXPECT_EQ(styled()->child_at(2)->bounds().right(),
373             styled()->child_at(3)->x());
374   EXPECT_EQ(0, styled()->child_at(4)->x());
375
376   base::string16 tooltip;
377   EXPECT_TRUE(
378       styled()->child_at(1)->GetTooltipText(gfx::Point(1, 1), &tooltip));
379   EXPECT_EQ(ASCIIToUTF16("tooltip"), tooltip);
380   EXPECT_TRUE(
381       styled()->child_at(2)->GetTooltipText(gfx::Point(1, 1), &tooltip));
382   EXPECT_EQ(ASCIIToUTF16("tooltip"), tooltip);
383 }
384
385 TEST_F(StyledLabelTest, HandleEmptyLayout) {
386   const std::string text("This is a test block of text.");
387   InitStyledLabel(text);
388   styled()->Layout();
389   EXPECT_EQ(0, styled()->child_count());
390 }
391
392 }  // namespace