| Index: views/controls/textfield/textfield_views_model_unittest.cc
|
| ===================================================================
|
| --- views/controls/textfield/textfield_views_model_unittest.cc (revision 100008)
|
| +++ views/controls/textfield/textfield_views_model_unittest.cc (working copy)
|
| @@ -2,6 +2,8 @@
|
| // Use of this source code is governed by a BSD-style license that can be
|
| // found in the LICENSE file.
|
|
|
| +#include <vector>
|
| +
|
| #include "base/auto_reset.h"
|
| #include "base/memory/scoped_ptr.h"
|
| #include "base/message_loop.h"
|
| @@ -17,6 +19,20 @@
|
| #include "views/test/views_test_base.h"
|
| #include "views/views_delegate.h"
|
|
|
| +namespace {
|
| +
|
| +struct WordAndCursor {
|
| + WordAndCursor(const wchar_t* w, size_t c)
|
| + : word(w),
|
| + cursor(c) {
|
| + }
|
| +
|
| + const wchar_t* word;
|
| + size_t cursor;
|
| +};
|
| +
|
| +} // namespace
|
| +
|
| namespace views {
|
|
|
| class TextfieldViewsModelTest : public ViewsTestBase,
|
| @@ -83,8 +99,146 @@
|
| // but backspace should work.
|
| EXPECT_TRUE(model.Backspace());
|
| EXPECT_STR_EQ("HELLORL", model.GetText());
|
| +
|
| + model.MoveCursorTo(gfx::SelectionModel(5));
|
| + model.ReplaceText(ASCIIToUTF16(" WOR"));
|
| + EXPECT_STR_EQ("HELLO WORL", model.GetText());
|
| }
|
|
|
| +TEST_F(TextfieldViewsModelTest, EditString_SimpleRTL) {
|
| + TextfieldViewsModel model(NULL);
|
| + // Append two strings.
|
| + model.Append(WideToUTF16(L"\x05d0\x05d1\x05d2"));
|
| + EXPECT_EQ(WideToUTF16(L"\x05d0\x05d1\x05d2"), model.GetText());
|
| + model.Append(WideToUTF16(L"\x05e0\x05e1\x05e2"));
|
| + EXPECT_EQ(WideToUTF16(L"\x05d0\x05d1\x05d2\x05e0\x05e1\x05e2"),
|
| + model.GetText());
|
| +
|
| + // Insert 0x05f0.
|
| + model.MoveCursorTo(gfx::SelectionModel(1U));
|
| + model.InsertChar(0x05f0);
|
| + EXPECT_EQ(WideToUTF16(L"\x05d0\x05f0\x05d1\x05d2\x05e0\x05e1\x05e2"),
|
| + model.GetText());
|
| +
|
| + // Replace "\x05d1" with "\x05f1".
|
| + model.ReplaceChar(0x05f1);
|
| + EXPECT_EQ(WideToUTF16(L"\x05d0\x05f0\x5f1\x05d2\x05e0\x05e1\x05e2"),
|
| + model.GetText());
|
| +
|
| + // Delete and backspace.
|
| + EXPECT_EQ(3U, model.GetCursorPosition());
|
| + EXPECT_TRUE(model.Delete());
|
| + EXPECT_EQ(WideToUTF16(L"\x05d0\x05f0\x5f1\x05e0\x05e1\x05e2"),
|
| + model.GetText());
|
| + EXPECT_TRUE(model.Backspace());
|
| + EXPECT_EQ(2U, model.GetCursorPosition());
|
| + EXPECT_EQ(WideToUTF16(L"\x05d0\x05f0\x05e0\x05e1\x05e2"), model.GetText());
|
| +}
|
| +
|
| +TEST_F(TextfieldViewsModelTest, EditString_ComplexScript) {
|
| + TextfieldViewsModel model(NULL);
|
| + // Append two Hindi strings.
|
| + model.Append(WideToUTF16(L"\x0915\x093f\x0915\x094d\x0915"));
|
| + EXPECT_EQ(WideToUTF16(L"\x0915\x093f\x0915\x094d\x0915"),
|
| + model.GetText());
|
| + model.Append(WideToUTF16(L"\x0915\x094d\x092e\x094d"));
|
| + EXPECT_EQ(WideToUTF16(
|
| + L"\x0915\x093f\x0915\x094d\x0915\x0915\x094d\x092e\x094d"),
|
| + model.GetText());
|
| +
|
| + // Check it is not able to place cursor in middle of a grapheme.
|
| + // TODO(xji): temporarily disable in platform Win since the complex script
|
| + // characters turned into empty square due to font regression. So, not able
|
| + // to test 2 characters belong to the same grapheme.
|
| +#if defined(OS_LINUX)
|
| + model.MoveCursorTo(gfx::SelectionModel(1U));
|
| + EXPECT_EQ(0U, model.GetCursorPosition());
|
| +#endif
|
| +
|
| + model.MoveCursorTo(gfx::SelectionModel(2U));
|
| + EXPECT_EQ(2U, model.GetCursorPosition());
|
| + model.InsertChar('a');
|
| + EXPECT_EQ(WideToUTF16(
|
| + L"\x0915\x093f\x0061\x0915\x094d\x0915\x0915\x094d\x092e\x094d"),
|
| + model.GetText());
|
| +
|
| + // ReplaceChar will replace the whole grapheme.
|
| + model.ReplaceChar('b');
|
| + // TODO(xji): temporarily disable in platform Win since the complex script
|
| + // characters turned into empty square due to font regression. So, not able
|
| + // to test 2 characters belong to the same grapheme.
|
| +#if defined(OS_LINUX)
|
| + EXPECT_EQ(WideToUTF16(
|
| + L"\x0915\x093f\x0061\x0062\x0915\x0915\x094d\x092e\x094d"),
|
| + model.GetText());
|
| +#endif
|
| + EXPECT_EQ(4U, model.GetCursorPosition());
|
| +
|
| + // Delete should delete the whole grapheme.
|
| + model.MoveCursorTo(gfx::SelectionModel(0U));
|
| + // TODO(xji): temporarily disable in platform Win since the complex script
|
| + // characters turned into empty square due to font regression. So, not able
|
| + // to test 2 characters belong to the same grapheme.
|
| +#if defined(OS_LINUX)
|
| + EXPECT_TRUE(model.Delete());
|
| + EXPECT_EQ(WideToUTF16(L"\x0061\x0062\x0915\x0915\x094d\x092e\x094d"),
|
| + model.GetText());
|
| + model.MoveCursorTo(gfx::SelectionModel(model.GetText().length()));
|
| + EXPECT_TRUE(model.Backspace());
|
| + EXPECT_EQ(WideToUTF16(L"\x0061\x0062\x0915\x0915\x094d\x092e"),
|
| + model.GetText());
|
| +#endif
|
| +
|
| + // Test cursor position and deletion for Hindi Virama.
|
| + model.SetText(WideToUTF16(L"\x0D38\x0D4D\x0D15\x0D16\x0D2E"));
|
| + model.MoveCursorTo(gfx::SelectionModel(0));
|
| + EXPECT_EQ(0U, model.GetCursorPosition());
|
| +
|
| + // TODO(xji): temporarily disable in platform Win since the complex script
|
| + // characters turned into empty square due to font regression. So, not able
|
| + // to test 2 characters belong to the same grapheme.
|
| +#if defined(OS_LINUX)
|
| + model.MoveCursorTo(gfx::SelectionModel(1));
|
| + EXPECT_EQ(0U, model.GetCursorPosition());
|
| +#endif
|
| +
|
| + model.MoveCursorTo(gfx::SelectionModel(2));
|
| + EXPECT_EQ(2U, model.GetCursorPosition());
|
| +
|
| + model.MoveCursorTo(gfx::SelectionModel(3));
|
| + EXPECT_EQ(3U, model.GetCursorPosition());
|
| +
|
| + model.MoveCursorTo(gfx::SelectionModel(2));
|
| +
|
| + EXPECT_TRUE(model.Backspace());
|
| + EXPECT_EQ(WideToUTF16(L"\x0D38\x0D15\x0D16\x0D2E"), model.GetText());
|
| +
|
| + // Test Delete/Backspace on Hebrew with non-spacing marks.
|
| + // TODO(xji): temporarily disable in platform Win since the complex script
|
| + // characters turned into empty square due to font regression. So, not able
|
| + // to test 2 characters belong to the same grapheme.
|
| +#if defined(OS_LINUX)
|
| + model.SetText(WideToUTF16(L"\x05d5\x05b7\x05D9\x05B0\x05D4\x05B4\x05D9"));
|
| + model.MoveCursorTo(gfx::SelectionModel(0));
|
| + EXPECT_TRUE(model.Delete());
|
| + EXPECT_TRUE(model.Delete());
|
| + EXPECT_TRUE(model.Delete());
|
| + EXPECT_TRUE(model.Delete());
|
| + EXPECT_EQ(WideToUTF16(L""), model.GetText());
|
| +#endif
|
| +
|
| + // The first 2 characters are not strong directionality characters.
|
| + model.SetText(WideToUTF16(L"\x002C\x0020\x05D1\x05BC\x05B7\x05E9\x05BC"));
|
| +#if defined(OS_WIN)
|
| + model.MoveCursorRight(gfx::LINE_BREAK, false);
|
| +#else
|
| + model.MoveCursorLeft(gfx::LINE_BREAK, false);
|
| +#endif
|
| + EXPECT_TRUE(model.Backspace());
|
| + EXPECT_EQ(WideToUTF16(L"\x002C\x0020\x05D1\x05BC\x05B7\x05E9"),
|
| + model.GetText());
|
| +}
|
| +
|
| TEST_F(TextfieldViewsModelTest, EmptyString) {
|
| TextfieldViewsModel model(NULL);
|
| EXPECT_EQ(string16(), model.GetText());
|
| @@ -143,6 +297,93 @@
|
| EXPECT_EQ(5U, model.GetCursorPosition());
|
| }
|
|
|
| +TEST_F(TextfieldViewsModelTest, Selection_BidiWithNonSpacingMarks) {
|
| + // Selection is a logical operation. And it should work with the arrow
|
| + // keys doing visual movements, while the selection is logical between
|
| + // the (logical) start and end points. Selection is simply defined as
|
| + // the portion of text between the logical positions of the start and end
|
| + // caret positions.
|
| + TextfieldViewsModel model(NULL);
|
| + // TODO(xji): temporarily disable in platform Win since the complex script
|
| + // characters turned into empty square due to font regression. So, not able
|
| + // to test 2 characters belong to the same grapheme.
|
| +#if defined(OS_LINUX)
|
| + model.Append(WideToUTF16(
|
| + L"abc\x05E9\x05BC\x05C1\x05B8\x05E0\x05B8"L"def"));
|
| + model.MoveCursorRight(gfx::CHARACTER_BREAK, false);
|
| + model.MoveCursorRight(gfx::CHARACTER_BREAK, false);
|
| +
|
| + model.MoveCursorRight(gfx::CHARACTER_BREAK, true);
|
| + EXPECT_EQ(2U, model.render_text()->GetSelectionStart());
|
| + EXPECT_EQ(3U, model.GetCursorPosition());
|
| + EXPECT_EQ(WideToUTF16(L"c"), model.GetSelectedText());
|
| +
|
| + model.MoveCursorRight(gfx::CHARACTER_BREAK, true);
|
| + EXPECT_EQ(2U, model.render_text()->GetSelectionStart());
|
| + EXPECT_EQ(7U, model.GetCursorPosition());
|
| + EXPECT_EQ(WideToUTF16(L"c\x05E9\x05BC\x05C1\x05B8"),
|
| + model.GetSelectedText());
|
| +
|
| + model.MoveCursorRight(gfx::CHARACTER_BREAK, true);
|
| + EXPECT_EQ(2U, model.render_text()->GetSelectionStart());
|
| + EXPECT_EQ(3U, model.GetCursorPosition());
|
| + EXPECT_EQ(WideToUTF16(L"c"), model.GetSelectedText());
|
| +
|
| + model.MoveCursorRight(gfx::CHARACTER_BREAK, true);
|
| + EXPECT_EQ(2U, model.render_text()->GetSelectionStart());
|
| + EXPECT_EQ(10U, model.GetCursorPosition());
|
| + EXPECT_EQ(WideToUTF16(L"c\x05E9\x05BC\x05C1\x05B8\x05E0\x05B8"L"d"),
|
| + model.GetSelectedText());
|
| +
|
| + model.ClearSelection();
|
| + EXPECT_EQ(string16(), model.GetSelectedText());
|
| + model.SelectAll();
|
| + EXPECT_EQ(WideToUTF16(L"abc\x05E9\x05BC\x05C1\x05B8\x05E0\x05B8"L"def"),
|
| + model.GetSelectedText());
|
| +#endif
|
| +
|
| + // In case of "aBc", this test shows how to select "aB" or "Bc", assume 'B' is
|
| + // an RTL character.
|
| + model.SetText(WideToUTF16(L"a\x05E9"L"b"));
|
| + model.MoveCursorTo(gfx::SelectionModel(0));
|
| + model.MoveCursorRight(gfx::CHARACTER_BREAK, true);
|
| + EXPECT_EQ(WideToUTF16(L"a"), model.GetSelectedText());
|
| +
|
| + model.MoveCursorRight(gfx::CHARACTER_BREAK, true);
|
| + EXPECT_EQ(WideToUTF16(L"a"), model.GetSelectedText());
|
| +
|
| + model.MoveCursorRight(gfx::CHARACTER_BREAK, true);
|
| + EXPECT_EQ(WideToUTF16(L"a\x05E9"L"b"), model.GetSelectedText());
|
| +
|
| + model.MoveCursorRight(gfx::CHARACTER_BREAK, false);
|
| + EXPECT_EQ(3U, model.GetCursorPosition());
|
| + model.MoveCursorLeft(gfx::CHARACTER_BREAK, true);
|
| + EXPECT_EQ(WideToUTF16(L"b"), model.GetSelectedText());
|
| +
|
| + model.MoveCursorLeft(gfx::CHARACTER_BREAK, true);
|
| + EXPECT_EQ(WideToUTF16(L"b"), model.GetSelectedText());
|
| +
|
| + model.MoveCursorLeft(gfx::CHARACTER_BREAK, true);
|
| + EXPECT_EQ(WideToUTF16(L"a\x05E9"L"b"), model.GetSelectedText());
|
| +
|
| + model.MoveCursorLeft(gfx::LINE_BREAK, false);
|
| + model.MoveCursorRight(gfx::CHARACTER_BREAK, true);
|
| + model.MoveCursorRight(gfx::CHARACTER_BREAK, true);
|
| + model.MoveCursorLeft(gfx::CHARACTER_BREAK, true);
|
| + EXPECT_EQ(WideToUTF16(L"a\x05E9"), model.GetSelectedText());
|
| +
|
| + model.MoveCursorRight(gfx::LINE_BREAK, false);
|
| + model.MoveCursorLeft(gfx::CHARACTER_BREAK, true);
|
| + model.MoveCursorLeft(gfx::CHARACTER_BREAK, true);
|
| + model.MoveCursorRight(gfx::CHARACTER_BREAK, true);
|
| + EXPECT_EQ(WideToUTF16(L"\x05E9"L"b"), model.GetSelectedText());
|
| +
|
| + model.ClearSelection();
|
| + EXPECT_EQ(string16(), model.GetSelectedText());
|
| + model.SelectAll();
|
| + EXPECT_EQ(WideToUTF16(L"a\x05E9"L"b"), model.GetSelectedText());
|
| +}
|
| +
|
| TEST_F(TextfieldViewsModelTest, SelectionAndEdit) {
|
| TextfieldViewsModel model(NULL);
|
| model.Append(ASCIIToUTF16("HELLO"));
|
| @@ -314,8 +555,8 @@
|
| }
|
|
|
| void SelectWordTestVerifier(TextfieldViewsModel &model,
|
| - const std::string &expected_selected_string, size_t expected_cursor_pos) {
|
| - EXPECT_STR_EQ(expected_selected_string, model.GetSelectedText());
|
| + const string16 &expected_selected_string, size_t expected_cursor_pos) {
|
| + EXPECT_EQ(expected_selected_string, model.GetSelectedText());
|
| EXPECT_EQ(expected_cursor_pos, model.GetCursorPosition());
|
| }
|
|
|
| @@ -326,40 +567,75 @@
|
| // Test when cursor is at the beginning.
|
| model.MoveCursorLeft(gfx::LINE_BREAK, false);
|
| model.SelectWord();
|
| - SelectWordTestVerifier(model, " ", 2U);
|
| + SelectWordTestVerifier(model, ASCIIToUTF16(" "), 2U);
|
|
|
| // Test when cursor is at the beginning of a word.
|
| gfx::SelectionModel selection(2U);
|
| model.MoveCursorTo(selection);
|
| model.SelectWord();
|
| - SelectWordTestVerifier(model, "HELLO", 7U);
|
| + SelectWordTestVerifier(model, ASCIIToUTF16("HELLO"), 7U);
|
|
|
| // Test when cursor is at the end of a word.
|
| selection = gfx::SelectionModel(15U);
|
| model.MoveCursorTo(selection);
|
| model.SelectWord();
|
| - SelectWordTestVerifier(model, "WO", 15U);
|
| + SelectWordTestVerifier(model, ASCIIToUTF16(" "), 20U);
|
|
|
| - // Test when cursor is somewhere in a non-alph-numeric fragment.
|
| + // Test when cursor is somewhere in a non-alpha-numeric fragment.
|
| for (size_t cursor_pos = 8; cursor_pos < 13U; cursor_pos++) {
|
| selection = gfx::SelectionModel(cursor_pos);
|
| model.MoveCursorTo(selection);
|
| model.SelectWord();
|
| - SelectWordTestVerifier(model, " !! ", 13U);
|
| + SelectWordTestVerifier(model, ASCIIToUTF16(" !! "), 13U);
|
| }
|
|
|
| // Test when cursor is somewhere in a whitespace fragment.
|
| selection = gfx::SelectionModel(17U);
|
| model.MoveCursorTo(selection);
|
| model.SelectWord();
|
| - SelectWordTestVerifier(model, " ", 20U);
|
| + SelectWordTestVerifier(model, ASCIIToUTF16(" "), 20U);
|
|
|
| // Test when cursor is at the end.
|
| model.MoveCursorRight(gfx::LINE_BREAK, false);
|
| model.SelectWord();
|
| - SelectWordTestVerifier(model, " ", 24U);
|
| + SelectWordTestVerifier(model, ASCIIToUTF16(" "), 24U);
|
| }
|
|
|
| +// TODO(xji): temporarily disable in platform Win since the complex script
|
| +// characters and Chinese characters are turned into empty square due to font
|
| +// regression.
|
| +#if defined(OS_LINUX)
|
| +TEST_F(TextfieldViewsModelTest, SelectWordTest_MixScripts) {
|
| + TextfieldViewsModel model(NULL);
|
| + std::vector<WordAndCursor> word_and_cursor;
|
| + word_and_cursor.push_back(WordAndCursor(L"a\x05d0", 2));
|
| + word_and_cursor.push_back(WordAndCursor(L"a\x05d0", 2));
|
| + word_and_cursor.push_back(WordAndCursor(L"\x05d1\x05d2", 5));
|
| + word_and_cursor.push_back(WordAndCursor(L"\x05d1\x05d2", 5));
|
| + word_and_cursor.push_back(WordAndCursor(L" ", 3));
|
| + word_and_cursor.push_back(WordAndCursor(L"a\x05d0", 2));
|
| + word_and_cursor.push_back(WordAndCursor(L"\x0915\x094d\x0915", 9));
|
| + word_and_cursor.push_back(WordAndCursor(L"\x0915\x094d\x0915", 9));
|
| + word_and_cursor.push_back(WordAndCursor(L" ", 10));
|
| + word_and_cursor.push_back(WordAndCursor(L"\x4E2D\x56FD", 12));
|
| + word_and_cursor.push_back(WordAndCursor(L"\x4E2D\x56FD", 12));
|
| + word_and_cursor.push_back(WordAndCursor(L"\x82B1", 13));
|
| + word_and_cursor.push_back(WordAndCursor(L"\x5929", 14));
|
| +
|
| + // The text consists of Ascii, Hebrew, Hindi with Virama sign, and Chinese.
|
| + model.SetText(WideToUTF16(L"a\x05d0 \x05d1\x05d2 \x0915\x094d\x0915 "
|
| + L"\x4E2D\x56FD\x82B1\x5929"));
|
| + for (size_t i = 0; i < word_and_cursor.size(); ++i) {
|
| + model.MoveCursorLeft(gfx::LINE_BREAK, false);
|
| + for (size_t j = 0; j < i; ++j)
|
| + model.MoveCursorRight(gfx::CHARACTER_BREAK, false);
|
| + model.SelectWord();
|
| + SelectWordTestVerifier(model, WideToUTF16(word_and_cursor[i].word),
|
| + word_and_cursor[i].cursor);
|
| + }
|
| +}
|
| +#endif
|
| +
|
| TEST_F(TextfieldViewsModelTest, RangeTest) {
|
| TextfieldViewsModel model(NULL);
|
| model.Append(ASCIIToUTF16("HELLO WORLD"));
|
|
|