diff options
Diffstat (limited to 'tests/auto/other/qaccessibility/tst_qaccessibility.cpp')
-rw-r--r-- | tests/auto/other/qaccessibility/tst_qaccessibility.cpp | 526 |
1 files changed, 391 insertions, 135 deletions
diff --git a/tests/auto/other/qaccessibility/tst_qaccessibility.cpp b/tests/auto/other/qaccessibility/tst_qaccessibility.cpp index 8b033efa4a..e6bcc33771 100644 --- a/tests/auto/other/qaccessibility/tst_qaccessibility.cpp +++ b/tests/auto/other/qaccessibility/tst_qaccessibility.cpp @@ -1,40 +1,32 @@ /**************************************************************************** ** -** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies). ** Contact: http://www.qt-project.org/legal ** ** This file is part of the test suite of the Qt Toolkit. ** -** $QT_BEGIN_LICENSE:LGPL$ +** $QT_BEGIN_LICENSE:LGPL21$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and Digia. For licensing terms and -** conditions see http://qt.digia.com/licensing. For further information +** a written agreement between you and Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information ** use the contact form at http://qt.digia.com/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** General Public License version 2.1 or version 3 as published by the Free +** Software Foundation and appearing in the file LICENSE.LGPLv21 and +** LICENSE.LGPLv3 included in the packaging of this file. Please review the +** following information to ensure the GNU Lesser General Public License +** requirements will be met: https://www.gnu.org/licenses/lgpl.html and +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, Digia gives you certain additional -** rights. These rights are described in the Digia Qt LGPL Exception +** rights. These rights are described in the Digia Qt LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3.0 as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU General Public License version 3.0 requirements will be -** met: http://www.gnu.org/copyleft/gpl.html. -** -** ** $QT_END_LICENSE$ ** ****************************************************************************/ @@ -75,6 +67,8 @@ #include <algorithm> +#include "accessiblewidgets.h" + // Make a widget frameless to prevent size constraints of title bars // from interfering (Windows). static inline void setFrameless(QWidget *w) @@ -243,6 +237,7 @@ private slots: void statesStructTest(); void navigateHierarchy(); void sliderTest(); + void textAttributes_data(); void textAttributes(); void hideShowTest(); @@ -250,6 +245,7 @@ private slots: void applicationTest(); void mainWindowTest(); + void subWindowTest(); void buttonTest(); void scrollBarTest(); void tabTest(); @@ -262,6 +258,10 @@ private slots: void mdiAreaTest(); void mdiSubWindowTest(); void lineEditTest(); + void lineEditTextFunctions_data(); + void lineEditTextFunctions(); + void textInterfaceTest_data(); + void textInterfaceTest(); void groupBoxTest(); void dialogButtonBoxTest(); void dialTest(); @@ -391,43 +391,6 @@ void tst_QAccessibility::eventTest() QTestAccessibility::clearEvents(); } - -class QtTestAccessibleWidget: public QWidget -{ - Q_OBJECT -public: - QtTestAccessibleWidget(QWidget *parent, const char *name): QWidget(parent) - { - setObjectName(name); - } -}; - -class QtTestAccessibleWidgetIface: public QAccessibleWidget -{ -public: - QtTestAccessibleWidgetIface(QtTestAccessibleWidget *w): QAccessibleWidget(w) {} - QString text(QAccessible::Text t) const - { - if (t == QAccessible::Help) - return QString::fromLatin1("Help yourself"); - return QAccessibleWidget::text(t); - } - static QAccessibleInterface *ifaceFactory(const QString &key, QObject *o) - { - if (key == "QtTestAccessibleWidget") - return new QtTestAccessibleWidgetIface(static_cast<QtTestAccessibleWidget*>(o)); - return 0; - } -}; - -class QtTestAccessibleWidgetSubclass: public QtTestAccessibleWidget -{ - Q_OBJECT -public: - QtTestAccessibleWidgetSubclass(QWidget *parent, const char *name): QtTestAccessibleWidget(parent, name) - {} -}; - void tst_QAccessibility::customWidget() { { @@ -487,14 +450,6 @@ void tst_QAccessibility::deletedWidget() // fixme: QVERIFY(!iface->isValid()); } -class KFooButton: public QPushButton -{ - Q_OBJECT -public: - KFooButton(const QString &text, QWidget* parent = 0) : QPushButton(text, parent) - {} -}; - void tst_QAccessibility::subclassedWidget() { KFooButton button("Ploink", 0); @@ -698,58 +653,118 @@ void tst_QAccessibility::accessibleName() QTestAccessibility::clearEvents(); } -void tst_QAccessibility::textAttributes() +// note: color should probably always be part of the attributes +void tst_QAccessibility::textAttributes_data() { - QTextEdit textEdit; - int startOffset; - int endOffset; - QString attributes; - QString text("<html><head></head><body>" + QTest::addColumn<QString>("text"); + QTest::addColumn<int>("offset"); + QTest::addColumn<int>("startOffsetResult"); + QTest::addColumn<int>("endOffsetResult"); + QTest::addColumn<QStringList>("attributeResult"); + + static QStringList defaults = QString("font-style:normal;font-weight:normal;text-align:left;text-position:baseline;text-underline-style:none").split(';'); + static QStringList bold = defaults; + bold[1] = QString::fromLatin1("font-weight:bold"); + + static QStringList italic = defaults; + italic[0] = QString::fromLatin1("font-style:italic"); + + static QStringList boldItalic = defaults; + boldItalic[0] = QString::fromLatin1("font-style:italic"); + boldItalic[1] = QString::fromLatin1("font-weight:bold"); + + static QStringList monospace = defaults; + monospace.append(QLatin1String("font-family:\"monospace\"")); + + static QStringList font8pt = defaults; + font8pt.append(QLatin1String("font-size:8pt")); + + static QStringList color = defaults; + color << QLatin1String("color:rgb(240,241,242)") << QLatin1String("background-color:rgb(20,240,30)"); + + static QStringList rightAlign = defaults; + rightAlign[2] = QStringLiteral("text-align:right"); + + QTest::newRow("defaults 1") << "hello" << 0 << 0 << 5 << defaults; + QTest::newRow("defaults 2") << "hello" << 1 << 0 << 5 << defaults; + QTest::newRow("defaults 3") << "hello" << 4 << 0 << 5 << defaults; + QTest::newRow("defaults 4") << "hello" << 5 << 0 << 5 << defaults; + QTest::newRow("offset -1 length") << "hello" << -1 << 0 << 5 << defaults; + QTest::newRow("offset -2 cursor pos") << "hello" << -2 << 0 << 5 << defaults; + QTest::newRow("offset -3") << "hello" << -3 << -1 << -1 << QStringList(); + QTest::newRow("invalid offset 2") << "hello" << 6 << -1 << -1 << QStringList(); + QTest::newRow("invalid offset 3") << "" << 1 << -1 << -1 << QStringList(); + + QString boldText = QLatin1String("<html><b>bold</b>text"); + QTest::newRow("bold 0") << boldText << 0 << 0 << 4 << bold; + QTest::newRow("bold 2") << boldText << 2 << 0 << 4 << bold; + QTest::newRow("bold 3") << boldText << 3 << 0 << 4 << bold; + QTest::newRow("bold 4") << boldText << 4 << 4 << 8 << defaults; + QTest::newRow("bold 6") << boldText << 6 << 4 << 8 << defaults; + + QString longText = QLatin1String("<html>" "Hello, <b>this</b> is an <i><b>example</b> text</i>." "<span style=\"font-family: monospace\">Multiple fonts are used.</span>" "Multiple <span style=\"font-size: 8pt\">text sizes</span> are used." - "Let's give some color to <span style=\"color:#f0f1f2; background-color:#14f01e\">Qt</span>." - "</body></html>"); + "Let's give some color to <span style=\"color:#f0f1f2; background-color:#14f01e\">Qt</span>."); + + QTest::newRow("default 5") << longText << 6 << 0 << 7 << defaults; + QTest::newRow("default 6") << longText << 7 << 7 << 11 << bold; + QTest::newRow("bold 7") << longText << 10 << 7 << 11 << bold; + QTest::newRow("bold 8") << longText << 10 << 7 << 11 << bold; + QTest::newRow("bold italic") << longText << 18 << 18 << 25 << boldItalic; + QTest::newRow("monospace") << longText << 34 << 31 << 55 << monospace; + QTest::newRow("8pt") << longText << 65 << 64 << 74 << font8pt; + QTest::newRow("color") << longText << 110 << 109 << 111 << color; + + QString rightAligned = QLatin1String("<html><p align=\"right\">right</p>"); + QTest::newRow("right aligned 1") << rightAligned << 0 << 0 << 5 << rightAlign; + QTest::newRow("right aligned 2") << rightAligned << 1 << 0 << 5 << rightAlign; + QTest::newRow("right aligned 3") << rightAligned << 5 << 0 << 5 << rightAlign; + + // left \n right \n left, make sure bold and alignment borders coincide + QString leftRightLeftAligned = QLatin1String("<html><p><b>left</b></p><p align=\"right\">right</p><p><b>left</b></p>"); + QTest::newRow("left right left aligned 1") << leftRightLeftAligned << 1 << 0 << 4 << bold; + QTest::newRow("left right left aligned 3") << leftRightLeftAligned << 3 << 0 << 4 << bold; + QTest::newRow("left right left aligned 4") << leftRightLeftAligned << 4 << 4 << 5 << defaults; + QTest::newRow("left right left aligned 5") << leftRightLeftAligned << 5 << 5 << 10 << rightAlign; + QTest::newRow("left right left aligned 8") << leftRightLeftAligned << 8 << 5 << 10 << rightAlign; + QTest::newRow("left right left aligned 9") << leftRightLeftAligned << 9 << 5 << 10 << rightAlign; + QTest::newRow("left right left aligned 10") << leftRightLeftAligned << 10 << 10 << 11 << rightAlign; + QTest::newRow("left right left aligned 11") << leftRightLeftAligned << 11 << 11 << 15 << bold; + QTest::newRow("left right left aligned 15") << leftRightLeftAligned << 15 << 11 << 15 << bold; +} +void tst_QAccessibility::textAttributes() +{ + { + QFETCH(QString, text); + QFETCH(int, offset); + QFETCH(int, startOffsetResult); + QFETCH(int, endOffsetResult); + QFETCH(QStringList, attributeResult); + + QTextEdit textEdit; textEdit.setText(text); + if (textEdit.document()->characterCount() > 1) + textEdit.textCursor().setPosition(1); QAccessibleInterface *interface = QAccessible::queryAccessibleInterface(&textEdit); - QAccessibleTextInterface *textInterface=interface->textInterface(); - QVERIFY(textInterface); - QCOMPARE(textInterface->characterCount(), 112); + QCOMPARE(textInterface->characterCount(), textEdit.toPlainText().length()); - attributes = textInterface->attributes(10, &startOffset, &endOffset); - QCOMPARE(startOffset, 7); - QCOMPARE(endOffset, 11); - attributes.prepend(';'); - QVERIFY(attributes.contains(QLatin1String(";font-weight:bold;"))); - - attributes = textInterface->attributes(18, &startOffset, &endOffset); - QCOMPARE(startOffset, 18); - QCOMPARE(endOffset, 25); - attributes.prepend(';'); - QVERIFY(attributes.contains(QLatin1String(";font-weight:bold;"))); - QVERIFY(attributes.contains(QLatin1String(";font-style:italic;"))); - - attributes = textInterface->attributes(34, &startOffset, &endOffset); - QCOMPARE(startOffset, 31); - QCOMPARE(endOffset, 55); - attributes.prepend(';'); - QVERIFY(attributes.contains(QLatin1String(";font-family:\"monospace\";"))); - - attributes = textInterface->attributes(65, &startOffset, &endOffset); - QCOMPARE(startOffset, 64); - QCOMPARE(endOffset, 74); - attributes.prepend(';'); - QVERIFY(attributes.contains(QLatin1String(";font-size:8pt;"))); - - attributes = textInterface->attributes(110, &startOffset, &endOffset); - QCOMPARE(startOffset, 109); - QCOMPARE(endOffset, 111); - attributes.prepend(';'); - QVERIFY(attributes.contains(QLatin1String(";background-color:rgb(20,240,30);"))); - QVERIFY(attributes.contains(QLatin1String(";color:rgb(240,241,242);"))); + int startOffset = -1; + int endOffset = -1; + QString attributes = textInterface->attributes(offset, &startOffset, &endOffset); + + QCOMPARE(startOffset, startOffsetResult); + QCOMPARE(endOffset, endOffsetResult); + QStringList attrList = attributes.split(QChar(';'), QString::SkipEmptyParts); + attributeResult.sort(); + attrList.sort(); + QCOMPARE(attrList, attributeResult); + } + QTestAccessibility::clearEvents(); } void tst_QAccessibility::hideShowTest() @@ -916,30 +931,80 @@ void tst_QAccessibility::mainWindowTest() window.show(); QTRY_VERIFY(QGuiApplication::focusWindow() == &window); -// We currently don't have an accessible interface for QWindow -// the active state is either in the QMainWindow or QQuickView -// QAccessibleInterface *windowIface(QAccessible::queryAccessibleInterface(&window)); -// QVERIFY(windowIface->state().active); + // We currently don't have an accessible interface for QWindow + // the active state is either in the QMainWindow or QQuickView + QAccessibleInterface *windowIface(QAccessible::queryAccessibleInterface(&window)); + QVERIFY(!windowIface); QAccessible::State activeState; activeState.active = true; + + // We should still not crash if we somehow end up sending state change events + // Note that we do not QVERIFY_EVENT, as that relies on the updateHandler being + // called, which does not happen/make sense when there's no interface for the event. QAccessibleStateChangeEvent active(&window, activeState); - QVERIFY_EVENT(&active); + QAccessibleStateChangeEvent deactivate(&window, activeState); + } +} - QWindow child; - child.setParent(&window); - child.setGeometry(10, 10, 20, 20); - child.show(); +// Dialogs and other sub-windows must appear in the +// accessibility hierarchy exactly once as top level objects +void tst_QAccessibility::subWindowTest() +{ + { + QWidget mainWidget; + mainWidget.setGeometry(100, 100, 100, 100); + mainWidget.show(); + QLabel label(QStringLiteral("Window Contents"), &mainWidget); + mainWidget.setLayout(new QHBoxLayout()); + mainWidget.layout()->addWidget(&label); - child.requestActivate(); - QTRY_VERIFY(QGuiApplication::focusWindow() == &child); + QDialog d(&mainWidget); + d.show(); - QAccessibleStateChangeEvent deactivate(&window, activeState); - QVERIFY_EVENT(&deactivate); // deactivation of parent + QAccessibleInterface *app = QAccessible::queryAccessibleInterface(qApp); + QVERIFY(app); + QCOMPARE(app->childCount(), 2); + + QAccessibleInterface *windowIface = QAccessible::queryAccessibleInterface(&mainWidget); + QVERIFY(windowIface); + QCOMPARE(windowIface->childCount(), 1); + QCOMPARE(app->child(0), windowIface); + QCOMPARE(windowIface->parent(), app); + + QAccessibleInterface *dialogIface = QAccessible::queryAccessibleInterface(&d); + QVERIFY(dialogIface); + QCOMPARE(app->child(1), dialogIface); + QCOMPARE(dialogIface->parent(), app); + QCOMPARE(dialogIface->parent(), app); + } - QAccessibleStateChangeEvent activeChild(&child, activeState); - QVERIFY_EVENT(&activeChild); + { + QMainWindow mainWindow; + mainWindow.setGeometry(100, 100, 100, 100); + mainWindow.show(); + QLabel label(QStringLiteral("Window Contents"), &mainWindow); + mainWindow.setCentralWidget(&label); + + QDialog d(&mainWindow); + d.show(); + + QAccessibleInterface *app = QAccessible::queryAccessibleInterface(qApp); + QVERIFY(app); + QCOMPARE(app->childCount(), 2); + + QAccessibleInterface *windowIface = QAccessible::queryAccessibleInterface(&mainWindow); + QVERIFY(windowIface); + QCOMPARE(windowIface->childCount(), 1); + QCOMPARE(app->child(0), windowIface); + + QAccessibleInterface *dialogIface = QAccessible::queryAccessibleInterface(&d); + QVERIFY(dialogIface); + QCOMPARE(app->child(1), dialogIface); + QCOMPARE(dialogIface->parent(), app); + QCOMPARE(windowIface->parent(), app); } + QTestAccessibility::clearEvents(); } class CounterButton : public QPushButton { @@ -1191,8 +1256,11 @@ void tst_QAccessibility::tabTest() QVERIFY(leftButton->state().invisible); const int lots = 5; - for (int i = 0; i < lots; ++i) + for (int i = 0; i < lots; ++i) { tabBar->addTab("Foo"); + tabBar->setTabToolTip(i, QLatin1String("Cool tool tip")); + tabBar->setTabWhatsThis(i, QLatin1String("I don't know")); + } QAccessibleInterface *child1 = interface->child(0); QAccessibleInterface *child2 = interface->child(1); @@ -1201,6 +1269,10 @@ void tst_QAccessibility::tabTest() QVERIFY(child2); QCOMPARE(child2->role(), QAccessible::PageTab); + QCOMPARE(child1->text(QAccessible::Name), QLatin1String("Foo")); + QCOMPARE(child1->text(QAccessible::Description), QLatin1String("Cool tool tip")); + QCOMPARE(child1->text(QAccessible::Help), QLatin1String("I don't know")); + QVERIFY((child1->state().invisible) == false); tabBar->hide(); @@ -1545,13 +1617,10 @@ void tst_QAccessibility::spinBoxTest() QCOMPARE(accessibleRect, widgetRect); QCOMPARE(interface->text(QAccessible::Value), QLatin1String("3")); - // one child, the line edit + // make sure that the line edit is not there const int numChildren = interface->childCount(); - QCOMPARE(numChildren, 1); - QAccessibleInterface *lineEdit = interface->child(0); - - QCOMPARE(lineEdit->role(), QAccessible::EditableText); - QCOMPARE(lineEdit->text(QAccessible::Value), QLatin1String("3")); + QCOMPARE(numChildren, 0); + QVERIFY(interface->child(0) == Q_NULLPTR); QVERIFY(interface->valueInterface()); QCOMPARE(interface->valueInterface()->currentValue().toInt(), 3); @@ -1565,6 +1634,10 @@ void tst_QAccessibility::spinBoxTest() QTest::qWait(200); QAccessibleValueChangeEvent expectedEvent(spinBox, spinBox->value()); QVERIFY(QTestAccessibility::containsEvent(&expectedEvent)); + + QAccessibleTextInterface *textIface = interface->textInterface(); + QVERIFY(textIface); + delete spinBox; QTestAccessibility::clearEvents(); } @@ -1652,6 +1725,11 @@ void tst_QAccessibility::textEditTest() QTest::qWaitForWindowShown(&edit); QAccessibleInterface *iface = QAccessible::queryAccessibleInterface(&edit); QCOMPARE(iface->text(QAccessible::Value), edit.toPlainText()); + QVERIFY(iface->state().focusable); + QVERIFY(!iface->state().selectable); + QVERIFY(!iface->state().selected); + QVERIFY(iface->state().selectableText); + QAccessibleTextInterface *textIface = iface->textInterface(); QVERIFY(textIface); @@ -1751,8 +1829,6 @@ void tst_QAccessibility::textEditTest() QAccessibleTextRemoveEvent remove(&edit, 0, " "); QVERIFY_EVENT(&remove); - // FIXME the new text is not there yet - QEXPECT_FAIL("", "Inserting should always contain the new text", Continue); QAccessibleTextInsertEvent insert(&edit, 0, "Accessibility rocks"); QVERIFY_EVENT(&insert); } @@ -1929,7 +2005,8 @@ void tst_QAccessibility::lineEditTest() QVERIFY(iface->state().sizeable); QVERIFY(iface->state().movable); QVERIFY(iface->state().focusable); - QVERIFY(iface->state().selectable); + QVERIFY(!iface->state().selectable); + QVERIFY(iface->state().selectableText); QVERIFY(!iface->state().hasPopup); QCOMPARE(bool(iface->state().focused), le->hasFocus()); @@ -1940,13 +2017,13 @@ void tst_QAccessibility::lineEditTest() QCOMPARE(iface->text(QAccessible::Value), secret); le->setEchoMode(QLineEdit::NoEcho); QVERIFY(iface->state().passwordEdit); - QVERIFY(iface->text(QAccessible::Value).isEmpty()); + QCOMPARE(iface->text(QAccessible::Value), QString()); le->setEchoMode(QLineEdit::Password); QVERIFY(iface->state().passwordEdit); - QVERIFY(iface->text(QAccessible::Value).isEmpty()); + QCOMPARE(iface->text(QAccessible::Value), QString(secret.length(), QLatin1Char('*'))); le->setEchoMode(QLineEdit::PasswordEchoOnEdit); QVERIFY(iface->state().passwordEdit); - QVERIFY(iface->text(QAccessible::Value).isEmpty()); + QCOMPARE(iface->text(QAccessible::Value), QString(secret.length(), QLatin1Char('*'))); le->setEchoMode(QLineEdit::Normal); QVERIFY(!(iface->state().passwordEdit)); QCOMPARE(iface->text(QAccessible::Value), secret); @@ -1957,7 +2034,9 @@ void tst_QAccessibility::lineEditTest() QVERIFY(!(iface->state().sizeable)); QVERIFY(!(iface->state().movable)); QVERIFY(iface->state().focusable); - QVERIFY(iface->state().selectable); + QVERIFY(!iface->state().selectable); + QVERIFY(!iface->state().selected); + QVERIFY(iface->state().selectableText); QVERIFY(!iface->state().hasPopup); QCOMPARE(bool(iface->state().focused), le->hasFocus()); @@ -2158,6 +2237,183 @@ void tst_QAccessibility::lineEditTest() QTestAccessibility::clearEvents(); } +void tst_QAccessibility::lineEditTextFunctions_data() +{ + QTest::addColumn<QString>("text"); + QTest::addColumn<int>("textFunction"); // before = 0, at = 1, after = 2 + QTest::addColumn<int>("boundaryType"); + QTest::addColumn<int>("cursorPosition"); + QTest::addColumn<int>("offset"); + QTest::addColumn<int>("expectedStart"); + QTest::addColumn<int>("expectedEnd"); + QTest::addColumn<QString>("expectedText"); + + // -2 gives cursor position, -1 is length + // invalid positions will return empty strings and either -1 and -1 or both the cursor position, both is fine + QTest::newRow("char before -2") << "hello" << 0 << (int) QAccessible::CharBoundary << 3 << -2 << 2 << 3 << "l"; + QTest::newRow("char at -2") << "hello" << 1 << (int) QAccessible::CharBoundary << 3 << -2 << 3 << 4 << "l"; + QTest::newRow("char after -2") << "hello" << 2 << (int) QAccessible::CharBoundary << 3 << -2 << 4 << 5 << "o"; + QTest::newRow("char before -1") << "hello" << 0 << (int) QAccessible::CharBoundary << 3 << -1 << 4 << 5 << "o"; + QTest::newRow("char at -1") << "hello" << 1 << (int) QAccessible::CharBoundary << 3 << -1 << -1 << -1 << ""; + QTest::newRow("char after -1") << "hello" << 2 << (int) QAccessible::CharBoundary << 3 << -1 << -1 << -1 << ""; + QTest::newRow("char before 0") << "hello" << 0 << (int) QAccessible::CharBoundary << 0 << 0 << -1 << -1 << ""; + QTest::newRow("char at 0") << "hello" << 1 << (int) QAccessible::CharBoundary << 0 << 0 << 0 << 1 << "h"; + QTest::newRow("char after 0") << "hello" << 2 << (int) QAccessible::CharBoundary << 0 << 0 << 1 << 2 << "e"; + QTest::newRow("char before 1") << "hello" << 0 << (int) QAccessible::CharBoundary << 3 << 1 << 0 << 1 << "h"; + QTest::newRow("char at 1") << "hello" << 1 << (int) QAccessible::CharBoundary << 3 << 1 << 1 << 2 << "e"; + QTest::newRow("char after 1") << "hello" << 2 << (int) QAccessible::CharBoundary << 3 << 1 << 2 << 3 << "l"; + QTest::newRow("char before 4") << "hello" << 0 << (int) QAccessible::CharBoundary << 3 << 4 << 3 << 4 << "l"; + QTest::newRow("char at 4") << "hello" << 1 << (int) QAccessible::CharBoundary << 3 << 4 << 4 << 5 << "o"; + QTest::newRow("char after 4") << "hello" << 2 << (int) QAccessible::CharBoundary << 3 << 4 << -1 << -1 << ""; + QTest::newRow("char before 5") << "hello" << 0 << (int) QAccessible::CharBoundary << 3 << 5 << 4 << 5 << "o"; + QTest::newRow("char at 5") << "hello" << 1 << (int) QAccessible::CharBoundary << 3 << 5 << -1 << -1 << ""; + QTest::newRow("char after 5") << "hello" << 2 << (int) QAccessible::CharBoundary << 3 << 5 << -1 << -1 << ""; + QTest::newRow("char before 6") << "hello" << 0 << (int) QAccessible::CharBoundary << 3 << 6 << -1 << -1 << ""; + QTest::newRow("char at 6") << "hello" << 1 << (int) QAccessible::CharBoundary << 3 << 6 << -1 << -1 << ""; + QTest::newRow("char after 6") << "hello" << 2 << (int) QAccessible::CharBoundary << 3 << 6 << -1 << -1 << ""; + + for (int i = -2; i < 6; ++i) { + QTest::newRow(QString::fromLatin1("line before %1").arg(i).toLocal8Bit().constData()) << "hello" << 0 << (int) QAccessible::LineBoundary << 3 << i << -1 << -1 << ""; + QTest::newRow(QString::fromLatin1("line at %1").arg(i).toLocal8Bit().constData()) << "hello" << 1 << (int) QAccessible::LineBoundary << 3 << i << 0 << 5 << "hello"; + QTest::newRow(QString::fromLatin1("line after %1").arg(i).toLocal8Bit().constData()) << "hello" << 2 << (int) QAccessible::LineBoundary << 3 << i << -1 << -1 << ""; + } +} + +void tst_QAccessibility::lineEditTextFunctions() +{ + { + QFETCH(QString, text); + QFETCH(int, textFunction); + QFETCH(int, boundaryType); + QFETCH(int, cursorPosition); + QFETCH(int, offset); + QFETCH(int, expectedStart); + QFETCH(int, expectedEnd); + QFETCH(QString, expectedText); + + QLineEdit le; + le.show(); + le.setText(text); + le.setCursorPosition(cursorPosition); + + QAccessibleInterface *iface = QAccessible::queryAccessibleInterface(&le); + QVERIFY(iface); + QAccessibleTextInterface *textIface = iface->textInterface(); + QVERIFY(textIface); + + int start = -33; + int end = -33; + QString result; + switch (textFunction) { + case 0: + result = textIface->textBeforeOffset(offset, (QAccessible::TextBoundaryType) boundaryType, &start, &end); + break; + case 1: + result = textIface->textAtOffset(offset, (QAccessible::TextBoundaryType) boundaryType, &start, &end); + break; + case 2: + result = textIface->textAfterOffset(offset, (QAccessible::TextBoundaryType) boundaryType, &start, &end); + break; + } + QCOMPARE(result, expectedText); + QCOMPARE(start, expectedStart); + QCOMPARE(end, expectedEnd); + } + QTestAccessibility::clearEvents(); +} + +void tst_QAccessibility::textInterfaceTest_data() +{ + lineEditTextFunctions_data(); + QString hello = QStringLiteral("hello\nworld\nend"); + QTest::newRow("multi line at 0") << hello << 1 << (int) QAccessible::LineBoundary << 0 << 0 << 0 << 6 << "hello\n"; + QTest::newRow("multi line at 1") << hello << 1 << (int) QAccessible::LineBoundary << 0 << 1 << 0 << 6 << "hello\n"; + QTest::newRow("multi line at 2") << hello << 1 << (int) QAccessible::LineBoundary << 0 << 2 << 0 << 6 << "hello\n"; + QTest::newRow("multi line at 5") << hello << 1 << (int) QAccessible::LineBoundary << 0 << 5 << 0 << 6 << "hello\n"; + QTest::newRow("multi line at 6") << hello << 1 << (int) QAccessible::LineBoundary << 0 << 6 << 6 << 12 << "world\n"; + QTest::newRow("multi line at 7") << hello << 1 << (int) QAccessible::LineBoundary << 0 << 7 << 6 << 12 << "world\n"; + QTest::newRow("multi line at 8") << hello << 1 << (int) QAccessible::LineBoundary << 0 << 8 << 6 << 12 << "world\n"; + QTest::newRow("multi line at 10") << hello << 1 << (int) QAccessible::LineBoundary << 0 << 10 << 6 << 12 << "world\n"; + QTest::newRow("multi line at 11") << hello << 1 << (int) QAccessible::LineBoundary << 0 << 11 << 6 << 12 << "world\n"; + QTest::newRow("multi line at 12") << hello << 1 << (int) QAccessible::LineBoundary << 0 << 12 << 12 << 15 << "end"; + + QTest::newRow("multi line before 0") << hello << 0 << (int) QAccessible::LineBoundary << 0 << 0 << -1 << -1 << ""; + QTest::newRow("multi line before 1") << hello << 0 << (int) QAccessible::LineBoundary << 0 << 1 << -1 << -1 << ""; + QTest::newRow("multi line before 2") << hello << 0 << (int) QAccessible::LineBoundary << 0 << 2 << -1 << -1 << ""; + QTest::newRow("multi line before 5") << hello << 0 << (int) QAccessible::LineBoundary << 0 << 5 << -1 << -1 << ""; + QTest::newRow("multi line before 6") << hello << 0 << (int) QAccessible::LineBoundary << 0 << 6 << 0 << 6 << "hello\n"; + QTest::newRow("multi line before 7") << hello << 0 << (int) QAccessible::LineBoundary << 0 << 7 << 0 << 6 << "hello\n"; + QTest::newRow("multi line before 8") << hello << 0 << (int) QAccessible::LineBoundary << 0 << 8 << 0 << 6 << "hello\n"; + QTest::newRow("multi line before 10") << hello << 0 << (int) QAccessible::LineBoundary << 0 << 10 << 0 << 6 << "hello\n"; + QTest::newRow("multi line before 11") << hello << 0 << (int) QAccessible::LineBoundary << 0 << 11 << 0 << 6 << "hello\n"; + QTest::newRow("multi line before 12") << hello << 0 << (int) QAccessible::LineBoundary << 0 << 12 << 6 << 12 << "world\n"; + + QTest::newRow("multi line after 0") << hello << 2 << (int) QAccessible::LineBoundary << 0 << 0 << 6 << 12 << "world\n"; + QTest::newRow("multi line after 1") << hello << 2 << (int) QAccessible::LineBoundary << 0 << 1 << 6 << 12 << "world\n"; + QTest::newRow("multi line after 2") << hello << 2 << (int) QAccessible::LineBoundary << 0 << 2 << 6 << 12 << "world\n"; + QTest::newRow("multi line after 5") << hello << 2 << (int) QAccessible::LineBoundary << 0 << 5 << 6 << 12 << "world\n"; + QTest::newRow("multi line after 6") << hello << 2 << (int) QAccessible::LineBoundary << 0 << 6 << 12 << 15 << "end"; + QTest::newRow("multi line after 7") << hello << 2 << (int) QAccessible::LineBoundary << 0 << 7 << 12 << 15 << "end"; + QTest::newRow("multi line after 8") << hello << 2 << (int) QAccessible::LineBoundary << 0 << 8 << 12 << 15 << "end"; + QTest::newRow("multi line after 10") << hello << 2 << (int) QAccessible::LineBoundary << 0 << 10 << 12 << 15 << "end"; + QTest::newRow("multi line after 11") << hello << 2 << (int) QAccessible::LineBoundary << 0 << 11 << 12 << 15 << "end"; + QTest::newRow("multi line after 12") << hello << 2 << (int) QAccessible::LineBoundary << 0 << 12 << -1 << -1 << ""; + + QTest::newRow("before 4 \\nFoo\\n") << QStringLiteral("\nFoo\n") << 0 << (int) QAccessible::LineBoundary << 0 << 4 << 0 << 1 << "\n"; + QTest::newRow("at 4 \\nFoo\\n") << QStringLiteral("\nFoo\n") << 1 << (int) QAccessible::LineBoundary << 0 << 4 << 1 << 5 << "Foo\n"; + QTest::newRow("after 4 \\nFoo\\n") << QStringLiteral("\nFoo\n") << 2 << (int) QAccessible::LineBoundary << 0 << 4 << 5 << 5 << ""; + QTest::newRow("before 4 Foo\\nBar\\n") << QStringLiteral("Foo\nBar\n") << 0 << (int) QAccessible::LineBoundary << 0 << 7 << 0 << 4 << "Foo\n"; + QTest::newRow("at 4 Foo\\nBar\\n") << QStringLiteral("Foo\nBar\n") << 1 << (int) QAccessible::LineBoundary << 0 << 7 << 4 << 8 << "Bar\n"; + QTest::newRow("after 4 Foo\\nBar\\n") << QStringLiteral("Foo\nBar\n") << 2 << (int) QAccessible::LineBoundary << 0 << 7 << 8 << 8 << ""; + QTest::newRow("at 0 Foo\\n") << QStringLiteral("Foo\n") << 1 << (int) QAccessible::LineBoundary << 0 << 0 << 0 << 4 << "Foo\n"; +} + +void tst_QAccessibility::textInterfaceTest() +{ + QFETCH(QString, text); + QFETCH(int, textFunction); + QFETCH(int, boundaryType); + QFETCH(int, cursorPosition); + QFETCH(int, offset); + QFETCH(int, expectedStart); + QFETCH(int, expectedEnd); + QFETCH(QString, expectedText); + + QAccessible::installFactory(CustomTextWidgetIface::ifaceFactory); + CustomTextWidget *w = new CustomTextWidget(); + w->text = text; + w->cursorPosition = cursorPosition; + + QAccessibleInterface *iface = QAccessible::queryAccessibleInterface(w); + QVERIFY(iface); + QCOMPARE(iface->text(QAccessible::Value), text); + QAccessibleTextInterface *textIface = iface->textInterface(); + QVERIFY(textIface); + + int start = -33; + int end = -33; + QString result; + switch (textFunction) { + case 0: + result = textIface->textBeforeOffset(offset, (QAccessible::TextBoundaryType) boundaryType, &start, &end); + break; + case 1: + result = textIface->textAtOffset(offset, (QAccessible::TextBoundaryType) boundaryType, &start, &end); + break; + case 2: + result = textIface->textAfterOffset(offset, (QAccessible::TextBoundaryType) boundaryType, &start, &end); + break; + } + + QCOMPARE(result, expectedText); + QCOMPARE(start, expectedStart); + QCOMPARE(end, expectedEnd); + + delete w; + QAccessible::removeFactory(CustomTextWidgetIface::ifaceFactory); + QTestAccessibility::clearEvents(); +} + void tst_QAccessibility::groupBoxTest() { { |