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