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