- add sources.
[platform/framework/web/crosswalk.git] / src / ui / views / controls / textfield / textfield_views_model_unittest.cc
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.
4
5 #include <vector>
6
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"
21
22 #if defined(OS_WIN)
23 #include "base/win/windows_version.h"
24 #endif
25
26 #define EXPECT_STR_EQ(ascii, utf16) EXPECT_EQ(ASCIIToUTF16(ascii), utf16)
27
28 namespace {
29
30 struct WordAndCursor {
31   WordAndCursor(const wchar_t* w, size_t c) : word(w), cursor(c) {}
32
33   const wchar_t* word;
34   size_t cursor;
35 };
36
37 void MoveCursorTo(views::TextfieldViewsModel& model, size_t pos) {
38   model.MoveCursorTo(gfx::SelectionModel(pos, gfx::CURSOR_FORWARD));
39 }
40
41 }  // namespace
42
43 namespace views {
44
45 class TextfieldViewsModelTest : public ViewsTestBase,
46                                 public TextfieldViewsModel::Delegate {
47  public:
48   TextfieldViewsModelTest()
49       : ViewsTestBase(),
50         composition_text_confirmed_or_cleared_(false) {
51   }
52
53   virtual void OnCompositionTextConfirmedOrCleared() OVERRIDE {
54     composition_text_confirmed_or_cleared_ = true;
55   }
56
57  protected:
58   void ResetModel(TextfieldViewsModel* model) const {
59     model->SetText(string16());
60     model->ClearEditHistory();
61   }
62
63   bool composition_text_confirmed_or_cleared_;
64
65  private:
66   DISALLOW_COPY_AND_ASSIGN(TextfieldViewsModelTest);
67 };
68
69 TEST_F(TextfieldViewsModelTest, EditString) {
70   TextfieldViewsModel model(NULL);
71   // append two strings
72   model.Append(ASCIIToUTF16("HILL"));
73   EXPECT_STR_EQ("HILL", model.GetText());
74   model.Append(ASCIIToUTF16("WORLD"));
75   EXPECT_STR_EQ("HILLWORLD", model.GetText());
76
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());
87
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());
95
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());
107
108   MoveCursorTo(model, 5);
109   model.ReplaceText(ASCIIToUTF16(" WOR"));
110   EXPECT_STR_EQ("HELLO WORL", model.GetText());
111 }
112
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"),
120             model.GetText());
121
122   // Insert 0x05f0.
123   MoveCursorTo(model, 1);
124   model.InsertChar(0x05f0);
125   EXPECT_EQ(WideToUTF16(L"\x05d0\x05f0\x05d1\x05d2\x05e0\x05e1\x05e2"),
126             model.GetText());
127
128   // Replace "\x05d1" with "\x05f1".
129   model.ReplaceChar(0x05f1);
130   EXPECT_EQ(WideToUTF16(L"\x05d0\x05f0\x5f1\x05d2\x05e0\x05e1\x05e2"),
131             model.GetText());
132
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"),
137             model.GetText());
138   EXPECT_TRUE(model.Backspace());
139   EXPECT_EQ(2U, model.GetCursorPosition());
140   EXPECT_EQ(WideToUTF16(L"\x05d0\x05f0\x05e0\x05e1\x05e2"), model.GetText());
141 }
142
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;
147 #if defined(OS_WIN)
148   on_windows_xp = base::win::GetVersion() < base::win::VERSION_VISTA;
149 #endif
150
151   TextfieldViewsModel model(NULL);
152
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"),
156             model.GetText());
157   model.Append(WideToUTF16(L"\x0915\x094d\x092e\x094d"));
158   EXPECT_EQ(WideToUTF16(
159       L"\x0915\x093f\x0915\x094d\x0915\x0915\x094d\x092e\x094d"),
160       model.GetText());
161
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());
168
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"),
174         model.GetText());
175
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"),
184         model.GetText());
185 #endif
186     EXPECT_EQ(4U, model.GetCursorPosition());
187   }
188
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"),
197             model.GetText());
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"),
202             model.GetText());
203 #endif
204
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());
209
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());
217   }
218
219   // TODO(asvitkine): Temporarily disable the following check on Windows. It
220   // seems Windows treats "\x0D38\x0D4D\x0D15" as a single grapheme.
221 #if !defined(OS_WIN)
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());
226 #endif
227
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());
235
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"),
241             model.GetText());
242 }
243
244 TEST_F(TextfieldViewsModelTest, EmptyString) {
245   TextfieldViewsModel model(NULL);
246   EXPECT_EQ(string16(), model.GetText());
247   EXPECT_EQ(string16(), model.GetSelectedText());
248
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());
253
254   EXPECT_EQ(string16(), model.GetSelectedText());
255
256   EXPECT_FALSE(model.Delete());
257   EXPECT_FALSE(model.Backspace());
258 }
259
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());
268
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());
275
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());
280
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());
285
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());
294
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());
302 }
303
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
309   // caret positions.
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);
319
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());
323
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());
328
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());
332
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());
337
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());
343 #endif
344
345   // In case of "aBc", this test shows how to select "aB" or "Bc", assume 'B' is
346   // an RTL character.
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());
351
352   model.MoveCursor(gfx::CHARACTER_BREAK, gfx::CURSOR_RIGHT, true);
353   EXPECT_EQ(WideToUTF16(L"a"), model.GetSelectedText());
354
355   model.MoveCursor(gfx::CHARACTER_BREAK, gfx::CURSOR_RIGHT, true);
356   EXPECT_EQ(WideToUTF16(L"a\x05E9" L"b"), model.GetSelectedText());
357
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());
362
363   model.MoveCursor(gfx::CHARACTER_BREAK, gfx::CURSOR_LEFT, true);
364   EXPECT_EQ(WideToUTF16(L"b"), model.GetSelectedText());
365
366   model.MoveCursor(gfx::CHARACTER_BREAK, gfx::CURSOR_LEFT, true);
367   EXPECT_EQ(WideToUTF16(L"a\x05E9" L"b"), model.GetSelectedText());
368
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());
374
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());
380
381   model.ClearSelection();
382   EXPECT_EQ(string16(), model.GetSelectedText());
383   model.SelectAll(false);
384   EXPECT_EQ(WideToUTF16(L"a\x05E9" L"b"), model.GetSelectedText());
385 }
386
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());
395
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());
414 }
415
416 TEST_F(TextfieldViewsModelTest, Word) {
417   TextfieldViewsModel model(NULL);
418   model.Append(
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());
427
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());
432
433   // Move to the end.
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());
443
444   // Now backwards.
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());
461 }
462
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());
475
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());
482 }
483
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);
489
490   string16 clipboard_text;
491   TextfieldViewsModel model(NULL);
492   model.Append(ASCIIToUTF16("HELLO WORLD"));
493
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());
501
502   // Copy with an empty selection should do nothing.
503   model.Copy();
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());
508
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());
517
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());
525
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());
535
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());
543
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());
553 }
554
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());
559 }
560
561 TEST_F(TextfieldViewsModelTest, SelectWordTest) {
562   TextfieldViewsModel model(NULL);
563   model.Append(ASCIIToUTF16("  HELLO  !!  WO     RLD "));
564
565   // Test when cursor is at the beginning.
566   model.MoveCursor(gfx::LINE_BREAK, gfx::CURSOR_LEFT, false);
567   model.SelectWord();
568   SelectWordTestVerifier(model, ASCIIToUTF16("  "), 2U);
569
570   // Test when cursor is at the beginning of a word.
571   MoveCursorTo(model, 2);
572   model.SelectWord();
573   SelectWordTestVerifier(model, ASCIIToUTF16("HELLO"), 7U);
574
575   // Test when cursor is at the end of a word.
576   MoveCursorTo(model, 15);
577   model.SelectWord();
578   SelectWordTestVerifier(model, ASCIIToUTF16("     "), 20U);
579
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);
583     model.SelectWord();
584     SelectWordTestVerifier(model, ASCIIToUTF16("  !!  "), 13U);
585   }
586
587   // Test when cursor is somewhere in a whitespace fragment.
588   MoveCursorTo(model, 17);
589   model.SelectWord();
590   SelectWordTestVerifier(model, ASCIIToUTF16("     "), 20U);
591
592   // Test when cursor is at the end.
593   model.MoveCursor(gfx::LINE_BREAK, gfx::CURSOR_RIGHT, false);
594   model.SelectWord();
595   SelectWordTestVerifier(model, ASCIIToUTF16(" "), 24U);
596 }
597
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
600 // regression.
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));
618
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);
626     model.SelectWord();
627     SelectWordTestVerifier(model, WideToUTF16(word_and_cursor[i].word),
628                            word_and_cursor[i].cursor);
629   }
630 }
631 #endif
632
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());
641
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());
648
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());
654
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());
660
661   // now from the 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());
667
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());
674
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());
681
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());
687
688   // Select All
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());
695 }
696
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());
704
705   range = gfx::Range(6, 1);
706   EXPECT_TRUE(range.is_reversed());
707   model.SelectRange(range);
708   EXPECT_STR_EQ("ELLO ", model.GetSelectedText());
709
710   range = gfx::Range(2, 1000);
711   EXPECT_FALSE(range.is_reversed());
712   model.SelectRange(range);
713   EXPECT_STR_EQ("LLO WORLD", model.GetSelectedText());
714
715   range = gfx::Range(1000, 3);
716   EXPECT_TRUE(range.is_reversed());
717   model.SelectRange(range);
718   EXPECT_STR_EQ("LO WORLD", model.GetSelectedText());
719
720   range = gfx::Range(0, 0);
721   EXPECT_TRUE(range.is_empty());
722   model.SelectRange(range);
723   EXPECT_TRUE(model.GetSelectedText().empty());
724
725   range = gfx::Range(3, 3);
726   EXPECT_TRUE(range.is_empty());
727   model.SelectRange(range);
728   EXPECT_TRUE(model.GetSelectedText().empty());
729
730   range = gfx::Range(1000, 100);
731   EXPECT_FALSE(range.is_empty());
732   model.SelectRange(range);
733   EXPECT_TRUE(model.GetSelectedText().empty());
734
735   range = gfx::Range(1000, 1000);
736   EXPECT_TRUE(range.is_empty());
737   model.SelectRange(range);
738   EXPECT_TRUE(model.GetSelectedText().empty());
739 }
740
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);
747
748   model.MoveCursor(gfx::WORD_BREAK, gfx::CURSOR_RIGHT, true);
749   selection = model.render_text()->selection();
750   EXPECT_EQ(gfx::Range(0, 5), selection);
751
752   model.MoveCursor(gfx::CHARACTER_BREAK, gfx::CURSOR_LEFT, true);
753   selection = model.render_text()->selection();
754   EXPECT_EQ(gfx::Range(0, 4), selection);
755
756   model.MoveCursor(gfx::WORD_BREAK, gfx::CURSOR_LEFT, true);
757   selection = model.render_text()->selection();
758   EXPECT_EQ(gfx::Range(0), selection);
759
760   // now from the end.
761   model.MoveCursor(gfx::LINE_BREAK, gfx::CURSOR_RIGHT, false);
762   selection = model.render_text()->selection();
763   EXPECT_EQ(gfx::Range(11), selection);
764
765   model.MoveCursor(gfx::WORD_BREAK, gfx::CURSOR_LEFT, true);
766   selection = model.render_text()->selection();
767   EXPECT_EQ(gfx::Range(11, 6), selection);
768
769   model.MoveCursor(gfx::CHARACTER_BREAK, gfx::CURSOR_RIGHT, true);
770   selection = model.render_text()->selection();
771   EXPECT_EQ(gfx::Range(11, 7), selection);
772
773   model.MoveCursor(gfx::WORD_BREAK, gfx::CURSOR_RIGHT, true);
774   selection = model.render_text()->selection();
775   EXPECT_EQ(gfx::Range(11), selection);
776
777   // Select All
778   model.MoveCursor(gfx::LINE_BREAK, gfx::CURSOR_LEFT, true);
779   selection = model.render_text()->selection();
780   EXPECT_EQ(gfx::Range(11, 0), selection);
781 }
782
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());
789
790   model.SelectSelectionModel(gfx::SelectionModel(gfx::Range(6, 1),
791       gfx::CURSOR_FORWARD));
792   EXPECT_STR_EQ("ELLO ", model.GetSelectedText());
793
794   model.SelectSelectionModel(gfx::SelectionModel(gfx::Range(2, 1000),
795       gfx::CURSOR_BACKWARD));
796   EXPECT_STR_EQ("LLO WORLD", model.GetSelectedText());
797
798   model.SelectSelectionModel(gfx::SelectionModel(gfx::Range(1000, 3),
799       gfx::CURSOR_FORWARD));
800   EXPECT_STR_EQ("LO WORLD", model.GetSelectedText());
801
802   model.SelectSelectionModel(gfx::SelectionModel(0, gfx::CURSOR_FORWARD));
803   EXPECT_TRUE(model.GetSelectedText().empty());
804
805   model.SelectSelectionModel(gfx::SelectionModel(3, gfx::CURSOR_FORWARD));
806   EXPECT_TRUE(model.GetSelectedText().empty());
807
808   model.SelectSelectionModel(gfx::SelectionModel(gfx::Range(1000, 100),
809       gfx::CURSOR_FORWARD));
810   EXPECT_TRUE(model.GetSelectedText().empty());
811
812   model.SelectSelectionModel(gfx::SelectionModel(1000, gfx::CURSOR_BACKWARD));
813   EXPECT_TRUE(model.GetSelectedText().empty());
814 }
815
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());
822
823   gfx::Range range;
824   model.GetTextRange(&range);
825   EXPECT_EQ(gfx::Range(0, 7), range);
826
827   ui::CompositionText composition;
828   composition.text = ASCIIToUTF16("678");
829   composition.underlines.push_back(ui::CompositionUnderline(0, 3, 0, false));
830
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());
836
837   // Cancel composition
838   model.CancelCompositionText();
839   composition_text_confirmed_or_cleared_ = false;
840
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());
850
851   model.GetTextRange(&range);
852   EXPECT_EQ(10U, range.end());
853   EXPECT_STR_EQ("1234567890", model.GetText());
854
855   model.GetCompositionTextRange(&range);
856   EXPECT_EQ(gfx::Range(5, 8), range);
857   // composition text
858   EXPECT_STR_EQ("456", model.GetTextFromRange(gfx::Range(3, 6)));
859   EXPECT_EQ(gfx::Range(5, 7), model.render_text()->selection());
860
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());
868
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);
875
876   model.SetCompositionText(composition);
877   EXPECT_STR_EQ("1234567890678", model.GetText());
878
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());
885
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());
890
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());
897
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());
903
904   model.SetCompositionText(composition);
905   model.Delete();
906   EXPECT_TRUE(composition_text_confirmed_or_cleared_);
907   composition_text_confirmed_or_cleared_ = false;
908   EXPECT_STR_EQ("1234567890-678-", model.GetText());
909
910   model.SetCompositionText(composition);
911   model.Backspace();
912   EXPECT_TRUE(composition_text_confirmed_or_cleared_);
913   composition_text_confirmed_or_cleared_ = false;
914   EXPECT_STR_EQ("1234567890-678-", model.GetText());
915
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());
923
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());
930
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());
936
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;
942
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());
948
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());
954
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());
963
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());
969
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());
975
976   model.SetCompositionText(composition);
977   model.SelectWord();
978   EXPECT_TRUE(composition_text_confirmed_or_cleared_);
979   composition_text_confirmed_or_cleared_ = false;
980   EXPECT_STR_EQ("678", model.GetText());
981
982   model.SetCompositionText(composition);
983   model.ClearSelection();
984   EXPECT_TRUE(composition_text_confirmed_or_cleared_);
985   composition_text_confirmed_or_cleared_ = false;
986
987   model.SetCompositionText(composition);
988   EXPECT_FALSE(model.Cut());
989   EXPECT_FALSE(composition_text_confirmed_or_cleared_);
990 }
991
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());
1000
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());
1011
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());
1018
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());
1026
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());
1051
1052   // Clear history
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());
1058
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());
1087 }
1088
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());
1116
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());
1149 }
1150
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());
1173 }
1174
1175 TEST_F(TextfieldViewsModelTest, UndoRedo_CutCopyPasteTest) {
1176   TextfieldViewsModel model(NULL);
1177   model.SetText(ASCIIToUTF16("ABCDE"));
1178   EXPECT_FALSE(model.Redo());  // nothing to redo
1179   // Cut
1180   model.SelectRange(gfx::Range(1, 3));
1181   model.Cut();
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());
1200
1201   model.Paste();
1202   model.Paste();
1203   model.Paste();
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());
1226
1227   // Redo
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());
1241
1242   // with SelectRange
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());
1260
1261   // Copy
1262   ResetModel(&model);
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());
1273   model.Paste();
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());
1286   // Redo
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());
1298
1299   // Test using SelectRange
1300   model.SelectRange(gfx::Range(1, 3));
1301   model.Copy();
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());
1310 }
1311
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());
1329 }
1330
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());
1352 }
1353
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());
1376 }
1377
1378 TEST_F(TextfieldViewsModelTest, UndoRedo_ReplaceTest) {
1379   // By Cursor
1380   {
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);
1386   }
1387   {
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);
1393   }
1394   {
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);
1400   }
1401   {
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);
1407   }
1408   // By SelectRange API
1409   {
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);
1415   }
1416   {
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);
1422   }
1423   {
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);
1429   }
1430   {
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);
1436   }
1437 }
1438
1439 TEST_F(TextfieldViewsModelTest, UndoRedo_CompositionText) {
1440   TextfieldViewsModel model(NULL);
1441
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);
1446
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());
1456
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());
1469
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());
1483
1484   // SetText with the same text as the result.
1485   ResetModel(&model);
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());
1497
1498   // SetText with the different text than the result should not
1499   // remember composition text.
1500   ResetModel(&model);
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());
1512
1513   // TODO(oshima): We need MockInputMethod to test the behavior with IME.
1514 }
1515
1516 }  // namespace views