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 28 namespace { 29 30 struct WordAndCursor { 31 WordAndCursor(const wchar_t* w, size_t c) : word(w), cursor(c) {} 32 33 const wchar_t* word; 34 size_t cursor; 35 }; 36 37 void MoveCursorTo(views::TextfieldModel& model, size_t pos) { 38 model.MoveCursorTo(gfx::SelectionModel(pos, gfx::CURSOR_FORWARD)); 39 } 40 41 } // namespace 42 43 namespace views { 44 45 class 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 69 TEST_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 111 TEST_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 141 TEST_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 237 TEST_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 253 TEST_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 297 TEST_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 381 TEST_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 410 TEST_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 457 TEST_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 478 TEST_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 550 static 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 558 TEST_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) 599 TEST_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 630 TEST_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 694 TEST_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 738 TEST_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 780 TEST_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 813 TEST_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 989 TEST_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 1086 TEST_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 1148 TEST_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 1172 TEST_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 1309 TEST_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 1328 void 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 1351 void 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 1375 TEST_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 1406 TEST_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