forked from mirrors/gecko-dev
Bug 1644810: Implement accessible subclasses for AXOutline and AXOutlineItem r=eeejay
Differential Revision: https://phabricator.services.mozilla.com/D96074
This commit is contained in:
parent
375f1764b4
commit
e45400e5b3
9 changed files with 655 additions and 1 deletions
|
|
@ -328,6 +328,13 @@ Class a11y::GetTypeFromRole(roles::Role aRole) {
|
|||
case roles::SUMMARY:
|
||||
return [MOXSummaryAccessible class];
|
||||
|
||||
case roles::OUTLINE:
|
||||
case roles::TREE_TABLE:
|
||||
return [mozOutlineAccessible class];
|
||||
|
||||
case roles::OUTLINEITEM:
|
||||
return [mozOutlineRowAccessible class];
|
||||
|
||||
default:
|
||||
return [mozAccessible class];
|
||||
}
|
||||
|
|
|
|||
|
|
@ -211,6 +211,23 @@
|
|||
// AXIdentifier
|
||||
- (NSString* _Nullable)moxIdentifier;
|
||||
|
||||
// Outline Attributes
|
||||
|
||||
// AXDisclosing
|
||||
- (NSNumber* _Nullable)moxDisclosing;
|
||||
|
||||
// AXDisclosedByRow
|
||||
- (id _Nullable)moxDisclosedByRow;
|
||||
|
||||
// AXDisclosureLevel
|
||||
- (NSNumber* _Nullable)moxDisclosureLevel;
|
||||
|
||||
// AXDisclosedRows
|
||||
- (NSArray* _Nullable)moxDisclosedRows;
|
||||
|
||||
// AXSelectedRows
|
||||
- (NSArray* _Nullable)moxSelectedRows;
|
||||
|
||||
// Math Attributes
|
||||
|
||||
// AXMathRootRadicand
|
||||
|
|
|
|||
|
|
@ -112,3 +112,14 @@ class RotorHeadingLevelRule : public RotorRoleRule {
|
|||
private:
|
||||
int32_t mLevel;
|
||||
};
|
||||
|
||||
/**
|
||||
* This rule matches all accessibles with roles::OUTLINEITEM. If
|
||||
* outlines are nested, it ignores the nested subtree and returns
|
||||
* only items which are descendants of the primary outline.
|
||||
*/
|
||||
class OutlineRule : public RotorRule {
|
||||
public:
|
||||
explicit OutlineRule();
|
||||
uint16_t Match(const AccessibleOrProxy& aAccOrProxy) override;
|
||||
};
|
||||
|
|
|
|||
|
|
@ -307,3 +307,27 @@ uint16_t RotorHeadingLevelRule::Match(const AccessibleOrProxy& aAccOrProxy) {
|
|||
|
||||
return result;
|
||||
}
|
||||
|
||||
// Outline Rule
|
||||
|
||||
OutlineRule::OutlineRule() : RotorRule(){};
|
||||
|
||||
uint16_t OutlineRule::Match(const AccessibleOrProxy& aAccOrProxy) {
|
||||
uint16_t result = RotorRule::Match(aAccOrProxy);
|
||||
|
||||
// if a match was found in the base-class's Match function,
|
||||
// it is valid to consider that match again here.
|
||||
if (result & nsIAccessibleTraversalRule::FILTER_MATCH) {
|
||||
if (aAccOrProxy.Role() == roles::OUTLINE) {
|
||||
// if the match is an outline, we ignore all children here
|
||||
// and unmatch the outline itself
|
||||
result &= ~nsIAccessibleTraversalRule::FILTER_MATCH;
|
||||
result |= nsIAccessibleTraversalRule::FILTER_IGNORE_SUBTREE;
|
||||
} else if (aAccOrProxy.Role() != roles::OUTLINEITEM) {
|
||||
// if the match is not an outline item, we unmatch here
|
||||
result &= ~nsIAccessibleTraversalRule::FILTER_MATCH;
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -167,7 +167,7 @@ static const uint64_t kCacheInitialized = ((uint64_t)0x1) << 63;
|
|||
// They may be named explicitly, but they still provide a label not a title.
|
||||
return mRole == roles::GROUPING || mRole == roles::RADIO_GROUP ||
|
||||
mRole == roles::FIGURE || mRole == roles::GRAPHIC ||
|
||||
mRole == roles::DOCUMENT;
|
||||
mRole == roles::DOCUMENT || mRole == roles::OUTLINE;
|
||||
}
|
||||
|
||||
- (mozilla::a11y::AccessibleOrProxy)geckoAccessible {
|
||||
|
|
|
|||
|
|
@ -113,3 +113,41 @@
|
|||
- (NSArray*)moxColumnHeaderUIElements;
|
||||
|
||||
@end
|
||||
|
||||
@interface mozOutlineAccessible : mozAccessible
|
||||
|
||||
// override
|
||||
- (NSArray*)moxRows;
|
||||
|
||||
// override
|
||||
- (NSArray*)moxColumns;
|
||||
|
||||
// override
|
||||
- (NSArray*)moxSelectedRows;
|
||||
|
||||
@end
|
||||
|
||||
@interface mozOutlineRowAccessible : mozTableRowAccessible
|
||||
|
||||
// override
|
||||
- (BOOL)isLayoutTablePart;
|
||||
|
||||
// override
|
||||
- (NSNumber*)moxDisclosing;
|
||||
|
||||
// override
|
||||
- (id)moxDisclosedByRow;
|
||||
|
||||
// override
|
||||
- (NSNumber*)moxDisclosureLevel;
|
||||
|
||||
// override
|
||||
- (NSArray*)moxDisclosedRows;
|
||||
|
||||
// override
|
||||
- (NSNumber*)moxIndex;
|
||||
|
||||
// override
|
||||
- (NSString*)moxLabel;
|
||||
|
||||
@end
|
||||
|
|
|
|||
|
|
@ -8,11 +8,14 @@
|
|||
#import "mozTableAccessible.h"
|
||||
#import "nsCocoaUtils.h"
|
||||
#import "MacUtils.h"
|
||||
#import "RotorRules.h"
|
||||
|
||||
#include "AccIterator.h"
|
||||
#include "Accessible.h"
|
||||
#include "TableAccessible.h"
|
||||
#include "TableCellAccessible.h"
|
||||
#include "Pivot.h"
|
||||
#include "Relation.h"
|
||||
|
||||
using namespace mozilla;
|
||||
using namespace mozilla::a11y;
|
||||
|
|
@ -127,6 +130,9 @@ using namespace mozilla::a11y;
|
|||
- (BOOL)isLayoutTablePart {
|
||||
if (Accessible* acc = mGeckoAccessible.AsAccessible()) {
|
||||
while (acc) {
|
||||
if (acc->Role() == roles::TREE_TABLE) {
|
||||
return false;
|
||||
}
|
||||
if (acc->IsTable()) {
|
||||
return acc->AsTable()->IsProbablyLayoutTable();
|
||||
}
|
||||
|
|
@ -137,6 +143,9 @@ using namespace mozilla::a11y;
|
|||
|
||||
if (ProxyAccessible* proxy = mGeckoAccessible.AsProxy()) {
|
||||
while (proxy) {
|
||||
if (proxy->Role() == roles::TREE_TABLE) {
|
||||
return false;
|
||||
}
|
||||
if (proxy->IsTable()) {
|
||||
return proxy->TableIsProbablyForLayout();
|
||||
}
|
||||
|
|
@ -379,3 +388,174 @@ using namespace mozilla::a11y;
|
|||
}
|
||||
|
||||
@end
|
||||
|
||||
@implementation mozOutlineAccessible
|
||||
|
||||
- (NSArray*)moxRows {
|
||||
// Create a new array with the list of outline rows. We
|
||||
// use pivot here to do a deep traversal of all rows nested
|
||||
// in this outline, not just those which are direct
|
||||
// children, since that's what VO expects.
|
||||
NSMutableArray* allRows = [[NSMutableArray alloc] init];
|
||||
Pivot p = Pivot(mGeckoAccessible);
|
||||
OutlineRule rule = OutlineRule();
|
||||
AccessibleOrProxy firstChild = mGeckoAccessible.FirstChild();
|
||||
AccessibleOrProxy match = p.Next(firstChild, rule, true);
|
||||
while (!match.IsNull()) {
|
||||
[allRows addObject:GetNativeFromGeckoAccessible(match)];
|
||||
match = p.Next(match, rule);
|
||||
}
|
||||
return allRows;
|
||||
}
|
||||
|
||||
- (NSArray*)moxColumns {
|
||||
// Webkit says we shouldn't do anything here
|
||||
return @[];
|
||||
}
|
||||
|
||||
- (NSArray*)moxSelectedRows {
|
||||
NSMutableArray* selectedRows = [[NSMutableArray alloc] init];
|
||||
NSArray* allRows = [self moxRows];
|
||||
for (mozAccessible* row in allRows) {
|
||||
if ([row stateWithMask:states::SELECTED] != 0) {
|
||||
[selectedRows addObject:row];
|
||||
}
|
||||
}
|
||||
|
||||
return selectedRows;
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@implementation mozOutlineRowAccessible
|
||||
|
||||
- (BOOL)isLayoutTablePart {
|
||||
return NO;
|
||||
}
|
||||
|
||||
- (NSNumber*)moxDisclosing {
|
||||
return @([self stateWithMask:states::EXPANDED] != 0);
|
||||
}
|
||||
|
||||
- (id)moxDisclosedByRow {
|
||||
// According to webkit: this attr corresponds to the row
|
||||
// that contains this row. It should be the same as the
|
||||
// first parent that is a treeitem. If the parent is the tree
|
||||
// itself, this should be nil. This is tricky for xul trees because
|
||||
// all rows are direct children of the outline; they use
|
||||
// relations to expose their heirarchy structure.
|
||||
|
||||
mozAccessible* disclosingRow = nil;
|
||||
// first we check the relations to see if we're in a xul tree
|
||||
// with weird row semantics
|
||||
if (mGeckoAccessible.IsAccessible()) {
|
||||
Relation rel = mGeckoAccessible.AsAccessible()->RelationByType(
|
||||
RelationType::NODE_CHILD_OF);
|
||||
Accessible* maybeParent = rel.Next();
|
||||
disclosingRow =
|
||||
maybeParent ? GetNativeFromGeckoAccessible(maybeParent) : nil;
|
||||
} else {
|
||||
nsTArray<ProxyAccessible*> accs =
|
||||
mGeckoAccessible.AsProxy()->RelationByType(RelationType::NODE_CHILD_OF);
|
||||
disclosingRow =
|
||||
accs.Length() > 0 ? GetNativeFromGeckoAccessible(accs[0]) : nil;
|
||||
}
|
||||
|
||||
if (disclosingRow) {
|
||||
// if we find a row from our relation check,
|
||||
// verify it isn't the outline itself and return
|
||||
// appropriately
|
||||
if ([[disclosingRow moxRole] isEqualToString:@"AXOutline"]) {
|
||||
return nil;
|
||||
}
|
||||
|
||||
return disclosingRow;
|
||||
}
|
||||
mozAccessible* parent = (mozAccessible*)[self moxUnignoredParent];
|
||||
// otherwise, its likely we're in an aria tree, so we can use
|
||||
// these role and subrole checks
|
||||
if ([[parent moxRole] isEqualToString:@"AXOutline"]) {
|
||||
return nil;
|
||||
}
|
||||
|
||||
if ([[parent moxSubrole] isEqualToString:@"AXOutlineRow"]) {
|
||||
disclosingRow = parent;
|
||||
}
|
||||
|
||||
return nil;
|
||||
}
|
||||
|
||||
- (NSNumber*)moxDisclosureLevel {
|
||||
GroupPos groupPos;
|
||||
if (Accessible* acc = mGeckoAccessible.AsAccessible()) {
|
||||
groupPos = acc->GroupPosition();
|
||||
} else if (ProxyAccessible* proxy = mGeckoAccessible.AsProxy()) {
|
||||
groupPos = proxy->GroupPosition();
|
||||
}
|
||||
|
||||
return @(groupPos.level);
|
||||
}
|
||||
|
||||
- (NSArray*)moxDisclosedRows {
|
||||
// According to webkit: this attr corresponds to the rows
|
||||
// that are considered inside this row. Again, this is weird for
|
||||
// xul trees so we have to use relations first and then fall-back
|
||||
// to the children filter for non-xul outlines.
|
||||
|
||||
NSMutableArray* disclosedRows = [[NSMutableArray alloc] init];
|
||||
// first we check the relations to see if we're in a xul tree
|
||||
// with weird row semantics
|
||||
if (mGeckoAccessible.IsAccessible()) {
|
||||
Relation rel = mGeckoAccessible.AsAccessible()->RelationByType(
|
||||
RelationType::NODE_PARENT_OF);
|
||||
Accessible* acc = nullptr;
|
||||
while ((acc = rel.Next())) {
|
||||
[disclosedRows addObject:GetNativeFromGeckoAccessible(acc)];
|
||||
}
|
||||
} else {
|
||||
nsTArray<ProxyAccessible*> accs =
|
||||
mGeckoAccessible.AsProxy()->RelationByType(
|
||||
RelationType::NODE_PARENT_OF);
|
||||
disclosedRows = utils::ConvertToNSArray(accs);
|
||||
}
|
||||
|
||||
if (disclosedRows) {
|
||||
// if we find rows from our relation check, return them here
|
||||
return disclosedRows;
|
||||
}
|
||||
|
||||
// otherwise, filter our children for outline rows
|
||||
return [[self moxChildren]
|
||||
filteredArrayUsingPredicate:[NSPredicate predicateWithBlock:^BOOL(
|
||||
mozAccessible* child,
|
||||
NSDictionary* bindings) {
|
||||
return [child isKindOfClass:[mozOutlineRowAccessible class]];
|
||||
}]];
|
||||
}
|
||||
|
||||
- (NSNumber*)moxIndex {
|
||||
mozAccessible* parent = (mozAccessible*)[self moxUnignoredParent];
|
||||
while (parent) {
|
||||
if ([[parent moxRole] isEqualToString:@"AXOutline"]) {
|
||||
break;
|
||||
}
|
||||
parent = (mozAccessible*)[parent moxUnignoredParent];
|
||||
}
|
||||
|
||||
NSUInteger index =
|
||||
[[(mozOutlineAccessible*)parent moxRows] indexOfObjectIdenticalTo:self];
|
||||
return index == NSNotFound ? nil : @(index);
|
||||
}
|
||||
|
||||
- (NSString*)moxLabel {
|
||||
nsAutoString title;
|
||||
if (Accessible* acc = mGeckoAccessible.AsAccessible()) {
|
||||
acc->Name(title);
|
||||
} else {
|
||||
mGeckoAccessible.AsProxy()->Name(title);
|
||||
}
|
||||
// remove listmarker for clean label
|
||||
return nsCocoaUtils::ToNSString(Substring(title, 1, title.Length()));
|
||||
}
|
||||
|
||||
@end
|
||||
|
|
|
|||
|
|
@ -37,4 +37,5 @@ skip-if = os == 'mac' && debug # Bug 1664577
|
|||
[browser_rootgroup.js]
|
||||
[browser_text_selection.js]
|
||||
[browser_navigate.js]
|
||||
[browser_outline.js]
|
||||
[browser_hierarchy.js]
|
||||
|
|
|
|||
376
accessible/tests/browser/mac/browser_outline.js
Normal file
376
accessible/tests/browser/mac/browser_outline.js
Normal file
|
|
@ -0,0 +1,376 @@
|
|||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
"use strict";
|
||||
|
||||
/**
|
||||
* Test outline, outline rows with computed properties
|
||||
*/
|
||||
addAccessibleTask(
|
||||
`
|
||||
<h3 id="tree1">
|
||||
Foods
|
||||
</h3>
|
||||
<ul role="tree" aria-labelledby="tree1" id="outline">
|
||||
<li role="treeitem" aria-expanded="false">
|
||||
<span>
|
||||
Fruits
|
||||
</span>
|
||||
<ul>
|
||||
<li role="none">Oranges</li>
|
||||
<li role="treeitem" aria-expanded="true">
|
||||
<span>
|
||||
Apples
|
||||
</span>
|
||||
<ul role="group">
|
||||
<li role="none">Honeycrisp</li>
|
||||
<li role="none">Granny Smith</li>
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
</li>
|
||||
<li role="treeitem" aria-expanded="false">
|
||||
<span>
|
||||
Vegetables
|
||||
</span>
|
||||
<ul role="group">
|
||||
<li role="treeitem" aria-expanded="true">
|
||||
<span>
|
||||
Podded Vegetables
|
||||
</span>
|
||||
<ul role="group">
|
||||
<li role="none">Lentil</li>
|
||||
<li role="none">Pea</li>
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
`,
|
||||
async (browser, accDoc) => {
|
||||
const outline = getNativeInterface(accDoc, "outline");
|
||||
is(
|
||||
outline.getAttributeValue("AXRole"),
|
||||
"AXOutline",
|
||||
"Correct role for outline"
|
||||
);
|
||||
|
||||
const outChildren = outline.getAttributeValue("AXChildren");
|
||||
is(outChildren.length, 2, "Outline has two direct children");
|
||||
is(outChildren[0].getAttributeValue("AXSubrole"), "AXOutlineRow");
|
||||
is(outChildren[1].getAttributeValue("AXSubrole"), "AXOutlineRow");
|
||||
|
||||
const outRows = outline.getAttributeValue("AXRows");
|
||||
is(outRows.length, 4, "Outline has four rows");
|
||||
is(
|
||||
outRows[0].getAttributeValue("AXDisclosing"),
|
||||
0,
|
||||
"Row is not disclosing"
|
||||
);
|
||||
is(
|
||||
outRows[0].getAttributeValue("AXDisclosedByRow"),
|
||||
null,
|
||||
"Row is direct child of outline"
|
||||
);
|
||||
is(
|
||||
outRows[0].getAttributeValue("AXDisclosedRows").length,
|
||||
0,
|
||||
"Row has no row children, only group"
|
||||
);
|
||||
is(
|
||||
outRows[0].getAttributeValue("AXDisclosureLevel"),
|
||||
1,
|
||||
"Row is level one"
|
||||
);
|
||||
|
||||
is(outRows[1].getAttributeValue("AXDisclosing"), 1, "Row is disclosing");
|
||||
is(
|
||||
outRows[1].getAttributeValue("AXDisclosedByRow"),
|
||||
null,
|
||||
"Row is direct child of group"
|
||||
);
|
||||
is(
|
||||
outRows[1].getAttributeValue("AXDisclosedRows").length,
|
||||
0,
|
||||
"Row has no row children"
|
||||
);
|
||||
is(
|
||||
outRows[1].getAttributeValue("AXDisclosureLevel"),
|
||||
1,
|
||||
"Row is level one"
|
||||
);
|
||||
|
||||
is(
|
||||
outRows[2].getAttributeValue("AXDisclosing"),
|
||||
0,
|
||||
"Row is not disclosing"
|
||||
);
|
||||
is(
|
||||
outRows[2].getAttributeValue("AXDisclosedByRow"),
|
||||
null,
|
||||
"Row is direct child of outline"
|
||||
);
|
||||
is(
|
||||
outRows[2].getAttributeValue("AXDisclosedRows").length,
|
||||
1,
|
||||
"Row has one row child"
|
||||
);
|
||||
is(
|
||||
outRows[2].getAttributeValue("AXDisclosureLevel"),
|
||||
1,
|
||||
"Row is level one"
|
||||
);
|
||||
|
||||
is(outRows[3].getAttributeValue("AXDisclosing"), 1, "Row is disclosing");
|
||||
is(
|
||||
outRows[3]
|
||||
.getAttributeValue("AXDisclosedByRow")
|
||||
.getAttributeValue("AXDescription"),
|
||||
outRows[2].getAttributeValue("AXDescription"),
|
||||
"Row is direct child of row[2]"
|
||||
);
|
||||
is(
|
||||
outRows[3].getAttributeValue("AXDisclosedRows").length,
|
||||
0,
|
||||
"Row has no row children"
|
||||
);
|
||||
is(
|
||||
outRows[3].getAttributeValue("AXDisclosureLevel"),
|
||||
2,
|
||||
"Row is level two"
|
||||
);
|
||||
}
|
||||
);
|
||||
|
||||
/**
|
||||
* Test outline, outline rows with declared properties
|
||||
*/
|
||||
addAccessibleTask(
|
||||
`
|
||||
<h3 id="tree1">
|
||||
Foods
|
||||
</h3>
|
||||
<ul role="tree" aria-labelledby="tree1" id="outline">
|
||||
<li role="treeitem"
|
||||
aria-level="1"
|
||||
aria-setsize="2"
|
||||
aria-posinset="1"
|
||||
aria-expanded="false">
|
||||
<span>
|
||||
Fruits
|
||||
</span>
|
||||
<ul>
|
||||
<li role="treeitem"
|
||||
aria-level="3"
|
||||
aria-setsize="2"
|
||||
aria-posinset="1">
|
||||
Oranges
|
||||
</li>
|
||||
<li role="treeitem"
|
||||
aria-level="2"
|
||||
aria-setsize="2"
|
||||
aria-posinset="2"
|
||||
aria-expanded="true">
|
||||
<span>
|
||||
Apples
|
||||
</span>
|
||||
<ul role="group">
|
||||
<li role="treeitem"
|
||||
aria-level="3"
|
||||
aria-setsize="2"
|
||||
aria-posinset="1">
|
||||
Honeycrisp
|
||||
</li>
|
||||
<li role="treeitem"
|
||||
aria-level="3"
|
||||
aria-setsize="2"
|
||||
aria-posinset="2">
|
||||
Granny Smith
|
||||
</li>
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
</li>
|
||||
<li role="treeitem"
|
||||
aria-level="1"
|
||||
aria-setsize="2"
|
||||
aria-posinset="2"
|
||||
aria-expanded="false">
|
||||
<span>
|
||||
Vegetables
|
||||
</span>
|
||||
<ul role="group">
|
||||
<li role="treeitem"
|
||||
aria-level="2"
|
||||
aria-setsize="1"
|
||||
aria-posinset="1"
|
||||
aria-expanded="true">
|
||||
<span>
|
||||
Podded Vegetables
|
||||
</span>
|
||||
<ul role="group">
|
||||
<li role="treeitem"
|
||||
aria-level="3"
|
||||
aria-setsize="2"
|
||||
aria-posinset="1">
|
||||
Lentil
|
||||
</li>
|
||||
<li role="treeitem"
|
||||
aria-level="3"
|
||||
aria-setsize="2"
|
||||
aria-posinset="2">
|
||||
Pea
|
||||
</li>
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
`,
|
||||
async (browser, accDoc) => {
|
||||
const outline = getNativeInterface(accDoc, "outline");
|
||||
is(
|
||||
outline.getAttributeValue("AXRole"),
|
||||
"AXOutline",
|
||||
"Correct role for outline"
|
||||
);
|
||||
|
||||
const outChildren = outline.getAttributeValue("AXChildren");
|
||||
is(outChildren.length, 2, "Outline has two direct children");
|
||||
is(outChildren[0].getAttributeValue("AXSubrole"), "AXOutlineRow");
|
||||
is(outChildren[1].getAttributeValue("AXSubrole"), "AXOutlineRow");
|
||||
|
||||
const outRows = outline.getAttributeValue("AXRows");
|
||||
for (let i = 0; i < outRows.length; i++) {
|
||||
console.log(i);
|
||||
console.log(outRows[i].getAttributeValue("AXDescription"));
|
||||
console.log("\n");
|
||||
}
|
||||
is(outRows.length, 9, "Outline has nine rows");
|
||||
is(
|
||||
outRows[0].getAttributeValue("AXDisclosing"),
|
||||
0,
|
||||
"Row is not disclosing"
|
||||
);
|
||||
is(
|
||||
outRows[0].getAttributeValue("AXDisclosedByRow"),
|
||||
null,
|
||||
"Row is direct child of outline"
|
||||
);
|
||||
is(
|
||||
outRows[0].getAttributeValue("AXDisclosedRows").length,
|
||||
0,
|
||||
"Row has no direct row children, has list"
|
||||
);
|
||||
is(
|
||||
outRows[0].getAttributeValue("AXDisclosureLevel"),
|
||||
1,
|
||||
"Row is level one"
|
||||
);
|
||||
|
||||
is(outRows[2].getAttributeValue("AXDisclosing"), 1, "Row is disclosing");
|
||||
is(
|
||||
outRows[2].getAttributeValue("AXDisclosedByRow"),
|
||||
null,
|
||||
"Row is direct child of group"
|
||||
);
|
||||
is(
|
||||
outRows[2].getAttributeValue("AXDisclosedRows").length,
|
||||
2,
|
||||
"Row has two row children"
|
||||
);
|
||||
is(
|
||||
outRows[2].getAttributeValue("AXDisclosureLevel"),
|
||||
2,
|
||||
"Row is level two"
|
||||
);
|
||||
|
||||
is(
|
||||
outRows[3].getAttributeValue("AXDisclosing"),
|
||||
0,
|
||||
"Row is not disclosing"
|
||||
);
|
||||
is(
|
||||
outRows[3]
|
||||
.getAttributeValue("AXDisclosedByRow")
|
||||
.getAttributeValue("AXDescription"),
|
||||
outRows[2].getAttributeValue("AXDescription"),
|
||||
"Row is direct child of row 2"
|
||||
);
|
||||
|
||||
is(
|
||||
outRows[3].getAttributeValue("AXDisclosedRows").length,
|
||||
0,
|
||||
"Row has no row children"
|
||||
);
|
||||
is(
|
||||
outRows[3].getAttributeValue("AXDisclosureLevel"),
|
||||
3,
|
||||
"Row is level three"
|
||||
);
|
||||
|
||||
is(
|
||||
outRows[5].getAttributeValue("AXDisclosing"),
|
||||
0,
|
||||
"Row is not disclosing"
|
||||
);
|
||||
is(
|
||||
outRows[5].getAttributeValue("AXDisclosedByRow"),
|
||||
null,
|
||||
"Row is direct child of outline"
|
||||
);
|
||||
is(
|
||||
outRows[5].getAttributeValue("AXDisclosedRows").length,
|
||||
1,
|
||||
"Row has no one row child"
|
||||
);
|
||||
is(
|
||||
outRows[5].getAttributeValue("AXDisclosureLevel"),
|
||||
1,
|
||||
"Row is level one"
|
||||
);
|
||||
|
||||
is(outRows[6].getAttributeValue("AXDisclosing"), 1, "Row is disclosing");
|
||||
is(
|
||||
outRows[6]
|
||||
.getAttributeValue("AXDisclosedByRow")
|
||||
.getAttributeValue("AXDescription"),
|
||||
outRows[5].getAttributeValue("AXDescription"),
|
||||
"Row is direct child of row 5"
|
||||
);
|
||||
is(
|
||||
outRows[6].getAttributeValue("AXDisclosedRows").length,
|
||||
2,
|
||||
"Row has two row children"
|
||||
);
|
||||
is(
|
||||
outRows[6].getAttributeValue("AXDisclosureLevel"),
|
||||
2,
|
||||
"Row is level two"
|
||||
);
|
||||
|
||||
is(
|
||||
outRows[7].getAttributeValue("AXDisclosing"),
|
||||
0,
|
||||
"Row is not disclosing"
|
||||
);
|
||||
is(
|
||||
outRows[7]
|
||||
.getAttributeValue("AXDisclosedByRow")
|
||||
.getAttributeValue("AXDescription"),
|
||||
outRows[6].getAttributeValue("AXDescription"),
|
||||
"Row is direct child of row 6"
|
||||
);
|
||||
is(
|
||||
outRows[7].getAttributeValue("AXDisclosedRows").length,
|
||||
0,
|
||||
"Row has no row children"
|
||||
);
|
||||
is(
|
||||
outRows[7].getAttributeValue("AXDisclosureLevel"),
|
||||
3,
|
||||
"Row is level three"
|
||||
);
|
||||
}
|
||||
);
|
||||
Loading…
Reference in a new issue