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