textfield_model_unittest.cc revision 5d1f7b1de12d16ceb2c938c56701a3e8bfa558f7
1// Copyright 2014 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_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
26using base::ASCIIToUTF16;
27using base::UTF8ToUTF16;
28using base::WideToUTF16;
29
30#define EXPECT_STR_EQ(ascii, utf16) EXPECT_EQ(ASCIIToUTF16(ascii), utf16)
31
32namespace {
33
34struct WordAndCursor {
35  WordAndCursor(const wchar_t* w, size_t c) : word(w), cursor(c) {}
36
37  const wchar_t* word;
38  size_t cursor;
39};
40
41void MoveCursorTo(views::TextfieldModel& model, size_t pos) {
42  model.MoveCursorTo(gfx::SelectionModel(pos, gfx::CURSOR_FORWARD));
43}
44
45}  // namespace
46
47namespace views {
48
49class TextfieldModelTest : public ViewsTestBase,
50                           public TextfieldModel::Delegate {
51 public:
52  TextfieldModelTest()
53      : ViewsTestBase(),
54        composition_text_confirmed_or_cleared_(false) {
55  }
56
57  virtual void OnCompositionTextConfirmedOrCleared() OVERRIDE {
58    composition_text_confirmed_or_cleared_ = true;
59  }
60
61 protected:
62  void ResetModel(TextfieldModel* model) const {
63    model->SetText(base::string16());
64    model->ClearEditHistory();
65  }
66
67  bool composition_text_confirmed_or_cleared_;
68
69 private:
70  DISALLOW_COPY_AND_ASSIGN(TextfieldModelTest);
71};
72
73TEST_F(TextfieldModelTest, EditString) {
74  TextfieldModel model(NULL);
75  // append two strings
76  model.Append(ASCIIToUTF16("HILL"));
77  EXPECT_STR_EQ("HILL", model.text());
78  model.Append(ASCIIToUTF16("WORLD"));
79  EXPECT_STR_EQ("HILLWORLD", model.text());
80
81  // Insert "E" to make hello
82  model.MoveCursor(gfx::CHARACTER_BREAK, gfx::CURSOR_RIGHT, false);
83  model.InsertChar('E');
84  EXPECT_STR_EQ("HEILLWORLD", model.text());
85  // Replace "I" with "L"
86  model.ReplaceChar('L');
87  EXPECT_STR_EQ("HELLLWORLD", model.text());
88  model.ReplaceChar('L');
89  model.ReplaceChar('O');
90  EXPECT_STR_EQ("HELLOWORLD", model.text());
91
92  // Delete 6th char "W", then delete 5th char O"
93  EXPECT_EQ(5U, model.GetCursorPosition());
94  EXPECT_TRUE(model.Delete());
95  EXPECT_STR_EQ("HELLOORLD", model.text());
96  EXPECT_TRUE(model.Backspace());
97  EXPECT_EQ(4U, model.GetCursorPosition());
98  EXPECT_STR_EQ("HELLORLD", model.text());
99
100  // Move the cursor to start. backspace should fail.
101  model.MoveCursor(gfx::LINE_BREAK, gfx::CURSOR_LEFT, false);
102  EXPECT_FALSE(model.Backspace());
103  EXPECT_STR_EQ("HELLORLD", model.text());
104  // Move the cursor to the end. delete should fail.
105  model.MoveCursor(gfx::LINE_BREAK, gfx::CURSOR_RIGHT, false);
106  EXPECT_FALSE(model.Delete());
107  EXPECT_STR_EQ("HELLORLD", model.text());
108  // but backspace should work.
109  EXPECT_TRUE(model.Backspace());
110  EXPECT_STR_EQ("HELLORL", model.text());
111
112  MoveCursorTo(model, 5);
113  model.ReplaceText(ASCIIToUTF16(" WOR"));
114  EXPECT_STR_EQ("HELLO WORL", model.text());
115}
116
117TEST_F(TextfieldModelTest, EditString_SimpleRTL) {
118  TextfieldModel model(NULL);
119  // Append two strings.
120  model.Append(WideToUTF16(L"\x05d0\x05d1\x05d2"));
121  EXPECT_EQ(WideToUTF16(L"\x05d0\x05d1\x05d2"), model.text());
122  model.Append(WideToUTF16(L"\x05e0\x05e1\x05e2"));
123  EXPECT_EQ(WideToUTF16(L"\x05d0\x05d1\x05d2\x05e0\x05e1\x05e2"), model.text());
124
125  // Insert 0x05f0.
126  MoveCursorTo(model, 1);
127  model.InsertChar(0x05f0);
128  EXPECT_EQ(WideToUTF16(L"\x05d0\x05f0\x05d1\x05d2\x05e0\x05e1\x05e2"),
129            model.text());
130
131  // Replace "\x05d1" with "\x05f1".
132  model.ReplaceChar(0x05f1);
133  EXPECT_EQ(WideToUTF16(L"\x05d0\x05f0\x5f1\x05d2\x05e0\x05e1\x05e2"),
134            model.text());
135
136  // Delete and backspace.
137  EXPECT_EQ(3U, model.GetCursorPosition());
138  EXPECT_TRUE(model.Delete());
139  EXPECT_EQ(WideToUTF16(L"\x05d0\x05f0\x5f1\x05e0\x05e1\x05e2"), model.text());
140  EXPECT_TRUE(model.Backspace());
141  EXPECT_EQ(2U, model.GetCursorPosition());
142  EXPECT_EQ(WideToUTF16(L"\x05d0\x05f0\x05e0\x05e1\x05e2"), model.text());
143}
144
145TEST_F(TextfieldModelTest, EditString_ComplexScript) {
146  // TODO(asvitkine): Disable tests that fail on XP bots due to lack of complete
147  //                  font support for some scripts - http://crbug.com/106450
148  bool on_windows_xp = false;
149#if defined(OS_WIN)
150  on_windows_xp = base::win::GetVersion() < base::win::VERSION_VISTA;
151#endif
152
153  TextfieldModel model(NULL);
154
155  // Append two Hindi strings.
156  model.Append(WideToUTF16(L"\x0915\x093f\x0915\x094d\x0915"));
157  EXPECT_EQ(WideToUTF16(L"\x0915\x093f\x0915\x094d\x0915"), model.text());
158  model.Append(WideToUTF16(L"\x0915\x094d\x092e\x094d"));
159  EXPECT_EQ(WideToUTF16(
160      L"\x0915\x093f\x0915\x094d\x0915\x0915\x094d\x092e\x094d"), model.text());
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.text());
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.text());
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.text());
198  MoveCursorTo(model, model.text().length());
199  EXPECT_EQ(model.text().length(), model.GetCursorPosition());
200  EXPECT_TRUE(model.Backspace());
201  EXPECT_EQ(WideToUTF16(L"\x0061\x0062\x0915\x0915\x094d\x092e"), model.text());
202#endif
203
204  // Test cursor position and deletion for Hindi Virama.
205  model.SetText(WideToUTF16(L"\x0D38\x0D4D\x0D15\x0D16\x0D2E"));
206  MoveCursorTo(model, 0);
207  EXPECT_EQ(0U, model.GetCursorPosition());
208
209  // TODO(asvitkine): Disable tests that fail on XP bots due to lack of complete
210  //                  font support for some scripts - http://crbug.com/106450
211  if (!on_windows_xp) {
212    MoveCursorTo(model, 1);
213    EXPECT_EQ(0U, model.GetCursorPosition());
214    MoveCursorTo(model, 3);
215    EXPECT_EQ(3U, model.GetCursorPosition());
216  }
217
218  // TODO(asvitkine): Temporarily disable the following check on Windows. It
219  // seems Windows treats "\x0D38\x0D4D\x0D15" as a single grapheme.
220#if !defined(OS_WIN)
221  MoveCursorTo(model, 2);
222  EXPECT_EQ(2U, model.GetCursorPosition());
223  EXPECT_TRUE(model.Backspace());
224  EXPECT_EQ(WideToUTF16(L"\x0D38\x0D15\x0D16\x0D2E"), model.text());
225#endif
226
227  model.SetText(WideToUTF16(L"\x05d5\x05b7\x05D9\x05B0\x05D4\x05B4\x05D9"));
228  MoveCursorTo(model, 0);
229  EXPECT_TRUE(model.Delete());
230  EXPECT_TRUE(model.Delete());
231  EXPECT_TRUE(model.Delete());
232  EXPECT_TRUE(model.Delete());
233  EXPECT_EQ(WideToUTF16(L""), model.text());
234
235  // The first 2 characters are not strong directionality characters.
236  model.SetText(WideToUTF16(L"\x002C\x0020\x05D1\x05BC\x05B7\x05E9\x05BC"));
237  model.MoveCursor(gfx::LINE_BREAK, gfx::CURSOR_LEFT, false);
238  EXPECT_TRUE(model.Backspace());
239  EXPECT_EQ(WideToUTF16(L"\x002C\x0020\x05D1\x05BC\x05B7\x05E9"), model.text());
240}
241
242TEST_F(TextfieldModelTest, EmptyString) {
243  TextfieldModel model(NULL);
244  EXPECT_EQ(base::string16(), model.text());
245  EXPECT_EQ(base::string16(), model.GetSelectedText());
246
247  model.MoveCursor(gfx::CHARACTER_BREAK, gfx::CURSOR_LEFT, true);
248  EXPECT_EQ(0U, model.GetCursorPosition());
249  model.MoveCursor(gfx::CHARACTER_BREAK, gfx::CURSOR_RIGHT, true);
250  EXPECT_EQ(0U, model.GetCursorPosition());
251
252  EXPECT_EQ(base::string16(), model.GetSelectedText());
253
254  EXPECT_FALSE(model.Delete());
255  EXPECT_FALSE(model.Backspace());
256}
257
258TEST_F(TextfieldModelTest, Selection) {
259  TextfieldModel model(NULL);
260  model.Append(ASCIIToUTF16("HELLO"));
261  model.MoveCursor(gfx::CHARACTER_BREAK, gfx::CURSOR_RIGHT, false);
262  model.MoveCursor(gfx::CHARACTER_BREAK, gfx::CURSOR_RIGHT, true);
263  EXPECT_STR_EQ("E", model.GetSelectedText());
264  model.MoveCursor(gfx::CHARACTER_BREAK, gfx::CURSOR_RIGHT, true);
265  EXPECT_STR_EQ("EL", model.GetSelectedText());
266
267  model.MoveCursor(gfx::LINE_BREAK, gfx::CURSOR_LEFT, true);
268  EXPECT_STR_EQ("H", model.GetSelectedText());
269  model.MoveCursor(gfx::LINE_BREAK, gfx::CURSOR_RIGHT, true);
270  EXPECT_STR_EQ("ELLO", model.GetSelectedText());
271  model.ClearSelection();
272  EXPECT_EQ(base::string16(), model.GetSelectedText());
273
274  // SelectAll(false) selects towards the end.
275  model.SelectAll(false);
276  EXPECT_STR_EQ("HELLO", model.GetSelectedText());
277  EXPECT_EQ(gfx::Range(0, 5), model.render_text()->selection());
278
279  // SelectAll(true) selects towards the beginning.
280  model.SelectAll(true);
281  EXPECT_STR_EQ("HELLO", model.GetSelectedText());
282  EXPECT_EQ(gfx::Range(5, 0), model.render_text()->selection());
283
284  // Select and move cursor.
285  model.SelectRange(gfx::Range(1U, 3U));
286  EXPECT_STR_EQ("EL", model.GetSelectedText());
287  model.MoveCursor(gfx::CHARACTER_BREAK, gfx::CURSOR_LEFT, false);
288  EXPECT_EQ(1U, model.GetCursorPosition());
289  model.SelectRange(gfx::Range(1U, 3U));
290  model.MoveCursor(gfx::CHARACTER_BREAK, gfx::CURSOR_RIGHT, false);
291  EXPECT_EQ(3U, model.GetCursorPosition());
292
293  // Select all and move cursor.
294  model.SelectAll(false);
295  model.MoveCursor(gfx::CHARACTER_BREAK, gfx::CURSOR_LEFT, false);
296  EXPECT_EQ(0U, model.GetCursorPosition());
297  model.SelectAll(false);
298  model.MoveCursor(gfx::CHARACTER_BREAK, gfx::CURSOR_RIGHT, false);
299  EXPECT_EQ(5U, model.GetCursorPosition());
300}
301
302TEST_F(TextfieldModelTest, Selection_BidiWithNonSpacingMarks) {
303  // Selection is a logical operation. And it should work with the arrow
304  // keys doing visual movements, while the selection is logical between
305  // the (logical) start and end points. Selection is simply defined as
306  // the portion of text between the logical positions of the start and end
307  // caret positions.
308  TextfieldModel model(NULL);
309  // TODO(xji): temporarily disable in platform Win since the complex script
310  // characters turned into empty square due to font regression. So, not able
311  // to test 2 characters belong to the same grapheme.
312#if defined(OS_LINUX)
313  model.Append(WideToUTF16(
314      L"abc\x05E9\x05BC\x05C1\x05B8\x05E0\x05B8" L"def"));
315  model.MoveCursor(gfx::CHARACTER_BREAK, gfx::CURSOR_RIGHT, false);
316  model.MoveCursor(gfx::CHARACTER_BREAK, gfx::CURSOR_RIGHT, false);
317
318  model.MoveCursor(gfx::CHARACTER_BREAK, gfx::CURSOR_RIGHT, true);
319  EXPECT_EQ(gfx::Range(2, 3), model.render_text()->selection());
320  EXPECT_EQ(WideToUTF16(L"c"), model.GetSelectedText());
321
322  model.MoveCursor(gfx::CHARACTER_BREAK, gfx::CURSOR_RIGHT, true);
323  EXPECT_EQ(gfx::Range(2, 7), model.render_text()->selection());
324  EXPECT_EQ(WideToUTF16(L"c\x05E9\x05BC\x05C1\x05B8"),
325            model.GetSelectedText());
326
327  model.MoveCursor(gfx::CHARACTER_BREAK, gfx::CURSOR_RIGHT, true);
328  EXPECT_EQ(gfx::Range(2, 3), model.render_text()->selection());
329  EXPECT_EQ(WideToUTF16(L"c"), model.GetSelectedText());
330
331  model.MoveCursor(gfx::CHARACTER_BREAK, gfx::CURSOR_RIGHT, true);
332  EXPECT_EQ(gfx::Range(2, 10), model.render_text()->selection());
333  EXPECT_EQ(WideToUTF16(L"c\x05E9\x05BC\x05C1\x05B8\x05E0\x05B8" L"d"),
334            model.GetSelectedText());
335
336  model.ClearSelection();
337  EXPECT_EQ(base::string16(), model.GetSelectedText());
338  model.SelectAll(false);
339  EXPECT_EQ(WideToUTF16(L"abc\x05E9\x05BC\x05C1\x05B8\x05E0\x05B8" L"def"),
340            model.GetSelectedText());
341#endif
342
343  // In case of "aBc", this test shows how to select "aB" or "Bc", assume 'B' is
344  // an RTL character.
345  model.SetText(WideToUTF16(L"a\x05E9" L"b"));
346  MoveCursorTo(model, 0);
347  model.MoveCursor(gfx::CHARACTER_BREAK, gfx::CURSOR_RIGHT, true);
348  EXPECT_EQ(WideToUTF16(L"a"), model.GetSelectedText());
349
350  model.MoveCursor(gfx::CHARACTER_BREAK, gfx::CURSOR_RIGHT, true);
351  EXPECT_EQ(WideToUTF16(L"a"), model.GetSelectedText());
352
353  model.MoveCursor(gfx::CHARACTER_BREAK, gfx::CURSOR_RIGHT, true);
354  EXPECT_EQ(WideToUTF16(L"a\x05E9" L"b"), model.GetSelectedText());
355
356  model.MoveCursor(gfx::CHARACTER_BREAK, gfx::CURSOR_RIGHT, false);
357  EXPECT_EQ(3U, model.GetCursorPosition());
358  model.MoveCursor(gfx::CHARACTER_BREAK, gfx::CURSOR_LEFT, true);
359  EXPECT_EQ(WideToUTF16(L"b"), model.GetSelectedText());
360
361  model.MoveCursor(gfx::CHARACTER_BREAK, gfx::CURSOR_LEFT, true);
362  EXPECT_EQ(WideToUTF16(L"b"), model.GetSelectedText());
363
364  model.MoveCursor(gfx::CHARACTER_BREAK, gfx::CURSOR_LEFT, true);
365  EXPECT_EQ(WideToUTF16(L"a\x05E9" L"b"), model.GetSelectedText());
366
367  model.MoveCursor(gfx::LINE_BREAK, gfx::CURSOR_LEFT, false);
368  model.MoveCursor(gfx::CHARACTER_BREAK, gfx::CURSOR_RIGHT, true);
369  model.MoveCursor(gfx::CHARACTER_BREAK, gfx::CURSOR_RIGHT, true);
370  model.MoveCursor(gfx::CHARACTER_BREAK, gfx::CURSOR_LEFT, true);
371  EXPECT_EQ(WideToUTF16(L"a\x05E9"), model.GetSelectedText());
372
373  model.MoveCursor(gfx::LINE_BREAK, gfx::CURSOR_RIGHT, false);
374  model.MoveCursor(gfx::CHARACTER_BREAK, gfx::CURSOR_LEFT, true);
375  model.MoveCursor(gfx::CHARACTER_BREAK, gfx::CURSOR_LEFT, true);
376  model.MoveCursor(gfx::CHARACTER_BREAK, gfx::CURSOR_RIGHT, true);
377  EXPECT_EQ(WideToUTF16(L"\x05E9" L"b"), model.GetSelectedText());
378
379  model.ClearSelection();
380  EXPECT_EQ(base::string16(), model.GetSelectedText());
381  model.SelectAll(false);
382  EXPECT_EQ(WideToUTF16(L"a\x05E9" L"b"), model.GetSelectedText());
383}
384
385TEST_F(TextfieldModelTest, SelectionAndEdit) {
386  TextfieldModel model(NULL);
387  model.Append(ASCIIToUTF16("HELLO"));
388  model.MoveCursor(gfx::CHARACTER_BREAK, gfx::CURSOR_RIGHT, false);
389  model.MoveCursor(gfx::CHARACTER_BREAK, gfx::CURSOR_RIGHT, true);
390  model.MoveCursor(gfx::CHARACTER_BREAK, gfx::CURSOR_RIGHT, true);  // "EL"
391  EXPECT_TRUE(model.Backspace());
392  EXPECT_STR_EQ("HLO", model.text());
393
394  model.Append(ASCIIToUTF16("ILL"));
395  model.MoveCursor(gfx::CHARACTER_BREAK, gfx::CURSOR_RIGHT, true);
396  model.MoveCursor(gfx::CHARACTER_BREAK, gfx::CURSOR_RIGHT, true);  // "LO"
397  EXPECT_TRUE(model.Delete());
398  EXPECT_STR_EQ("HILL", model.text());
399  EXPECT_EQ(1U, model.GetCursorPosition());
400  model.MoveCursor(gfx::CHARACTER_BREAK, gfx::CURSOR_RIGHT, true);  // "I"
401  model.InsertChar('E');
402  EXPECT_STR_EQ("HELL", model.text());
403  model.MoveCursor(gfx::LINE_BREAK, gfx::CURSOR_LEFT, false);
404  model.MoveCursor(gfx::CHARACTER_BREAK, gfx::CURSOR_RIGHT, true);  // "H"
405  model.ReplaceChar('B');
406  EXPECT_STR_EQ("BELL", model.text());
407  model.MoveCursor(gfx::LINE_BREAK, gfx::CURSOR_RIGHT, false);
408  model.MoveCursor(gfx::CHARACTER_BREAK, gfx::CURSOR_LEFT, true);
409  model.MoveCursor(gfx::CHARACTER_BREAK, gfx::CURSOR_LEFT, true);  // "ELL"
410  model.ReplaceChar('E');
411  EXPECT_STR_EQ("BEE", model.text());
412}
413
414TEST_F(TextfieldModelTest, Word) {
415  TextfieldModel model(NULL);
416  model.Append(
417      ASCIIToUTF16("The answer to Life, the Universe, and Everything"));
418  model.MoveCursor(gfx::WORD_BREAK, gfx::CURSOR_RIGHT, false);
419  EXPECT_EQ(3U, model.GetCursorPosition());
420  model.MoveCursor(gfx::WORD_BREAK, gfx::CURSOR_RIGHT, false);
421  EXPECT_EQ(10U, model.GetCursorPosition());
422  model.MoveCursor(gfx::WORD_BREAK, gfx::CURSOR_RIGHT, false);
423  model.MoveCursor(gfx::WORD_BREAK, gfx::CURSOR_RIGHT, false);
424  EXPECT_EQ(18U, model.GetCursorPosition());
425
426  // Should passes the non word char ','
427  model.MoveCursor(gfx::WORD_BREAK, gfx::CURSOR_RIGHT, true);
428  EXPECT_EQ(23U, model.GetCursorPosition());
429  EXPECT_STR_EQ(", the", model.GetSelectedText());
430
431  // Move to the end.
432  model.MoveCursor(gfx::WORD_BREAK, gfx::CURSOR_RIGHT, true);
433  model.MoveCursor(gfx::WORD_BREAK, gfx::CURSOR_RIGHT, true);
434  model.MoveCursor(gfx::WORD_BREAK, gfx::CURSOR_RIGHT, true);
435  EXPECT_STR_EQ(", the Universe, and Everything", model.GetSelectedText());
436  // Should be safe to go next word at the end.
437  model.MoveCursor(gfx::WORD_BREAK, gfx::CURSOR_RIGHT, true);
438  EXPECT_STR_EQ(", the Universe, and Everything", model.GetSelectedText());
439  model.InsertChar('2');
440  EXPECT_EQ(19U, model.GetCursorPosition());
441
442  // Now backwards.
443  model.MoveCursor(gfx::CHARACTER_BREAK, gfx::CURSOR_LEFT, false);  // leave 2.
444  model.MoveCursor(gfx::WORD_BREAK, gfx::CURSOR_LEFT, true);
445  EXPECT_EQ(14U, model.GetCursorPosition());
446  EXPECT_STR_EQ("Life", model.GetSelectedText());
447  model.MoveCursor(gfx::WORD_BREAK, gfx::CURSOR_LEFT, true);
448  EXPECT_STR_EQ("to Life", model.GetSelectedText());
449  model.MoveCursor(gfx::WORD_BREAK, gfx::CURSOR_LEFT, true);
450  model.MoveCursor(gfx::WORD_BREAK, gfx::CURSOR_LEFT, true);
451  model.MoveCursor(gfx::WORD_BREAK, gfx::CURSOR_LEFT, true);  // Now at start.
452  EXPECT_STR_EQ("The answer to Life", model.GetSelectedText());
453  // Should be safe to go to the previous word at the beginning.
454  model.MoveCursor(gfx::WORD_BREAK, gfx::CURSOR_LEFT, true);
455  EXPECT_STR_EQ("The answer to Life", model.GetSelectedText());
456  model.ReplaceChar('4');
457  EXPECT_EQ(base::string16(), model.GetSelectedText());
458  EXPECT_STR_EQ("42", model.text());
459}
460
461TEST_F(TextfieldModelTest, SetText) {
462  TextfieldModel model(NULL);
463  model.Append(ASCIIToUTF16("HELLO"));
464  model.MoveCursor(gfx::LINE_BREAK, gfx::CURSOR_RIGHT, false);
465  model.SetText(ASCIIToUTF16("GOODBYE"));
466  EXPECT_STR_EQ("GOODBYE", model.text());
467  // SetText move the cursor to the end of the new text.
468  EXPECT_EQ(7U, model.GetCursorPosition());
469  model.SelectAll(false);
470  EXPECT_STR_EQ("GOODBYE", model.GetSelectedText());
471  model.MoveCursor(gfx::LINE_BREAK, gfx::CURSOR_RIGHT, false);
472  EXPECT_EQ(7U, model.GetCursorPosition());
473
474  model.SetText(ASCIIToUTF16("BYE"));
475  // Setting shorter string moves the cursor to the end of the new string.
476  EXPECT_EQ(3U, model.GetCursorPosition());
477  EXPECT_EQ(base::string16(), model.GetSelectedText());
478  model.SetText(base::string16());
479  EXPECT_EQ(0U, model.GetCursorPosition());
480}
481
482TEST_F(TextfieldModelTest, Clipboard) {
483  ui::Clipboard* clipboard = ui::Clipboard::GetForCurrentThread();
484  const base::string16 initial_clipboard_text = ASCIIToUTF16("initial text");
485  ui::ScopedClipboardWriter(clipboard, ui::CLIPBOARD_TYPE_COPY_PASTE).
486      WriteText(initial_clipboard_text);
487
488  base::string16 clipboard_text;
489  TextfieldModel model(NULL);
490  model.Append(ASCIIToUTF16("HELLO WORLD"));
491
492  // Cut with an empty selection should do nothing.
493  model.MoveCursor(gfx::LINE_BREAK, gfx::CURSOR_RIGHT, false);
494  EXPECT_FALSE(model.Cut());
495  clipboard->ReadText(ui::CLIPBOARD_TYPE_COPY_PASTE, &clipboard_text);
496  EXPECT_EQ(initial_clipboard_text, clipboard_text);
497  EXPECT_STR_EQ("HELLO WORLD", model.text());
498  EXPECT_EQ(11U, model.GetCursorPosition());
499
500  // Copy with an empty selection should do nothing.
501  model.Copy();
502  clipboard->ReadText(ui::CLIPBOARD_TYPE_COPY_PASTE, &clipboard_text);
503  EXPECT_EQ(initial_clipboard_text, clipboard_text);
504  EXPECT_STR_EQ("HELLO WORLD", model.text());
505  EXPECT_EQ(11U, model.GetCursorPosition());
506
507  // Cut on obscured (password) text should do nothing.
508  model.render_text()->SetObscured(true);
509  model.SelectAll(false);
510  EXPECT_FALSE(model.Cut());
511  clipboard->ReadText(ui::CLIPBOARD_TYPE_COPY_PASTE, &clipboard_text);
512  EXPECT_EQ(initial_clipboard_text, clipboard_text);
513  EXPECT_STR_EQ("HELLO WORLD", model.text());
514  EXPECT_STR_EQ("HELLO WORLD", model.GetSelectedText());
515
516  // Copy on obscured (password) text should do nothing.
517  model.SelectAll(false);
518  EXPECT_FALSE(model.Copy());
519  clipboard->ReadText(ui::CLIPBOARD_TYPE_COPY_PASTE, &clipboard_text);
520  EXPECT_EQ(initial_clipboard_text, clipboard_text);
521  EXPECT_STR_EQ("HELLO WORLD", model.text());
522  EXPECT_STR_EQ("HELLO WORLD", model.GetSelectedText());
523
524  // Cut with non-empty selection.
525  model.render_text()->SetObscured(false);
526  model.MoveCursor(gfx::LINE_BREAK, gfx::CURSOR_RIGHT, false);
527  model.MoveCursor(gfx::WORD_BREAK, gfx::CURSOR_LEFT, true);
528  EXPECT_TRUE(model.Cut());
529  clipboard->ReadText(ui::CLIPBOARD_TYPE_COPY_PASTE, &clipboard_text);
530  EXPECT_STR_EQ("WORLD", clipboard_text);
531  EXPECT_STR_EQ("HELLO ", model.text());
532  EXPECT_EQ(6U, model.GetCursorPosition());
533
534  // Copy with non-empty selection.
535  model.SelectAll(false);
536  EXPECT_TRUE(model.Copy());
537  clipboard->ReadText(ui::CLIPBOARD_TYPE_COPY_PASTE, &clipboard_text);
538  EXPECT_STR_EQ("HELLO ", clipboard_text);
539  EXPECT_STR_EQ("HELLO ", model.text());
540  EXPECT_EQ(6U, model.GetCursorPosition());
541
542  // Test that paste works regardless of the obscured bit.
543  model.MoveCursor(gfx::LINE_BREAK, gfx::CURSOR_RIGHT, false);
544  EXPECT_TRUE(model.Paste());
545  EXPECT_STR_EQ("HELLO HELLO ", model.text());
546  EXPECT_EQ(12U, model.GetCursorPosition());
547  model.render_text()->SetObscured(true);
548  EXPECT_TRUE(model.Paste());
549  EXPECT_STR_EQ("HELLO HELLO HELLO ", model.text());
550  EXPECT_EQ(18U, model.GetCursorPosition());
551}
552
553static void SelectWordTestVerifier(
554    const TextfieldModel& model,
555    const base::string16 &expected_selected_string,
556    size_t expected_cursor_pos) {
557  EXPECT_EQ(expected_selected_string, model.GetSelectedText());
558  EXPECT_EQ(expected_cursor_pos, model.GetCursorPosition());
559}
560
561TEST_F(TextfieldModelTest, SelectWordTest) {
562  TextfieldModel 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)
602TEST_F(TextfieldModelTest, SelectWordTest_MixScripts) {
603  TextfieldModel 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
633TEST_F(TextfieldModelTest, RangeTest) {
634  TextfieldModel 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
697TEST_F(TextfieldModelTest, SelectRangeTest) {
698  TextfieldModel 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
741TEST_F(TextfieldModelTest, SelectionTest) {
742  TextfieldModel 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
783TEST_F(TextfieldModelTest, SelectSelectionModelTest) {
784  TextfieldModel 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
816TEST_F(TextfieldModelTest, CompositionTextTest) {
817  TextfieldModel 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.text());
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.text());
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.text());
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.text());
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.text());
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.text());
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.text());
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.text());
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.text());
915
916  model.SetText(base::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.text());
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.text());
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.text());
936
937  model.SetText(base::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.text());
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.text());
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.text());
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.text());
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.text());
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.text());
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
992TEST_F(TextfieldModelTest, UndoRedo_BasicTest) {
993  TextfieldModel model(NULL);
994  model.InsertChar('a');
995  EXPECT_FALSE(model.Redo());  // nothing to redo
996  EXPECT_TRUE(model.Undo());
997  EXPECT_STR_EQ("", model.text());
998  EXPECT_TRUE(model.Redo());
999  EXPECT_STR_EQ("a", model.text());
1000
1001  // Continuous inserts are treated as one edit.
1002  model.InsertChar('b');
1003  model.InsertChar('c');
1004  EXPECT_STR_EQ("abc", model.text());
1005  EXPECT_TRUE(model.Undo());
1006  EXPECT_STR_EQ("a", model.text());
1007  EXPECT_EQ(1U, model.GetCursorPosition());
1008  EXPECT_TRUE(model.Undo());
1009  EXPECT_STR_EQ("", model.text());
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.text());
1015  EXPECT_FALSE(model.Undo());
1016  EXPECT_STR_EQ("", model.text());
1017  EXPECT_EQ(0U, model.GetCursorPosition());
1018
1019  // Redoing to the latest text.
1020  EXPECT_TRUE(model.Redo());
1021  EXPECT_STR_EQ("a", model.text());
1022  EXPECT_EQ(1U, model.GetCursorPosition());
1023  EXPECT_TRUE(model.Redo());
1024  EXPECT_STR_EQ("abc", model.text());
1025  EXPECT_EQ(3U, model.GetCursorPosition());
1026
1027  // Backspace ===============================
1028  EXPECT_TRUE(model.Backspace());
1029  EXPECT_STR_EQ("ab", model.text());
1030  EXPECT_TRUE(model.Undo());
1031  EXPECT_STR_EQ("abc", model.text());
1032  EXPECT_EQ(3U, model.GetCursorPosition());
1033  EXPECT_TRUE(model.Redo());
1034  EXPECT_STR_EQ("ab", model.text());
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.text());
1040  // Extra backspace shouldn't affect the history.
1041  EXPECT_FALSE(model.Backspace());
1042  EXPECT_TRUE(model.Undo());
1043  EXPECT_STR_EQ("ab", model.text());
1044  EXPECT_EQ(2U, model.GetCursorPosition());
1045  EXPECT_TRUE(model.Undo());
1046  EXPECT_STR_EQ("abc", model.text());
1047  EXPECT_EQ(3U, model.GetCursorPosition());
1048  EXPECT_TRUE(model.Undo());
1049  EXPECT_STR_EQ("a", model.text());
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.text());
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.text());
1065  model.MoveCursor(gfx::LINE_BREAK, gfx::CURSOR_LEFT, false);
1066  EXPECT_TRUE(model.Delete());
1067  EXPECT_STR_EQ("BDE", model.text());
1068  EXPECT_TRUE(model.Undo());
1069  EXPECT_STR_EQ("ABDE", model.text());
1070  EXPECT_EQ(0U, model.GetCursorPosition());
1071  EXPECT_TRUE(model.Undo());
1072  EXPECT_STR_EQ("ABCDE", model.text());
1073  EXPECT_EQ(2U, model.GetCursorPosition());
1074  EXPECT_TRUE(model.Redo());
1075  EXPECT_STR_EQ("ABDE", model.text());
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.text());
1081  EXPECT_TRUE(model.Undo());
1082  EXPECT_STR_EQ("ABDE", model.text());
1083  EXPECT_EQ(2U, model.GetCursorPosition());
1084  EXPECT_TRUE(model.Redo());
1085  EXPECT_STR_EQ("AB", model.text());
1086  EXPECT_EQ(2U, model.GetCursorPosition());
1087}
1088
1089TEST_F(TextfieldModelTest, UndoRedo_SetText) {
1090  // This is to test the undo/redo behavior of omnibox.
1091  TextfieldModel model(NULL);
1092  model.InsertChar('w');
1093  EXPECT_STR_EQ("w", model.text());
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.text());
1098  model.SelectRange(gfx::Range(14, 1));
1099  model.InsertChar('w');
1100  EXPECT_STR_EQ("ww", model.text());
1101  model.SetText(ASCIIToUTF16("www.google.com"));
1102  model.SelectRange(gfx::Range(14, 2));
1103  model.InsertChar('w');
1104  EXPECT_STR_EQ("www", model.text());
1105  model.SetText(ASCIIToUTF16("www.google.com"));
1106  model.SelectRange(gfx::Range(14, 3));
1107  model.InsertChar('.');
1108  EXPECT_STR_EQ("www.", model.text());
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.text());
1113  model.SetText(ASCIIToUTF16("www.youtube.com"));
1114  EXPECT_STR_EQ("www.youtube.com", model.text());
1115  EXPECT_EQ(15U, model.GetCursorPosition());
1116
1117  EXPECT_TRUE(model.Undo());
1118  EXPECT_STR_EQ("www.google.com", model.text());
1119  EXPECT_EQ(4U, model.GetCursorPosition());
1120  EXPECT_TRUE(model.Undo());
1121  EXPECT_STR_EQ("www.google.com", model.text());
1122  EXPECT_EQ(3U, model.GetCursorPosition());
1123  EXPECT_TRUE(model.Undo());
1124  EXPECT_STR_EQ("www.google.com", model.text());
1125  EXPECT_EQ(2U, model.GetCursorPosition());
1126  EXPECT_TRUE(model.Undo());
1127  EXPECT_STR_EQ("www.google.com", model.text());
1128  EXPECT_EQ(1U, model.GetCursorPosition());
1129  EXPECT_TRUE(model.Undo());
1130  EXPECT_STR_EQ("", model.text());
1131  EXPECT_EQ(0U, model.GetCursorPosition());
1132  EXPECT_FALSE(model.Undo());
1133  EXPECT_TRUE(model.Redo());
1134  EXPECT_STR_EQ("www.google.com", model.text());
1135  EXPECT_EQ(1U, model.GetCursorPosition());
1136  EXPECT_TRUE(model.Redo());
1137  EXPECT_STR_EQ("www.google.com", model.text());
1138  EXPECT_EQ(2U, model.GetCursorPosition());
1139  EXPECT_TRUE(model.Redo());
1140  EXPECT_STR_EQ("www.google.com", model.text());
1141  EXPECT_EQ(3U, model.GetCursorPosition());
1142  EXPECT_TRUE(model.Redo());
1143  EXPECT_STR_EQ("www.google.com", model.text());
1144  EXPECT_EQ(4U, model.GetCursorPosition());
1145  EXPECT_TRUE(model.Redo());
1146  EXPECT_STR_EQ("www.youtube.com", model.text());
1147  EXPECT_EQ(5U, model.GetCursorPosition());
1148  EXPECT_FALSE(model.Redo());
1149}
1150
1151TEST_F(TextfieldModelTest, UndoRedo_BackspaceThenSetText) {
1152  // This is to test the undo/redo behavior of omnibox.
1153  TextfieldModel model(NULL);
1154  model.InsertChar('w');
1155  EXPECT_STR_EQ("w", model.text());
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.text());
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.text());
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.text());
1169  EXPECT_TRUE(model.Undo());
1170  EXPECT_STR_EQ("www.google.c", model.text());
1171  EXPECT_TRUE(model.Undo());
1172  EXPECT_STR_EQ("www.google.com", model.text());
1173}
1174
1175TEST_F(TextfieldModelTest, UndoRedo_CutCopyPasteTest) {
1176  TextfieldModel 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.text());
1183  EXPECT_EQ(1U, model.GetCursorPosition());
1184  EXPECT_TRUE(model.Undo());
1185  EXPECT_STR_EQ("ABCDE", model.text());
1186  EXPECT_EQ(3U, model.GetCursorPosition());
1187  EXPECT_TRUE(model.Undo());
1188  EXPECT_STR_EQ("", model.text());
1189  EXPECT_EQ(0U, model.GetCursorPosition());
1190  EXPECT_FALSE(model.Undo());  // no more undo
1191  EXPECT_STR_EQ("", model.text());
1192  EXPECT_TRUE(model.Redo());
1193  EXPECT_STR_EQ("ABCDE", model.text());
1194  EXPECT_EQ(5U, model.GetCursorPosition());
1195  EXPECT_TRUE(model.Redo());
1196  EXPECT_STR_EQ("ADE", model.text());
1197  EXPECT_EQ(1U, model.GetCursorPosition());
1198  EXPECT_FALSE(model.Redo());  // no more redo
1199  EXPECT_STR_EQ("ADE", model.text());
1200
1201  model.Paste();
1202  model.Paste();
1203  model.Paste();
1204  EXPECT_STR_EQ("ABCBCBCDE", model.text());
1205  EXPECT_EQ(7U, model.GetCursorPosition());
1206  EXPECT_TRUE(model.Undo());
1207  EXPECT_STR_EQ("ABCBCDE", model.text());
1208  EXPECT_EQ(5U, model.GetCursorPosition());
1209  EXPECT_TRUE(model.Undo());
1210  EXPECT_STR_EQ("ABCDE", model.text());
1211  EXPECT_EQ(3U, model.GetCursorPosition());
1212  EXPECT_TRUE(model.Undo());
1213  EXPECT_STR_EQ("ADE", model.text());
1214  EXPECT_EQ(1U, model.GetCursorPosition());
1215  EXPECT_TRUE(model.Undo());
1216  EXPECT_STR_EQ("ABCDE", model.text());
1217  EXPECT_EQ(3U, model.GetCursorPosition());
1218  EXPECT_TRUE(model.Undo());
1219  EXPECT_STR_EQ("", model.text());
1220  EXPECT_EQ(0U, model.GetCursorPosition());
1221  EXPECT_FALSE(model.Undo());
1222  EXPECT_STR_EQ("", model.text());
1223  EXPECT_TRUE(model.Redo());
1224  EXPECT_STR_EQ("ABCDE", model.text());  // Redoing SetText
1225  EXPECT_EQ(5U, model.GetCursorPosition());
1226
1227  // Redo
1228  EXPECT_TRUE(model.Redo());
1229  EXPECT_STR_EQ("ADE", model.text());
1230  EXPECT_EQ(1U, model.GetCursorPosition());
1231  EXPECT_TRUE(model.Redo());
1232  EXPECT_STR_EQ("ABCDE", model.text());
1233  EXPECT_EQ(3U, model.GetCursorPosition());
1234  EXPECT_TRUE(model.Redo());
1235  EXPECT_STR_EQ("ABCBCDE", model.text());
1236  EXPECT_EQ(5U, model.GetCursorPosition());
1237  EXPECT_TRUE(model.Redo());
1238  EXPECT_STR_EQ("ABCBCBCDE", model.text());
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.text());
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.text());
1252  EXPECT_EQ(9U, model.GetCursorPosition());
1253  EXPECT_TRUE(model.Undo());
1254  EXPECT_STR_EQ("ABCBCDE", model.text());
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.text());
1259  EXPECT_EQ(3U, model.GetCursorPosition());
1260
1261  // Copy
1262  ResetModel(&model);
1263  model.SetText(ASCIIToUTF16("12345"));
1264  EXPECT_STR_EQ("12345", model.text());
1265  EXPECT_EQ(5U, model.GetCursorPosition());
1266  model.SelectRange(gfx::Range(1, 3));
1267  model.Copy();  // Copy "23"
1268  EXPECT_STR_EQ("12345", model.text());
1269  EXPECT_EQ(3U, model.GetCursorPosition());
1270  model.Paste();  // Paste "23" into "23".
1271  EXPECT_STR_EQ("12345", model.text());
1272  EXPECT_EQ(3U, model.GetCursorPosition());
1273  model.Paste();
1274  EXPECT_STR_EQ("1232345", model.text());
1275  EXPECT_EQ(5U, model.GetCursorPosition());
1276  EXPECT_TRUE(model.Undo());
1277  EXPECT_STR_EQ("12345", model.text());
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.text());
1282  EXPECT_EQ(3U, model.GetCursorPosition());
1283  EXPECT_TRUE(model.Undo());
1284  EXPECT_STR_EQ("", model.text());
1285  EXPECT_FALSE(model.Undo());
1286  // Redo
1287  EXPECT_TRUE(model.Redo());
1288  EXPECT_STR_EQ("12345", model.text());
1289  EXPECT_EQ(5U, model.GetCursorPosition());
1290  EXPECT_TRUE(model.Redo());
1291  EXPECT_STR_EQ("12345", model.text());  // For 1st paste
1292  EXPECT_EQ(3U, model.GetCursorPosition());
1293  EXPECT_TRUE(model.Redo());
1294  EXPECT_STR_EQ("1232345", model.text());
1295  EXPECT_EQ(5U, model.GetCursorPosition());
1296  EXPECT_FALSE(model.Redo());
1297  EXPECT_STR_EQ("1232345", model.text());
1298
1299  // Test using SelectRange
1300  model.SelectRange(gfx::Range(1, 3));
1301  model.Copy();
1302  EXPECT_STR_EQ("1232345", model.text());
1303  model.MoveCursor(gfx::LINE_BREAK, gfx::CURSOR_RIGHT, false);
1304  EXPECT_TRUE(model.Paste());
1305  EXPECT_STR_EQ("123234523", model.text());
1306  EXPECT_EQ(9U, model.GetCursorPosition());
1307  EXPECT_TRUE(model.Undo());
1308  EXPECT_STR_EQ("1232345", model.text());
1309  EXPECT_EQ(7U, model.GetCursorPosition());
1310}
1311
1312TEST_F(TextfieldModelTest, UndoRedo_CursorTest) {
1313  TextfieldModel 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.text());
1320  EXPECT_FALSE(model.Redo());
1321  EXPECT_TRUE(model.Undo());
1322  EXPECT_STR_EQ("", model.text());
1323  EXPECT_FALSE(model.Undo());
1324  EXPECT_STR_EQ("", model.text());
1325  EXPECT_TRUE(model.Redo());
1326  EXPECT_STR_EQ("ab", model.text());
1327  EXPECT_EQ(2U, model.GetCursorPosition());
1328  EXPECT_FALSE(model.Redo());
1329}
1330
1331void RunInsertReplaceTest(TextfieldModel& 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.text());
1337  EXPECT_EQ(4U, model.GetCursorPosition());
1338  EXPECT_TRUE(model.Undo());
1339  EXPECT_STR_EQ("abcd", model.text());
1340  EXPECT_EQ(reverse ? 1U : 3U, model.GetCursorPosition());
1341  EXPECT_TRUE(model.Undo());
1342  EXPECT_STR_EQ("", model.text());
1343  EXPECT_EQ(0U, model.GetCursorPosition());
1344  EXPECT_FALSE(model.Undo());
1345  EXPECT_TRUE(model.Redo());
1346  EXPECT_STR_EQ("abcd", model.text());
1347  EXPECT_EQ(4U, model.GetCursorPosition());  // By SetText
1348  EXPECT_TRUE(model.Redo());
1349  EXPECT_STR_EQ("a123d", model.text());
1350  EXPECT_EQ(4U, model.GetCursorPosition());
1351  EXPECT_FALSE(model.Redo());
1352}
1353
1354void RunOverwriteReplaceTest(TextfieldModel& 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.text());
1361  EXPECT_EQ(5U, model.GetCursorPosition());
1362  EXPECT_TRUE(model.Undo());
1363  EXPECT_STR_EQ("abcd", model.text());
1364  EXPECT_EQ(reverse ? 1U : 3U, model.GetCursorPosition());
1365  EXPECT_TRUE(model.Undo());
1366  EXPECT_STR_EQ("", model.text());
1367  EXPECT_EQ(0U, model.GetCursorPosition());
1368  EXPECT_FALSE(model.Undo());
1369  EXPECT_TRUE(model.Redo());
1370  EXPECT_STR_EQ("abcd", model.text());
1371  EXPECT_EQ(4U, model.GetCursorPosition());
1372  EXPECT_TRUE(model.Redo());
1373  EXPECT_STR_EQ("a1234", model.text());
1374  EXPECT_EQ(5U, model.GetCursorPosition());
1375  EXPECT_FALSE(model.Redo());
1376}
1377
1378TEST_F(TextfieldModelTest, UndoRedo_ReplaceTest) {
1379  // By Cursor
1380  {
1381    SCOPED_TRACE("forward & insert by cursor");
1382    TextfieldModel 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    TextfieldModel 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    TextfieldModel 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    TextfieldModel 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    TextfieldModel 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    TextfieldModel 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    TextfieldModel 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    TextfieldModel model(NULL);
1433    model.SetText(ASCIIToUTF16("abcd"));
1434    model.SelectRange(gfx::Range(3, 1));
1435    RunOverwriteReplaceTest(model);
1436  }
1437}
1438
1439TEST_F(TextfieldModelTest, UndoRedo_CompositionText) {
1440  TextfieldModel 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.text());
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.text());
1456
1457  // Accepting composition
1458  model.ConfirmCompositionText();
1459  EXPECT_STR_EQ("ABCDEabc", model.text());
1460  EXPECT_TRUE(model.Undo());
1461  EXPECT_STR_EQ("ABCDE", model.text());
1462  EXPECT_TRUE(model.Undo());
1463  EXPECT_STR_EQ("", model.text());
1464  EXPECT_TRUE(model.Redo());
1465  EXPECT_STR_EQ("ABCDE", model.text());
1466  EXPECT_TRUE(model.Redo());
1467  EXPECT_STR_EQ("ABCDEabc", model.text());
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.text());
1474  model.CancelCompositionText();
1475  EXPECT_STR_EQ("ABCDEabc", model.text());
1476  EXPECT_FALSE(model.Redo());
1477  EXPECT_STR_EQ("ABCDEabc", model.text());
1478  EXPECT_TRUE(model.Undo());
1479  EXPECT_STR_EQ("ABCDE", model.text());
1480  EXPECT_TRUE(model.Redo());
1481  EXPECT_STR_EQ("ABCDEabc", model.text());
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.text());
1490  model.SetText(ASCIIToUTF16("ABCDEabc"));
1491  EXPECT_STR_EQ("ABCDEabc", model.text());
1492  EXPECT_TRUE(model.Undo());
1493  EXPECT_STR_EQ("ABCDE", model.text());
1494  EXPECT_TRUE(model.Redo());
1495  EXPECT_STR_EQ("ABCDEabc", model.text());
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.text());
1505  model.SetText(ASCIIToUTF16("1234"));
1506  EXPECT_STR_EQ("1234", model.text());
1507  EXPECT_TRUE(model.Undo());
1508  EXPECT_STR_EQ("ABCDE", model.text());
1509  EXPECT_TRUE(model.Redo());
1510  EXPECT_STR_EQ("1234", model.text());
1511  EXPECT_FALSE(model.Redo());
1512
1513  // TODO(oshima): We need MockInputMethod to test the behavior with IME.
1514}
1515
1516}  // namespace views
1517