1/****************************************************************************
2**
3** Copyright (C) 2016 The Qt Company Ltd.
4** Contact: https://www.qt.io/licensing/
5**
6** This file is part of the QtQml module of the Qt Toolkit.
7**
8** $QT_BEGIN_LICENSE:GPL-EXCEPT$
9** Commercial License Usage
10** Licensees holding valid commercial Qt licenses may use this file in
11** accordance with the commercial license agreement provided with the
12** Software or, alternatively, in accordance with the terms contained in
13** a written agreement between you and The Qt Company. For licensing terms
14** and conditions see https://www.qt.io/terms-conditions. For further
15** information use the contact form at https://www.qt.io/contact-us.
16**
17** GNU General Public License Usage
18** Alternatively, this file may be used under the terms of the GNU
19** General Public License version 3 as published by the Free Software
20** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
21** included in the packaging of this file. Please review the following
22** information to ensure the GNU General Public License requirements will
23** be met: https://www.gnu.org/licenses/gpl-3.0.html.
24**
25** $QT_END_LICENSE$
26**
27****************************************************************************/
28
29
30#include <QtTest/QtTest>
31#include <QtTest/qtestaccessible.h>
32
33#include <QtGui/qaccessible.h>
34#include <QtGui/private/qguiapplication_p.h>
35#include <qpa/qplatformnativeinterface.h>
36#include <qpa/qplatformintegration.h>
37#include <qpa/qplatformaccessibility.h>
38
39#include <QtQuick/qquickview.h>
40#include <QtQuick/qquickitem.h>
41
42#include <QtQml/qqmlengine.h>
43#include <QtQml/qqmlproperty.h>
44#include <QtQuick/private/qquickaccessibleattached_p.h>
45#include <QtQuick/private/qquicklistview_p.h>
46#include <QtQuick/private/qquicktext_p.h>
47
48#include "../../shared/util.h"
49#include "../shared/visualtestutil.h"
50
51#define EXPECT(cond) \
52 do { \
53 if (!errorAt && !(cond)) { \
54 errorAt = __LINE__; \
55 qWarning("level: %d, middle: %d, role: %d (%s)", treelevel, middle, iface->role(), #cond); \
56 } \
57 } while (0)
58
59
60//TESTED_FILES=
61
62class tst_QQuickAccessible : public QQmlDataTest
63{
64 Q_OBJECT
65public:
66 tst_QQuickAccessible();
67 virtual ~tst_QQuickAccessible();
68
69public slots:
70 void initTestCase();
71 void cleanupTestCase();
72 void init();
73 void cleanup();
74
75private slots:
76 void commonTests_data();
77 void commonTests();
78
79 void quickAttachedProperties();
80 void basicPropertiesTest();
81 void hitTest();
82 void checkableTest();
83 void ignoredTest();
84};
85
86tst_QQuickAccessible::tst_QQuickAccessible()
87{
88
89}
90
91tst_QQuickAccessible::~tst_QQuickAccessible()
92{
93
94}
95
96void tst_QQuickAccessible::initTestCase()
97{
98 QQmlDataTest::initTestCase();
99 QTestAccessibility::initialize();
100 QPlatformIntegration *pfIntegration = QGuiApplicationPrivate::platformIntegration();
101 if (!pfIntegration->accessibility())
102 QSKIP("This platform does not support accessibility");
103 pfIntegration->accessibility()->setActive(true);
104}
105
106void tst_QQuickAccessible::cleanupTestCase()
107{
108 QTestAccessibility::cleanup();
109}
110
111void tst_QQuickAccessible::init()
112{
113 QTestAccessibility::clearEvents();
114}
115
116void tst_QQuickAccessible::cleanup()
117{
118 const EventList list = QTestAccessibility::events();
119 if (!list.isEmpty()) {
120 qWarning(msg: "%d accessibility event(s) were not handled in testfunction '%s':", list.count(),
121 QString(QTest::currentTestFunction()).toLatin1().constData());
122 for (int i = 0; i < list.count(); ++i)
123 qWarning(msg: " %d: Object: %p Event: '%s' Child: %d", i + 1, list.at(i)->object(),
124 qAccessibleEventString(event: list.at(i)->type()), list.at(i)->child());
125 }
126 QTestAccessibility::clearEvents();
127}
128
129void tst_QQuickAccessible::commonTests_data()
130{
131 QTest::addColumn<QString>(name: "accessibleRoleFileName");
132
133 QTest::newRow(dataTag: "Text") << "text.qml";
134 QTest::newRow(dataTag: "PushButton") << "pushbutton.qml";
135}
136
137void tst_QQuickAccessible::commonTests()
138{
139 QFETCH(QString, accessibleRoleFileName);
140
141 qDebug() << "testing" << accessibleRoleFileName;
142
143 QQuickView *view = new QQuickView();
144// view->setFixedSize(240,320);
145 view->setSource(testFileUrl(fileName: accessibleRoleFileName));
146 view->show();
147// view->setFocus();
148 QVERIFY(view->rootObject() != nullptr);
149
150 QAccessibleInterface *iface = QAccessible::queryAccessibleInterface(view);
151 QVERIFY(iface);
152
153 delete view;
154 QTestAccessibility::clearEvents();
155}
156
157void tst_QQuickAccessible::quickAttachedProperties()
158{
159 {
160 QQmlEngine engine;
161 QQmlComponent component(&engine);
162 component.setData("import QtQuick 2.0\nItem {\n"
163 "}", baseUrl: QUrl());
164 QObject *object = component.create();
165 QVERIFY(object != nullptr);
166
167 QObject *attachedObject = QQuickAccessibleAttached::attachedProperties(obj: object);
168 QCOMPARE(attachedObject, static_cast<QObject*>(nullptr));
169 delete object;
170 }
171
172 // Attaching to non-item
173 {
174 QObject parent;
175 QTest::ignoreMessage(type: QtWarningMsg, message: "<Unknown File>: QML QtObject: Accessible must be attached to an Item");
176 QQuickAccessibleAttached *attachedObj = new QQuickAccessibleAttached(&parent);
177
178 QCOMPARE(attachedObj->ignored(), false);
179 attachedObj->setIgnored(true);
180 QCOMPARE(attachedObj->ignored(), false);
181 attachedObj->setIgnored(false);
182 QCOMPARE(attachedObj->ignored(), false);
183 }
184
185 // Attached property
186 {
187 QQuickItem parent;
188 QQuickAccessibleAttached *attachedObj = new QQuickAccessibleAttached(&parent);
189
190 attachedObj->name();
191
192 QVariant pp = attachedObj->property(name: "name");
193 QQmlEngine engine;
194 QQmlComponent component(&engine);
195 component.setData("import QtQuick 2.0\nItem {\n"
196 "Accessible.role: Accessible.Button\n"
197 "}", baseUrl: QUrl());
198 QObject *object = component.create();
199 QVERIFY(object != nullptr);
200
201 const auto attachedObject = qobject_cast<QQuickAccessibleAttached*>(
202 object: QQuickAccessibleAttached::attachedProperties(obj: object));
203 QVERIFY(attachedObject);
204 if (attachedObject) {
205 QVariant p = attachedObject->property(name: "role");
206 QCOMPARE(p.isNull(), false);
207 QCOMPARE(p.toInt(), int(QAccessible::PushButton));
208 p = attachedObject->property(name: "name");
209 QCOMPARE(p.isNull(), true);
210 p = attachedObject->property(name: "description");
211 QCOMPARE(p.isNull(), true);
212 QCOMPARE(attachedObject->wasNameExplicitlySet(), false);
213 }
214 delete object;
215 }
216
217 // Attached property
218 {
219 QQmlEngine engine;
220 QQmlComponent component(&engine);
221 component.setData("import QtQuick 2.0\nItem {\n"
222 "Accessible.role: Accessible.Button\n"
223 "Accessible.name: \"Donald\"\n"
224 "Accessible.description: \"Duck\"\n"
225 "}", baseUrl: QUrl());
226 QObject *object = component.create();
227 QVERIFY(object != nullptr);
228
229 const auto attachedObject = qobject_cast<QQuickAccessibleAttached*>(
230 object: QQuickAccessibleAttached::attachedProperties(obj: object));
231 QVERIFY(attachedObject);
232 if (attachedObject) {
233 QVariant p = attachedObject->property(name: "role");
234 QCOMPARE(p.isNull(), false);
235 QCOMPARE(p.toInt(), int(QAccessible::PushButton));
236 p = attachedObject->property(name: "name");
237 QCOMPARE(p.isNull(), false);
238 QCOMPARE(p.toString(), QLatin1String("Donald"));
239 p = attachedObject->property(name: "description");
240 QCOMPARE(p.isNull(), false);
241 QCOMPARE(p.toString(), QLatin1String("Duck"));
242 QCOMPARE(attachedObject->wasNameExplicitlySet(), true);
243 }
244 delete object;
245 }
246
247 // Check overriding of attached role for Text
248 {
249 QQmlEngine engine;
250 QQmlComponent component(&engine);
251 component.setData("import QtQuick 2.0\nText {\n"
252 "Accessible.role: Accessible.Button\n"
253 "Accessible.name: \"TextButton\"\n"
254 "Accessible.description: \"Text Button\"\n"
255 "}", baseUrl: QUrl());
256 QObject *object = component.create();
257 QVERIFY(object != nullptr);
258
259 QObject *attachedObject = QQuickAccessibleAttached::attachedProperties(obj: object);
260 QVERIFY(attachedObject);
261 if (attachedObject) {
262 QVariant p = attachedObject->property(name: "role");
263 QCOMPARE(p.isNull(), false);
264 QCOMPARE(p.toInt(), int(QAccessible::PushButton));
265 p = attachedObject->property(name: "name");
266 QCOMPARE(p.isNull(), false);
267 QCOMPARE(p.toString(), QLatin1String("TextButton"));
268 p = attachedObject->property(name: "description");
269 QCOMPARE(p.isNull(), false);
270 QCOMPARE(p.toString(), QLatin1String("Text Button"));
271 }
272 delete object;
273 }
274 // Check overriding of attached role for Text
275 {
276 QQmlEngine engine;
277 QQmlComponent component(&engine);
278 component.setData("import QtQuick 2.0\nListView {\n"
279 "id: list\n"
280 "model: 5\n"
281 "delegate: Text {\n"
282 "objectName: \"acc_text\"\n"
283 "Accessible.role: Accessible.Button\n"
284 "Accessible.name: \"TextButton\"\n"
285 "Accessible.description: \"Text Button\"\n"
286 "}\n"
287 "}", baseUrl: QUrl());
288 QObject *object = component.create();
289 QVERIFY(object != nullptr);
290
291 QQuickListView *listview = qobject_cast<QQuickListView *>(object);
292 QVERIFY(listview != nullptr);
293 QQuickItem *contentItem = listview->contentItem();
294 QQuickText *childItem = QQuickVisualTestUtil::findItem<QQuickText>(parent: contentItem, objectName: "acc_text");
295 QVERIFY(childItem != nullptr);
296
297 QObject *attachedObject = QQuickAccessibleAttached::attachedProperties(obj: childItem);
298 QVERIFY(attachedObject);
299 if (attachedObject) {
300 QVariant p = attachedObject->property(name: "role");
301 QCOMPARE(p.isNull(), false);
302 QCOMPARE(p.toInt(), int(QAccessible::PushButton));
303 p = attachedObject->property(name: "name");
304 QCOMPARE(p.isNull(), false);
305 QCOMPARE(p.toString(), QLatin1String("TextButton"));
306 p = attachedObject->property(name: "description");
307 QCOMPARE(p.isNull(), false);
308 QCOMPARE(p.toString(), QLatin1String("Text Button"));
309 }
310 delete object;
311 }
312 // Check that a name can be implicitly set.
313 {
314 QQmlEngine engine;
315 QQmlComponent component(&engine);
316 component.setData(R"(
317 import QtQuick 2.0
318 Text {
319 Accessible.role: Accessible.Button
320 Accessible.description: "Text Button"
321 })", baseUrl: QUrl());
322 QScopedPointer<QObject> object(component.create());
323 QVERIFY(object);
324
325 const auto attachedObject = qobject_cast<QQuickAccessibleAttached*>(
326 object: QQuickAccessibleAttached::attachedProperties(obj: object.data()));
327 QVERIFY(attachedObject);
328 QVERIFY(!attachedObject->wasNameExplicitlySet());
329
330 attachedObject->setNameImplicitly(QLatin1String("Implicit"));
331 QCOMPARE(attachedObject->name(), QLatin1String("Implicit"));
332 QVERIFY(!attachedObject->wasNameExplicitlySet());
333
334 attachedObject->setName(QLatin1String("Explicit"));
335 QCOMPARE(attachedObject->name(), QLatin1String("Explicit"));
336 QVERIFY(attachedObject->wasNameExplicitlySet());
337 }
338 QTestAccessibility::clearEvents();
339}
340
341
342void tst_QQuickAccessible::basicPropertiesTest()
343{
344 QAccessibleInterface *app = QAccessible::queryAccessibleInterface(qApp);
345 QCOMPARE(app->childCount(), 0);
346
347 QQuickView *window = new QQuickView();
348 window->setSource(testFileUrl(fileName: "text.qml"));
349 window->show();
350 QCOMPARE(app->childCount(), 1);
351
352 QAccessibleInterface *iface = QAccessible::queryAccessibleInterface(window);
353 QVERIFY(iface);
354 QCOMPARE(iface->childCount(), 1);
355
356 QAccessibleInterface *item = iface->child(index: 0);
357 QVERIFY(item);
358 QCOMPARE(item->childCount(), 5);
359 QCOMPARE(item->rect().size(), QSize(400, 400));
360 QCOMPARE(item->role(), QAccessible::Client);
361 QCOMPARE(iface->indexOfChild(item), 0);
362
363 QAccessibleInterface *text = item->child(index: 0);
364 QVERIFY(text);
365 QCOMPARE(text->childCount(), 0);
366
367 QCOMPARE(text->text(QAccessible::Name), QLatin1String("Hello Accessibility"));
368 QCOMPARE(text->rect().size(), QSize(200, 50));
369 QCOMPARE(text->rect().x(), item->rect().x() + 100);
370 QCOMPARE(text->rect().y(), item->rect().y() + 20);
371 QCOMPARE(text->role(), QAccessible::StaticText);
372 QCOMPARE(item->indexOfChild(text), 0);
373
374 QAccessibleInterface *text2 = item->child(index: 1);
375 QVERIFY(text2);
376 QCOMPARE(text2->childCount(), 0);
377
378 QCOMPARE(text2->text(QAccessible::Name), QLatin1String("The Hello 2 accessible text"));
379 QCOMPARE(text2->rect().size(), QSize(100, 40));
380 QCOMPARE(text2->rect().x(), item->rect().x() + 100);
381 QCOMPARE(text2->rect().y(), item->rect().y() + 40);
382 QCOMPARE(text2->role(), QAccessible::StaticText);
383 QCOMPARE(item->indexOfChild(text2), 1);
384 QCOMPARE(text2->state().editable, 0u);
385 QCOMPARE(text2->state().readOnly, 1);
386 QCOMPARE(text2->state().focusable, 1);
387
388 QCOMPARE(iface->indexOfChild(text2), -1);
389 QCOMPARE(text2->indexOfChild(item), -1);
390
391 // TextInput
392 QAccessibleInterface *textInput = item->child(index: 2);
393 QVERIFY(textInput);
394 QCOMPARE(textInput->childCount(), 0);
395 QCOMPARE(textInput->role(), QAccessible::EditableText);
396 QCOMPARE(textInput->state().editable, 1);
397 QCOMPARE(textInput->state().readOnly, 0);
398 QCOMPARE(textInput->state().multiLine, 0);
399 QCOMPARE(textInput->state().focusable, 1);
400 QCOMPARE(textInput->text(QAccessible::Value), "A text input");
401 auto textInterface = textInput->textInterface();
402 QVERIFY(textInterface);
403 auto editableTextInterface = textInput->editableTextInterface();
404 QEXPECT_FAIL("", "EditableTextInterface is not implemented", Continue);
405 QVERIFY(editableTextInterface);
406 auto newText = QString("a new text");
407 textInput->setText(t: QAccessible::Value, text: newText);
408 QCOMPARE(textInput->text(QAccessible::Value), newText);
409
410 // TextEdit
411 QAccessibleInterface *textEdit = item->child(index: 3);
412 QVERIFY(textEdit);
413 QCOMPARE(textEdit->childCount(), 0);
414 QCOMPARE(textEdit->role(), QAccessible::EditableText);
415 QCOMPARE(textEdit->state().editable, 1);
416 QCOMPARE(textEdit->state().readOnly, 0);
417 QCOMPARE(textEdit->state().focusable, 1);
418 QCOMPARE(textEdit->text(QAccessible::Value), "A multi-line text edit\nTesting Accessibility.");
419 auto textEditTextInterface = textEdit->textInterface();
420 QVERIFY(textEditTextInterface);
421 auto textEditEditableTextInterface = textEdit->editableTextInterface();
422 QEXPECT_FAIL("", "EditableTextInterface is not implemented", Continue);
423 QVERIFY(textEditEditableTextInterface);
424 textEdit->setText(t: QAccessible::Value, text: newText);
425 QCOMPARE(textEdit->text(QAccessible::Value), newText);
426 QEXPECT_FAIL("", "multi line is not implemented", Continue);
427 QCOMPARE(textInput->state().multiLine, 1);
428
429 // Text "Hello 3"
430 QAccessibleInterface *text3 = item->child(index: 4);
431 QVERIFY(text3);
432 QCOMPARE(text3->childCount(), 0);
433 QCOMPARE(text3->text(QAccessible::Name), QLatin1String("Hello 3"));
434 QCOMPARE(text3->role(), QAccessible::StaticText);
435 QCOMPARE(item->indexOfChild(text3), 4);
436 QCOMPARE(text3->state().editable, 0);
437 QCOMPARE(text3->state().readOnly, 0);
438 // test implicit state values due to role change
439 QQuickAccessibleAttached *attached = QQuickAccessibleAttached::attachedProperties(obj: text3->object());
440 attached->setRole(QAccessible::StaticText);
441 QCOMPARE(text3->role(), QAccessible::StaticText);
442 QCOMPARE(text3->state().readOnly, 1);
443
444 // see if implicit changes back
445 attached->setRole(QAccessible::EditableText);
446 QEXPECT_FAIL("", "EditableText does not implicitly set readOnly to false", Continue);
447 QCOMPARE(text3->state().readOnly, 0);
448 // explicitly set state
449 attached->set_readOnly(false);
450 attached->setRole(QAccessible::StaticText);
451 QCOMPARE(text3->state().readOnly, 0);
452
453 delete window;
454 QTestAccessibility::clearEvents();
455}
456
457QAccessibleInterface *topLevelChildAt(QAccessibleInterface *iface, int x, int y)
458{
459 QAccessibleInterface *child = iface->childAt(x, y);
460 if (!child)
461 return nullptr;
462
463 QAccessibleInterface *childOfChild;
464 while ( ( childOfChild = child->childAt(x, y)) ) {
465 child = childOfChild;
466 }
467 return child;
468}
469
470void tst_QQuickAccessible::hitTest()
471{
472 QQuickView *window = new QQuickView;
473 window->setSource(testFileUrl(fileName: "hittest.qml"));
474 window->show();
475
476 QAccessibleInterface *windowIface = QAccessible::queryAccessibleInterface(window);
477 QVERIFY(windowIface);
478 QAccessibleInterface *rootItem = windowIface->child(index: 0);
479 QRect rootRect = rootItem->rect();
480
481 // check the root item from app
482 QAccessibleInterface *appIface = QAccessible::queryAccessibleInterface(qApp);
483 QVERIFY(appIface);
484 QAccessibleInterface *itemHit = appIface->childAt(x: rootRect.x() + 200, y: rootRect.y() + 50);
485 QVERIFY(itemHit);
486 QCOMPARE(itemHit->rect(), rootRect);
487
488 QAccessibleInterface *rootItemIface;
489 for (int c = 0; c < rootItem->childCount(); ++c) {
490 QAccessibleInterface *iface = rootItem->child(index: c);
491 QString name = iface->text(t: QAccessible::Name);
492 if (name == QLatin1String("rect1")) {
493 // hit rect1
494 QAccessibleInterface *rect1 = iface;
495 QRect rect1Rect = rect1->rect();
496 QAccessibleInterface *rootItemIface = rootItem->childAt(x: rect1Rect.x() + 10, y: rect1Rect.y() + 10);
497 QVERIFY(rootItemIface);
498 QCOMPARE(rect1Rect, rootItemIface->rect());
499 QCOMPARE(rootItemIface->text(QAccessible::Name), QLatin1String("rect1"));
500
501 // should also work from top level (app)
502 QAccessibleInterface *app(QAccessible::queryAccessibleInterface(qApp));
503 QAccessibleInterface *itemHit2(topLevelChildAt(iface: app, x: rect1Rect.x() + 10, y: rect1Rect.y() + 10));
504 QVERIFY(itemHit2);
505 QCOMPARE(itemHit2->rect(), rect1Rect);
506 QCOMPARE(itemHit2->text(QAccessible::Name), QLatin1String("rect1"));
507 } else if (name == QLatin1String("rect2")) {
508 QAccessibleInterface *rect2 = iface;
509 // FIXME: This is seems broken on OS X
510 // QCOMPARE(rect2->rect().translated(rootItem->rect().x(), rootItem->rect().y()), QRect(0, 50, 100, 100));
511 QAccessibleInterface *rect20 = rect2->child(index: 0);
512 QVERIFY(rect20);
513 QCOMPARE(rect20->text(QAccessible::Name), QLatin1String("rect20"));
514 QPoint p = rect20->rect().bottomRight() + QPoint(20, 20);
515 QAccessibleInterface *rect201 = rect20->childAt(x: p.x(), y: p.y());
516 QVERIFY(rect201);
517 QCOMPARE(rect201->text(QAccessible::Name), QLatin1String("rect201"));
518 rootItemIface = topLevelChildAt(iface: windowIface, x: p.x(), y: p.y());
519 QVERIFY(rootItemIface);
520 QCOMPARE(rootItemIface->text(QAccessible::Name), QLatin1String("rect201"));
521
522 }
523 }
524
525 delete window;
526 QTestAccessibility::clearEvents();
527}
528
529void tst_QQuickAccessible::checkableTest()
530{
531 QScopedPointer<QQuickView> window(new QQuickView());
532 window->setSource(testFileUrl(fileName: "checkbuttons.qml"));
533 window->show();
534
535 QQuickItem *contentItem = window->contentItem();
536 QVERIFY(contentItem);
537 QQuickItem *rootItem = contentItem->childItems().first();
538 QVERIFY(rootItem);
539
540 // the window becomes active
541 QAccessible::State activatedChange;
542 activatedChange.active = true;
543
544 QAccessibleInterface *iface = QAccessible::queryAccessibleInterface(window.data());
545 QVERIFY(iface);
546 QAccessibleInterface *root = iface->child(index: 0);
547
548 QAccessibleInterface *button1 = root->child(index: 0);
549 QCOMPARE(button1->role(), QAccessible::Button);
550 QVERIFY(!(button1->state().checked));
551 QVERIFY(!(button1->state().checkable));
552
553 QVERIFY(button1->state().focusable);
554 QVERIFY(!button1->state().focused);
555
556 QTestAccessibility::clearEvents();
557
558 // set properties
559 QQuickItem *button1item = qobject_cast<QQuickItem*>(object: rootItem->childItems().at(i: 0));
560 QVERIFY(button1item);
561 QCOMPARE(button1item->objectName(), QLatin1String("button1"));
562 button1item->forceActiveFocus();
563 QVERIFY(button1->state().focusable);
564 QVERIFY(button1->state().focused);
565
566 QAccessibleEvent focusEvent(button1item, QAccessible::Focus);
567 QVERIFY_EVENT(&focusEvent);
568
569 QAccessibleInterface *button2 = root->child(index: 1);
570 QVERIFY(!(button2->state().checked));
571 QVERIFY(button2->state().checkable);
572 QQuickItem *button2item = qobject_cast<QQuickItem*>(object: rootItem->childItems().at(i: 1));
573 QVERIFY(button2item);
574 QCOMPARE(button2item->objectName(), QLatin1String("button2"));
575
576 QAccessibleInterface *button3 = root->child(index: 2);
577 QVERIFY(button3->state().checked);
578 QVERIFY(button3->state().checkable);
579
580 QAccessibleInterface *checkBox1 = root->child(index: 3);
581 QCOMPARE(checkBox1->role(), QAccessible::CheckBox);
582 QVERIFY(checkBox1->state().checked);
583 QVERIFY(checkBox1->state().checkable);
584 QQuickItem *checkbox1item = qobject_cast<QQuickItem*>(object: rootItem->childItems().at(i: 3));
585 QVERIFY(checkbox1item);
586 QCOMPARE(checkbox1item->objectName(), QLatin1String("checkbox1"));
587
588 checkbox1item->setProperty(name: "checked", value: false);
589 QVERIFY(!checkBox1->state().checked);
590 QAccessible::State checkState;
591 checkState.checked = true;
592 QAccessibleStateChangeEvent checkChanged(checkbox1item, checkState);
593 QVERIFY_EVENT(&checkChanged);
594
595 checkbox1item->setProperty(name: "checked", value: true);
596 QVERIFY(checkBox1->state().checked);
597 QVERIFY_EVENT(&checkChanged);
598
599 QAccessibleInterface *checkBox2 = root->child(index: 4);
600 QVERIFY(!(checkBox2->state().checked));
601 QVERIFY(checkBox2->state().checkable);
602
603 QTestAccessibility::clearEvents();
604}
605
606void tst_QQuickAccessible::ignoredTest()
607{
608 QScopedPointer<QQuickView> window(new QQuickView());
609 window->setSource(testFileUrl(fileName: "ignored.qml"));
610 window->show();
611
612 QQuickItem *contentItem = window->contentItem();
613 QVERIFY(contentItem);
614 QQuickItem *rootItem = contentItem->childItems().first();
615 QVERIFY(rootItem);
616
617 // the window becomes active
618 QAccessible::State activatedChange;
619 activatedChange.active = true;
620
621 QAccessibleInterface *iface = QAccessible::queryAccessibleInterface(window.data());
622 QVERIFY(iface);
623 QAccessibleInterface *rectangleA = iface->child(index: 0);
624
625 QCOMPARE(rectangleA->role(), QAccessible::StaticText);
626 QCOMPARE(rectangleA->text(QAccessible::Name), QLatin1String("A"));
627 static const char *expected = "BEFIHD";
628 // check if node "C" and "G" is skipped and that the order is as expected.
629 for (int i = 0; i < rectangleA->childCount(); ++i) {
630 QAccessibleInterface *child = rectangleA->child(index: i);
631 QCOMPARE(child->text(QAccessible::Name), QString(QLatin1Char(expected[i])));
632 }
633 QTestAccessibility::clearEvents();
634}
635
636QTEST_MAIN(tst_QQuickAccessible)
637
638#include "tst_qquickaccessible.moc"
639

source code of qtdeclarative/tests/auto/quick/qquickaccessible/tst_qquickaccessible.cpp