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.
5 #include "ui/message_center/views/bounded_label.h"
9 #include "base/strings/string_util.h"
10 #include "base/strings/utf_string_conversions.h"
11 #include "testing/gtest/include/gtest/gtest.h"
12 #include "ui/gfx/font_list.h"
13 #include "ui/gfx/text_utils.h"
14 #include "ui/views/controls/label.h"
16 namespace message_center
{
20 /* Test fixture ***************************************************************/
22 class BoundedLabelTest
: public testing::Test
{
25 digit_pixels_
= gfx::GetStringWidth(base::UTF8ToUTF16("0"), font_list_
);
26 space_pixels_
= gfx::GetStringWidth(base::UTF8ToUTF16(" "), font_list_
);
27 ellipsis_pixels_
= gfx::GetStringWidth(base::UTF8ToUTF16("\xE2\x80\xA6"),
31 ~BoundedLabelTest() override
{}
33 // Replaces all occurences of three periods ("...") in the specified string
34 // with an ellipses character (UTF8 "\xE2\x80\xA6") and returns a string16
35 // with the results. This allows test strings to be specified as ASCII const
36 // char* strings, making tests more readable and easier to write.
37 base::string16
ToString(const char* string
) {
38 const char kPeriods
[] = "...";
39 const char kEllipses
[] = "\xE2\x80\xA6";
40 std::string result
= string
;
41 ReplaceSubstringsAfterOffset(&result
, 0, kPeriods
, kEllipses
);
42 return base::UTF8ToUTF16(result
);
45 // Converts the specified elision width to pixels. To make tests somewhat
46 // independent of the fonts of the platform on which they're run, the elision
47 // widths are specified as XYZ integers, with the corresponding width in
48 // pixels being X times the width of digit characters plus Y times the width
49 // of spaces plus Z times the width of ellipses in the default font of the
50 // test plaform. It is assumed that all digits have the same width in that
51 // font, that this width is greater than the width of spaces, and that the
52 // width of 3 digits is greater than the width of ellipses.
53 int ToPixels(int width
) {
54 return digit_pixels_
* width
/ 100 +
55 space_pixels_
* (width
% 100) / 10 +
56 ellipsis_pixels_
* (width
% 10);
59 // Exercise BounderLabel::GetWrappedText() using the fixture's test label.
60 base::string16
GetWrappedText(int width
) {
61 return label_
->GetWrappedTextForTest(width
, lines_
);
64 // Exercise BounderLabel::GetLinesForWidthAndLimit() using the test label.
65 int GetLinesForWidth(int width
) {
66 label_
->SetBounds(0, 0, width
, font_list_
.GetHeight() * lines_
);
67 return label_
->GetLinesForWidthAndLimit(width
, lines_
);
71 // Creates a label to test with. Returns this fixture, which can be used to
72 // test the newly created label using the exercise methods above.
73 BoundedLabelTest
& Label(base::string16 text
, int lines
) {
75 label_
.reset(new BoundedLabel(text
, font_list_
));
76 label_
->SetLineLimit(lines_
);
81 // The default font list, which will be used for tests.
82 gfx::FontList font_list_
;
86 scoped_ptr
<BoundedLabel
> label_
;
90 /* Test macro *****************************************************************/
92 #define TEST_WRAP(expected, text, width, lines) \
93 EXPECT_EQ(ToString(expected), \
94 Label(ToString(text), lines).GetWrappedText(ToPixels(width)))
96 #define TEST_LINES(expected, text, width, lines) \
98 Label(ToString(text), lines).GetLinesForWidth(ToPixels(width)))
100 /* Elision tests **************************************************************/
102 TEST_F(BoundedLabelTest
, GetWrappedTextTest
) {
103 // One word per line: No ellision should be made when not necessary.
104 TEST_WRAP("123", "123", 301, 1);
105 TEST_WRAP("123", "123", 301, 2);
106 TEST_WRAP("123", "123", 301, 3);
107 TEST_WRAP("123\n456", "123 456", 301, 2);
108 TEST_WRAP("123\n456", "123 456", 301, 3);
109 TEST_WRAP("123\n456\n789", "123 456 789", 301, 3);
111 // One word per line: Ellisions should be made when necessary.
112 TEST_WRAP("123...", "123 456", 301, 1);
113 TEST_WRAP("123...", "123 456 789", 301, 1);
114 TEST_WRAP("123\n456...", "123 456 789", 301, 2);
116 // Two words per line: No ellision should be made when not necessary.
117 TEST_WRAP("123 456", "123 456", 621, 1);
118 TEST_WRAP("123 456", "123 456", 621, 2);
119 TEST_WRAP("123 456", "123 456", 621, 3);
120 TEST_WRAP("123 456\n789 012", "123 456 789 012", 621, 2);
121 TEST_WRAP("123 456\n789 012", "123 456 789 012", 621, 3);
122 TEST_WRAP("123 456\n789 012\n345 678", "123 456 789 012 345 678", 621, 3);
124 // Two words per line: Ellisions should be made when necessary.
125 TEST_WRAP("123 456...", "123 456 789 012", 621, 1);
126 TEST_WRAP("123 456...", "123 456 789 012 345 678", 621, 1);
127 TEST_WRAP("123 456\n789 012...", "123 456 789 012 345 678", 621, 2);
129 // Single trailing spaces: No ellipses should be added.
130 TEST_WRAP("123", "123 ", 301, 1);
131 TEST_WRAP("123\n456", "123 456 ", 301, 2);
132 TEST_WRAP("123\n456\n789", "123 456 789 ", 301, 3);
133 TEST_WRAP("123 456", "123 456 ", 611, 1);
134 TEST_WRAP("123 456\n789 012", "123 456 789 012 ", 611, 2);
135 TEST_WRAP("123 456\n789 012\n345 678", "123 456 789 012 345 678 ", 611, 3);
137 // Multiple trailing spaces: No ellipses should be added.
138 TEST_WRAP("123", "123 ", 301, 1);
139 TEST_WRAP("123\n456", "123 456 ", 301, 2);
140 TEST_WRAP("123\n456\n789", "123 456 789 ", 301, 3);
141 TEST_WRAP("123 456", "123 456 ", 611, 1);
142 TEST_WRAP("123 456\n789 012", "123 456 789 012 ", 611, 2);
143 TEST_WRAP("123 456\n789 012\n345 678",
144 "123 456 789 012 345 678 ", 611, 3);
146 // Multiple spaces between words on the same line: Spaces should be preserved.
147 // Test cases for single spaces between such words are included in the "Two
148 // words per line" sections above.
149 TEST_WRAP("123 456", "123 456", 621, 1);
150 TEST_WRAP("123 456...", "123 456 789 012", 631, 1);
151 TEST_WRAP("123 456\n789 012", "123 456 789 012", 631, 2);
152 TEST_WRAP("123 456...", "123 456 789 012 345 678", 621, 1);
153 TEST_WRAP("123 456\n789 012...", "123 456 789 012 345 678", 631, 2);
154 TEST_WRAP("123 456\n789 012\n345 678",
155 "123 456 789 012 345 678", 641, 3);
157 // Multiple spaces between words split across lines: Spaces should be removed
158 // even if lines are wide enough to include those spaces. Test cases for
159 // single spaces between such words are included in the "Two words per line"
161 TEST_WRAP("123\n456", "123 456", 321, 2);
162 TEST_WRAP("123\n456", "123 456", 391, 2);
163 TEST_WRAP("123\n456...", "123 456 789", 321, 2);
164 TEST_WRAP("123\n456...", "123 456 789", 391, 2);
165 TEST_WRAP("123 456\n789 012", "123 456 789 012", 641, 2);
166 TEST_WRAP("123 456\n789 012...", "123 456 789 012 345 678", 641, 2);
168 // Long words without spaces should be wrapped when necessary.
169 TEST_WRAP("123\n456", "123456", 300, 9);
171 // TODO(dharcourt): Add test cases to verify that:
172 // - Spaces before elisions are removed
173 // - Leading spaces are preserved
174 // - Words are split when they are longer than lines
175 // - Words are clipped when they are longer than the last line
176 // - No blank line are created before or after clipped word
177 // - Spaces at the end of the text are removed
179 // TODO(dharcourt): Add test cases for:
180 // - Empty and very large strings
181 // - Zero, very large, and negative line limit values
182 // - Other input boundary conditions
183 // TODO(dharcourt): Add some randomly generated fuzz test cases.
186 /* GetLinesTest ***************************************************************/
188 TEST_F(BoundedLabelTest
, GetLinesTest
) {
189 // Zero and negative width values should yield zero lines.
190 TEST_LINES(0, "123 456", 0, 1);
191 TEST_LINES(0, "123 456", -1, 1);
192 TEST_LINES(0, "123 456", -2, 1);
193 TEST_LINES(0, "123 456", std::numeric_limits
<int>::min(), 1);
195 // Small width values should yield one word per line.
196 TEST_LINES(1, "123 456", 1, 1);
197 TEST_LINES(2, "123 456", 1, 2);
198 TEST_LINES(1, "123 456", 2, 1);
199 TEST_LINES(2, "123 456", 2, 2);
200 TEST_LINES(1, "123 456", 3, 1);
201 TEST_LINES(2, "123 456", 3, 2);
203 // Large width values should yield all words on one line.
204 TEST_LINES(1, "123 456", 610, 1);
205 TEST_LINES(1, "123 456", std::numeric_limits
<int>::max(), 1);
208 /* Other tests ****************************************************************/
210 // TODO(dharcourt): Add test cases to verify that:
211 // - SetMaxLines() affects the return values of some methods but not others.
212 // - Bound changes affects GetPreferredLines(), GetTextSize(), and
213 // GetWrappedText() return values.
214 // - GetTextFlags are as expected.
218 } // namespace message_center