Chromium Code Reviews| Index: ui/gfx/render_text_unittest.cc |
| =================================================================== |
| --- ui/gfx/render_text_unittest.cc (revision 100777) |
| +++ ui/gfx/render_text_unittest.cc (working copy) |
| @@ -178,4 +178,169 @@ |
| EXPECT_FALSE(render_text->style_ranges()[0].strike); |
| } |
| +// TODO(xji): Make these work on Windows. |
| +#if defined(OS_LINUX) |
| +void MoveLeftRightByWordVerifier(RenderText* render_text, |
| + const wchar_t* str) { |
| + render_text->SetText(WideToUTF16(str)); |
| + |
| + // Test moving by word from left ro right. |
| + render_text->MoveCursorLeft(LINE_BREAK, false); |
| + bool first_word = true; |
| + while (true) { |
| + // First, test moving by word from a word break position, such as from |
| + // "|abc def" to "abc| def". |
| + SelectionModel start = render_text->selection_model(); |
| + render_text->MoveCursorRight(WORD_BREAK, false); |
| + SelectionModel end = render_text->selection_model(); |
| + if (end.Equals(start)) // reach the end. |
| + break; |
| + |
| + // For testing simplicity, each word is a 3-character word. |
| + int num_of_character_moves = first_word ? 3 : 4; |
| + first_word = false; |
| + render_text->MoveCursorTo(start); |
| + for (int j = 0; j < num_of_character_moves; ++j) |
| + render_text->MoveCursorRight(CHARACTER_BREAK, false); |
| + EXPECT_TRUE(render_text->selection_model().Equals(end)); |
| + |
| + // Then, test moving by word from positions inside the word, such as from |
| + // "a|bc def" to "abc| def", and from "ab|c def" to "abc| def". |
| + for (int j = 1; j < num_of_character_moves; ++j) { |
| + render_text->MoveCursorTo(start); |
| + for (int k = 0; k < j; ++k) |
| + render_text->MoveCursorRight(CHARACTER_BREAK, false); |
| + render_text->MoveCursorRight(WORD_BREAK, false); |
| + EXPECT_TRUE(render_text->selection_model().Equals(end)); |
| + } |
| + } |
| + |
| + // Test moving by word from right to left. |
| + render_text->MoveCursorRight(LINE_BREAK, false); |
| + first_word = true; |
| + while (true) { |
| + SelectionModel start = render_text->selection_model(); |
| + render_text->MoveCursorLeft(WORD_BREAK, false); |
| + SelectionModel end = render_text->selection_model(); |
| + if (end.Equals(start)) // reach the end. |
| + break; |
| + |
| + int num_of_character_moves = first_word ? 3 : 4; |
| + first_word = false; |
| + render_text->MoveCursorTo(start); |
| + for (int j = 0; j < num_of_character_moves; ++j) |
| + render_text->MoveCursorLeft(CHARACTER_BREAK, false); |
| + EXPECT_TRUE(render_text->selection_model().Equals(end)); |
| + |
| + for (int j = 1; j < num_of_character_moves; ++j) { |
| + render_text->MoveCursorTo(start); |
| + for (int k = 0; k < j; ++k) |
| + render_text->MoveCursorLeft(CHARACTER_BREAK, false); |
| + render_text->MoveCursorLeft(WORD_BREAK, false); |
| + EXPECT_TRUE(render_text->selection_model().Equals(end)); |
| + } |
| + } |
| +} |
| + |
| +TEST_F(RenderTextTest, MoveLeftRightByWordInBidiText) { |
| + scoped_ptr<RenderText> render_text(RenderText::CreateRenderText()); |
| + |
| + // For testing simplicity, each word is a 3-character word. |
| + std::vector<const wchar_t*> test; |
| + test.push_back(L"abc"); |
| + test.push_back(L"abc def"); |
| + test.push_back(L"\x05E1\x05E2\x05E3"); |
| + test.push_back(L"\x05E1\x05E2\x05E3 \x05E4\x05E5\x05E6"); |
| + test.push_back(L"abc \x05E1\x05E2\x05E3"); |
| + test.push_back(L"abc def \x05E1\x05E2\x05E3 \x05E4\x05E5\x05E6"); |
| + test.push_back(L"abc def hij \x05E1\x05E2\x05E3 \x05E4\x05E5\x05E6" |
| + L" \x05E7\x05E8\x05E9"); |
| + |
| + test.push_back(L"abc \x05E1\x05E2\x05E3 hij"); |
| + test.push_back(L"abc def \x05E1\x05E2\x05E3 \x05E4\x05E5\x05E6 hij opq"); |
| + test.push_back(L"abc def hij \x05E1\x05E2\x05E3 \x05E4\x05E5\x05E6" |
| + L" \x05E7\x05E8\x05E9"L" opq rst uvw"); |
| + |
| + test.push_back(L"\x05E1\x05E2\x05E3 abc"); |
| + test.push_back(L"\x05E1\x05E2\x05E3 \x05E4\x05E5\x05E6 abc def"); |
| + test.push_back(L"\x05E1\x05E2\x05E3 \x05E4\x05E5\x05E6 \x05E7\x05E8\x05E9" |
| + L" abc def hij"); |
| + |
| + test.push_back(L"\x05D1\x05D2\x05D3 abc \x05E1\x05E2\x05E3"); |
| + test.push_back(L"\x05D1\x05D2\x05D3 \x05D4\x05D5\x05D6 abc def" |
| + L" \x05E1\x05E2\x05E3 \x05E4\x05E5\x05E6"); |
| + test.push_back(L"\x05D1\x05D2\x05D3 \x05D4\x05D5\x05D6 \x05D7\x05D8\x05D9" |
| + L" abc def hij \x05E1\x05E2\x05E3 \x05E4\x05E5\x05E6" |
| + L" \x05E7\x05E8\x05E9"); |
| + |
| + for (size_t i = 0; i < test.size(); ++i) |
| + MoveLeftRightByWordVerifier(render_text.get(), test[i]); |
| +} |
| + |
| +TEST_F(RenderTextTest, MoveLeftRightByWordInBidiText_TestEndOfText) { |
| + scoped_ptr<RenderText> render_text(RenderText::CreateRenderText()); |
| + |
| + render_text->SetText(WideToUTF16(L"ab\x05E1")); |
| + // Moving cursor by word from "abC|" to left should return "|abC". |
|
msw
2011/09/17 00:27:10
"Moving *the* cursor"... "to *the* left"
Same corr
|
| + // But since end of text is always treated as a word breaker, it returns |
| + // position "ab|C". |
| + // TODO(xji): Need to make it work as expected. |
| + render_text->MoveCursorRight(LINE_BREAK, false); |
| + render_text->MoveCursorLeft(WORD_BREAK, false); |
| + // EXPECT_TRUE(render_text->selection_model().Equals(SelectionModel(0))); |
| + |
| + // Moving cursor by word from "|abC" to right returns "abC|". |
|
msw
2011/09/17 00:27:10
"Moving *the* cursor"... "to *the* right"
|
| + render_text->MoveCursorLeft(LINE_BREAK, false); |
| + render_text->MoveCursorRight(WORD_BREAK, false); |
| + EXPECT_TRUE(render_text->selection_model().Equals( |
| + SelectionModel(3, 2, SelectionModel::LEADING))); |
| + |
| + render_text->SetText(WideToUTF16(L"\x05E1\x05E2"L"a")); |
| + // For logical text "BCa", moving cursor by word from "aCB|" to left returns |
|
msw
2011/09/17 00:27:10
"moving *the* cursor"... "to *the* left"
|
| + // "|aCB". |
| + render_text->MoveCursorRight(LINE_BREAK, false); |
| + render_text->MoveCursorLeft(WORD_BREAK, false); |
| + EXPECT_TRUE(render_text->selection_model().Equals( |
| + SelectionModel(3, 2, SelectionModel::LEADING))); |
| + |
| + // Moving cursor by word from "|aCB" to right should return "returns "aCB|". |
|
msw
2011/09/17 00:27:10
You have a stray bit of text ("returns)...
"*the*
|
| + // But since end of text is always treated as a word breaker, it returns |
|
msw
2011/09/17 00:27:11
"word break" I don't think 'breaker' is correct.
|
| + // position "a|CB". |
| + // TODO(xji): Need to make it work as expected. |
| + render_text->MoveCursorLeft(LINE_BREAK, false); |
| + render_text->MoveCursorRight(WORD_BREAK, false); |
| + // EXPECT_TRUE(render_text->selection_model().Equals(SelectionModel(0))); |
| +} |
| + |
| +TEST_F(RenderTextTest, MoveLeftRightByWordInTextWithMultiSpaces) { |
| + scoped_ptr<RenderText> render_text(RenderText::CreateRenderText()); |
| + render_text->SetText(WideToUTF16(L"abc def")); |
| + render_text->MoveCursorTo(SelectionModel(5)); |
| + render_text->MoveCursorRight(WORD_BREAK, false); |
| + EXPECT_EQ(11U, render_text->GetCursorPosition()); |
| + |
| + render_text->MoveCursorTo(SelectionModel(5)); |
| + render_text->MoveCursorLeft(WORD_BREAK, false); |
| + EXPECT_EQ(0U, render_text->GetCursorPosition()); |
| +} |
| + |
| +TEST_F(RenderTextTest, MoveLeftRightByWordInChineseText) { |
| + scoped_ptr<RenderText> render_text(RenderText::CreateRenderText()); |
| + render_text->SetText(WideToUTF16(L"\x6211\x4EEC\x53BB\x516C\x56ED\x73A9")); |
| + render_text->MoveCursorLeft(LINE_BREAK, false); |
| + EXPECT_EQ(0U, render_text->GetCursorPosition()); |
| + render_text->MoveCursorRight(WORD_BREAK, false); |
| + EXPECT_EQ(2U, render_text->GetCursorPosition()); |
| + render_text->MoveCursorRight(WORD_BREAK, false); |
| + EXPECT_EQ(3U, render_text->GetCursorPosition()); |
| + render_text->MoveCursorRight(WORD_BREAK, false); |
| + EXPECT_EQ(5U, render_text->GetCursorPosition()); |
| + render_text->MoveCursorRight(WORD_BREAK, false); |
| + EXPECT_EQ(6U, render_text->GetCursorPosition()); |
| + render_text->MoveCursorRight(WORD_BREAK, false); |
| + EXPECT_EQ(6U, render_text->GetCursorPosition()); |
| +} |
| + |
| +#endif |
| + |
| } // namespace gfx |