OLD | NEW |
---|---|
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2011 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 "base/auto_reset.h" | 5 #include "base/auto_reset.h" |
6 #include "base/memory/scoped_ptr.h" | 6 #include "base/memory/scoped_ptr.h" |
7 #include "base/message_loop.h" | 7 #include "base/message_loop.h" |
8 #include "base/utf_string_conversions.h" | 8 #include "base/utf_string_conversions.h" |
9 #include "testing/gtest/include/gtest/gtest.h" | 9 #include "testing/gtest/include/gtest/gtest.h" |
10 #include "ui/base/clipboard/clipboard.h" | 10 #include "ui/base/clipboard/clipboard.h" |
11 #include "ui/base/clipboard/scoped_clipboard_writer.h" | 11 #include "ui/base/clipboard/scoped_clipboard_writer.h" |
12 #include "ui/base/range/range.h" | 12 #include "ui/base/range/range.h" |
13 #include "ui/gfx/render_text.h" | 13 #include "ui/gfx/render_text.h" |
14 #include "views/controls/textfield/textfield.h" | 14 #include "views/controls/textfield/textfield.h" |
15 #include "views/controls/textfield/textfield_views_model.h" | 15 #include "views/controls/textfield/textfield_views_model.h" |
16 #include "views/test/test_views_delegate.h" | 16 #include "views/test/test_views_delegate.h" |
17 #include "views/test/views_test_base.h" | 17 #include "views/test/views_test_base.h" |
18 #include "views/views_delegate.h" | 18 #include "views/views_delegate.h" |
19 | 19 |
20 namespace { | |
21 | |
22 struct Selection { | |
23 size_t cursor; | |
24 size_t caret; | |
25 gfx::SelectionModel::CaretPlacement placement; | |
26 }; | |
27 | |
28 } // namespace | |
29 | |
20 namespace views { | 30 namespace views { |
21 | 31 |
22 class TextfieldViewsModelTest : public ViewsTestBase, | 32 class TextfieldViewsModelTest : public ViewsTestBase, |
23 public TextfieldViewsModel::Delegate { | 33 public TextfieldViewsModel::Delegate { |
24 public: | 34 public: |
25 TextfieldViewsModelTest() | 35 TextfieldViewsModelTest() |
26 : ViewsTestBase(), | 36 : ViewsTestBase(), |
27 composition_text_confirmed_or_cleared_(false) { | 37 composition_text_confirmed_or_cleared_(false) { |
28 } | 38 } |
29 | 39 |
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
76 model.MoveCursorLeft(gfx::LINE_BREAK, false); | 86 model.MoveCursorLeft(gfx::LINE_BREAK, false); |
77 EXPECT_FALSE(model.Backspace()); | 87 EXPECT_FALSE(model.Backspace()); |
78 EXPECT_STR_EQ("HELLORLD", model.GetText()); | 88 EXPECT_STR_EQ("HELLORLD", model.GetText()); |
79 // Move the cursor to the end. delete should fail. | 89 // Move the cursor to the end. delete should fail. |
80 model.MoveCursorRight(gfx::LINE_BREAK, false); | 90 model.MoveCursorRight(gfx::LINE_BREAK, false); |
81 EXPECT_FALSE(model.Delete()); | 91 EXPECT_FALSE(model.Delete()); |
82 EXPECT_STR_EQ("HELLORLD", model.GetText()); | 92 EXPECT_STR_EQ("HELLORLD", model.GetText()); |
83 // but backspace should work. | 93 // but backspace should work. |
84 EXPECT_TRUE(model.Backspace()); | 94 EXPECT_TRUE(model.Backspace()); |
85 EXPECT_STR_EQ("HELLORL", model.GetText()); | 95 EXPECT_STR_EQ("HELLORL", model.GetText()); |
96 | |
97 model.MoveCursorTo(gfx::SelectionModel(5)); | |
98 model.ReplaceText(ASCIIToUTF16(" WOR")); | |
99 EXPECT_STR_EQ("HELLO WORL", model.GetText()); | |
100 } | |
101 | |
102 TEST_F(TextfieldViewsModelTest, EditString_SimpleRTL) { | |
103 TextfieldViewsModel model(NULL); | |
104 // Append two strings. | |
105 model.Append(WideToUTF16(L"\x05d0\x05d1\x05d2")); | |
106 EXPECT_EQ(WideToUTF16(L"\x05d0\x05d1\x05d2"), model.GetText()); | |
107 model.Append(WideToUTF16(L"\x05e0\x05e1\x05e2")); | |
msw
2011/09/09 23:03:24
Perhaps make the second string different than the
xji
2011/09/12 21:31:48
they are different.
msw
2011/09/14 02:43:48
doh! you are right.
| |
108 EXPECT_EQ(WideToUTF16(L"\x05d0\x05d1\x05d2\x05e0\x05e1\x05e2"), | |
109 model.GetText()); | |
110 | |
111 // Insert 0x05f0. | |
112 model.MoveCursorTo(gfx::SelectionModel(1U)); | |
113 model.InsertChar(0x05f0); | |
114 EXPECT_EQ(WideToUTF16(L"\x05d0\x05f0\x05d1\x05d2\x05e0\x05e1\x05e2"), | |
115 model.GetText()); | |
116 | |
117 // Replace "\x05d1" with "\x05f1". | |
118 model.ReplaceChar(0x05f1); | |
119 EXPECT_EQ(WideToUTF16(L"\x05d0\x05f0\x5f1\x05d2\x05e0\x05e1\x05e2"), | |
120 model.GetText()); | |
121 | |
122 // Delete and backspace. | |
123 EXPECT_EQ(3U, model.GetCursorPosition()); | |
124 EXPECT_TRUE(model.Delete()); | |
125 EXPECT_EQ(WideToUTF16(L"\x05d0\x05f0\x5f1\x05e0\x05e1\x05e2"), | |
126 model.GetText()); | |
127 EXPECT_TRUE(model.Backspace()); | |
128 EXPECT_EQ(2U, model.GetCursorPosition()); | |
129 EXPECT_EQ(WideToUTF16(L"\x05d0\x05f0\x05e0\x05e1\x05e2"), model.GetText()); | |
130 } | |
131 | |
132 TEST_F(TextfieldViewsModelTest, EditString_ComplexScript) { | |
133 TextfieldViewsModel model(NULL); | |
134 // Append two Hindi strings. | |
135 model.Append(WideToUTF16(L"\x0915\x093f\x0915\x094d\x0915")); | |
136 EXPECT_EQ(WideToUTF16(L"\x0915\x093f\x0915\x094d\x0915"), | |
137 model.GetText()); | |
138 model.Append(WideToUTF16(L"\x0915\x094d\x092e\x094d")); | |
139 EXPECT_EQ(WideToUTF16( | |
140 L"\x0915\x093f\x0915\x094d\x0915\x0915\x094d\x092e\x094d"), | |
141 model.GetText()); | |
142 | |
143 // Check it is not able to place cursor in middle of a grapheme. | |
144 model.MoveCursorTo(gfx::SelectionModel(1U)); | |
145 EXPECT_EQ(0U, model.GetCursorPosition()); | |
146 | |
147 model.MoveCursorTo(gfx::SelectionModel(2U)); | |
148 EXPECT_EQ(2U, model.GetCursorPosition()); | |
149 model.InsertChar('a'); | |
150 EXPECT_EQ(WideToUTF16( | |
151 L"\x0915\x093f\x0061\x0915\x094d\x0915\x0915\x094d\x092e\x094d"), | |
152 model.GetText()); | |
153 | |
154 // ReplaceChar will replace the whole grapheme. | |
155 model.ReplaceChar('b'); | |
156 EXPECT_EQ(WideToUTF16( | |
157 L"\x0915\x093f\x0061\x0062\x0915\x0915\x094d\x092e\x094d"), | |
158 model.GetText()); | |
159 EXPECT_EQ(4U, model.GetCursorPosition()); | |
160 | |
161 // DELETE should delte the whole grapheme. | |
msw
2011/09/09 23:03:24
"Delete" isn't all-caps and "del*e*te".
xji
2011/09/12 21:31:48
Done.
| |
162 model.MoveCursorTo(gfx::SelectionModel(0U)); | |
163 EXPECT_TRUE(model.Delete()); | |
164 EXPECT_EQ(WideToUTF16(L"\x0061\x0062\x0915\x0915\x094d\x092e\x094d"), | |
165 model.GetText()); | |
166 model.MoveCursorTo(gfx::SelectionModel(model.GetText().length())); | |
167 EXPECT_TRUE(model.Backspace()); | |
168 EXPECT_EQ(WideToUTF16(L"\x0061\x0062\x0915\x0915\x094d\x092e"), | |
169 model.GetText()); | |
170 | |
171 // Test cursor position and deletion for Hindi VIRAMA. | |
msw
2011/09/09 23:03:24
Virama isn't all-caps.
xji
2011/09/12 21:31:48
Done.
| |
172 model.SetText(WideToUTF16(L"\x0D38\x0D4D\x0D15\x0D16\x0D2E")); | |
173 model.MoveCursorTo(gfx::SelectionModel(0)); | |
174 EXPECT_EQ(0U, model.GetCursorPosition()); | |
175 | |
176 model.MoveCursorTo(gfx::SelectionModel(1)); | |
177 EXPECT_EQ(0U, model.GetCursorPosition()); | |
178 | |
179 model.MoveCursorTo(gfx::SelectionModel(2)); | |
180 EXPECT_EQ(2U, model.GetCursorPosition()); | |
181 | |
182 model.MoveCursorTo(gfx::SelectionModel(3)); | |
183 EXPECT_EQ(3U, model.GetCursorPosition()); | |
184 | |
185 model.MoveCursorTo(gfx::SelectionModel(2)); | |
186 | |
187 EXPECT_TRUE(model.Backspace()); | |
188 EXPECT_EQ(WideToUTF16(L"\x0D38\x0D15\x0D16\x0D2E"), model.GetText()); | |
189 | |
190 // Test DELETE/BACKSPACE on Hebrew with non-spacing marks. | |
msw
2011/09/09 23:03:24
Delete and Backspace are not all-caps.
xji
2011/09/12 21:31:48
Done.
| |
191 model.SetText(WideToUTF16(L"\x05d5\x05b7\x05D9\x05B0\x05D4\x05B4\x05D9")); | |
192 model.MoveCursorTo(gfx::SelectionModel(0)); | |
193 EXPECT_TRUE(model.Delete()); | |
194 EXPECT_TRUE(model.Delete()); | |
195 EXPECT_TRUE(model.Delete()); | |
196 EXPECT_TRUE(model.Delete()); | |
197 EXPECT_EQ(WideToUTF16(L""), model.GetText()); | |
198 | |
199 model.SetText(WideToUTF16(L"\x002C\x0020\x05D1\x05BC\x05B7\x05E9\x05BC")); | |
200 model.MoveCursorLeft(gfx::LINE_BREAK, false); | |
msw
2011/09/09 23:03:24
Won't this fail on windows if the UI mode isn't RT
xji
2011/09/12 21:31:48
add #if defined and use move to right line end for
| |
201 EXPECT_TRUE(model.Backspace()); | |
202 EXPECT_EQ(WideToUTF16(L"\x002C\x0020\x05D1\x05BC\x05B7\x05E9"), | |
203 model.GetText()); | |
204 } | |
205 | |
206 void RunMoveCursorLeftRightTest(TextfieldViewsModel* model, | |
207 struct Selection* expected, | |
208 int num_of_selection_entry, | |
209 bool move_right) { | |
210 for (int i = 0; i <= num_of_selection_entry + 1; ++i) { | |
msw
2011/09/09 23:03:24
Why are you looping i from 0 to n+1 but then clamp
xji
2011/09/12 21:31:48
It is to test when cursor is at the HOME/END, pres
| |
211 int index = std::min(i, num_of_selection_entry - 1); | |
212 struct Selection sel = expected[index]; | |
msw
2011/09/09 23:03:24
I don't believe 'struct' is needed here and elsewh
xji
2011/09/12 21:31:48
removed struct.
| |
213 EXPECT_TRUE(model->render_text()->selection_model().Equals( | |
214 gfx::SelectionModel(sel.cursor, sel.caret, sel.placement))); | |
215 | |
216 if (move_right) | |
217 model->MoveCursorRight(gfx::CHARACTER_BREAK, false); | |
218 else | |
219 model->MoveCursorLeft(gfx::CHARACTER_BREAK, false); | |
220 } | |
221 | |
222 struct Selection sel = expected[num_of_selection_entry - 1]; | |
223 if (move_right) | |
224 model->MoveCursorRight(gfx::LINE_BREAK, false); | |
225 else | |
226 model->MoveCursorLeft(gfx::LINE_BREAK, false); | |
227 EXPECT_TRUE(model->render_text()->selection_model().Equals( | |
228 gfx::SelectionModel(sel.cursor, sel.caret, sel.placement))); | |
229 } | |
230 | |
231 TEST_F(TextfieldViewsModelTest, MoveCursorLeftRight) { | |
232 TextfieldViewsModel model(NULL); | |
233 | |
234 // Pure LTR. | |
235 model.SetText(ASCIIToUTF16("abc")); | |
236 // left_to_right saves the expected (cursor, caret, caret_placement) triplet | |
237 // when moving cursor from left to right. | |
238 struct Selection left_to_right[] = { | |
msw
2011/09/09 23:03:24
Use std::vector<gfx::SelectionModel> instead here
xji
2011/09/12 21:31:48
Done.
| |
239 {0, 0, gfx::SelectionModel::LEADING}, | |
240 {1, 0, gfx::SelectionModel::TRAILING}, | |
241 {2, 1, gfx::SelectionModel::TRAILING}, | |
242 {3, 2, gfx::SelectionModel::TRAILING}, | |
243 }; | |
244 RunMoveCursorLeftRightTest(&model, left_to_right, | |
245 sizeof(left_to_right)/sizeof(struct Selection), true); | |
246 | |
247 struct Selection right_to_left[] = { | |
248 {3, 2, gfx::SelectionModel::TRAILING}, | |
249 {2, 2, gfx::SelectionModel::LEADING}, | |
250 {1, 1, gfx::SelectionModel::LEADING}, | |
251 {0, 0, gfx::SelectionModel::LEADING}, | |
252 }; | |
253 RunMoveCursorLeftRightTest(&model, right_to_left, | |
254 sizeof(right_to_left)/sizeof(struct Selection), false); | |
255 | |
256 // Pure RTL. | |
257 model.SetText(WideToUTF16(L"\x05d0\x05d1\x05d2")); | |
258 struct Selection right_to_left_h[] = { | |
259 {0, 0, gfx::SelectionModel::LEADING}, | |
260 {1, 0, gfx::SelectionModel::TRAILING}, | |
261 {2, 1, gfx::SelectionModel::TRAILING}, | |
262 {3, 2, gfx::SelectionModel::TRAILING}, | |
263 }; | |
264 RunMoveCursorLeftRightTest(&model, right_to_left_h, | |
265 sizeof(right_to_left_h)/sizeof(struct Selection), false); | |
266 | |
267 struct Selection left_to_right_h[] = { | |
268 {3, 2, gfx::SelectionModel::TRAILING}, | |
269 {2, 2, gfx::SelectionModel::LEADING}, | |
270 {1, 1, gfx::SelectionModel::LEADING}, | |
271 {0, 0, gfx::SelectionModel::LEADING}, | |
272 }; | |
273 RunMoveCursorLeftRightTest(&model, left_to_right_h, | |
274 sizeof(left_to_right_h)/sizeof(struct Selection), true); | |
275 | |
276 // LTR-RTL | |
277 model.SetText(WideToUTF16(L"abc\x05d0\x05d1\x05d2")); | |
278 // The last one is the expected END position. | |
279 struct Selection right_to_left_eh[] = { | |
280 {0, 0, gfx::SelectionModel::LEADING}, | |
281 {1, 0, gfx::SelectionModel::TRAILING}, | |
282 {2, 1, gfx::SelectionModel::TRAILING}, | |
283 {3, 2, gfx::SelectionModel::TRAILING}, | |
284 {5, 5, gfx::SelectionModel::LEADING}, | |
285 {4, 4, gfx::SelectionModel::LEADING}, | |
286 {3, 3, gfx::SelectionModel::LEADING}, | |
287 {6, 3, gfx::SelectionModel::LEADING}, | |
288 }; | |
289 RunMoveCursorLeftRightTest(&model, right_to_left_eh, | |
290 sizeof(right_to_left_eh)/sizeof(struct Selection), true); | |
291 | |
292 struct Selection left_to_right_eh[] = { | |
293 {6, 3, gfx::SelectionModel::LEADING}, | |
294 {4, 3, gfx::SelectionModel::TRAILING}, | |
295 {5, 4, gfx::SelectionModel::TRAILING}, | |
296 {6, 5, gfx::SelectionModel::TRAILING}, | |
297 {2, 2, gfx::SelectionModel::LEADING}, | |
298 {1, 1, gfx::SelectionModel::LEADING}, | |
299 {0, 0, gfx::SelectionModel::LEADING}, | |
300 }; | |
301 RunMoveCursorLeftRightTest(&model, left_to_right_eh, | |
302 sizeof(left_to_right_eh)/sizeof(struct Selection), false); | |
303 | |
304 // RTL-LTR | |
305 model.SetText(WideToUTF16(L"\x05d0\x05d1\x05d2"L"abc")); | |
306 struct Selection right_to_left_he[] = { | |
307 {0, 0, gfx::SelectionModel::LEADING}, | |
308 {1, 0, gfx::SelectionModel::TRAILING}, | |
309 {2, 1, gfx::SelectionModel::TRAILING}, | |
310 {3, 2, gfx::SelectionModel::TRAILING}, | |
311 {5, 5, gfx::SelectionModel::LEADING}, | |
312 {4, 4, gfx::SelectionModel::LEADING}, | |
313 {3, 3, gfx::SelectionModel::LEADING}, | |
314 {6, 3, gfx::SelectionModel::LEADING}, | |
315 }; | |
316 RunMoveCursorLeftRightTest(&model, right_to_left_he, | |
317 sizeof(right_to_left_he)/sizeof(struct Selection), false); | |
318 | |
319 struct Selection left_to_right_he[] = { | |
320 {6, 3, gfx::SelectionModel::LEADING}, | |
321 {4, 3, gfx::SelectionModel::TRAILING}, | |
322 {5, 4, gfx::SelectionModel::TRAILING}, | |
323 {6, 5, gfx::SelectionModel::TRAILING}, | |
324 {2, 2, gfx::SelectionModel::LEADING}, | |
325 {1, 1, gfx::SelectionModel::LEADING}, | |
326 {0, 0, gfx::SelectionModel::LEADING}, | |
327 }; | |
328 RunMoveCursorLeftRightTest(&model, left_to_right_he, | |
329 sizeof(left_to_right_he)/sizeof(struct Selection), true); | |
330 | |
331 // LTR-RTL-LTR. | |
332 model.SetText(WideToUTF16(L"a"L"\x05d1"L"b")); | |
333 struct Selection left_to_right_ehe[] = { | |
334 {0, 0, gfx::SelectionModel::LEADING}, | |
335 {1, 0, gfx::SelectionModel::TRAILING}, | |
336 {1, 1, gfx::SelectionModel::LEADING}, | |
337 {3, 2, gfx::SelectionModel::TRAILING}, | |
338 }; | |
339 RunMoveCursorLeftRightTest(&model, left_to_right_ehe, | |
340 sizeof(left_to_right_ehe)/sizeof(struct Selection), true); | |
341 | |
342 struct Selection right_to_left_ehe[] = { | |
343 {3, 2, gfx::SelectionModel::TRAILING}, | |
344 {2, 2, gfx::SelectionModel::LEADING}, | |
345 {2, 1, gfx::SelectionModel::TRAILING}, | |
346 {0, 0, gfx::SelectionModel::LEADING}, | |
347 }; | |
348 RunMoveCursorLeftRightTest(&model, right_to_left_ehe, | |
349 sizeof(right_to_left_ehe)/sizeof(struct Selection), false); | |
350 | |
351 // RTL-LTR-RTL. | |
352 model.SetText(WideToUTF16(L"\x05d0"L"a"L"\x05d1")); | |
353 struct Selection right_to_left_heh[] = { | |
354 {0, 0, gfx::SelectionModel::LEADING}, | |
355 {1, 0, gfx::SelectionModel::TRAILING}, | |
356 {1, 1, gfx::SelectionModel::LEADING}, | |
357 {3, 2, gfx::SelectionModel::TRAILING}, | |
358 }; | |
359 RunMoveCursorLeftRightTest(&model, right_to_left_heh, | |
360 sizeof(right_to_left_heh)/sizeof(struct Selection), false); | |
361 | |
362 struct Selection left_to_right_heh[] = { | |
363 {3, 2, gfx::SelectionModel::TRAILING}, | |
364 {2, 2, gfx::SelectionModel::LEADING}, | |
365 {2, 1, gfx::SelectionModel::TRAILING}, | |
366 {0, 0, gfx::SelectionModel::LEADING}, | |
367 }; | |
368 RunMoveCursorLeftRightTest(&model, left_to_right_heh, | |
369 sizeof(left_to_right_heh)/sizeof(struct Selection), true); | |
370 } | |
371 | |
372 TEST_F(TextfieldViewsModelTest, MoveCursorLeftRight_ComplexScript) { | |
373 TextfieldViewsModel model(NULL); | |
374 | |
375 model.Append(WideToUTF16(L"\x0915\x093f\x0915\x094d\x0915")); | |
msw
2011/09/09 23:03:24
Any reason you chose not to use RunMoveCursorLeftR
xji
2011/09/12 21:31:48
since this is uni-directional text, I am not testi
| |
376 EXPECT_EQ(0U, model.GetCursorPosition()); | |
377 model.MoveCursorRight(gfx::CHARACTER_BREAK, false); | |
378 EXPECT_EQ(2U, model.GetCursorPosition()); | |
379 model.MoveCursorRight(gfx::CHARACTER_BREAK, false); | |
380 EXPECT_EQ(4U, model.GetCursorPosition()); | |
381 model.MoveCursorRight(gfx::CHARACTER_BREAK, false); | |
382 EXPECT_EQ(5U, model.GetCursorPosition()); | |
383 model.MoveCursorRight(gfx::CHARACTER_BREAK, false); | |
384 EXPECT_EQ(5U, model.GetCursorPosition()); | |
385 | |
386 model.MoveCursorLeft(gfx::CHARACTER_BREAK, false); | |
387 EXPECT_EQ(4U, model.GetCursorPosition()); | |
388 model.MoveCursorLeft(gfx::CHARACTER_BREAK, false); | |
389 EXPECT_EQ(2U, model.GetCursorPosition()); | |
390 model.MoveCursorLeft(gfx::CHARACTER_BREAK, false); | |
391 EXPECT_EQ(0U, model.GetCursorPosition()); | |
392 model.MoveCursorLeft(gfx::CHARACTER_BREAK, false); | |
393 EXPECT_EQ(0U, model.GetCursorPosition()); | |
86 } | 394 } |
87 | 395 |
88 TEST_F(TextfieldViewsModelTest, EmptyString) { | 396 TEST_F(TextfieldViewsModelTest, EmptyString) { |
89 TextfieldViewsModel model(NULL); | 397 TextfieldViewsModel model(NULL); |
90 EXPECT_EQ(string16(), model.GetText()); | 398 EXPECT_EQ(string16(), model.GetText()); |
91 EXPECT_EQ(string16(), model.GetSelectedText()); | 399 EXPECT_EQ(string16(), model.GetSelectedText()); |
92 EXPECT_EQ(string16(), model.GetVisibleText()); | 400 EXPECT_EQ(string16(), model.GetVisibleText()); |
93 | 401 |
94 model.MoveCursorLeft(gfx::CHARACTER_BREAK, true); | 402 model.MoveCursorLeft(gfx::CHARACTER_BREAK, true); |
95 EXPECT_EQ(0U, model.GetCursorPosition()); | 403 EXPECT_EQ(0U, model.GetCursorPosition()); |
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
136 | 444 |
137 // Select all and move cursor | 445 // Select all and move cursor |
138 model.SelectAll(); | 446 model.SelectAll(); |
139 model.MoveCursorLeft(gfx::CHARACTER_BREAK, false); | 447 model.MoveCursorLeft(gfx::CHARACTER_BREAK, false); |
140 EXPECT_EQ(0U, model.GetCursorPosition()); | 448 EXPECT_EQ(0U, model.GetCursorPosition()); |
141 model.SelectAll(); | 449 model.SelectAll(); |
142 model.MoveCursorRight(gfx::CHARACTER_BREAK, false); | 450 model.MoveCursorRight(gfx::CHARACTER_BREAK, false); |
143 EXPECT_EQ(5U, model.GetCursorPosition()); | 451 EXPECT_EQ(5U, model.GetCursorPosition()); |
144 } | 452 } |
145 | 453 |
454 TEST_F(TextfieldViewsModelTest, Selection_BidiWithNonSpacingMarks) { | |
455 TextfieldViewsModel model(NULL); | |
456 model.Append(WideToUTF16( | |
457 L"abc\x05E9\x05BC\x05C1\x05B8\x05E0\x05B8"L"def")); | |
458 model.MoveCursorRight(gfx::CHARACTER_BREAK, false); | |
459 model.MoveCursorRight(gfx::CHARACTER_BREAK, false); | |
460 | |
461 model.MoveCursorRight(gfx::CHARACTER_BREAK, true); | |
462 EXPECT_EQ(WideToUTF16(L"c"), model.GetSelectedText()); | |
463 | |
464 model.MoveCursorRight(gfx::CHARACTER_BREAK, true); | |
465 EXPECT_EQ(WideToUTF16(L"c\x05E9\x05BC\x05C1\x05B8"), | |
466 model.GetSelectedText()); | |
467 | |
468 model.MoveCursorRight(gfx::CHARACTER_BREAK, true); | |
469 EXPECT_EQ(WideToUTF16(L"c"), model.GetSelectedText()); | |
msw
2011/09/09 23:03:24
This is the spec'ed behavior, but it might confuse
xji
2011/09/12 21:31:48
added comments and selection_start/end expected re
| |
470 | |
471 model.MoveCursorRight(gfx::CHARACTER_BREAK, true); | |
472 EXPECT_EQ(WideToUTF16(L"c\x05E9\x05BC\x05C1\x05B8\x05E0\x05B8"L"d"), | |
473 model.GetSelectedText()); | |
474 | |
475 model.ClearSelection(); | |
476 EXPECT_EQ(string16(), model.GetSelectedText()); | |
477 model.SelectAll(); | |
478 EXPECT_EQ(WideToUTF16(L"abc\x05E9\x05BC\x05C1\x05B8\x05E0\x05B8"L"def"), | |
479 model.GetSelectedText()); | |
480 | |
481 // In case of "aBc", this test shows how to select "aB" or "Bc", assume 'B' is | |
482 // an RTL character. | |
483 model.SetText(WideToUTF16(L"a\x05E9"L"b")); | |
484 model.MoveCursorTo(gfx::SelectionModel(0)); | |
485 model.MoveCursorRight(gfx::CHARACTER_BREAK, true); | |
486 EXPECT_EQ(WideToUTF16(L"a"), model.GetSelectedText()); | |
487 | |
488 model.MoveCursorRight(gfx::CHARACTER_BREAK, true); | |
489 EXPECT_EQ(WideToUTF16(L"a"), model.GetSelectedText()); | |
490 | |
491 model.MoveCursorRight(gfx::CHARACTER_BREAK, true); | |
492 EXPECT_EQ(WideToUTF16(L"a\x05E9"L"b"), model.GetSelectedText()); | |
493 | |
494 model.MoveCursorRight(gfx::CHARACTER_BREAK, false); | |
495 EXPECT_EQ(3U, model.GetCursorPosition()); | |
496 model.MoveCursorLeft(gfx::CHARACTER_BREAK, true); | |
497 EXPECT_EQ(WideToUTF16(L"b"), model.GetSelectedText()); | |
498 | |
499 model.MoveCursorLeft(gfx::CHARACTER_BREAK, true); | |
500 EXPECT_EQ(WideToUTF16(L"b"), model.GetSelectedText()); | |
501 | |
502 model.MoveCursorLeft(gfx::CHARACTER_BREAK, true); | |
503 EXPECT_EQ(WideToUTF16(L"a\x05E9"L"b"), model.GetSelectedText()); | |
504 | |
505 model.MoveCursorLeft(gfx::LINE_BREAK, false); | |
506 model.MoveCursorRight(gfx::CHARACTER_BREAK, true); | |
507 model.MoveCursorRight(gfx::CHARACTER_BREAK, true); | |
508 model.MoveCursorLeft(gfx::CHARACTER_BREAK, true); | |
509 EXPECT_EQ(WideToUTF16(L"a\x05E9"), model.GetSelectedText()); | |
510 | |
511 model.MoveCursorRight(gfx::LINE_BREAK, false); | |
512 model.MoveCursorLeft(gfx::CHARACTER_BREAK, true); | |
513 model.MoveCursorLeft(gfx::CHARACTER_BREAK, true); | |
514 model.MoveCursorRight(gfx::CHARACTER_BREAK, true); | |
515 EXPECT_EQ(WideToUTF16(L"\x05E9"L"b"), model.GetSelectedText()); | |
516 | |
517 model.ClearSelection(); | |
518 EXPECT_EQ(string16(), model.GetSelectedText()); | |
519 model.SelectAll(); | |
520 EXPECT_EQ(WideToUTF16(L"a\x05E9"L"b"), model.GetSelectedText()); | |
521 } | |
522 | |
523 TEST_F(TextfieldViewsModelTest, MoveCursorLeftRightWithSelection) { | |
524 TextfieldViewsModel model(NULL); | |
525 model.SetText(WideToUTF16(L"abc\x05d0\x05d1\x05d2")); | |
msw
2011/09/09 23:03:24
Please add EXPECT_EQs for model.GetCursorPosition
xji
2011/09/12 21:31:48
Done.
| |
526 model.MoveCursorRight(gfx::LINE_BREAK, false); | |
527 model.MoveCursorLeft(gfx::CHARACTER_BREAK, false); | |
528 model.MoveCursorLeft(gfx::CHARACTER_BREAK, false); | |
529 model.MoveCursorLeft(gfx::CHARACTER_BREAK, false); | |
530 model.MoveCursorRight(gfx::CHARACTER_BREAK, true); | |
531 model.MoveCursorRight(gfx::CHARACTER_BREAK, true); | |
532 model.MoveCursorLeft(gfx::CHARACTER_BREAK, false); | |
533 EXPECT_EQ(6U, model.GetCursorPosition()); | |
534 | |
535 model.MoveCursorLeft(gfx::LINE_BREAK, false); | |
536 model.MoveCursorRight(gfx::CHARACTER_BREAK, false); | |
537 model.MoveCursorRight(gfx::CHARACTER_BREAK, false); | |
538 model.MoveCursorRight(gfx::CHARACTER_BREAK, false); | |
539 model.MoveCursorRight(gfx::CHARACTER_BREAK, false); | |
540 model.MoveCursorRight(gfx::CHARACTER_BREAK, false); | |
541 | |
msw
2011/09/09 23:03:24
nit: The very similar block above doesn't have a b
xji
2011/09/12 21:31:48
removed blank line.
| |
542 model.MoveCursorLeft(gfx::CHARACTER_BREAK, true); | |
543 model.MoveCursorLeft(gfx::CHARACTER_BREAK, true); | |
544 model.MoveCursorRight(gfx::CHARACTER_BREAK, false); | |
545 EXPECT_EQ(4U, model.GetCursorPosition()); | |
546 } | |
547 | |
146 TEST_F(TextfieldViewsModelTest, SelectionAndEdit) { | 548 TEST_F(TextfieldViewsModelTest, SelectionAndEdit) { |
147 TextfieldViewsModel model(NULL); | 549 TextfieldViewsModel model(NULL); |
148 model.Append(ASCIIToUTF16("HELLO")); | 550 model.Append(ASCIIToUTF16("HELLO")); |
149 model.MoveCursorRight(gfx::CHARACTER_BREAK, false); | 551 model.MoveCursorRight(gfx::CHARACTER_BREAK, false); |
150 model.MoveCursorRight(gfx::CHARACTER_BREAK, true); | 552 model.MoveCursorRight(gfx::CHARACTER_BREAK, true); |
151 model.MoveCursorRight(gfx::CHARACTER_BREAK, true); // select "EL" | 553 model.MoveCursorRight(gfx::CHARACTER_BREAK, true); // select "EL" |
152 EXPECT_TRUE(model.Backspace()); | 554 EXPECT_TRUE(model.Backspace()); |
153 EXPECT_STR_EQ("HLO", model.GetText()); | 555 EXPECT_STR_EQ("HLO", model.GetText()); |
154 | 556 |
155 model.Append(ASCIIToUTF16("ILL")); | 557 model.Append(ASCIIToUTF16("ILL")); |
(...skipping 151 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
307 model.MoveCursorRight(gfx::LINE_BREAK, false); | 709 model.MoveCursorRight(gfx::LINE_BREAK, false); |
308 model.MoveCursorLeft(gfx::WORD_BREAK, true); | 710 model.MoveCursorLeft(gfx::WORD_BREAK, true); |
309 EXPECT_TRUE(model.Paste()); | 711 EXPECT_TRUE(model.Paste()); |
310 clipboard->ReadText(ui::Clipboard::BUFFER_STANDARD, &clipboard_text); | 712 clipboard->ReadText(ui::Clipboard::BUFFER_STANDARD, &clipboard_text); |
311 EXPECT_STR_EQ("HELLO HELLO WORLD", clipboard_text); | 713 EXPECT_STR_EQ("HELLO HELLO WORLD", clipboard_text); |
312 EXPECT_STR_EQ("HELLO HELLO HELLO HELLO WORLD", model.GetText()); | 714 EXPECT_STR_EQ("HELLO HELLO HELLO HELLO WORLD", model.GetText()); |
313 EXPECT_EQ(29U, model.GetCursorPosition()); | 715 EXPECT_EQ(29U, model.GetCursorPosition()); |
314 } | 716 } |
315 | 717 |
316 void SelectWordTestVerifier(TextfieldViewsModel &model, | 718 void SelectWordTestVerifier(TextfieldViewsModel &model, |
317 const std::string &expected_selected_string, size_t expected_cursor_pos) { | 719 const string16 &expected_selected_string, size_t expected_cursor_pos) { |
318 EXPECT_STR_EQ(expected_selected_string, model.GetSelectedText()); | 720 EXPECT_EQ(expected_selected_string, model.GetSelectedText()); |
319 EXPECT_EQ(expected_cursor_pos, model.GetCursorPosition()); | 721 EXPECT_EQ(expected_cursor_pos, model.GetCursorPosition()); |
320 } | 722 } |
321 | 723 |
322 TEST_F(TextfieldViewsModelTest, SelectWordTest) { | 724 TEST_F(TextfieldViewsModelTest, SelectWordTest) { |
323 TextfieldViewsModel model(NULL); | 725 TextfieldViewsModel model(NULL); |
324 model.Append(ASCIIToUTF16(" HELLO !! WO RLD ")); | 726 model.Append(ASCIIToUTF16(" HELLO !! WO RLD ")); |
325 | 727 |
326 // Test when cursor is at the beginning. | 728 // Test when cursor is at the beginning. |
327 model.MoveCursorLeft(gfx::LINE_BREAK, false); | 729 model.MoveCursorLeft(gfx::LINE_BREAK, false); |
328 model.SelectWord(); | 730 model.SelectWord(); |
329 SelectWordTestVerifier(model, " ", 2U); | 731 SelectWordTestVerifier(model, ASCIIToUTF16(" "), 2U); |
330 | 732 |
331 // Test when cursor is at the beginning of a word. | 733 // Test when cursor is at the beginning of a word. |
332 gfx::SelectionModel selection(2U); | 734 gfx::SelectionModel selection(2U); |
333 model.MoveCursorTo(selection); | 735 model.MoveCursorTo(selection); |
334 model.SelectWord(); | 736 model.SelectWord(); |
335 SelectWordTestVerifier(model, "HELLO", 7U); | 737 SelectWordTestVerifier(model, ASCIIToUTF16("HELLO"), 7U); |
336 | 738 |
337 // Test when cursor is at the end of a word. | 739 // Test when cursor is at the end of a word. |
338 selection = gfx::SelectionModel(15U); | 740 selection = gfx::SelectionModel(15U); |
339 model.MoveCursorTo(selection); | 741 model.MoveCursorTo(selection); |
340 model.SelectWord(); | 742 model.SelectWord(); |
341 SelectWordTestVerifier(model, "WO", 15U); | 743 SelectWordTestVerifier(model, ASCIIToUTF16(" "), 20U); |
342 | 744 |
343 // Test when cursor is somewhere in a non-alph-numeric fragment. | 745 // Test when cursor is somewhere in a non-alph-numeric fragment. |
msw
2011/09/09 23:03:24
nit: mind fixing "alph*a*"?
xji
2011/09/12 21:31:48
Done.
| |
344 for (size_t cursor_pos = 8; cursor_pos < 13U; cursor_pos++) { | 746 for (size_t cursor_pos = 8; cursor_pos < 13U; cursor_pos++) { |
345 selection = gfx::SelectionModel(cursor_pos); | 747 selection = gfx::SelectionModel(cursor_pos); |
346 model.MoveCursorTo(selection); | 748 model.MoveCursorTo(selection); |
347 model.SelectWord(); | 749 model.SelectWord(); |
348 SelectWordTestVerifier(model, " !! ", 13U); | 750 SelectWordTestVerifier(model, ASCIIToUTF16(" !! "), 13U); |
349 } | 751 } |
350 | 752 |
351 // Test when cursor is somewhere in a whitespace fragment. | 753 // Test when cursor is somewhere in a whitespace fragment. |
352 selection = gfx::SelectionModel(17U); | 754 selection = gfx::SelectionModel(17U); |
353 model.MoveCursorTo(selection); | 755 model.MoveCursorTo(selection); |
354 model.SelectWord(); | 756 model.SelectWord(); |
355 SelectWordTestVerifier(model, " ", 20U); | 757 SelectWordTestVerifier(model, ASCIIToUTF16(" "), 20U); |
356 | 758 |
357 // Test when cursor is at the end. | 759 // Test when cursor is at the end. |
358 model.MoveCursorRight(gfx::LINE_BREAK, false); | 760 model.MoveCursorRight(gfx::LINE_BREAK, false); |
359 model.SelectWord(); | 761 model.SelectWord(); |
360 SelectWordTestVerifier(model, " ", 24U); | 762 SelectWordTestVerifier(model, ASCIIToUTF16(" "), 24U); |
763 } | |
764 | |
765 TEST_F(TextfieldViewsModelTest, SelectWordTest_MixScripts) { | |
766 TextfieldViewsModel model(NULL); | |
767 const struct WordAndCursor { | |
768 const wchar_t* word; | |
769 size_t cursor; | |
770 } words_and_cursor[] = { | |
msw
2011/09/09 23:03:24
I suppose this works, but would you mind splitting
xji
2011/09/12 21:31:48
Done.
| |
771 {L"a\x05d0", 2}, | |
772 {L"a\x05d0", 2}, | |
773 {L"\x05d1\x05d2", 5}, | |
774 {L"\x05d1\x05d2", 5}, | |
775 {L" ", 3}, | |
776 {L"a\x05d0", 2}, | |
777 {L"\x0915\x094d\x0915", 9}, | |
778 {L"\x0915\x094d\x0915", 9}, | |
779 {L" ", 10}, | |
780 {L"\x4E2D\x56FD", 12}, | |
781 {L"\x4E2D\x56FD", 12}, | |
782 {L"\x82B1", 13}, | |
783 {L"\x5929", 14}, | |
784 }; | |
785 // The text consists of Ascii, Hebrew, Hindi with Virama sign, and Chinese. | |
msw
2011/09/09 23:03:24
Extra space in "with * *Virama"
xji
2011/09/12 21:31:48
Done.
| |
786 model.SetText(WideToUTF16(L"a\x05d0 \x05d1\x05d2 \x0915\x094d\x0915 " | |
787 L"\x4E2D\x56FD\x82B1\x5929")); | |
788 for (size_t i = 0; i < sizeof(words_and_cursor)/sizeof(WordAndCursor); | |
msw
2011/09/09 23:03:24
Wouldn't it be a bit clearer to remove the WordAnd
xji
2011/09/12 21:31:48
that is true. But the current one also tests the s
| |
789 ++i) { | |
790 model.MoveCursorLeft(gfx::LINE_BREAK, false); | |
791 for (size_t j = 0; j < i; ++j) | |
792 model.MoveCursorRight(gfx::CHARACTER_BREAK, false); | |
793 model.SelectWord(); | |
794 SelectWordTestVerifier(model, WideToUTF16(words_and_cursor[i].word), | |
795 words_and_cursor[i].cursor); | |
796 } | |
361 } | 797 } |
362 | 798 |
363 TEST_F(TextfieldViewsModelTest, RangeTest) { | 799 TEST_F(TextfieldViewsModelTest, RangeTest) { |
364 TextfieldViewsModel model(NULL); | 800 TextfieldViewsModel model(NULL); |
365 model.Append(ASCIIToUTF16("HELLO WORLD")); | 801 model.Append(ASCIIToUTF16("HELLO WORLD")); |
366 model.MoveCursorLeft(gfx::LINE_BREAK, false); | 802 model.MoveCursorLeft(gfx::LINE_BREAK, false); |
367 ui::Range range; | 803 ui::Range range; |
368 model.GetSelectedRange(&range); | 804 model.GetSelectedRange(&range); |
369 EXPECT_TRUE(range.is_empty()); | 805 EXPECT_TRUE(range.is_empty()); |
370 EXPECT_EQ(0U, range.start()); | 806 EXPECT_EQ(0U, range.start()); |
(...skipping 764 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1135 EXPECT_TRUE(model.Undo()); | 1571 EXPECT_TRUE(model.Undo()); |
1136 EXPECT_STR_EQ("ABCDE", model.GetText()); | 1572 EXPECT_STR_EQ("ABCDE", model.GetText()); |
1137 EXPECT_TRUE(model.Redo()); | 1573 EXPECT_TRUE(model.Redo()); |
1138 EXPECT_STR_EQ("1234", model.GetText()); | 1574 EXPECT_STR_EQ("1234", model.GetText()); |
1139 EXPECT_FALSE(model.Redo()); | 1575 EXPECT_FALSE(model.Redo()); |
1140 | 1576 |
1141 // TODO(oshima): We need MockInputMethod to test the behavior with IME. | 1577 // TODO(oshima): We need MockInputMethod to test the behavior with IME. |
1142 } | 1578 } |
1143 | 1579 |
1144 } // namespace views | 1580 } // namespace views |
OLD | NEW |