Chromium Code Reviews| Index: content/browser/accessibility/accessibility_win_browsertest.cc |
| diff --git a/content/browser/accessibility/accessibility_win_browsertest.cc b/content/browser/accessibility/accessibility_win_browsertest.cc |
| index 058e033ae4e4fb959d92411fde0d05f5f6440969..50cb6c0009cf577f4d7565f1c05ca20bc33003ba 100644 |
| --- a/content/browser/accessibility/accessibility_win_browsertest.cc |
| +++ b/content/browser/accessibility/accessibility_win_browsertest.cc |
| @@ -119,6 +119,24 @@ void RecursiveFindNodeInAccessibilityTree(IAccessible* node, |
| } |
| } |
| +// Ensures that the text, the start and end offsets retrieved using |
| +// get_textAtOffset match the expected values. |
| +void CheckTextAtOffset(IAccessible2 element, |
| + LONG offset, IA2TextBoundaryType boundary_type, |
| + LONG expected_start_offset, LONG expected_end_offset, |
| + std::wstring expected_text) { |
| + LONG start_offset = 0; |
|
dmazzoni
2014/10/29 21:49:43
Consider adding a SCOPED_TRACE here to aid in debu
|
| + LONG end_offset = 0; |
| + base::win::ScopedBstr text; |
| + HRESULT hr = element->get_textAtOffset( |
| + offset, boundary_type, |
| + &start_offset, &end_offset, text.Receive()); |
| + EXPECT_EQ(S_OK, hr); |
| + EXPECT_EQ(expected_start_offset, start_offset); |
| + EXPECT_EQ(expected_end_offset, end_offset); |
| + EXPECT_EQ(expected_text, std:wstring(text, text.Length())); |
| +} |
| + |
| // AccessibilityWinBrowserTest ------------------------------------------------ |
| @@ -753,4 +771,171 @@ IN_PROC_BROWSER_TEST_F(AccessibilityWinBrowserTest, TestRoleGroup) { |
| document_checker.CheckAccessible(GetRendererAccessible()); |
| } |
| +IN_PROC_BROWSER_TEST_F(AccessibilityWinBrowserTest, TestTextAtOffset) { |
| + const char input_contents[] = "Mozilla/5.0 (NT 6.x; WOW64) " |
| + "WebKit (KHTML, like)."; |
| + const char textarea_contents[] = "Mozilla/5.0 (NT 6.x; WOW64)\n" |
| + "WebKit \n(KHTML, like)."; |
| + LONG contents_length = sizeof(input_contents) / sizeof(char); |
| + LoadInitialAccessibilityTreeFromHtml("<!DOCTYPE html>" |
| + "<html><body><form>" |
| + "<label for='name'>Browser name:</label>" |
| + "<input type='text' id='name' name='name' value='" |
| + "Mozilla/5.0 (NT 6.x; WOW64) WebKit " |
| + "(KHTML, like).'>" |
| + "</form><textarea rows='3' cols='60'>" |
| + "Mozilla/5.0 (NT 6.x; WOW64)<br>" |
| + "WebKit <br>(KHTML, like)." |
| + "</textarea></body></html>"); |
| + |
| + // Retrieve the IAccessible interface for the web page. |
| + base::win::ScopedComPtr<IAccessible> document = GetRendererAccessible(); |
| + LONG child_count = 0; |
| + HRESULT hr = document->get_accChildCount(&child_count); |
| + ASSERT_EQ(S_OK, hr); |
| + ASSERT_EQ(2, child_count); |
| + // Get all the document's children. |
| + scoped_ptr<VARIANT[]> children(new VARIANT[child_count]); |
| + LONG obtained_count = 0; |
| + hr = AccessibleChildren( |
| + document, 0, child_count, children.get(), &obtained_count); |
| + ASSERT_EQ(S_OK, hr); |
| + ASSERT_EQ(child_count, obtained_count); |
| + |
| + // Find the two edit fields (simple and text area). |
| + base::win::ScopedComPtr<IAccessible2> input; |
| + hr = QueryIAccessible2(GetAccessibleFromResultVariant( |
| + document, children.get()[0]), input.Receive()); |
| + ASSERT_EQ(S_OK, hr); |
| + base::win::ScopedComPtr<IAccessible2> textarea; |
| + hr = QueryIAccessible2(GetAccessibleFromResultVariant( |
| + document, children.get()[1]), textarea.Receive()); |
| + ASSERT_EQ(S_OK, hr); |
| + |
| + // Retrieve the IAccessibleText interface for both of the fields. |
| + base::win::ScopedComPtr<IAccessibleText> input_text; |
| + hr = input->QueryInterface(input_text.Receive()); |
| + ASSERT_EQ(S_OK, hr); |
| + base::win::ScopedComPtr<IAccessibleText> textarea_text; |
| + hr = textarea->QueryInterface(textarea_text.Receive()); |
| + ASSERT_EQ(S_OK, hr); |
| + |
| + // Test invalid arguments. |
| + hr = input_text->get_textAtOffset( |
| + 0, IA2_TEXT_BOUNDARY_CHAR, NULL, NULL, NULL); |
| + EXPECT_EQ(E_INVALIDARG, hr); |
| + hr = textarea_text->get_textAtOffset( |
| + 0, IA2_TEXT_BOUNDARY_CHAR, NULL, NULL, NULL); |
| + EXPECT_EQ(E_INVALIDARG, hr); |
| + |
| + // Test invalid offset. |
| + LONG invalid_offset = -5; |
| + LONG start_offset = 0; |
| + LONG end_offset = 0; |
| + base::win::ScopedBstr text; |
| + hr = input_text->get_textAtOffset( |
| + invalid_offset, IA2_TEXT_BOUNDARY_CHAR, |
| + &start_offset, &end_offset, text.Receive()); |
| + EXPECT_EQ(E_FAIL, hr); |
| + hr = textarea_text->get_textAtOffset( |
| + invalid_offset, IA2_TEXT_BOUNDARY_CHAR, |
| + &start_offset, &end_offset, text.Receive()); |
| + EXPECT_EQ(E_FAIL, hr); |
| + invalid_offset = contents_length; |
| + hr = input_text->get_textAtOffset( |
| + invalid_offset, IA2_TEXT_BOUNDARY_CHAR, |
| + &start_offset, &end_offset, text.Receive()); |
| + EXPECT_EQ(E_FAIL, hr); |
| + hr = textarea_text->get_textAtOffset( |
| + invalid_offset, IA2_TEXT_BOUNDARY_CHAR, |
| + &start_offset, &end_offset, text.Receive()); |
| + EXPECT_EQ(E_FAIL, hr); |
| + |
| + // Test character navigation. |
| + for (LONG offset = 0; offset < contents_length; ++offset) { |
|
dmazzoni
2014/10/29 21:49:43
Consider a SCOPED_TRACE inside each loop - that wa
|
| + std::wstring expected_text(input_contents[offset], 1); |
| + LONG expected_start_offset = offset; |
| + LONG expected_end_offset = offset + 1; |
| + CheckTextAtOffset(input_text, offset, IA2_TEXT_BOUNDARY_CHAR, |
| + expected_start_offset, expected_end_offset, expected_text); |
| + } |
| + for (LONG offset = contents_length - 1; offset >= 0; --offset) { |
| + std::wstring expected_text(textarea_contents[offset], 1); |
| + LONG expected_start_offset = offset; |
| + LONG expected_end_offset = offset + 1; |
| + CheckTextAtOffset(textarea_text, offset, IA2_TEXT_BOUNDARY_CHAR, |
| + expected_start_offset, expected_end_offset, expected_text); |
| + } |
| + |
| + // Test word navigation. |
| + // (Imitate Firefox behavior.) |
| + // Trailing punctuation should be included as part of the previous word. |
| + CheckTextAtOffset(input_text, 0, IA2_TEXT_BOUNDARY_WORD, |
| + 0, 8, L"Mozilla/"); |
| + CheckTextAtOffset(textarea_text, 6, IA2_TEXT_BOUNDARY_WORD, |
| + 0, 8, L"Mozilla/"); |
| + // If the offset is at the punctuation, it should return |
| + // the previous word. |
| + CheckTextAtOffset(textarea_text, 7, IA2_TEXT_BOUNDARY_WORD, |
| + 0, 8, L"Mozilla/"); |
| + // Numbers with a decimal point (U.S), should be treated as two words. |
| + CheckTextAtOffset(input_text, 8, IA2_TEXT_BOUNDARY_WORD, |
| + 8, 10, L"5."); |
| + CheckTextAtOffset(textarea_text, 9, IA2_TEXT_BOUNDARY_WORD, |
| + 8, 10, L"5."); |
| + // Also, trailing punctuation that occurs after empty space should not be |
| + // part of the word. ("0 " and not "0 (".) |
| + CheckTextAtOffset(input_text, 10, IA2_TEXT_BOUNDARY_WORD, |
| + 10, 12, L"0 "); |
| + CheckTextAtOffset(textarea_text, 11, IA2_TEXT_BOUNDARY_WORD, |
| + 10, 12, L"0 "); |
| + // Leading punctuation should be included with the word after it. |
| + CheckTextAtOffset(input_text, 12, IA2_TEXT_BOUNDARY_WORD, |
| + 12, 16, L"(NT "); |
| + CheckTextAtOffset(textarea_text, 15, IA2_TEXT_BOUNDARY_WORD, |
| + 12, 16, L"(NT "); |
| + // Numbers separated from letters with trailing punctuation should |
| + // behave like decimal numbers above. |
| + CheckTextAtOffset(input_text, 16, IA2_TEXT_BOUNDARY_WORD, |
| + 16, 18, L"6."); |
| + CheckTextAtOffset(textarea_text, 19, IA2_TEXT_BOUNDARY_WORD, |
| + 18, 21, L"x; "); |
| + // Words with numbers should be treated like ordinary words. |
| + CheckTextAtOffset(input_text, 24, IA2_TEXT_BOUNDARY_WORD, |
| + 21, 28, L"WOW64) "); |
| + CheckTextAtOffset(textarea_text, 26, IA2_TEXT_BOUNDARY_WORD, |
| + 21, 28, L"WOW64)\n"); |
| + // Multiple trailing empty spaces should be part of the word preceding it. |
| + CheckTextAtOffset(input_text, 30, IA2_TEXT_BOUNDARY_WORD, |
| + 28, 36, L"WebKit "); |
| + CheckTextAtOffset(textarea_text, 35, IA2_TEXT_BOUNDARY_WORD, |
| + 28, 36, L"WebKit \n"); |
| + |
| + // Test sentense navigation (not currently implemented). |
|
dmazzoni
2014/10/29 21:49:43
nit: sentense -> sentence
|
| + hr = input_text->get_textAtOffset( |
| + 5, IA2_TEXT_BOUNDARY_SENTENSE, |
| + &start_offset, &end_offset, text.Receive()); |
| + EXPECT_EQ(S_FALSE, hr); |
| + hr = textarea_text->get_textAtOffset( |
| + 25, IA2_TEXT_BOUNDARY_CHAR, |
| + &start_offset, &end_offset, text.Receive()); |
| + EXPECT_EQ(S_FALSE, hr); |
| + |
| + // Test line navigation. |
| + CheckTextAtOffset(textarea_text, 0, IA2_TEXT_BOUNDARY_LINE, |
| + 0, 28, L"Mozilla/5.0 (NT 6.x; WOW64)\n"); |
| + // If the offset is at the newline, return the line preceding it. |
| + CheckTextAtOffset(textarea_text, 35, IA2_TEXT_BOUNDARY_LINE, |
| + 28, 36, L"WebKit \n"); |
| + // Last line does not have a trailing newline. |
| + CheckTextAtOffset(textarea_text, 36, IA2_TEXT_BOUNDARY_LINE, |
| + 36, contents_length, L"(KHTML, like)."); |
| + |
| + // Return the whole of the text. |
| + CheckTextAtOffset(input_text, 0, IA2_TEXT_BOUNDARY_ALL, |
| + 0, contents_length, std::string(input_contents, contents_length)); |
| + CheckTextAtOffset(textarea_text, contents_length - 1, IA2_TEXT_BOUNDARY_ALL, |
| + 0, contents_length, std::string(textarea_contents, contents_length)); |
| +} |
| + |
| } // namespace content |