/* Copyright (C) 2015 The Qt Company Ltd. This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include #include #include #include #include #include #include #include #include class tst_Accessibility : public QObject { Q_OBJECT public Q_SLOTS: void initTestCase(); void cleanupTestCase(); void init(); void cleanup(); private Q_SLOTS: void noPage(); void hierarchy(); void focusChild(); void focusChild_data(); void text(); void value(); void roles_data(); void roles(); void objectName(); void crossTreeParent(); }; // This will be called before the first test function is executed. // It is only called once. void tst_Accessibility::initTestCase() { } // This will be called after the last test function is executed. // It is only called once. void tst_Accessibility::cleanupTestCase() { } // This will be called before each test function is executed. void tst_Accessibility::init() { } // This will be called after every test function. void tst_Accessibility::cleanup() { } void tst_Accessibility::noPage() { QWebEngineView webView; webView.show(); QAccessibleInterface *view = nullptr; QTRY_VERIFY((view = QAccessible::queryAccessibleInterface(&webView))); QCOMPARE(view->role(), QAccessible::Client); QTRY_COMPARE(view->childCount(), 1); QAccessibleInterface *document = view->child(0); QCOMPARE(document->role(), QAccessible::WebDocument); QCOMPARE(document->parent(), view); QCOMPARE(document->childCount(), 0); } void tst_Accessibility::hierarchy() { QWebEngineView webView; webView.setHtml("" \ "Hello world" \ "" \ ""); webView.show(); QSignalSpy spyFinished(&webView, &QWebEngineView::loadFinished); QVERIFY(spyFinished.wait()); QAccessibleInterface *view = QAccessible::queryAccessibleInterface(&webView); QVERIFY(view); QCOMPARE(view->role(), QAccessible::Client); QCOMPARE(view->childCount(), 1); // Wait for accessibility to be fully initialized QTRY_COMPARE(view->child(0)->childCount(), 1); QAccessibleInterface *document = view->child(0); QCOMPARE(document->role(), QAccessible::WebDocument); QCOMPARE(document->parent(), view); QCOMPARE(view->indexOfChild(document), 0); QCOMPARE(document->childCount(), 1); QAccessibleInterface *grouping = document->child(0); QVERIFY(grouping); QCOMPARE(grouping->parent(), document); QCOMPARE(document->indexOfChild(grouping), 0); QCOMPARE(grouping->childCount(), 2); QAccessibleInterface *text = grouping->child(0); QCOMPARE(text->role(), QAccessible::StaticText); QCOMPARE(text->parent(), grouping); QCOMPARE(grouping->indexOfChild(text), 0); QCOMPARE(text->childCount(), 0); QCOMPARE(text->text(QAccessible::Name), QStringLiteral("Hello world")); QCOMPARE(text->text(QAccessible::Description), QString()); QCOMPARE(text->text(QAccessible::Value), QString()); QAccessibleInterface *input = grouping->child(1); QCOMPARE(input->role(), QAccessible::EditableText); QCOMPARE(input->parent(), grouping); QCOMPARE(grouping->indexOfChild(input), 1); QCOMPARE(input->childCount(), 0); QCOMPARE(input->text(QAccessible::Name), QString()); QCOMPARE(input->text(QAccessible::Description), QString()); QCOMPARE(input->text(QAccessible::Value), QStringLiteral("some text")); QRect windowRect = webView.geometry(); QRect inputRect = input->rect(); QVERIFY(!inputRect.isEmpty()); QVERIFY(windowRect.contains(inputRect)); QPoint inputCenter = inputRect.center(); QAccessibleInterface *hitTest = view; QAccessibleInterface *child = nullptr; while (hitTest) { child = hitTest; hitTest = hitTest->childAt(inputCenter.x(), inputCenter.y()); } QCOMPARE(input, child); } void tst_Accessibility::focusChild_data() { QTest::addColumn("interfaceName"); QTest::addColumn>("ancestorRoles"); QTest::newRow("QWebEngineView") << QString("QWebEngineView") << QList({QAccessible::Client}); QTest::newRow("RenderWidgetHostViewQtDelegate") << QString("RenderWidgetHostViewQtDelegate") << QList({QAccessible::Client}); QTest::newRow("QMainWindow") << QString("QMainWindow") << QList({QAccessible::Window, QAccessible::Client /* central widget */, QAccessible::Client /* view */}); } void tst_Accessibility::focusChild() { auto traverseToWebDocumentAccessibleInterface = [](QAccessibleInterface *iface) -> QAccessibleInterface * { QFETCH(QList, ancestorRoles); for (int i = 0; i < ancestorRoles.size(); ++i) { if (iface->childCount() == 0 || iface->role() != ancestorRoles[i]) return nullptr; iface = iface->child(0); } if (iface->role() != QAccessible::WebDocument) return nullptr; return iface; }; QMainWindow mainWindow; QWebEngineView *webView = new QWebEngineView; QWidget *centralWidget = new QWidget; QHBoxLayout *centralLayout = new QHBoxLayout; centralWidget->setLayout(centralLayout); mainWindow.setCentralWidget(centralWidget); centralLayout->addWidget(webView); mainWindow.show(); QVERIFY(QTest::qWaitForWindowExposed(&mainWindow)); webView->settings()->setAttribute(QWebEngineSettings::FocusOnNavigationEnabled, true); webView->setHtml("" \ "" \ ""); webView->show(); QSignalSpy spyFinished(webView, &QWebEngineView::loadFinished); QVERIFY(spyFinished.wait()); QVERIFY(webView->focusWidget()); QAccessibleInterface *iface = nullptr; QFETCH(QString, interfaceName); if (interfaceName == "QWebEngineView") iface = QAccessible::queryAccessibleInterface(webView); else if (interfaceName == "RenderWidgetHostViewQtDelegate") iface = QAccessible::queryAccessibleInterface(webView->focusWidget()); else if (interfaceName == "QMainWindow") iface = QAccessible::queryAccessibleInterface(&mainWindow); QVERIFY(iface); // Make sure the input field does not have the focus. evaluateJavaScriptSync(webView->page(), "document.getElementById('input1').blur()"); QTRY_VERIFY(evaluateJavaScriptSync(webView->page(), "document.activeElement.id").toString().isEmpty()); QVERIFY(iface->focusChild()); QTRY_COMPARE(iface->focusChild()->role(), QAccessible::WebDocument); QCOMPARE(traverseToWebDocumentAccessibleInterface(iface), iface->focusChild()); // Set active focus on the input field. evaluateJavaScriptSync(webView->page(), "document.getElementById('input1').focus()"); QTRY_COMPARE(evaluateJavaScriptSync(webView->page(), "document.activeElement.id").toString(), QStringLiteral("input1")); QVERIFY(iface->focusChild()); QTRY_COMPARE(iface->focusChild()->role(), QAccessible::EditableText); // -> -> QCOMPARE(traverseToWebDocumentAccessibleInterface(iface)->child(0)->child(0), iface->focusChild()); } void tst_Accessibility::text() { QWebEngineView webView; webView.setHtml("" \ "" \ "

Enter your name here:

" \ "" \ "

Provide both first and last name.

" \ "" \ ""); webView.show(); QSignalSpy spyFinished(&webView, &QWebEngineView::loadFinished); QVERIFY(spyFinished.wait()); QAccessibleInterface *view = QAccessible::queryAccessibleInterface(&webView); // Wait for accessibility to be fully initialized QTRY_COMPARE(view->child(0)->childCount(), 5); QAccessibleInterface *document = view->child(0); QVERIFY(document); // Good morning! [edit] QAccessibleInterface *grouping1 = document->child(0); QAccessibleInterface *input1 = grouping1; QCOMPARE(input1->role(), QAccessible::EditableText); QCOMPARE(input1->text(QAccessible::Name), QString()); QCOMPARE(input1->text(QAccessible::Description), QString()); QCOMPARE(input1->text(QAccessible::Value), QStringLiteral("Good morning!")); QAccessibleTextInterface *textInterface1 = input1->textInterface(); QVERIFY(textInterface1); QCOMPARE(textInterface1->characterCount(), 13); QCOMPARE(textInterface1->selectionCount(), 0); QCOMPARE(textInterface1->text(2, 9), QStringLiteral("od morn")); int start = -1; int end = -1; QCOMPARE(textInterface1->textAtOffset(8, QAccessible::WordBoundary, &start, &end), QStringLiteral("morning")); // Enter your name here: // my name [edit] // Provide both first and last name here. QAccessibleInterface *grouping2 = document->child(1); QAccessibleInterface *label1 = grouping2->child(0); QCOMPARE(label1->role(), QAccessible::StaticText); QCOMPARE(label1->text(QAccessible::Name), QStringLiteral("Enter your name here:")); QCOMPARE(label1->text(QAccessible::Description), QString()); QCOMPARE(label1->text(QAccessible::Value), QString()); QAccessibleInterface *grouping3 = document->child(2); QAccessibleInterface *input2 = grouping3; QCOMPARE(input2->role(), QAccessible::EditableText); QCOMPARE(input2->text(QAccessible::Name), QStringLiteral("Enter your name here:")); QCOMPARE(input2->text(QAccessible::Description), QStringLiteral("Provide both first and last name.")); QCOMPARE(input2->text(QAccessible::Value), QStringLiteral("my name")); QAccessibleInterface *grouping4 = document->child(3); QAccessibleInterface *label2 = grouping4->child(0); QCOMPARE(label2->role(), QAccessible::StaticText); QCOMPARE(label2->text(QAccessible::Name), QStringLiteral("Provide both first and last name.")); QCOMPARE(label2->text(QAccessible::Description), QString()); QCOMPARE(label2->text(QAccessible::Value), QString()); // Good day! [edit] QAccessibleInterface *grouping5 = document->child(4); QAccessibleInterface *input3 = grouping5; QCOMPARE(input3->role(), QAccessible::EditableText); QCOMPARE(input3->text(QAccessible::Name), QStringLiteral("day")); QCOMPARE(input3->text(QAccessible::Description), QString()); QCOMPARE(input3->text(QAccessible::Value), QStringLiteral("Good day!")); } void tst_Accessibility::value() { QWebEngineView webView; webView.setHtml("" \ "
" \ "
" \ ""); webView.show(); QSignalSpy spyFinished(&webView, &QWebEngineView::loadFinished); QVERIFY(spyFinished.wait()); QAccessibleInterface *view = QAccessible::queryAccessibleInterface(&webView); QTRY_COMPARE(view->child(0)->childCount(), 2); QAccessibleInterface *document = view->child(0); QCOMPARE(document->childCount(), 2); QAccessibleInterface *slider = document->child(0); QCOMPARE(slider->role(), QAccessible::Slider); QCOMPARE(slider->text(QAccessible::Name), QString()); QCOMPARE(slider->text(QAccessible::Description), QString()); QCOMPARE(slider->text(QAccessible::Value), QString()); QAccessibleValueInterface *valueInterface = slider->valueInterface(); QVERIFY(valueInterface); QCOMPARE(valueInterface->currentValue().toInt(), 4); QCOMPARE(valueInterface->minimumValue().toInt(), 1); QCOMPARE(valueInterface->maximumValue().toInt(), 10); QAccessibleInterface *progressBar = document->child(1); QCOMPARE(progressBar->role(), QAccessible::ProgressBar); QCOMPARE(progressBar->text(QAccessible::Name), QString()); QCOMPARE(progressBar->text(QAccessible::Description), QString()); QCOMPARE(progressBar->text(QAccessible::Value), QString()); QAccessibleValueInterface *progressBarValueInterface = progressBar->valueInterface(); QVERIFY(progressBarValueInterface); QCOMPARE(progressBarValueInterface->currentValue().toInt(), 77); QCOMPARE(progressBarValueInterface->minimumValue().toInt(), 22); QCOMPARE(progressBarValueInterface->maximumValue().toInt(), 99); } void tst_Accessibility::roles_data() { QTest::addColumn("html"); QTest::addColumn("nested"); QTest::addColumn("role"); QTest::newRow("ax::mojom::Role::kAbbr") << QString("a") << 1 << QAccessible::StaticText; QTest::newRow("ax::mojom::Role::kAlert") << QString("
alert
") << 0 << QAccessible::AlertMessage; QTest::newRow("ax::mojom::Role::kAlertDialog") << QString("
alert
") << 0 << QAccessible::AlertMessage; QTest::newRow("ax::mojom::Role::kAnchor") << QString("Chapter a") << 1 << QAccessible::Section; QTest::newRow("ax::mojom::Role::kApplication") << QString("
landmark
") << 0 << QAccessible::Document; QTest::newRow("ax::mojom::Role::kArticle") << QString("
a
") << 0 << QAccessible::Section; QTest::newRow("ax::mojom::Role::kAudio") << QString("") << 1 << QAccessible::Sound; QTest::newRow("ax::mojom::Role::kBanner") << QString("
a
") << 0 << QAccessible::Section; QTest::newRow("ax::mojom::Role::kBlockquote") << QString("
a
") << 0 << QAccessible::Section; QTest::newRow("ax::mojom::Role::kButton") << QString("") << 1 << QAccessible::Button; //QTest::newRow("ax::mojom::Role::kCanvas") << QString("") << 0 << QAccessible::Canvas; // FIXME: The test case might be wrong (see AXLayoutObject.cpp) QTest::newRow("ax::mojom::Role::kCaption") << QString("
a
") << 1 << QAccessible::Heading; //QTest::newRow("ax::mojom::Role::kCaret"); // No mapping to ARIA role QTest::newRow("ax::mojom::Role::kCell") << QString("
a
") << 2 << QAccessible::Cell; QTest::newRow("ax::mojom::Role::kCheckBox") << QString("a") << 1 << QAccessible::CheckBox; QTest::newRow("ax::mojom::Role::kClient") << QString("") << 0 << QAccessible::Client; QTest::newRow("ax::mojom::Role::kCode") << QString("a") << 1 << QAccessible::StaticText; QTest::newRow("ax::mojom::Role::kColorWell") << QString("a") << 1 << QAccessible::ColorChooser; //QTest::newRow("ax::mojom::Role::kColumn") << QString("
a
") << 0 << QAccessible::Column; // FIXME: The test case might be wrong (see AXTableColumn.h) QTest::newRow("ax::mojom::Role::kColumnHeader") << QString("
a
a
") << 2 << QAccessible::ColumnHeader; QTest::newRow("ax::mojom::Role::kComboBoxGrouping") << QString("
") << 0 << QAccessible::ComboBox; QTest::newRow("ax::mojom::Role::kComboBoxMenuButton") << QString("
Select
") << 0 << QAccessible::ComboBox; QTest::newRow("ax::mojom::Role::kTextFieldWithComboBox") << QString("") << 1 << QAccessible::ComboBox; QTest::newRow("ax::mojom::Role::kComplementary") << QString("") << 0 << QAccessible::ComplementaryContent; QTest::newRow("ax::mojom::Role::kComment") << QString("
") << 0 << QAccessible::Section; QTest::newRow("ax::mojom::Role::kContentDeletion") << QString("
") << 0 << QAccessible::Grouping; QTest::newRow("ax::mojom::Role::kContentInsertion") << QString("
") << 0 << QAccessible::Grouping; QTest::newRow("ax::mojom::Role::kContentInfo") << QString("
") << 0 << QAccessible::Section; QTest::newRow("ax::mojom::Role::kData") << QString("") << 1 << QAccessible::Clock; QTest::newRow("ax::mojom::Role::kDateTime") << QString("") << 1 << QAccessible::Clock; QTest::newRow("ax::mojom::Role::kDefinition") << QString("
landmark
") << 0 << QAccessible::Paragraph; QTest::newRow("ax::mojom::Role::kDescriptionList") << QString("
a
") << 0 << QAccessible::List; QTest::newRow("ax::mojom::Role::kDescriptionListDetail") << QString("
a
") << 0 << QAccessible::Paragraph; QTest::newRow("ax::mojom::Role::kDescriptionListTerm") << QString("
a
") << 0 << QAccessible::ListItem; QTest::newRow("ax::mojom::Role::kDetails") << QString("
a
") << 0 << QAccessible::Grouping; //QTest::newRow("ax::mojom::Role::kDesktop"); // No mapping to ARIA role QTest::newRow("ax::mojom::Role::kDialog") << QString("
") << 0 << QAccessible::Dialog; //QTest::newRow("ax::mojom::Role::kDirectory") << QString("
    ") << 0 << QAccessible::List; // FIXME: Aria role 'directory' should work QTest::newRow("ax::mojom::Role::kDisclosureTriangle") << QString("
    a
    ") << 1 << QAccessible::Button; QTest::newRow("ax::mojom::Role::kGenericContainer") << QString("
    a
    ") << 0 << QAccessible::Section; QTest::newRow("ax::mojom::Role::kDocCover") << QString("
    ") << 0 << QAccessible::Graphic; QTest::newRow("ax::mojom::Role::kDocBackLink") << QString("
    ") << 0 << QAccessible::Link; QTest::newRow("ax::mojom::Role::kDocBiblioRef") << QString("
    ") << 0 << QAccessible::Link; QTest::newRow("ax::mojom::Role::kDocGlossRef") << QString("
    ") << 0 << QAccessible::Link; QTest::newRow("ax::mojom::Role::kDocNoteRef") << QString("
    ") << 0 << QAccessible::Link; QTest::newRow("ax::mojom::Role::kDocBiblioEntry") << QString("
    ") << 0 << QAccessible::ListItem; QTest::newRow("ax::mojom::Role::kDocEndnote") << QString("
    ") << 0 << QAccessible::ListItem; QTest::newRow("ax::mojom::Role::kDocFootnote") << QString("
    ") << 0 << QAccessible::ListItem; QTest::newRow("ax::mojom::Role::kDocPageBreak") << QString("
    ") << 0 << QAccessible::Separator; QTest::newRow("ax::mojom::Role::kDocAbstract") << QString("
    ") << 0 << QAccessible::Section; QTest::newRow("ax::mojom::Role::kDocAcknowledgements") << QString("
    ") << 0 << QAccessible::Section; QTest::newRow("ax::mojom::Role::kDocAfterword") << QString("
    ") << 0 << QAccessible::Section; QTest::newRow("ax::mojom::Role::kDocAppendix") << QString("
    ") << 0 << QAccessible::Section; QTest::newRow("ax::mojom::Role::kDocBibliography") << QString("
    ") << 0 << QAccessible::Section; QTest::newRow("ax::mojom::Role::kDocChapter") << QString("
    ") << 0 << QAccessible::Section; QTest::newRow("ax::mojom::Role::kDocColophon") << QString("
    ") << 0 << QAccessible::Section; QTest::newRow("ax::mojom::Role::kDocConclusion") << QString("
    ") << 0 << QAccessible::Section; QTest::newRow("ax::mojom::Role::kDocCredit") << QString("
    ") << 0 << QAccessible::Section; QTest::newRow("ax::mojom::Role::kDocCredits") << QString("
    ") << 0 << QAccessible::Section; QTest::newRow("ax::mojom::Role::kDocDedication") << QString("
    ") << 0 << QAccessible::Section; QTest::newRow("ax::mojom::Role::kDocEndnotes") << QString("
    ") << 0 << QAccessible::Section; QTest::newRow("ax::mojom::Role::kDocEpigraph") << QString("
    ") << 0 << QAccessible::Section; QTest::newRow("ax::mojom::Role::kDocEpilogue") << QString("
    ") << 0 << QAccessible::Section; QTest::newRow("ax::mojom::Role::kDocErrata") << QString("
    ") << 0 << QAccessible::Section; QTest::newRow("ax::mojom::Role::kDocExample") << QString("
    ") << 0 << QAccessible::Section; QTest::newRow("ax::mojom::Role::kDocFooter") << QString("
    a
    ") << 0 << QAccessible::Footer; QTest::newRow("ax::mojom::Role::kDocForeword") << QString("
    ") << 0 << QAccessible::Section; QTest::newRow("ax::mojom::Role::kDocGlossary") << QString("
    ") << 0 << QAccessible::Section; QTest::newRow("ax::mojom::Role::kDocHeader") << QString("
    a
    ") << 0 << QAccessible::Heading; QTest::newRow("ax::mojom::Role::kDocIndex") << QString("
    ") << 0 << QAccessible::Section; QTest::newRow("ax::mojom::Role::kDocIntroduction") << QString("
    ") << 0 << QAccessible::Section; QTest::newRow("ax::mojom::Role::kDocNotice") << QString("
    ") << 0 << QAccessible::Section; QTest::newRow("ax::mojom::Role::kDocPageList") << QString("
    ") << 0 << QAccessible::Section; QTest::newRow("ax::mojom::Role::kDocPart") << QString("
    ") << 0 << QAccessible::Section; QTest::newRow("ax::mojom::Role::kDocPreface") << QString("
    ") << 0 << QAccessible::Section; QTest::newRow("ax::mojom::Role::kDocPrologue") << QString("
    ") << 0 << QAccessible::Section; QTest::newRow("ax::mojom::Role::kDocPullquote") << QString("
    ") << 0 << QAccessible::Section; QTest::newRow("ax::mojom::Role::kDocQna") << QString("
    ") << 0 << QAccessible::Section; QTest::newRow("ax::mojom::Role::kDocSubtitle") << QString("
    ") << 0 << QAccessible::Heading; QTest::newRow("ax::mojom::Role::kDocTip") << QString("
    ") << 0 << QAccessible::Section; QTest::newRow("ax::mojom::Role::kDocToc") << QString("
    ") << 0 << QAccessible::Section; QTest::newRow("ax::mojom::Role::kDocument") << QString("
    a
    ") << 0 << QAccessible::Document; QTest::newRow("ax::mojom::Role::kEmbeddedObject") << QString("") << 1 << QAccessible::Grouping; QTest::newRow("ax::mojom::Role::kEmphasis") << QString("a") << 1 << QAccessible::StaticText; QTest::newRow("ax::mojom::Role::kFeed") << QString("
    a
    ") << 0 << QAccessible::Section; QTest::newRow("ax::mojom::Role::kFigcaption") << QString("
    a
    ") << 0 << QAccessible::Heading; QTest::newRow("ax::mojom::Role::kFigure") << QString("
    a
    ") << 0 << QAccessible::Section; QTest::newRow("ax::mojom::Role::kFooter") << QString("
    a
    ") << 0 << QAccessible::Section; QTest::newRow("ax::mojom::Role::kFooterAsNonLandmark") << QString("
    a
    ") << 1 << QAccessible::Section; QTest::newRow("ax::mojom::Role::kForm") << QString("
    ") << 0 << QAccessible::Form; QTest::newRow("ax::mojom::Role::kGraphicsDocument") << QString("
    ") << 0 << QAccessible::Document; QTest::newRow("ax::mojom::Role::kGraphicsObject") << QString("
    ") << 0 << QAccessible::Pane; QTest::newRow("ax::mojom::Role::kGraphicsSymbol") << QString("
    ") << 0 << QAccessible::Graphic; QTest::newRow("ax::mojom::Role::kGrid") << QString("
    ") << 0 << QAccessible::Table; QTest::newRow("ax::mojom::Role::kGroup") << QString("
    ") << 0 << QAccessible::Grouping; QTest::newRow("ax::mojom::Role::Header") << QString("
    a
    ") << 0 << QAccessible::Section; QTest::newRow("ax::mojom::Role::HeaderAsNonLandMark") << QString("
    a
    ") << 1 << QAccessible::Section; QTest::newRow("ax::mojom::Role::kHeading") << QString("

    a

    ") << 0 << QAccessible::Heading; QTest::newRow("ax::mojom::Role::kIframe") << QString("") << 1 << QAccessible::WebDocument; QTest::newRow("ax::mojom::Role::kIframePresentational") << QString("") << 1 << QAccessible::Grouping; //QTest::newRow("ax::mojom::Role::kIgnored") << QString("a") << 0 << QAccessible::NoRole; // FIXME: The HTML element should not be exposed as an element (see AXNodeObject.cpp) QTest::newRow("ax::mojom::Role::kImage") << QString("") << 1 << QAccessible::Graphic; //QTest::newRow("ax::mojom::Role::kImageMap") << QString("") << 0 << QAccessible::Document; // FIXME: AXLayoutObject::DetermineAccessiblityRole returns kImageMap but something overrides it //QTest::newRow("ax::mojom::Role::kInlineTextBox"); // No mapping to ARIA role QTest::newRow("ax::mojom::Role::kInputTime") << QString("") << 1 << QAccessible::SpinBox; //QTest::newRow("ax::mojom::Role::kKeyboard"); // No mapping to ARIA role QTest::newRow("ax::mojom::Role::kLabelText") << QString("") << 1 << QAccessible::StaticText; QTest::newRow("ax::mojom::Role::kLayoutTable") << QString("
    ") << 0 << QAccessible::Section; QTest::newRow("ax::mojom::Role::kLayoutTableCell") << QString("
    ") << 2 << QAccessible::Section; //QTest::newRow("ax::mojom::Role::kLayoutTableColumn") << QString("
    ") << 1 << QAccessible::Section; // FIXME: The test case might be wrong QTest::newRow("ax::mojom::Role::kLayoutTableRow") << QString("
    ") << 1 << QAccessible::Section; QTest::newRow("ax::mojom::Role::kLegend") << QString("a") << 0 << QAccessible::StaticText; QTest::newRow("ax::mojom::Role::kLineBreak") << QString("
    ") << 1 << QAccessible::Separator; QTest::newRow("ax::mojom::Role::kLink") << QString("link") << 1 << QAccessible::Link; QTest::newRow("ax::mojom::Role::kList") << QString("
      ") << 0 << QAccessible::List; QTest::newRow("ax::mojom::Role::kListBox") << QString("") << 1 << QAccessible::ComboBox; QTest::newRow("ax::mojom::Role::kListBoxOption") << QString("") << 0 << QAccessible::ListItem; QTest::newRow("ax::mojom::Role::kListItem") << QString("
    • a
    • ") << 0 << QAccessible::ListItem; //QTest::newRow("ax::mojom::Role::kListGrid"); // No mapping to ARIA role QTest::newRow("ax::mojom::Role::kListMarker") << QString("
      • ") << 1 << QAccessible::StaticText; QTest::newRow("ax::mojom::Role::kLog") << QString("
        a
        ") << 0 << QAccessible::Section; QTest::newRow("ax::mojom::Role::kMain") << QString("
        a
        ") << 0 << QAccessible::Grouping; QTest::newRow("ax::mojom::Role::kMark") << QString("a") << 1 << QAccessible::StaticText; QTest::newRow("ax::mojom::Role::kMarquee") << QString("
        a
        ") << 0 << QAccessible::Section; QTest::newRow("ax::mojom::Role::kMath") << QString("a") << 1 << QAccessible::Equation; QTest::newRow("ax::mojom::Role::kMenu") << QString("
        a
        ") << 0 << QAccessible::PopupMenu; QTest::newRow("ax::mojom::Role::kMenuBar") << QString("
        a
        ") << 0 << QAccessible::MenuBar; QTest::newRow("ax::mojom::Role::kMenuItem") << QString("
        a
        ") << 1 << QAccessible::MenuItem; QTest::newRow("ax::mojom::Role::kMenuItemCheckBox") << QString("") << 1 << QAccessible::CheckBox; QTest::newRow("ax::mojom::Role::kMenuItemRadio") << QString("") << 1 << QAccessible::RadioButton; QTest::newRow("ax::mojom::Role::kMenuButton") << QString("") << 1 << QAccessible::Button; QTest::newRow("ax::mojom::Role::kMenuListOption") << QString("") << 3 << QAccessible::MenuItem; QTest::newRow("ax::mojom::Role::kMenuListPopup") << QString("") << 2 << QAccessible::PopupMenu; QTest::newRow("ax::mojom::Role::kMeter") << QString("a") << 1 << QAccessible::Chart; QTest::newRow("ax::mojom::Role::kNavigation") << QString("") << 0 << QAccessible::Section; QTest::newRow("ax::mojom::Role::kNote") << QString("
        a
        ") << 0 << QAccessible::Note; //QTest::newRow("ax::mojom::Role::kPane"); // No mapping to ARIA role QTest::newRow("ax::mojom::Role::kParagraph") << QString("

        a

        ") << 0 << QAccessible::Paragraph; QTest::newRow("ax::mojom::Role::kPopUpButton") << QString("") << 1 << QAccessible::ComboBox; QTest::newRow("ax::mojom::Role::kPre") << QString("
        a
        ") << 0 << QAccessible::Section; //QTest::newRow("ax::mojom::Role::kPresentational") << QString("
        a
        ") << 0 << QAccessible::NoRole; // FIXME: Aria role 'presentation' should work QTest::newRow("ax::mojom::Role::kProgressIndicator") << QString("
        ") << 0 << QAccessible::ProgressBar; QTest::newRow("ax::mojom::Role::kRadioButton") << QString("") << 1 << QAccessible::RadioButton; QTest::newRow("ax::mojom::Role::kRadioGroup") << QString("
        ") << 0 << QAccessible::Grouping; QTest::newRow("ax::mojom::Role::kRegion") << QString("
        a
        ") << 0 << QAccessible::Section; QTest::newRow("ax::mojom::Role::kRow") << QString("
        a
        ") << 1 << QAccessible::Row; QTest::newRow("ax::mojom::Role::kRowGroup") << QString("
        a
        ") << 1 << QAccessible::Section; QTest::newRow("ax::mojom::Role::kRowHeader") << QString("
        ab
        ") << 2 << QAccessible::RowHeader; QTest::newRow("ax::mojom::Role::kRuby") << QString("a") << 1 << QAccessible::Grouping; //QTest::newRow("ax::mojom::Role::kRubyAnnotation") // No mapping to ARIA role (presents as property on enclosing ruby element) QTest::newRow("ax::mojom::Role::kScrollBar") << QString("
        a") << 0 << QAccessible::ScrollBar; //QTest::newRow("ax::mojom::Role::kScrollView"); // No mapping to ARIA role QTest::newRow("ax::mojom::Role::kSearch") << QString("
        landmark
        ") << 0 << QAccessible::Section; QTest::newRow("ax::mojom::Role::kSearchBox") << QString("") << 1 << QAccessible::EditableText; QTest::newRow("ax::mojom::Role::kSection") << QString("
        ") << 0 << QAccessible::Section; QTest::newRow("ax::mojom::Role::kSlider") << QString("") << 1 << QAccessible::Slider; //QTest::newRow("ax::mojom::Role::kSliderThumb") << QString("") << 1 << QAccessible::Slider; // TODO: blink/renderer/modules/accessibility/ax_slider.cc QTest::newRow("ax::mojom::Role::kSpinButton") << QString("") << 1 << QAccessible::SpinBox; QTest::newRow("ax::mojom::Role::kSplitter") << QString("
        ") << 0 << QAccessible::Splitter; QTest::newRow("ax::mojom::Role::kStaticText") << QString("a") << 1 << QAccessible::StaticText; QTest::newRow("ax::mojom::Role::kStatus") << QString("a") << 1 << QAccessible::Indicator; QTest::newRow("ax::mojom::Role::kStrong") << QString("a") << 1 << QAccessible::StaticText; QTest::newRow("ax::mojom::Role::kSuggestion") << QString("
        ") << 0 << QAccessible::Section; QTest::newRow("ax::mojom::Role::kSvgRoot") << QString("SVG") << 1 << QAccessible::WebDocument; QTest::newRow("ax::mojom::Role::kSwitch") << QString("") << 1 << QAccessible::Button; QTest::newRow("ax::mojom::Role::kTable") << QString("
        a
        ") << 0 << QAccessible::Table; //QTest::newRow("ax::mojom::Role::kTableHeaderContainer"); // No mapping to ARIA role QTest::newRow("ax::mojom::Role::kTab") << QString("
        a
        ") << 0 << QAccessible::PageTab; QTest::newRow("ax::mojom::Role::kTabList") << QString("
        a
        ") << 0 << QAccessible::PageTabList; QTest::newRow("ax::mojom::Role::kTabPanel") << QString("
        a
        ") << 0 << QAccessible::Pane; QTest::newRow("ax::mojom::Role::kTerm") << QString("
        a
        ") << 0 << QAccessible::StaticText; QTest::newRow("ax::mojom::Role::kTextField") << QString("") << 1 << QAccessible::EditableText; QTest::newRow("ax::mojom::Role::kTime") << QString("") << 1 << QAccessible::Clock; QTest::newRow("ax::mojom::Role::kTimer") << QString("
        a
        ") << 0 << QAccessible::Clock; //QTest::newRow("ax::mojom::Role::kTitleBar"); // No mapping to ARIA role QTest::newRow("ax::mojom::Role::kToggleButton") << QString("") << 1 << QAccessible::Button; QTest::newRow("ax::mojom::Role::kToolbar") << QString("
        a
        ") << 0 << QAccessible::ToolBar; QTest::newRow("ax::mojom::Role::kToolTip") << QString("
        a
        ") << 0 << QAccessible::ToolTip; QTest::newRow("ax::mojom::Role::kTree") << QString("
        a
        ") << 0 << QAccessible::Tree; QTest::newRow("ax::mojom::Role::kTreeGrid") << QString("
        a
        ") << 0 << QAccessible::Tree; QTest::newRow("ax::mojom::Role::kTreeItem") << QString("
        a
        ") << 0 << QAccessible::TreeItem; QTest::newRow("ax::mojom::Role::kVideo") << QString("") << 1 << QAccessible::Animation; //QTest::newRow("ax::mojom::Role::kWindow"); // No mapping to ARIA role } void tst_Accessibility::roles() { QFETCH(QString, html); QFETCH(int, nested); QFETCH(QAccessible::Role, role); QWebEngineView webView; webView.setHtml("" + html + ""); webView.show(); QSignalSpy spyFinished(&webView, &QWebEngineView::loadFinished); QVERIFY(spyFinished.wait()); QAccessibleInterface *view = QAccessible::queryAccessibleInterface(&webView); // Corner case for Client role if (html.isEmpty()) { QCOMPARE(view->role(), QAccessible::Client); return; } QTRY_COMPARE(view->child(0)->childCount(), 1); QAccessibleInterface *document = view->child(0); QAccessibleInterface *element = document->child(0); while (nested--) { QTRY_VERIFY(element->child(0)); element = element->child(0); } QCOMPARE(element->role(), role); } void tst_Accessibility::objectName() { QWebEngineView webView; QSignalSpy spyFinished(&webView, &QWebEngineView::loadFinished); webView.setHtml("

        "); webView.show(); QVERIFY(spyFinished.wait()); QAccessibleInterface *view = QAccessible::queryAccessibleInterface(&webView); QAccessibleInterface *document = view->child(0); QTRY_COMPARE(document->childCount(), 1); QAccessibleInterface *p = document->child(0); QVERIFY(p); QVERIFY(p->object()); QCOMPARE(p->role(), QAccessible::Paragraph); QCOMPARE(p->object()->objectName(), QStringLiteral("my_id")); } void tst_Accessibility::crossTreeParent() { QWebEngineView webView; QSignalSpy spyFinished(&webView, &QWebEngineView::loadFinished); webView.setHtml(""); webView.show(); QVERIFY(spyFinished.wait()); QAccessibleInterface *view = QAccessible::queryAccessibleInterface(&webView); QAccessibleInterface *document = view->child(0); QCOMPARE(document->role(), QAccessible::WebDocument); QTRY_COMPARE(document->childCount(), 1); QAccessibleInterface *p = document->child(0); QVERIFY(p); QCOMPARE(p->parent(), document); p = p->child(0); QVERIFY(p); QCOMPARE(p->role(), QAccessible::WebDocument); QCOMPARE(p->parent()->parent(), document); QTRY_COMPARE(p->childCount(), 1); p = p->child(0); QVERIFY(p); QAccessibleInterface *subdocument = p; QCOMPARE(p->role(), QAccessible::WebDocument); QCOMPARE(p->parent()->parent()->parent(), document); p = p->child(0); QVERIFY(p); QVERIFY(p->object()); QCOMPARE(p->role(), QAccessible::Paragraph); QCOMPARE(p->parent(), subdocument); QCOMPARE(p->parent()->parent()->parent()->parent(), document); QCOMPARE(p->parent()->parent()->parent()->parent()->parent(), view); QCOMPARE(p->object()->objectName(), QStringLiteral("my_id")); } static QByteArrayList params = QByteArrayList() << "--force-renderer-accessibility" << "--enable-features=AccessibilityExposeARIAAnnotations"; W_QTEST_MAIN(tst_Accessibility, params) #include "tst_accessibility.moc"