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.
7 #include "base/auto_reset.h"
8 #include "base/memory/scoped_ptr.h"
9 #include "base/message_loop/message_loop.h"
10 #include "base/strings/string16.h"
11 #include "base/strings/utf_string_conversions.h"
12 #include "testing/gtest/include/gtest/gtest.h"
13 #include "ui/base/clipboard/clipboard.h"
14 #include "ui/base/clipboard/scoped_clipboard_writer.h"
15 #include "ui/gfx/range/range.h"
16 #include "ui/gfx/render_text.h"
17 #include "ui/views/controls/textfield/textfield.h"
18 #include "ui/views/controls/textfield/textfield_views_model.h"
19 #include "ui/views/test/test_views_delegate.h"
20 #include "ui/views/test/views_test_base.h"
23 #include "base/win/windows_version.h"
26 #define EXPECT_STR_EQ(ascii, utf16) EXPECT_EQ(ASCIIToUTF16(ascii), utf16)
30 struct WordAndCursor {
31 WordAndCursor(const wchar_t* w, size_t c) : word(w), cursor(c) {}
37 void MoveCursorTo(views::TextfieldViewsModel& model, size_t pos) {
38 model.MoveCursorTo(gfx::SelectionModel(pos, gfx::CURSOR_FORWARD));
45 class TextfieldViewsModelTest : public ViewsTestBase,
46 public TextfieldViewsModel::Delegate {
48 TextfieldViewsModelTest()
50 composition_text_confirmed_or_cleared_(false) {
53 virtual void OnCompositionTextConfirmedOrCleared() OVERRIDE {
54 composition_text_confirmed_or_cleared_ = true;
58 void ResetModel(TextfieldViewsModel* model) const {
59 model->SetText(string16());
60 model->ClearEditHistory();
63 bool composition_text_confirmed_or_cleared_;
66 DISALLOW_COPY_AND_ASSIGN(TextfieldViewsModelTest);
69 TEST_F(TextfieldViewsModelTest, EditString) {
70 TextfieldViewsModel model(NULL);
72 model.Append(ASCIIToUTF16("HILL"));
73 EXPECT_STR_EQ("HILL", model.GetText());
74 model.Append(ASCIIToUTF16("WORLD"));
75 EXPECT_STR_EQ("HILLWORLD", model.GetText());
77 // Insert "E" to make hello
78 model.MoveCursor(gfx::CHARACTER_BREAK, gfx::CURSOR_RIGHT, false);
79 model.InsertChar('E');
80 EXPECT_STR_EQ("HEILLWORLD", model.GetText());
81 // Replace "I" with "L"
82 model.ReplaceChar('L');
83 EXPECT_STR_EQ("HELLLWORLD", model.GetText());
84 model.ReplaceChar('L');
85 model.ReplaceChar('O');
86 EXPECT_STR_EQ("HELLOWORLD", model.GetText());
88 // Delete 6th char "W", then delete 5th char O"
89 EXPECT_EQ(5U, model.GetCursorPosition());
90 EXPECT_TRUE(model.Delete());
91 EXPECT_STR_EQ("HELLOORLD", model.GetText());
92 EXPECT_TRUE(model.Backspace());
93 EXPECT_EQ(4U, model.GetCursorPosition());
94 EXPECT_STR_EQ("HELLORLD", model.GetText());
96 // Move the cursor to start. backspace should fail.
97 model.MoveCursor(gfx::LINE_BREAK, gfx::CURSOR_LEFT, false);
98 EXPECT_FALSE(model.Backspace());
99 EXPECT_STR_EQ("HELLORLD", model.GetText());
100 // Move the cursor to the end. delete should fail.
101 model.MoveCursor(gfx::LINE_BREAK, gfx::CURSOR_RIGHT, false);
102 EXPECT_FALSE(model.Delete());
103 EXPECT_STR_EQ("HELLORLD", model.GetText());
104 // but backspace should work.
105 EXPECT_TRUE(model.Backspace());
106 EXPECT_STR_EQ("HELLORL", model.GetText());
108 MoveCursorTo(model, 5);
109 model.ReplaceText(ASCIIToUTF16(" WOR"));
110 EXPECT_STR_EQ("HELLO WORL", model.GetText());
113 TEST_F(TextfieldViewsModelTest, EditString_SimpleRTL) {
114 TextfieldViewsModel model(NULL);
115 // Append two strings.
116 model.Append(WideToUTF16(L"\x05d0\x05d1\x05d2"));
117 EXPECT_EQ(WideToUTF16(L"\x05d0\x05d1\x05d2"), model.GetText());
118 model.Append(WideToUTF16(L"\x05e0\x05e1\x05e2"));
119 EXPECT_EQ(WideToUTF16(L"\x05d0\x05d1\x05d2\x05e0\x05e1\x05e2"),
123 MoveCursorTo(model, 1);
124 model.InsertChar(0x05f0);
125 EXPECT_EQ(WideToUTF16(L"\x05d0\x05f0\x05d1\x05d2\x05e0\x05e1\x05e2"),
128 // Replace "\x05d1" with "\x05f1".
129 model.ReplaceChar(0x05f1);
130 EXPECT_EQ(WideToUTF16(L"\x05d0\x05f0\x5f1\x05d2\x05e0\x05e1\x05e2"),
133 // Delete and backspace.
134 EXPECT_EQ(3U, model.GetCursorPosition());
135 EXPECT_TRUE(model.Delete());
136 EXPECT_EQ(WideToUTF16(L"\x05d0\x05f0\x5f1\x05e0\x05e1\x05e2"),
138 EXPECT_TRUE(model.Backspace());
139 EXPECT_EQ(2U, model.GetCursorPosition());
140 EXPECT_EQ(WideToUTF16(L"\x05d0\x05f0\x05e0\x05e1\x05e2"), model.GetText());
143 TEST_F(TextfieldViewsModelTest, EditString_ComplexScript) {
144 // TODO(asvitkine): Disable tests that fail on XP bots due to lack of complete
145 // font support for some scripts - http://crbug.com/106450
146 bool on_windows_xp = false;
148 on_windows_xp = base::win::GetVersion() < base::win::VERSION_VISTA;
151 TextfieldViewsModel model(NULL);
153 // Append two Hindi strings.
154 model.Append(WideToUTF16(L"\x0915\x093f\x0915\x094d\x0915"));
155 EXPECT_EQ(WideToUTF16(L"\x0915\x093f\x0915\x094d\x0915"),
157 model.Append(WideToUTF16(L"\x0915\x094d\x092e\x094d"));
158 EXPECT_EQ(WideToUTF16(
159 L"\x0915\x093f\x0915\x094d\x0915\x0915\x094d\x092e\x094d"),
162 // TODO(asvitkine): Disable tests that fail on XP bots due to lack of complete
163 // font support for some scripts - http://crbug.com/106450
164 if (!on_windows_xp) {
165 // Check it is not able to place cursor in middle of a grapheme.
166 MoveCursorTo(model, 1);
167 EXPECT_EQ(0U, model.GetCursorPosition());
169 MoveCursorTo(model, 2);
170 EXPECT_EQ(2U, model.GetCursorPosition());
171 model.InsertChar('a');
172 EXPECT_EQ(WideToUTF16(
173 L"\x0915\x093f\x0061\x0915\x094d\x0915\x0915\x094d\x092e\x094d"),
176 // ReplaceChar will replace the whole grapheme.
177 model.ReplaceChar('b');
178 // TODO(xji): temporarily disable in platform Win since the complex script
179 // characters turned into empty square due to font regression. So, not able
180 // to test 2 characters belong to the same grapheme.
181 #if defined(OS_LINUX)
182 EXPECT_EQ(WideToUTF16(
183 L"\x0915\x093f\x0061\x0062\x0915\x0915\x094d\x092e\x094d"),
186 EXPECT_EQ(4U, model.GetCursorPosition());
189 // Delete should delete the whole grapheme.
190 MoveCursorTo(model, 0);
191 // TODO(xji): temporarily disable in platform Win since the complex script
192 // characters turned into empty square due to font regression. So, not able
193 // to test 2 characters belong to the same grapheme.
194 #if defined(OS_LINUX)
195 EXPECT_TRUE(model.Delete());
196 EXPECT_EQ(WideToUTF16(L"\x0061\x0062\x0915\x0915\x094d\x092e\x094d"),
198 MoveCursorTo(model, model.GetText().length());
199 EXPECT_EQ(model.GetText().length(), model.GetCursorPosition());
200 EXPECT_TRUE(model.Backspace());
201 EXPECT_EQ(WideToUTF16(L"\x0061\x0062\x0915\x0915\x094d\x092e"),
205 // Test cursor position and deletion for Hindi Virama.
206 model.SetText(WideToUTF16(L"\x0D38\x0D4D\x0D15\x0D16\x0D2E"));
207 MoveCursorTo(model, 0);
208 EXPECT_EQ(0U, model.GetCursorPosition());
210 // TODO(asvitkine): Disable tests that fail on XP bots due to lack of complete
211 // font support for some scripts - http://crbug.com/106450
212 if (!on_windows_xp) {
213 MoveCursorTo(model, 1);
214 EXPECT_EQ(0U, model.GetCursorPosition());
215 MoveCursorTo(model, 3);
216 EXPECT_EQ(3U, model.GetCursorPosition());
219 // TODO(asvitkine): Temporarily disable the following check on Windows. It
220 // seems Windows treats "\x0D38\x0D4D\x0D15" as a single grapheme.
222 MoveCursorTo(model, 2);
223 EXPECT_EQ(2U, model.GetCursorPosition());
224 EXPECT_TRUE(model.Backspace());
225 EXPECT_EQ(WideToUTF16(L"\x0D38\x0D15\x0D16\x0D2E"), model.GetText());
228 model.SetText(WideToUTF16(L"\x05d5\x05b7\x05D9\x05B0\x05D4\x05B4\x05D9"));
229 MoveCursorTo(model, 0);
230 EXPECT_TRUE(model.Delete());
231 EXPECT_TRUE(model.Delete());
232 EXPECT_TRUE(model.Delete());
233 EXPECT_TRUE(model.Delete());
234 EXPECT_EQ(WideToUTF16(L""), model.GetText());
236 // The first 2 characters are not strong directionality characters.
237 model.SetText(WideToUTF16(L"\x002C\x0020\x05D1\x05BC\x05B7\x05E9\x05BC"));
238 model.MoveCursor(gfx::LINE_BREAK, gfx::CURSOR_LEFT, false);
239 EXPECT_TRUE(model.Backspace());
240 EXPECT_EQ(WideToUTF16(L"\x002C\x0020\x05D1\x05BC\x05B7\x05E9"),
244 TEST_F(TextfieldViewsModelTest, EmptyString) {
245 TextfieldViewsModel model(NULL);
246 EXPECT_EQ(string16(), model.GetText());
247 EXPECT_EQ(string16(), model.GetSelectedText());
249 model.MoveCursor(gfx::CHARACTER_BREAK, gfx::CURSOR_LEFT, true);
250 EXPECT_EQ(0U, model.GetCursorPosition());
251 model.MoveCursor(gfx::CHARACTER_BREAK, gfx::CURSOR_RIGHT, true);
252 EXPECT_EQ(0U, model.GetCursorPosition());
254 EXPECT_EQ(string16(), model.GetSelectedText());
256 EXPECT_FALSE(model.Delete());
257 EXPECT_FALSE(model.Backspace());
260 TEST_F(TextfieldViewsModelTest, Selection) {
261 TextfieldViewsModel model(NULL);
262 model.Append(ASCIIToUTF16("HELLO"));
263 model.MoveCursor(gfx::CHARACTER_BREAK, gfx::CURSOR_RIGHT, false);
264 model.MoveCursor(gfx::CHARACTER_BREAK, gfx::CURSOR_RIGHT, true);
265 EXPECT_STR_EQ("E", model.GetSelectedText());
266 model.MoveCursor(gfx::CHARACTER_BREAK, gfx::CURSOR_RIGHT, true);
267 EXPECT_STR_EQ("EL", model.GetSelectedText());
269 model.MoveCursor(gfx::LINE_BREAK, gfx::CURSOR_LEFT, true);
270 EXPECT_STR_EQ("H", model.GetSelectedText());
271 model.MoveCursor(gfx::LINE_BREAK, gfx::CURSOR_RIGHT, true);
272 EXPECT_STR_EQ("ELLO", model.GetSelectedText());
273 model.ClearSelection();
274 EXPECT_EQ(string16(), model.GetSelectedText());
276 // SelectAll(false) selects towards the end.
277 model.SelectAll(false);
278 EXPECT_STR_EQ("HELLO", model.GetSelectedText());
279 EXPECT_EQ(gfx::Range(0, 5), model.render_text()->selection());
281 // SelectAll(true) selects towards the beginning.
282 model.SelectAll(true);
283 EXPECT_STR_EQ("HELLO", model.GetSelectedText());
284 EXPECT_EQ(gfx::Range(5, 0), model.render_text()->selection());
286 // Select and move cursor.
287 model.SelectRange(gfx::Range(1U, 3U));
288 EXPECT_STR_EQ("EL", model.GetSelectedText());
289 model.MoveCursor(gfx::CHARACTER_BREAK, gfx::CURSOR_LEFT, false);
290 EXPECT_EQ(1U, model.GetCursorPosition());
291 model.SelectRange(gfx::Range(1U, 3U));
292 model.MoveCursor(gfx::CHARACTER_BREAK, gfx::CURSOR_RIGHT, false);
293 EXPECT_EQ(3U, model.GetCursorPosition());
295 // Select all and move cursor.
296 model.SelectAll(false);
297 model.MoveCursor(gfx::CHARACTER_BREAK, gfx::CURSOR_LEFT, false);
298 EXPECT_EQ(0U, model.GetCursorPosition());
299 model.SelectAll(false);
300 model.MoveCursor(gfx::CHARACTER_BREAK, gfx::CURSOR_RIGHT, false);
301 EXPECT_EQ(5U, model.GetCursorPosition());
304 TEST_F(TextfieldViewsModelTest, Selection_BidiWithNonSpacingMarks) {
305 // Selection is a logical operation. And it should work with the arrow
306 // keys doing visual movements, while the selection is logical between
307 // the (logical) start and end points. Selection is simply defined as
308 // the portion of text between the logical positions of the start and end
310 TextfieldViewsModel model(NULL);
311 // TODO(xji): temporarily disable in platform Win since the complex script
312 // characters turned into empty square due to font regression. So, not able
313 // to test 2 characters belong to the same grapheme.
314 #if defined(OS_LINUX)
315 model.Append(WideToUTF16(
316 L"abc\x05E9\x05BC\x05C1\x05B8\x05E0\x05B8" L"def"));
317 model.MoveCursor(gfx::CHARACTER_BREAK, gfx::CURSOR_RIGHT, false);
318 model.MoveCursor(gfx::CHARACTER_BREAK, gfx::CURSOR_RIGHT, false);
320 model.MoveCursor(gfx::CHARACTER_BREAK, gfx::CURSOR_RIGHT, true);
321 EXPECT_EQ(gfx::Range(2, 3), model.render_text()->selection());
322 EXPECT_EQ(WideToUTF16(L"c"), model.GetSelectedText());
324 model.MoveCursor(gfx::CHARACTER_BREAK, gfx::CURSOR_RIGHT, true);
325 EXPECT_EQ(gfx::Range(2, 7), model.render_text()->selection());
326 EXPECT_EQ(WideToUTF16(L"c\x05E9\x05BC\x05C1\x05B8"),
327 model.GetSelectedText());
329 model.MoveCursor(gfx::CHARACTER_BREAK, gfx::CURSOR_RIGHT, true);
330 EXPECT_EQ(gfx::Range(2, 3), model.render_text()->selection());
331 EXPECT_EQ(WideToUTF16(L"c"), model.GetSelectedText());
333 model.MoveCursor(gfx::CHARACTER_BREAK, gfx::CURSOR_RIGHT, true);
334 EXPECT_EQ(gfx::Range(2, 10), model.render_text()->selection());
335 EXPECT_EQ(WideToUTF16(L"c\x05E9\x05BC\x05C1\x05B8\x05E0\x05B8" L"d"),
336 model.GetSelectedText());
338 model.ClearSelection();
339 EXPECT_EQ(string16(), model.GetSelectedText());
340 model.SelectAll(false);
341 EXPECT_EQ(WideToUTF16(L"abc\x05E9\x05BC\x05C1\x05B8\x05E0\x05B8" L"def"),
342 model.GetSelectedText());
345 // In case of "aBc", this test shows how to select "aB" or "Bc", assume 'B' is
347 model.SetText(WideToUTF16(L"a\x05E9" L"b"));
348 MoveCursorTo(model, 0);
349 model.MoveCursor(gfx::CHARACTER_BREAK, gfx::CURSOR_RIGHT, true);
350 EXPECT_EQ(WideToUTF16(L"a"), model.GetSelectedText());
352 model.MoveCursor(gfx::CHARACTER_BREAK, gfx::CURSOR_RIGHT, true);
353 EXPECT_EQ(WideToUTF16(L"a"), model.GetSelectedText());
355 model.MoveCursor(gfx::CHARACTER_BREAK, gfx::CURSOR_RIGHT, true);
356 EXPECT_EQ(WideToUTF16(L"a\x05E9" L"b"), model.GetSelectedText());
358 model.MoveCursor(gfx::CHARACTER_BREAK, gfx::CURSOR_RIGHT, false);
359 EXPECT_EQ(3U, model.GetCursorPosition());
360 model.MoveCursor(gfx::CHARACTER_BREAK, gfx::CURSOR_LEFT, true);
361 EXPECT_EQ(WideToUTF16(L"b"), model.GetSelectedText());
363 model.MoveCursor(gfx::CHARACTER_BREAK, gfx::CURSOR_LEFT, true);
364 EXPECT_EQ(WideToUTF16(L"b"), model.GetSelectedText());
366 model.MoveCursor(gfx::CHARACTER_BREAK, gfx::CURSOR_LEFT, true);
367 EXPECT_EQ(WideToUTF16(L"a\x05E9" L"b"), model.GetSelectedText());
369 model.MoveCursor(gfx::LINE_BREAK, gfx::CURSOR_LEFT, false);
370 model.MoveCursor(gfx::CHARACTER_BREAK, gfx::CURSOR_RIGHT, true);
371 model.MoveCursor(gfx::CHARACTER_BREAK, gfx::CURSOR_RIGHT, true);
372 model.MoveCursor(gfx::CHARACTER_BREAK, gfx::CURSOR_LEFT, true);
373 EXPECT_EQ(WideToUTF16(L"a\x05E9"), model.GetSelectedText());
375 model.MoveCursor(gfx::LINE_BREAK, gfx::CURSOR_RIGHT, false);
376 model.MoveCursor(gfx::CHARACTER_BREAK, gfx::CURSOR_LEFT, true);
377 model.MoveCursor(gfx::CHARACTER_BREAK, gfx::CURSOR_LEFT, true);
378 model.MoveCursor(gfx::CHARACTER_BREAK, gfx::CURSOR_RIGHT, true);
379 EXPECT_EQ(WideToUTF16(L"\x05E9" L"b"), model.GetSelectedText());
381 model.ClearSelection();
382 EXPECT_EQ(string16(), model.GetSelectedText());
383 model.SelectAll(false);
384 EXPECT_EQ(WideToUTF16(L"a\x05E9" L"b"), model.GetSelectedText());
387 TEST_F(TextfieldViewsModelTest, SelectionAndEdit) {
388 TextfieldViewsModel model(NULL);
389 model.Append(ASCIIToUTF16("HELLO"));
390 model.MoveCursor(gfx::CHARACTER_BREAK, gfx::CURSOR_RIGHT, false);
391 model.MoveCursor(gfx::CHARACTER_BREAK, gfx::CURSOR_RIGHT, true);
392 model.MoveCursor(gfx::CHARACTER_BREAK, gfx::CURSOR_RIGHT, true); // "EL"
393 EXPECT_TRUE(model.Backspace());
394 EXPECT_STR_EQ("HLO", model.GetText());
396 model.Append(ASCIIToUTF16("ILL"));
397 model.MoveCursor(gfx::CHARACTER_BREAK, gfx::CURSOR_RIGHT, true);
398 model.MoveCursor(gfx::CHARACTER_BREAK, gfx::CURSOR_RIGHT, true); // "LO"
399 EXPECT_TRUE(model.Delete());
400 EXPECT_STR_EQ("HILL", model.GetText());
401 EXPECT_EQ(1U, model.GetCursorPosition());
402 model.MoveCursor(gfx::CHARACTER_BREAK, gfx::CURSOR_RIGHT, true); // "I"
403 model.InsertChar('E');
404 EXPECT_STR_EQ("HELL", model.GetText());
405 model.MoveCursor(gfx::LINE_BREAK, gfx::CURSOR_LEFT, false);
406 model.MoveCursor(gfx::CHARACTER_BREAK, gfx::CURSOR_RIGHT, true); // "H"
407 model.ReplaceChar('B');
408 EXPECT_STR_EQ("BELL", model.GetText());
409 model.MoveCursor(gfx::LINE_BREAK, gfx::CURSOR_RIGHT, false);
410 model.MoveCursor(gfx::CHARACTER_BREAK, gfx::CURSOR_LEFT, true);
411 model.MoveCursor(gfx::CHARACTER_BREAK, gfx::CURSOR_LEFT, true); // "ELL"
412 model.ReplaceChar('E');
413 EXPECT_STR_EQ("BEE", model.GetText());
416 TEST_F(TextfieldViewsModelTest, Word) {
417 TextfieldViewsModel model(NULL);
419 ASCIIToUTF16("The answer to Life, the Universe, and Everything"));
420 model.MoveCursor(gfx::WORD_BREAK, gfx::CURSOR_RIGHT, false);
421 EXPECT_EQ(3U, model.GetCursorPosition());
422 model.MoveCursor(gfx::WORD_BREAK, gfx::CURSOR_RIGHT, false);
423 EXPECT_EQ(10U, model.GetCursorPosition());
424 model.MoveCursor(gfx::WORD_BREAK, gfx::CURSOR_RIGHT, false);
425 model.MoveCursor(gfx::WORD_BREAK, gfx::CURSOR_RIGHT, false);
426 EXPECT_EQ(18U, model.GetCursorPosition());
428 // Should passes the non word char ','
429 model.MoveCursor(gfx::WORD_BREAK, gfx::CURSOR_RIGHT, true);
430 EXPECT_EQ(23U, model.GetCursorPosition());
431 EXPECT_STR_EQ(", the", model.GetSelectedText());
434 model.MoveCursor(gfx::WORD_BREAK, gfx::CURSOR_RIGHT, true);
435 model.MoveCursor(gfx::WORD_BREAK, gfx::CURSOR_RIGHT, true);
436 model.MoveCursor(gfx::WORD_BREAK, gfx::CURSOR_RIGHT, true);
437 EXPECT_STR_EQ(", the Universe, and Everything", model.GetSelectedText());
438 // Should be safe to go next word at the end.
439 model.MoveCursor(gfx::WORD_BREAK, gfx::CURSOR_RIGHT, true);
440 EXPECT_STR_EQ(", the Universe, and Everything", model.GetSelectedText());
441 model.InsertChar('2');
442 EXPECT_EQ(19U, model.GetCursorPosition());
445 model.MoveCursor(gfx::CHARACTER_BREAK, gfx::CURSOR_LEFT, false); // leave 2.
446 model.MoveCursor(gfx::WORD_BREAK, gfx::CURSOR_LEFT, true);
447 EXPECT_EQ(14U, model.GetCursorPosition());
448 EXPECT_STR_EQ("Life", model.GetSelectedText());
449 model.MoveCursor(gfx::WORD_BREAK, gfx::CURSOR_LEFT, true);
450 EXPECT_STR_EQ("to Life", model.GetSelectedText());
451 model.MoveCursor(gfx::WORD_BREAK, gfx::CURSOR_LEFT, true);
452 model.MoveCursor(gfx::WORD_BREAK, gfx::CURSOR_LEFT, true);
453 model.MoveCursor(gfx::WORD_BREAK, gfx::CURSOR_LEFT, true); // Now at start.
454 EXPECT_STR_EQ("The answer to Life", model.GetSelectedText());
455 // Should be safe to go to the previous word at the beginning.
456 model.MoveCursor(gfx::WORD_BREAK, gfx::CURSOR_LEFT, true);
457 EXPECT_STR_EQ("The answer to Life", model.GetSelectedText());
458 model.ReplaceChar('4');
459 EXPECT_EQ(string16(), model.GetSelectedText());
460 EXPECT_STR_EQ("42", model.GetText());
463 TEST_F(TextfieldViewsModelTest, SetText) {
464 TextfieldViewsModel model(NULL);
465 model.Append(ASCIIToUTF16("HELLO"));
466 model.MoveCursor(gfx::LINE_BREAK, gfx::CURSOR_RIGHT, false);
467 model.SetText(ASCIIToUTF16("GOODBYE"));
468 EXPECT_STR_EQ("GOODBYE", model.GetText());
469 // SetText move the cursor to the end of the new text.
470 EXPECT_EQ(7U, model.GetCursorPosition());
471 model.SelectAll(false);
472 EXPECT_STR_EQ("GOODBYE", model.GetSelectedText());
473 model.MoveCursor(gfx::LINE_BREAK, gfx::CURSOR_RIGHT, false);
474 EXPECT_EQ(7U, model.GetCursorPosition());
476 model.SetText(ASCIIToUTF16("BYE"));
477 // Setting shorter string moves the cursor to the end of the new string.
478 EXPECT_EQ(3U, model.GetCursorPosition());
479 EXPECT_EQ(string16(), model.GetSelectedText());
480 model.SetText(string16());
481 EXPECT_EQ(0U, model.GetCursorPosition());
484 TEST_F(TextfieldViewsModelTest, Clipboard) {
485 ui::Clipboard* clipboard = ui::Clipboard::GetForCurrentThread();
486 const string16 initial_clipboard_text = ASCIIToUTF16("initial text");
487 ui::ScopedClipboardWriter(clipboard, ui::CLIPBOARD_TYPE_COPY_PASTE).
488 WriteText(initial_clipboard_text);
490 string16 clipboard_text;
491 TextfieldViewsModel model(NULL);
492 model.Append(ASCIIToUTF16("HELLO WORLD"));
494 // Cut with an empty selection should do nothing.
495 model.MoveCursor(gfx::LINE_BREAK, gfx::CURSOR_RIGHT, false);
496 EXPECT_FALSE(model.Cut());
497 clipboard->ReadText(ui::CLIPBOARD_TYPE_COPY_PASTE, &clipboard_text);
498 EXPECT_EQ(initial_clipboard_text, clipboard_text);
499 EXPECT_STR_EQ("HELLO WORLD", model.GetText());
500 EXPECT_EQ(11U, model.GetCursorPosition());
502 // Copy with an empty selection should do nothing.
504 clipboard->ReadText(ui::CLIPBOARD_TYPE_COPY_PASTE, &clipboard_text);
505 EXPECT_EQ(initial_clipboard_text, clipboard_text);
506 EXPECT_STR_EQ("HELLO WORLD", model.GetText());
507 EXPECT_EQ(11U, model.GetCursorPosition());
509 // Cut on obscured (password) text should do nothing.
510 model.render_text()->SetObscured(true);
511 model.SelectAll(false);
512 EXPECT_FALSE(model.Cut());
513 clipboard->ReadText(ui::CLIPBOARD_TYPE_COPY_PASTE, &clipboard_text);
514 EXPECT_EQ(initial_clipboard_text, clipboard_text);
515 EXPECT_STR_EQ("HELLO WORLD", model.GetText());
516 EXPECT_STR_EQ("HELLO WORLD", model.GetSelectedText());
518 // Copy on obscured text should do nothing.
519 model.SelectAll(false);
520 EXPECT_FALSE(model.Copy());
521 clipboard->ReadText(ui::CLIPBOARD_TYPE_COPY_PASTE, &clipboard_text);
522 EXPECT_EQ(initial_clipboard_text, clipboard_text);
523 EXPECT_STR_EQ("HELLO WORLD", model.GetText());
524 EXPECT_STR_EQ("HELLO WORLD", model.GetSelectedText());
526 // Cut with non-empty selection.
527 model.render_text()->SetObscured(false);
528 model.MoveCursor(gfx::LINE_BREAK, gfx::CURSOR_RIGHT, false);
529 model.MoveCursor(gfx::WORD_BREAK, gfx::CURSOR_LEFT, true);
530 EXPECT_TRUE(model.Cut());
531 clipboard->ReadText(ui::CLIPBOARD_TYPE_COPY_PASTE, &clipboard_text);
532 EXPECT_STR_EQ("WORLD", clipboard_text);
533 EXPECT_STR_EQ("HELLO ", model.GetText());
534 EXPECT_EQ(6U, model.GetCursorPosition());
536 // Copy with non-empty selection.
537 model.SelectAll(false);
538 EXPECT_TRUE(model.Copy());
539 clipboard->ReadText(ui::CLIPBOARD_TYPE_COPY_PASTE, &clipboard_text);
540 EXPECT_STR_EQ("HELLO ", clipboard_text);
541 EXPECT_STR_EQ("HELLO ", model.GetText());
542 EXPECT_EQ(6U, model.GetCursorPosition());
544 // Test that paste works regardless of the obscured bit.
545 model.MoveCursor(gfx::LINE_BREAK, gfx::CURSOR_RIGHT, false);
546 EXPECT_TRUE(model.Paste());
547 EXPECT_STR_EQ("HELLO HELLO ", model.GetText());
548 EXPECT_EQ(12U, model.GetCursorPosition());
549 model.render_text()->SetObscured(true);
550 EXPECT_TRUE(model.Paste());
551 EXPECT_STR_EQ("HELLO HELLO HELLO ", model.GetText());
552 EXPECT_EQ(18U, model.GetCursorPosition());
555 static void SelectWordTestVerifier(const TextfieldViewsModel& model,
556 const string16 &expected_selected_string, size_t expected_cursor_pos) {
557 EXPECT_EQ(expected_selected_string, model.GetSelectedText());
558 EXPECT_EQ(expected_cursor_pos, model.GetCursorPosition());
561 TEST_F(TextfieldViewsModelTest, SelectWordTest) {
562 TextfieldViewsModel model(NULL);
563 model.Append(ASCIIToUTF16(" HELLO !! WO RLD "));
565 // Test when cursor is at the beginning.
566 model.MoveCursor(gfx::LINE_BREAK, gfx::CURSOR_LEFT, false);
568 SelectWordTestVerifier(model, ASCIIToUTF16(" "), 2U);
570 // Test when cursor is at the beginning of a word.
571 MoveCursorTo(model, 2);
573 SelectWordTestVerifier(model, ASCIIToUTF16("HELLO"), 7U);
575 // Test when cursor is at the end of a word.
576 MoveCursorTo(model, 15);
578 SelectWordTestVerifier(model, ASCIIToUTF16(" "), 20U);
580 // Test when cursor is somewhere in a non-alpha-numeric fragment.
581 for (size_t cursor_pos = 8; cursor_pos < 13U; cursor_pos++) {
582 MoveCursorTo(model, cursor_pos);
584 SelectWordTestVerifier(model, ASCIIToUTF16(" !! "), 13U);
587 // Test when cursor is somewhere in a whitespace fragment.
588 MoveCursorTo(model, 17);
590 SelectWordTestVerifier(model, ASCIIToUTF16(" "), 20U);
592 // Test when cursor is at the end.
593 model.MoveCursor(gfx::LINE_BREAK, gfx::CURSOR_RIGHT, false);
595 SelectWordTestVerifier(model, ASCIIToUTF16(" "), 24U);
598 // TODO(xji): temporarily disable in platform Win since the complex script
599 // characters and Chinese characters are turned into empty square due to font
601 #if defined(OS_LINUX)
602 TEST_F(TextfieldViewsModelTest, SelectWordTest_MixScripts) {
603 TextfieldViewsModel model(NULL);
604 std::vector<WordAndCursor> word_and_cursor;
605 word_and_cursor.push_back(WordAndCursor(L"a\x05d0", 2));
606 word_and_cursor.push_back(WordAndCursor(L"a\x05d0", 2));
607 word_and_cursor.push_back(WordAndCursor(L"\x05d1\x05d2", 5));
608 word_and_cursor.push_back(WordAndCursor(L"\x05d1\x05d2", 5));
609 word_and_cursor.push_back(WordAndCursor(L" ", 3));
610 word_and_cursor.push_back(WordAndCursor(L"a\x05d0", 2));
611 word_and_cursor.push_back(WordAndCursor(L"\x0915\x094d\x0915", 9));
612 word_and_cursor.push_back(WordAndCursor(L"\x0915\x094d\x0915", 9));
613 word_and_cursor.push_back(WordAndCursor(L" ", 10));
614 word_and_cursor.push_back(WordAndCursor(L"\x4E2D\x56FD", 12));
615 word_and_cursor.push_back(WordAndCursor(L"\x4E2D\x56FD", 12));
616 word_and_cursor.push_back(WordAndCursor(L"\x82B1", 13));
617 word_and_cursor.push_back(WordAndCursor(L"\x5929", 14));
619 // The text consists of Ascii, Hebrew, Hindi with Virama sign, and Chinese.
620 model.SetText(WideToUTF16(L"a\x05d0 \x05d1\x05d2 \x0915\x094d\x0915 "
621 L"\x4E2D\x56FD\x82B1\x5929"));
622 for (size_t i = 0; i < word_and_cursor.size(); ++i) {
623 model.MoveCursor(gfx::LINE_BREAK, gfx::CURSOR_LEFT, false);
624 for (size_t j = 0; j < i; ++j)
625 model.MoveCursor(gfx::CHARACTER_BREAK, gfx::CURSOR_RIGHT, false);
627 SelectWordTestVerifier(model, WideToUTF16(word_and_cursor[i].word),
628 word_and_cursor[i].cursor);
633 TEST_F(TextfieldViewsModelTest, RangeTest) {
634 TextfieldViewsModel model(NULL);
635 model.Append(ASCIIToUTF16("HELLO WORLD"));
636 model.MoveCursor(gfx::LINE_BREAK, gfx::CURSOR_LEFT, false);
637 gfx::Range range = model.render_text()->selection();
638 EXPECT_TRUE(range.is_empty());
639 EXPECT_EQ(0U, range.start());
640 EXPECT_EQ(0U, range.end());
642 model.MoveCursor(gfx::WORD_BREAK, gfx::CURSOR_RIGHT, true);
643 range = model.render_text()->selection();
644 EXPECT_FALSE(range.is_empty());
645 EXPECT_FALSE(range.is_reversed());
646 EXPECT_EQ(0U, range.start());
647 EXPECT_EQ(5U, range.end());
649 model.MoveCursor(gfx::CHARACTER_BREAK, gfx::CURSOR_LEFT, true);
650 range = model.render_text()->selection();
651 EXPECT_FALSE(range.is_empty());
652 EXPECT_EQ(0U, range.start());
653 EXPECT_EQ(4U, range.end());
655 model.MoveCursor(gfx::WORD_BREAK, gfx::CURSOR_LEFT, true);
656 range = model.render_text()->selection();
657 EXPECT_TRUE(range.is_empty());
658 EXPECT_EQ(0U, range.start());
659 EXPECT_EQ(0U, range.end());
662 model.MoveCursor(gfx::LINE_BREAK, gfx::CURSOR_RIGHT, false);
663 range = model.render_text()->selection();
664 EXPECT_TRUE(range.is_empty());
665 EXPECT_EQ(11U, range.start());
666 EXPECT_EQ(11U, range.end());
668 model.MoveCursor(gfx::WORD_BREAK, gfx::CURSOR_LEFT, true);
669 range = model.render_text()->selection();
670 EXPECT_FALSE(range.is_empty());
671 EXPECT_TRUE(range.is_reversed());
672 EXPECT_EQ(11U, range.start());
673 EXPECT_EQ(6U, range.end());
675 model.MoveCursor(gfx::CHARACTER_BREAK, gfx::CURSOR_RIGHT, true);
676 range = model.render_text()->selection();
677 EXPECT_FALSE(range.is_empty());
678 EXPECT_TRUE(range.is_reversed());
679 EXPECT_EQ(11U, range.start());
680 EXPECT_EQ(7U, range.end());
682 model.MoveCursor(gfx::WORD_BREAK, gfx::CURSOR_RIGHT, true);
683 range = model.render_text()->selection();
684 EXPECT_TRUE(range.is_empty());
685 EXPECT_EQ(11U, range.start());
686 EXPECT_EQ(11U, range.end());
689 model.MoveCursor(gfx::LINE_BREAK, gfx::CURSOR_LEFT, true);
690 range = model.render_text()->selection();
691 EXPECT_FALSE(range.is_empty());
692 EXPECT_TRUE(range.is_reversed());
693 EXPECT_EQ(11U, range.start());
694 EXPECT_EQ(0U, range.end());
697 TEST_F(TextfieldViewsModelTest, SelectRangeTest) {
698 TextfieldViewsModel model(NULL);
699 model.Append(ASCIIToUTF16("HELLO WORLD"));
700 gfx::Range range(0, 6);
701 EXPECT_FALSE(range.is_reversed());
702 model.SelectRange(range);
703 EXPECT_STR_EQ("HELLO ", model.GetSelectedText());
705 range = gfx::Range(6, 1);
706 EXPECT_TRUE(range.is_reversed());
707 model.SelectRange(range);
708 EXPECT_STR_EQ("ELLO ", model.GetSelectedText());
710 range = gfx::Range(2, 1000);
711 EXPECT_FALSE(range.is_reversed());
712 model.SelectRange(range);
713 EXPECT_STR_EQ("LLO WORLD", model.GetSelectedText());
715 range = gfx::Range(1000, 3);
716 EXPECT_TRUE(range.is_reversed());
717 model.SelectRange(range);
718 EXPECT_STR_EQ("LO WORLD", model.GetSelectedText());
720 range = gfx::Range(0, 0);
721 EXPECT_TRUE(range.is_empty());
722 model.SelectRange(range);
723 EXPECT_TRUE(model.GetSelectedText().empty());
725 range = gfx::Range(3, 3);
726 EXPECT_TRUE(range.is_empty());
727 model.SelectRange(range);
728 EXPECT_TRUE(model.GetSelectedText().empty());
730 range = gfx::Range(1000, 100);
731 EXPECT_FALSE(range.is_empty());
732 model.SelectRange(range);
733 EXPECT_TRUE(model.GetSelectedText().empty());
735 range = gfx::Range(1000, 1000);
736 EXPECT_TRUE(range.is_empty());
737 model.SelectRange(range);
738 EXPECT_TRUE(model.GetSelectedText().empty());
741 TEST_F(TextfieldViewsModelTest, SelectionTest) {
742 TextfieldViewsModel model(NULL);
743 model.Append(ASCIIToUTF16("HELLO WORLD"));
744 model.MoveCursor(gfx::LINE_BREAK, gfx::CURSOR_LEFT, false);
745 gfx::Range selection = model.render_text()->selection();
746 EXPECT_EQ(gfx::Range(0), selection);
748 model.MoveCursor(gfx::WORD_BREAK, gfx::CURSOR_RIGHT, true);
749 selection = model.render_text()->selection();
750 EXPECT_EQ(gfx::Range(0, 5), selection);
752 model.MoveCursor(gfx::CHARACTER_BREAK, gfx::CURSOR_LEFT, true);
753 selection = model.render_text()->selection();
754 EXPECT_EQ(gfx::Range(0, 4), selection);
756 model.MoveCursor(gfx::WORD_BREAK, gfx::CURSOR_LEFT, true);
757 selection = model.render_text()->selection();
758 EXPECT_EQ(gfx::Range(0), selection);
761 model.MoveCursor(gfx::LINE_BREAK, gfx::CURSOR_RIGHT, false);
762 selection = model.render_text()->selection();
763 EXPECT_EQ(gfx::Range(11), selection);
765 model.MoveCursor(gfx::WORD_BREAK, gfx::CURSOR_LEFT, true);
766 selection = model.render_text()->selection();
767 EXPECT_EQ(gfx::Range(11, 6), selection);
769 model.MoveCursor(gfx::CHARACTER_BREAK, gfx::CURSOR_RIGHT, true);
770 selection = model.render_text()->selection();
771 EXPECT_EQ(gfx::Range(11, 7), selection);
773 model.MoveCursor(gfx::WORD_BREAK, gfx::CURSOR_RIGHT, true);
774 selection = model.render_text()->selection();
775 EXPECT_EQ(gfx::Range(11), selection);
778 model.MoveCursor(gfx::LINE_BREAK, gfx::CURSOR_LEFT, true);
779 selection = model.render_text()->selection();
780 EXPECT_EQ(gfx::Range(11, 0), selection);
783 TEST_F(TextfieldViewsModelTest, SelectSelectionModelTest) {
784 TextfieldViewsModel model(NULL);
785 model.Append(ASCIIToUTF16("HELLO WORLD"));
786 model.SelectSelectionModel(gfx::SelectionModel(gfx::Range(0, 6),
787 gfx::CURSOR_BACKWARD));
788 EXPECT_STR_EQ("HELLO ", model.GetSelectedText());
790 model.SelectSelectionModel(gfx::SelectionModel(gfx::Range(6, 1),
791 gfx::CURSOR_FORWARD));
792 EXPECT_STR_EQ("ELLO ", model.GetSelectedText());
794 model.SelectSelectionModel(gfx::SelectionModel(gfx::Range(2, 1000),
795 gfx::CURSOR_BACKWARD));
796 EXPECT_STR_EQ("LLO WORLD", model.GetSelectedText());
798 model.SelectSelectionModel(gfx::SelectionModel(gfx::Range(1000, 3),
799 gfx::CURSOR_FORWARD));
800 EXPECT_STR_EQ("LO WORLD", model.GetSelectedText());
802 model.SelectSelectionModel(gfx::SelectionModel(0, gfx::CURSOR_FORWARD));
803 EXPECT_TRUE(model.GetSelectedText().empty());
805 model.SelectSelectionModel(gfx::SelectionModel(3, gfx::CURSOR_FORWARD));
806 EXPECT_TRUE(model.GetSelectedText().empty());
808 model.SelectSelectionModel(gfx::SelectionModel(gfx::Range(1000, 100),
809 gfx::CURSOR_FORWARD));
810 EXPECT_TRUE(model.GetSelectedText().empty());
812 model.SelectSelectionModel(gfx::SelectionModel(1000, gfx::CURSOR_BACKWARD));
813 EXPECT_TRUE(model.GetSelectedText().empty());
816 TEST_F(TextfieldViewsModelTest, CompositionTextTest) {
817 TextfieldViewsModel model(this);
818 model.Append(ASCIIToUTF16("1234590"));
819 model.SelectRange(gfx::Range(5, 5));
820 EXPECT_FALSE(model.HasSelection());
821 EXPECT_EQ(5U, model.GetCursorPosition());
824 model.GetTextRange(&range);
825 EXPECT_EQ(gfx::Range(0, 7), range);
827 ui::CompositionText composition;
828 composition.text = ASCIIToUTF16("678");
829 composition.underlines.push_back(ui::CompositionUnderline(0, 3, 0, false));
831 // Cursor should be at the end of composition when characters are just typed.
832 composition.selection = gfx::Range(3, 3);
833 model.SetCompositionText(composition);
834 EXPECT_TRUE(model.HasCompositionText());
835 EXPECT_FALSE(model.HasSelection());
837 // Cancel composition
838 model.CancelCompositionText();
839 composition_text_confirmed_or_cleared_ = false;
841 // Restart composition with targeting "67" in "678".
842 composition.selection = gfx::Range(0, 2);
843 composition.underlines.clear();
844 composition.underlines.push_back(ui::CompositionUnderline(0, 2, 0, true));
845 composition.underlines.push_back(ui::CompositionUnderline(2, 3, 0, false));
846 model.SetCompositionText(composition);
847 EXPECT_TRUE(model.HasCompositionText());
848 EXPECT_TRUE(model.HasSelection());
849 EXPECT_EQ(gfx::Range(5, 7), model.render_text()->selection());
851 model.GetTextRange(&range);
852 EXPECT_EQ(10U, range.end());
853 EXPECT_STR_EQ("1234567890", model.GetText());
855 model.GetCompositionTextRange(&range);
856 EXPECT_EQ(gfx::Range(5, 8), range);
858 EXPECT_STR_EQ("456", model.GetTextFromRange(gfx::Range(3, 6)));
859 EXPECT_EQ(gfx::Range(5, 7), model.render_text()->selection());
861 EXPECT_FALSE(composition_text_confirmed_or_cleared_);
862 model.CancelCompositionText();
863 EXPECT_TRUE(composition_text_confirmed_or_cleared_);
864 composition_text_confirmed_or_cleared_ = false;
865 EXPECT_FALSE(model.HasCompositionText());
866 EXPECT_FALSE(model.HasSelection());
867 EXPECT_EQ(5U, model.GetCursorPosition());
869 model.SetCompositionText(composition);
870 EXPECT_STR_EQ("1234567890", model.GetText());
871 EXPECT_TRUE(model.SetText(ASCIIToUTF16("1234567890")));
872 EXPECT_TRUE(composition_text_confirmed_or_cleared_);
873 composition_text_confirmed_or_cleared_ = false;
874 model.MoveCursor(gfx::LINE_BREAK, gfx::CURSOR_RIGHT, false);
876 model.SetCompositionText(composition);
877 EXPECT_STR_EQ("1234567890678", model.GetText());
879 model.InsertText(UTF8ToUTF16("-"));
880 EXPECT_TRUE(composition_text_confirmed_or_cleared_);
881 composition_text_confirmed_or_cleared_ = false;
882 EXPECT_STR_EQ("1234567890-", model.GetText());
883 EXPECT_FALSE(model.HasCompositionText());
884 EXPECT_FALSE(model.HasSelection());
886 model.MoveCursor(gfx::CHARACTER_BREAK, gfx::CURSOR_LEFT, true);
887 EXPECT_STR_EQ("-", model.GetSelectedText());
888 model.SetCompositionText(composition);
889 EXPECT_STR_EQ("1234567890678", model.GetText());
891 model.ReplaceText(UTF8ToUTF16("-"));
892 EXPECT_TRUE(composition_text_confirmed_or_cleared_);
893 composition_text_confirmed_or_cleared_ = false;
894 EXPECT_STR_EQ("1234567890-", model.GetText());
895 EXPECT_FALSE(model.HasCompositionText());
896 EXPECT_FALSE(model.HasSelection());
898 model.SetCompositionText(composition);
899 model.Append(UTF8ToUTF16("-"));
900 EXPECT_TRUE(composition_text_confirmed_or_cleared_);
901 composition_text_confirmed_or_cleared_ = false;
902 EXPECT_STR_EQ("1234567890-678-", model.GetText());
904 model.SetCompositionText(composition);
906 EXPECT_TRUE(composition_text_confirmed_or_cleared_);
907 composition_text_confirmed_or_cleared_ = false;
908 EXPECT_STR_EQ("1234567890-678-", model.GetText());
910 model.SetCompositionText(composition);
912 EXPECT_TRUE(composition_text_confirmed_or_cleared_);
913 composition_text_confirmed_or_cleared_ = false;
914 EXPECT_STR_EQ("1234567890-678-", model.GetText());
916 model.SetText(string16());
917 model.SetCompositionText(composition);
918 model.MoveCursor(gfx::CHARACTER_BREAK, gfx::CURSOR_LEFT, false);
919 EXPECT_TRUE(composition_text_confirmed_or_cleared_);
920 composition_text_confirmed_or_cleared_ = false;
921 EXPECT_STR_EQ("678", model.GetText());
922 EXPECT_EQ(2U, model.GetCursorPosition());
924 model.SetCompositionText(composition);
925 model.MoveCursor(gfx::CHARACTER_BREAK, gfx::CURSOR_RIGHT, false);
926 EXPECT_TRUE(composition_text_confirmed_or_cleared_);
927 composition_text_confirmed_or_cleared_ = false;
928 EXPECT_STR_EQ("676788", model.GetText());
929 EXPECT_EQ(6U, model.GetCursorPosition());
931 model.SetCompositionText(composition);
932 model.MoveCursor(gfx::WORD_BREAK, gfx::CURSOR_LEFT, false);
933 EXPECT_TRUE(composition_text_confirmed_or_cleared_);
934 composition_text_confirmed_or_cleared_ = false;
935 EXPECT_STR_EQ("676788678", model.GetText());
937 model.SetText(string16());
938 model.SetCompositionText(composition);
939 model.MoveCursor(gfx::WORD_BREAK, gfx::CURSOR_RIGHT, false);
940 EXPECT_TRUE(composition_text_confirmed_or_cleared_);
941 composition_text_confirmed_or_cleared_ = false;
943 model.SetCompositionText(composition);
944 model.MoveCursor(gfx::LINE_BREAK, gfx::CURSOR_LEFT, true);
945 EXPECT_TRUE(composition_text_confirmed_or_cleared_);
946 composition_text_confirmed_or_cleared_ = false;
947 EXPECT_STR_EQ("678678", model.GetText());
949 model.SetCompositionText(composition);
950 model.MoveCursor(gfx::LINE_BREAK, gfx::CURSOR_RIGHT, false);
951 EXPECT_TRUE(composition_text_confirmed_or_cleared_);
952 composition_text_confirmed_or_cleared_ = false;
953 EXPECT_STR_EQ("678", model.GetText());
955 model.SetCompositionText(composition);
956 gfx::SelectionModel sel(
957 gfx::Range(model.render_text()->selection().start(), 0),
958 gfx::CURSOR_FORWARD);
959 model.MoveCursorTo(sel);
960 EXPECT_TRUE(composition_text_confirmed_or_cleared_);
961 composition_text_confirmed_or_cleared_ = false;
962 EXPECT_STR_EQ("678678", model.GetText());
964 model.SetCompositionText(composition);
965 model.SelectRange(gfx::Range(0, 3));
966 EXPECT_TRUE(composition_text_confirmed_or_cleared_);
967 composition_text_confirmed_or_cleared_ = false;
968 EXPECT_STR_EQ("678", model.GetText());
970 model.SetCompositionText(composition);
971 model.SelectAll(false);
972 EXPECT_TRUE(composition_text_confirmed_or_cleared_);
973 composition_text_confirmed_or_cleared_ = false;
974 EXPECT_STR_EQ("678", model.GetText());
976 model.SetCompositionText(composition);
978 EXPECT_TRUE(composition_text_confirmed_or_cleared_);
979 composition_text_confirmed_or_cleared_ = false;
980 EXPECT_STR_EQ("678", model.GetText());
982 model.SetCompositionText(composition);
983 model.ClearSelection();
984 EXPECT_TRUE(composition_text_confirmed_or_cleared_);
985 composition_text_confirmed_or_cleared_ = false;
987 model.SetCompositionText(composition);
988 EXPECT_FALSE(model.Cut());
989 EXPECT_FALSE(composition_text_confirmed_or_cleared_);
992 TEST_F(TextfieldViewsModelTest, UndoRedo_BasicTest) {
993 TextfieldViewsModel model(NULL);
994 model.InsertChar('a');
995 EXPECT_FALSE(model.Redo()); // nothing to redo
996 EXPECT_TRUE(model.Undo());
997 EXPECT_STR_EQ("", model.GetText());
998 EXPECT_TRUE(model.Redo());
999 EXPECT_STR_EQ("a", model.GetText());
1001 // Continuous inserts are treated as one edit.
1002 model.InsertChar('b');
1003 model.InsertChar('c');
1004 EXPECT_STR_EQ("abc", model.GetText());
1005 EXPECT_TRUE(model.Undo());
1006 EXPECT_STR_EQ("a", model.GetText());
1007 EXPECT_EQ(1U, model.GetCursorPosition());
1008 EXPECT_TRUE(model.Undo());
1009 EXPECT_STR_EQ("", model.GetText());
1010 EXPECT_EQ(0U, model.GetCursorPosition());
1012 // Undoing further shouldn't change the text.
1013 EXPECT_FALSE(model.Undo());
1014 EXPECT_STR_EQ("", model.GetText());
1015 EXPECT_FALSE(model.Undo());
1016 EXPECT_STR_EQ("", model.GetText());
1017 EXPECT_EQ(0U, model.GetCursorPosition());
1019 // Redoing to the latest text.
1020 EXPECT_TRUE(model.Redo());
1021 EXPECT_STR_EQ("a", model.GetText());
1022 EXPECT_EQ(1U, model.GetCursorPosition());
1023 EXPECT_TRUE(model.Redo());
1024 EXPECT_STR_EQ("abc", model.GetText());
1025 EXPECT_EQ(3U, model.GetCursorPosition());
1027 // Backspace ===============================
1028 EXPECT_TRUE(model.Backspace());
1029 EXPECT_STR_EQ("ab", model.GetText());
1030 EXPECT_TRUE(model.Undo());
1031 EXPECT_STR_EQ("abc", model.GetText());
1032 EXPECT_EQ(3U, model.GetCursorPosition());
1033 EXPECT_TRUE(model.Redo());
1034 EXPECT_STR_EQ("ab", model.GetText());
1035 EXPECT_EQ(2U, model.GetCursorPosition());
1036 // Continous backspaces are treated as one edit.
1037 EXPECT_TRUE(model.Backspace());
1038 EXPECT_TRUE(model.Backspace());
1039 EXPECT_STR_EQ("", model.GetText());
1040 // Extra backspace shouldn't affect the history.
1041 EXPECT_FALSE(model.Backspace());
1042 EXPECT_TRUE(model.Undo());
1043 EXPECT_STR_EQ("ab", model.GetText());
1044 EXPECT_EQ(2U, model.GetCursorPosition());
1045 EXPECT_TRUE(model.Undo());
1046 EXPECT_STR_EQ("abc", model.GetText());
1047 EXPECT_EQ(3U, model.GetCursorPosition());
1048 EXPECT_TRUE(model.Undo());
1049 EXPECT_STR_EQ("a", model.GetText());
1050 EXPECT_EQ(1U, model.GetCursorPosition());
1053 model.ClearEditHistory();
1054 EXPECT_FALSE(model.Undo());
1055 EXPECT_FALSE(model.Redo());
1056 EXPECT_STR_EQ("a", model.GetText());
1057 EXPECT_EQ(1U, model.GetCursorPosition());
1059 // Delete ===============================
1060 model.SetText(ASCIIToUTF16("ABCDE"));
1061 model.ClearEditHistory();
1062 MoveCursorTo(model, 2);
1063 EXPECT_TRUE(model.Delete());
1064 EXPECT_STR_EQ("ABDE", model.GetText());
1065 model.MoveCursor(gfx::LINE_BREAK, gfx::CURSOR_LEFT, false);
1066 EXPECT_TRUE(model.Delete());
1067 EXPECT_STR_EQ("BDE", model.GetText());
1068 EXPECT_TRUE(model.Undo());
1069 EXPECT_STR_EQ("ABDE", model.GetText());
1070 EXPECT_EQ(0U, model.GetCursorPosition());
1071 EXPECT_TRUE(model.Undo());
1072 EXPECT_STR_EQ("ABCDE", model.GetText());
1073 EXPECT_EQ(2U, model.GetCursorPosition());
1074 EXPECT_TRUE(model.Redo());
1075 EXPECT_STR_EQ("ABDE", model.GetText());
1076 EXPECT_EQ(2U, model.GetCursorPosition());
1077 // Continous deletes are treated as one edit.
1078 EXPECT_TRUE(model.Delete());
1079 EXPECT_TRUE(model.Delete());
1080 EXPECT_STR_EQ("AB", model.GetText());
1081 EXPECT_TRUE(model.Undo());
1082 EXPECT_STR_EQ("ABDE", model.GetText());
1083 EXPECT_EQ(2U, model.GetCursorPosition());
1084 EXPECT_TRUE(model.Redo());
1085 EXPECT_STR_EQ("AB", model.GetText());
1086 EXPECT_EQ(2U, model.GetCursorPosition());
1089 TEST_F(TextfieldViewsModelTest, UndoRedo_SetText) {
1090 // This is to test the undo/redo behavior of omnibox.
1091 TextfieldViewsModel model(NULL);
1092 model.InsertChar('w');
1093 EXPECT_STR_EQ("w", model.GetText());
1094 EXPECT_EQ(1U, model.GetCursorPosition());
1095 model.SetText(ASCIIToUTF16("www.google.com"));
1096 EXPECT_EQ(14U, model.GetCursorPosition());
1097 EXPECT_STR_EQ("www.google.com", model.GetText());
1098 model.SelectRange(gfx::Range(14, 1));
1099 model.InsertChar('w');
1100 EXPECT_STR_EQ("ww", model.GetText());
1101 model.SetText(ASCIIToUTF16("www.google.com"));
1102 model.SelectRange(gfx::Range(14, 2));
1103 model.InsertChar('w');
1104 EXPECT_STR_EQ("www", model.GetText());
1105 model.SetText(ASCIIToUTF16("www.google.com"));
1106 model.SelectRange(gfx::Range(14, 3));
1107 model.InsertChar('.');
1108 EXPECT_STR_EQ("www.", model.GetText());
1109 model.SetText(ASCIIToUTF16("www.google.com"));
1110 model.SelectRange(gfx::Range(14, 4));
1111 model.InsertChar('y');
1112 EXPECT_STR_EQ("www.y", model.GetText());
1113 model.SetText(ASCIIToUTF16("www.youtube.com"));
1114 EXPECT_STR_EQ("www.youtube.com", model.GetText());
1115 EXPECT_EQ(15U, model.GetCursorPosition());
1117 EXPECT_TRUE(model.Undo());
1118 EXPECT_STR_EQ("www.google.com", model.GetText());
1119 EXPECT_EQ(4U, model.GetCursorPosition());
1120 EXPECT_TRUE(model.Undo());
1121 EXPECT_STR_EQ("www.google.com", model.GetText());
1122 EXPECT_EQ(3U, model.GetCursorPosition());
1123 EXPECT_TRUE(model.Undo());
1124 EXPECT_STR_EQ("www.google.com", model.GetText());
1125 EXPECT_EQ(2U, model.GetCursorPosition());
1126 EXPECT_TRUE(model.Undo());
1127 EXPECT_STR_EQ("www.google.com", model.GetText());
1128 EXPECT_EQ(1U, model.GetCursorPosition());
1129 EXPECT_TRUE(model.Undo());
1130 EXPECT_STR_EQ("", model.GetText());
1131 EXPECT_EQ(0U, model.GetCursorPosition());
1132 EXPECT_FALSE(model.Undo());
1133 EXPECT_TRUE(model.Redo());
1134 EXPECT_STR_EQ("www.google.com", model.GetText());
1135 EXPECT_EQ(1U, model.GetCursorPosition());
1136 EXPECT_TRUE(model.Redo());
1137 EXPECT_STR_EQ("www.google.com", model.GetText());
1138 EXPECT_EQ(2U, model.GetCursorPosition());
1139 EXPECT_TRUE(model.Redo());
1140 EXPECT_STR_EQ("www.google.com", model.GetText());
1141 EXPECT_EQ(3U, model.GetCursorPosition());
1142 EXPECT_TRUE(model.Redo());
1143 EXPECT_STR_EQ("www.google.com", model.GetText());
1144 EXPECT_EQ(4U, model.GetCursorPosition());
1145 EXPECT_TRUE(model.Redo());
1146 EXPECT_STR_EQ("www.youtube.com", model.GetText());
1147 EXPECT_EQ(5U, model.GetCursorPosition());
1148 EXPECT_FALSE(model.Redo());
1151 TEST_F(TextfieldViewsModelTest, UndoRedo_BackspaceThenSetText) {
1152 // This is to test the undo/redo behavior of omnibox.
1153 TextfieldViewsModel model(NULL);
1154 model.InsertChar('w');
1155 EXPECT_STR_EQ("w", model.GetText());
1156 EXPECT_EQ(1U, model.GetCursorPosition());
1157 model.SetText(ASCIIToUTF16("www.google.com"));
1158 EXPECT_EQ(14U, model.GetCursorPosition());
1159 EXPECT_STR_EQ("www.google.com", model.GetText());
1160 model.SetText(ASCIIToUTF16("www.google.com")); // Confirm the text.
1161 model.MoveCursor(gfx::LINE_BREAK, gfx::CURSOR_RIGHT, false);
1162 EXPECT_EQ(14U, model.GetCursorPosition());
1163 EXPECT_TRUE(model.Backspace());
1164 EXPECT_TRUE(model.Backspace());
1165 EXPECT_STR_EQ("www.google.c", model.GetText());
1166 // Autocomplete sets the text
1167 model.SetText(ASCIIToUTF16("www.google.com/search=www.google.c"));
1168 EXPECT_STR_EQ("www.google.com/search=www.google.c", model.GetText());
1169 EXPECT_TRUE(model.Undo());
1170 EXPECT_STR_EQ("www.google.c", model.GetText());
1171 EXPECT_TRUE(model.Undo());
1172 EXPECT_STR_EQ("www.google.com", model.GetText());
1175 TEST_F(TextfieldViewsModelTest, UndoRedo_CutCopyPasteTest) {
1176 TextfieldViewsModel model(NULL);
1177 model.SetText(ASCIIToUTF16("ABCDE"));
1178 EXPECT_FALSE(model.Redo()); // nothing to redo
1180 model.SelectRange(gfx::Range(1, 3));
1182 EXPECT_STR_EQ("ADE", model.GetText());
1183 EXPECT_EQ(1U, model.GetCursorPosition());
1184 EXPECT_TRUE(model.Undo());
1185 EXPECT_STR_EQ("ABCDE", model.GetText());
1186 EXPECT_EQ(3U, model.GetCursorPosition());
1187 EXPECT_TRUE(model.Undo());
1188 EXPECT_STR_EQ("", model.GetText());
1189 EXPECT_EQ(0U, model.GetCursorPosition());
1190 EXPECT_FALSE(model.Undo()); // no more undo
1191 EXPECT_STR_EQ("", model.GetText());
1192 EXPECT_TRUE(model.Redo());
1193 EXPECT_STR_EQ("ABCDE", model.GetText());
1194 EXPECT_EQ(5U, model.GetCursorPosition());
1195 EXPECT_TRUE(model.Redo());
1196 EXPECT_STR_EQ("ADE", model.GetText());
1197 EXPECT_EQ(1U, model.GetCursorPosition());
1198 EXPECT_FALSE(model.Redo()); // no more redo
1199 EXPECT_STR_EQ("ADE", model.GetText());
1204 EXPECT_STR_EQ("ABCBCBCDE", model.GetText());
1205 EXPECT_EQ(7U, model.GetCursorPosition());
1206 EXPECT_TRUE(model.Undo());
1207 EXPECT_STR_EQ("ABCBCDE", model.GetText());
1208 EXPECT_EQ(5U, model.GetCursorPosition());
1209 EXPECT_TRUE(model.Undo());
1210 EXPECT_STR_EQ("ABCDE", model.GetText());
1211 EXPECT_EQ(3U, model.GetCursorPosition());
1212 EXPECT_TRUE(model.Undo());
1213 EXPECT_STR_EQ("ADE", model.GetText());
1214 EXPECT_EQ(1U, model.GetCursorPosition());
1215 EXPECT_TRUE(model.Undo());
1216 EXPECT_STR_EQ("ABCDE", model.GetText());
1217 EXPECT_EQ(3U, model.GetCursorPosition());
1218 EXPECT_TRUE(model.Undo());
1219 EXPECT_STR_EQ("", model.GetText());
1220 EXPECT_EQ(0U, model.GetCursorPosition());
1221 EXPECT_FALSE(model.Undo());
1222 EXPECT_STR_EQ("", model.GetText());
1223 EXPECT_TRUE(model.Redo());
1224 EXPECT_STR_EQ("ABCDE", model.GetText()); // Redoing SetText
1225 EXPECT_EQ(5U, model.GetCursorPosition());
1228 EXPECT_TRUE(model.Redo());
1229 EXPECT_STR_EQ("ADE", model.GetText());
1230 EXPECT_EQ(1U, model.GetCursorPosition());
1231 EXPECT_TRUE(model.Redo());
1232 EXPECT_STR_EQ("ABCDE", model.GetText());
1233 EXPECT_EQ(3U, model.GetCursorPosition());
1234 EXPECT_TRUE(model.Redo());
1235 EXPECT_STR_EQ("ABCBCDE", model.GetText());
1236 EXPECT_EQ(5U, model.GetCursorPosition());
1237 EXPECT_TRUE(model.Redo());
1238 EXPECT_STR_EQ("ABCBCBCDE", model.GetText());
1239 EXPECT_EQ(7U, model.GetCursorPosition());
1240 EXPECT_FALSE(model.Redo());
1243 model.SelectRange(gfx::Range(1, 3));
1244 EXPECT_TRUE(model.Cut());
1245 EXPECT_STR_EQ("ABCBCDE", model.GetText());
1246 EXPECT_EQ(1U, model.GetCursorPosition());
1247 model.SelectRange(gfx::Range(1, 1));
1248 EXPECT_FALSE(model.Cut());
1249 model.MoveCursor(gfx::LINE_BREAK, gfx::CURSOR_RIGHT, false);
1250 EXPECT_TRUE(model.Paste());
1251 EXPECT_STR_EQ("ABCBCDEBC", model.GetText());
1252 EXPECT_EQ(9U, model.GetCursorPosition());
1253 EXPECT_TRUE(model.Undo());
1254 EXPECT_STR_EQ("ABCBCDE", model.GetText());
1255 EXPECT_EQ(7U, model.GetCursorPosition());
1256 // empty cut shouldn't create an edit.
1257 EXPECT_TRUE(model.Undo());
1258 EXPECT_STR_EQ("ABCBCBCDE", model.GetText());
1259 EXPECT_EQ(3U, model.GetCursorPosition());
1263 model.SetText(ASCIIToUTF16("12345"));
1264 EXPECT_STR_EQ("12345", model.GetText());
1265 EXPECT_EQ(5U, model.GetCursorPosition());
1266 model.SelectRange(gfx::Range(1, 3));
1267 model.Copy(); // Copy "23"
1268 EXPECT_STR_EQ("12345", model.GetText());
1269 EXPECT_EQ(3U, model.GetCursorPosition());
1270 model.Paste(); // Paste "23" into "23".
1271 EXPECT_STR_EQ("12345", model.GetText());
1272 EXPECT_EQ(3U, model.GetCursorPosition());
1274 EXPECT_STR_EQ("1232345", model.GetText());
1275 EXPECT_EQ(5U, model.GetCursorPosition());
1276 EXPECT_TRUE(model.Undo());
1277 EXPECT_STR_EQ("12345", model.GetText());
1278 EXPECT_EQ(3U, model.GetCursorPosition());
1279 // TODO(oshima): We need to change the return type from bool to enum.
1280 EXPECT_FALSE(model.Undo()); // No text change.
1281 EXPECT_STR_EQ("12345", model.GetText());
1282 EXPECT_EQ(3U, model.GetCursorPosition());
1283 EXPECT_TRUE(model.Undo());
1284 EXPECT_STR_EQ("", model.GetText());
1285 EXPECT_FALSE(model.Undo());
1287 EXPECT_TRUE(model.Redo());
1288 EXPECT_STR_EQ("12345", model.GetText());
1289 EXPECT_EQ(5U, model.GetCursorPosition());
1290 EXPECT_TRUE(model.Redo());
1291 EXPECT_STR_EQ("12345", model.GetText()); // For 1st paste
1292 EXPECT_EQ(3U, model.GetCursorPosition());
1293 EXPECT_TRUE(model.Redo());
1294 EXPECT_STR_EQ("1232345", model.GetText());
1295 EXPECT_EQ(5U, model.GetCursorPosition());
1296 EXPECT_FALSE(model.Redo());
1297 EXPECT_STR_EQ("1232345", model.GetText());
1299 // Test using SelectRange
1300 model.SelectRange(gfx::Range(1, 3));
1302 EXPECT_STR_EQ("1232345", model.GetText());
1303 model.MoveCursor(gfx::LINE_BREAK, gfx::CURSOR_RIGHT, false);
1304 EXPECT_TRUE(model.Paste());
1305 EXPECT_STR_EQ("123234523", model.GetText());
1306 EXPECT_EQ(9U, model.GetCursorPosition());
1307 EXPECT_TRUE(model.Undo());
1308 EXPECT_STR_EQ("1232345", model.GetText());
1309 EXPECT_EQ(7U, model.GetCursorPosition());
1312 TEST_F(TextfieldViewsModelTest, UndoRedo_CursorTest) {
1313 TextfieldViewsModel model(NULL);
1314 model.InsertChar('a');
1315 model.MoveCursor(gfx::CHARACTER_BREAK, gfx::CURSOR_LEFT, false);
1316 model.MoveCursor(gfx::CHARACTER_BREAK, gfx::CURSOR_RIGHT, false);
1317 model.InsertChar('b');
1318 // Moving the cursor shouldn't create a new edit.
1319 EXPECT_STR_EQ("ab", model.GetText());
1320 EXPECT_FALSE(model.Redo());
1321 EXPECT_TRUE(model.Undo());
1322 EXPECT_STR_EQ("", model.GetText());
1323 EXPECT_FALSE(model.Undo());
1324 EXPECT_STR_EQ("", model.GetText());
1325 EXPECT_TRUE(model.Redo());
1326 EXPECT_STR_EQ("ab", model.GetText());
1327 EXPECT_EQ(2U, model.GetCursorPosition());
1328 EXPECT_FALSE(model.Redo());
1331 void RunInsertReplaceTest(TextfieldViewsModel& model) {
1332 const bool reverse = model.render_text()->selection().is_reversed();
1333 model.InsertChar('1');
1334 model.InsertChar('2');
1335 model.InsertChar('3');
1336 EXPECT_STR_EQ("a123d", model.GetText());
1337 EXPECT_EQ(4U, model.GetCursorPosition());
1338 EXPECT_TRUE(model.Undo());
1339 EXPECT_STR_EQ("abcd", model.GetText());
1340 EXPECT_EQ(reverse ? 1U : 3U, model.GetCursorPosition());
1341 EXPECT_TRUE(model.Undo());
1342 EXPECT_STR_EQ("", model.GetText());
1343 EXPECT_EQ(0U, model.GetCursorPosition());
1344 EXPECT_FALSE(model.Undo());
1345 EXPECT_TRUE(model.Redo());
1346 EXPECT_STR_EQ("abcd", model.GetText());
1347 EXPECT_EQ(4U, model.GetCursorPosition()); // By SetText
1348 EXPECT_TRUE(model.Redo());
1349 EXPECT_STR_EQ("a123d", model.GetText());
1350 EXPECT_EQ(4U, model.GetCursorPosition());
1351 EXPECT_FALSE(model.Redo());
1354 void RunOverwriteReplaceTest(TextfieldViewsModel& model) {
1355 const bool reverse = model.render_text()->selection().is_reversed();
1356 model.ReplaceChar('1');
1357 model.ReplaceChar('2');
1358 model.ReplaceChar('3');
1359 model.ReplaceChar('4');
1360 EXPECT_STR_EQ("a1234", model.GetText());
1361 EXPECT_EQ(5U, model.GetCursorPosition());
1362 EXPECT_TRUE(model.Undo());
1363 EXPECT_STR_EQ("abcd", model.GetText());
1364 EXPECT_EQ(reverse ? 1U : 3U, model.GetCursorPosition());
1365 EXPECT_TRUE(model.Undo());
1366 EXPECT_STR_EQ("", model.GetText());
1367 EXPECT_EQ(0U, model.GetCursorPosition());
1368 EXPECT_FALSE(model.Undo());
1369 EXPECT_TRUE(model.Redo());
1370 EXPECT_STR_EQ("abcd", model.GetText());
1371 EXPECT_EQ(4U, model.GetCursorPosition());
1372 EXPECT_TRUE(model.Redo());
1373 EXPECT_STR_EQ("a1234", model.GetText());
1374 EXPECT_EQ(5U, model.GetCursorPosition());
1375 EXPECT_FALSE(model.Redo());
1378 TEST_F(TextfieldViewsModelTest, UndoRedo_ReplaceTest) {
1381 SCOPED_TRACE("forward & insert by cursor");
1382 TextfieldViewsModel model(NULL);
1383 model.SetText(ASCIIToUTF16("abcd"));
1384 model.SelectRange(gfx::Range(1, 3));
1385 RunInsertReplaceTest(model);
1388 SCOPED_TRACE("backward & insert by cursor");
1389 TextfieldViewsModel model(NULL);
1390 model.SetText(ASCIIToUTF16("abcd"));
1391 model.SelectRange(gfx::Range(3, 1));
1392 RunInsertReplaceTest(model);
1395 SCOPED_TRACE("forward & overwrite by cursor");
1396 TextfieldViewsModel model(NULL);
1397 model.SetText(ASCIIToUTF16("abcd"));
1398 model.SelectRange(gfx::Range(1, 3));
1399 RunOverwriteReplaceTest(model);
1402 SCOPED_TRACE("backward & overwrite by cursor");
1403 TextfieldViewsModel model(NULL);
1404 model.SetText(ASCIIToUTF16("abcd"));
1405 model.SelectRange(gfx::Range(3, 1));
1406 RunOverwriteReplaceTest(model);
1408 // By SelectRange API
1410 SCOPED_TRACE("forward & insert by SelectRange");
1411 TextfieldViewsModel model(NULL);
1412 model.SetText(ASCIIToUTF16("abcd"));
1413 model.SelectRange(gfx::Range(1, 3));
1414 RunInsertReplaceTest(model);
1417 SCOPED_TRACE("backward & insert by SelectRange");
1418 TextfieldViewsModel model(NULL);
1419 model.SetText(ASCIIToUTF16("abcd"));
1420 model.SelectRange(gfx::Range(3, 1));
1421 RunInsertReplaceTest(model);
1424 SCOPED_TRACE("forward & overwrite by SelectRange");
1425 TextfieldViewsModel model(NULL);
1426 model.SetText(ASCIIToUTF16("abcd"));
1427 model.SelectRange(gfx::Range(1, 3));
1428 RunOverwriteReplaceTest(model);
1431 SCOPED_TRACE("backward & overwrite by SelectRange");
1432 TextfieldViewsModel model(NULL);
1433 model.SetText(ASCIIToUTF16("abcd"));
1434 model.SelectRange(gfx::Range(3, 1));
1435 RunOverwriteReplaceTest(model);
1439 TEST_F(TextfieldViewsModelTest, UndoRedo_CompositionText) {
1440 TextfieldViewsModel model(NULL);
1442 ui::CompositionText composition;
1443 composition.text = ASCIIToUTF16("abc");
1444 composition.underlines.push_back(ui::CompositionUnderline(0, 3, 0, false));
1445 composition.selection = gfx::Range(2, 3);
1447 model.SetText(ASCIIToUTF16("ABCDE"));
1448 model.MoveCursor(gfx::LINE_BREAK, gfx::CURSOR_RIGHT, false);
1449 model.InsertChar('x');
1450 EXPECT_STR_EQ("ABCDEx", model.GetText());
1451 EXPECT_TRUE(model.Undo()); // set composition should forget undone edit.
1452 model.SetCompositionText(composition);
1453 EXPECT_TRUE(model.HasCompositionText());
1454 EXPECT_TRUE(model.HasSelection());
1455 EXPECT_STR_EQ("ABCDEabc", model.GetText());
1457 // Accepting composition
1458 model.ConfirmCompositionText();
1459 EXPECT_STR_EQ("ABCDEabc", model.GetText());
1460 EXPECT_TRUE(model.Undo());
1461 EXPECT_STR_EQ("ABCDE", model.GetText());
1462 EXPECT_TRUE(model.Undo());
1463 EXPECT_STR_EQ("", model.GetText());
1464 EXPECT_TRUE(model.Redo());
1465 EXPECT_STR_EQ("ABCDE", model.GetText());
1466 EXPECT_TRUE(model.Redo());
1467 EXPECT_STR_EQ("ABCDEabc", model.GetText());
1468 EXPECT_FALSE(model.Redo());
1470 // Canceling composition
1471 model.MoveCursor(gfx::LINE_BREAK, gfx::CURSOR_LEFT, false);
1472 model.SetCompositionText(composition);
1473 EXPECT_STR_EQ("abcABCDEabc", model.GetText());
1474 model.CancelCompositionText();
1475 EXPECT_STR_EQ("ABCDEabc", model.GetText());
1476 EXPECT_FALSE(model.Redo());
1477 EXPECT_STR_EQ("ABCDEabc", model.GetText());
1478 EXPECT_TRUE(model.Undo());
1479 EXPECT_STR_EQ("ABCDE", model.GetText());
1480 EXPECT_TRUE(model.Redo());
1481 EXPECT_STR_EQ("ABCDEabc", model.GetText());
1482 EXPECT_FALSE(model.Redo());
1484 // SetText with the same text as the result.
1486 model.SetText(ASCIIToUTF16("ABCDE"));
1487 model.MoveCursor(gfx::LINE_BREAK, gfx::CURSOR_RIGHT, false);
1488 model.SetCompositionText(composition);
1489 EXPECT_STR_EQ("ABCDEabc", model.GetText());
1490 model.SetText(ASCIIToUTF16("ABCDEabc"));
1491 EXPECT_STR_EQ("ABCDEabc", model.GetText());
1492 EXPECT_TRUE(model.Undo());
1493 EXPECT_STR_EQ("ABCDE", model.GetText());
1494 EXPECT_TRUE(model.Redo());
1495 EXPECT_STR_EQ("ABCDEabc", model.GetText());
1496 EXPECT_FALSE(model.Redo());
1498 // SetText with the different text than the result should not
1499 // remember composition text.
1501 model.SetText(ASCIIToUTF16("ABCDE"));
1502 model.MoveCursor(gfx::LINE_BREAK, gfx::CURSOR_RIGHT, false);
1503 model.SetCompositionText(composition);
1504 EXPECT_STR_EQ("ABCDEabc", model.GetText());
1505 model.SetText(ASCIIToUTF16("1234"));
1506 EXPECT_STR_EQ("1234", model.GetText());
1507 EXPECT_TRUE(model.Undo());
1508 EXPECT_STR_EQ("ABCDE", model.GetText());
1509 EXPECT_TRUE(model.Redo());
1510 EXPECT_STR_EQ("1234", model.GetText());
1511 EXPECT_FALSE(model.Redo());
1513 // TODO(oshima): We need MockInputMethod to test the behavior with IME.
1516 } // namespace views