summaryrefslogtreecommitdiffstats
path: root/tests/auto/other
diff options
context:
space:
mode:
authorJan Arve Sæther <jan-arve.saether@qt.io>2023-11-10 11:19:11 +0100
committerJan Arve Sæther <jan-arve.saether@qt.io>2023-11-23 13:25:41 +0100
commitbc8141d286727e7c7b21d61556852ee78acd56c3 (patch)
tree2045745fa8f7cbb585116291bf185ef4e8869409 /tests/auto/other
parent1082038bd89d0bbba4df0d9b3f8af3cd0a2f96f2 (diff)
a11y: Fix bug where some characters were not spoken while moving cursor
The problem occurred when we moved the cursor to the penultimate character of the string, because the boundary condition was wrong. It is important to realize that the offsets are moved *between* each character (and also before and after the whole string), just like you would move a cursor. This means that the offsets can be in the range [0, len] (closed interval) The problem could only be reproduced with JAWS. Pick-to: 6.6 6.5 6.2 Fixes: QTBUG-115156 Change-Id: I0c5f05fa391e6c7744ab22d71afe8904b49e89bc Reviewed-by: Volker Hilsheimer <volker.hilsheimer@qt.io> Reviewed-by: Michael Weghorn <m.weghorn@posteo.de>
Diffstat (limited to 'tests/auto/other')
-rw-r--r--tests/auto/other/qaccessibility/tst_qaccessibility.cpp100
1 files changed, 97 insertions, 3 deletions
diff --git a/tests/auto/other/qaccessibility/tst_qaccessibility.cpp b/tests/auto/other/qaccessibility/tst_qaccessibility.cpp
index 99136979d6..37cff128b7 100644
--- a/tests/auto/other/qaccessibility/tst_qaccessibility.cpp
+++ b/tests/auto/other/qaccessibility/tst_qaccessibility.cpp
@@ -3966,6 +3966,7 @@ void tst_QAccessibility::bridgeTest()
// For now this is a simple test to see if the bridge is working at all.
// Ideally it should be extended to test all aspects of the bridge.
#if defined(Q_OS_WIN)
+ auto guard = qScopeGuard([]() { QTestAccessibility::clearEvents(); });
QWidget window;
QVBoxLayout *lay = new QVBoxLayout(&window);
@@ -4103,10 +4104,105 @@ void tst_QAccessibility::bridgeTest()
QCOMPARE(controlTypeId, UIA_ButtonControlTypeId);
// Edit
- hr = nodeList.at(2)->get_CurrentControlType(&controlTypeId);
+ IUIAutomationElement *uiaElement = nodeList.at(2);
+ hr = uiaElement->get_CurrentControlType(&controlTypeId);
QVERIFY(SUCCEEDED(hr));
QCOMPARE(controlTypeId, UIA_EditControlTypeId);
+ // "hello world\nhow are you today?\n"
+ IUIAutomationTextPattern *textPattern = nullptr;
+ hr = uiaElement->GetCurrentPattern(UIA_TextPattern2Id, reinterpret_cast<IUnknown**>(&textPattern));
+ QVERIFY(SUCCEEDED(hr));
+ QVERIFY(textPattern);
+
+ IUIAutomationTextRange *docRange = nullptr;
+ hr = textPattern->get_DocumentRange(&docRange);
+ QVERIFY(SUCCEEDED(hr));
+ QVERIFY(docRange);
+
+ IUIAutomationTextRange *textRange = nullptr;
+ hr = docRange->Clone(&textRange);
+ QVERIFY(SUCCEEDED(hr));
+ QVERIFY(textRange);
+ int moved;
+
+ auto rangeText = [](IUIAutomationTextRange *textRange) {
+ BSTR str;
+ QString res = "IUIAutomationTextRange::GetText() failed";
+ HRESULT hr = textRange->GetText(-1, &str);
+ if (SUCCEEDED(hr)) {
+ res = QString::fromWCharArray(str);
+ ::SysFreeString(str);
+ }
+ return res;
+ };
+
+ // Move start endpoint past "hello " to "world"
+ hr = textRange->Move(TextUnit_Character, 6, &moved);
+ QVERIFY(SUCCEEDED(hr));
+ QCOMPARE(moved, 6);
+ // If the range was not empty, it should be collapsed to contain a single text unit
+ QCOMPARE(rangeText(textRange), QString("w"));
+
+ // Move end endpoint to end of "world"
+ hr = textRange->MoveEndpointByUnit(TextPatternRangeEndpoint_End, TextUnit_Character, 4, &moved);
+ QVERIFY(SUCCEEDED(hr));
+ QCOMPARE(moved, 4);
+ QCOMPARE(rangeText(textRange), QString("world"));
+
+ // MSDN: "Zero has no effect". This behavior was also verified with native controls.
+ hr = textRange->Move(TextUnit_Character, 0, &moved);
+ QVERIFY(SUCCEEDED(hr));
+ QCOMPARE(moved, 0);
+ QCOMPARE(rangeText(textRange), QString("world"));
+
+ hr = textRange->Move(TextUnit_Character, 1, &moved);
+ QVERIFY(SUCCEEDED(hr));
+ QCOMPARE(rangeText(textRange), QString("o"));
+
+ // move as far towards the end as possible
+ hr = textRange->Move(TextUnit_Character, 999, &moved);
+ QVERIFY(SUCCEEDED(hr));
+ QCOMPARE(rangeText(textRange), QString(""));
+
+ hr = textRange->MoveEndpointByUnit(TextPatternRangeEndpoint_Start, TextUnit_Character, -1, &moved);
+ QVERIFY(SUCCEEDED(hr));
+ QCOMPARE(rangeText(textRange), QString("\n"));
+
+ // move one forward (last possible position again)
+ hr = textRange->Move(TextUnit_Character, 1, &moved);
+ QVERIFY(SUCCEEDED(hr));
+ QCOMPARE(rangeText(textRange), QString(""));
+
+ hr = textRange->Move(TextUnit_Character, -7, &moved);
+ QVERIFY(SUCCEEDED(hr));
+ QCOMPARE(moved, -7);
+ QCOMPARE(rangeText(textRange), QString(""));
+ // simulate moving cursor (empty range) towards (and past) the end
+ QString today(" today?\n");
+ for (int i = 1; i < 9; ++i) { // 9 is deliberately too much
+ // peek one character back
+ hr = textRange->MoveEndpointByUnit(TextPatternRangeEndpoint_Start, TextUnit_Character, -1, &moved);
+ QVERIFY(SUCCEEDED(hr));
+ QCOMPARE(rangeText(textRange), today.mid(i - 1, 1));
+
+ hr = textRange->Move(TextUnit_Character, 1, &moved);
+ QVERIFY(SUCCEEDED(hr));
+ QCOMPARE(rangeText(textRange), today.mid(i, moved)); // when we cannot move further, moved will be 0
+
+ // Make the range empty again
+ hr = textRange->MoveEndpointByUnit(TextPatternRangeEndpoint_End, TextUnit_Character, -moved, &moved);
+ QVERIFY(SUCCEEDED(hr));
+
+ // advance the empty range
+ hr = textRange->Move(TextUnit_Character, 1, &moved);
+ QVERIFY(SUCCEEDED(hr));
+ }
+ docRange->Release();
+ textRange->Release();
+ textPattern->Release();
+
+
// Table
hr = nodeList.at(3)->get_CurrentControlType(&controlTypeId);
QVERIFY(SUCCEEDED(hr));
@@ -4124,8 +4220,6 @@ void tst_QAccessibility::bridgeTest()
controlWalker->Release();
windowElement->Release();
automation->Release();
-
- QTestAccessibility::clearEvents();
#endif
}