blob: 33efb29b47d3e409540dee11e611d5effef0d54f [file] [log] [blame]
//
// Copyright 2018 Google Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
#import <CoreGraphics/CoreGraphics.h>
#import <UIKit/UIKit.h>
#import <XCTest/XCTest.h>
#import "GTXAccessibilityTree.h"
#import "GTXTestAccessibilityElements.h"
@interface GTXAccessibilityTreeTests : XCTestCase
@end
@implementation GTXAccessibilityTreeTests
- (void)testGTXAccessibilityTreeWorksWithEmptyLists {
for (id element in [[GTXAccessibilityTree alloc] initWithRootElements:@[]]) {
XCTAssertTrue(FALSE, @"Unknown element found %@", element);
}
}
- (void)testGTXAccessibilityTreeWorksWithSingleElement {
id element = [self newUIElementWithAccessibility:YES];
[self assertGTXAccessibilityTreeWithRootElements:@[element]
yields:@[element]];
}
- (void)testGTXAccessibilityTreeWorksWithMultipleElementsAtSameLevel {
id element1 = [self newUIElementWithAccessibility:YES];
id element2 = [self newUIElementWithAccessibility:YES];
NSArray *elements = @[element1, element2];
[self assertGTXAccessibilityTreeWithRootElements:elements
yields:elements];
}
- (void)testGTXAccessibilityTreeWorksWithAOneLevelTree {
id element1 = [self newUIElementWithAccessibility:NO];
id element2 = [self newUIElementWithAccessibility:NO];
id element3 = [self newUIElementWithAccessibility:NO];
[(UIView *)element1 addSubview:element2];
[(UIView *)element1 addSubview:element3];
NSArray *elements = @[element1, element2, element3];
[self assertGTXAccessibilityTreeWithRootElements:@[element1]
yields:elements];
}
- (void)testGTXAccessibilityTreeSkipsChildrenOfAccessibilityElements {
UIView *root = [self newTestElementWithChildren];
UIView *subTreeView = root.subviews[0];
[subTreeView setIsAccessibilityElement:YES];
NSArray *actualElements = [self accessibilityElementsInTree:root];
XCTAssertFalse([actualElements containsObject:subTreeView.subviews[0]]);
XCTAssertFalse([actualElements containsObject:subTreeView.subviews[1]]);
[root setIsAccessibilityElement:YES];
// Enumeration should now contain just the root element.
actualElements = [self accessibilityElementsInTree:root];
XCTAssertTrue([actualElements containsObject:root]);
XCTAssertEqual([actualElements count], (NSUInteger)1);
}
- (void)testGTXAccessibilityTreeSkipsHiddenElements {
UIView *root = [self newTestElementWithChildren];
[root setHidden:YES];
// Enumeration should be empty.
NSArray *actualElements = [self accessibilityElementsInTree:root];
XCTAssertEqual([actualElements count], (NSUInteger)0);
}
- (void)testGTXAccessibilityTreeSkipsAccessibilityHiddenElements {
UIView *root = [self newTestElementWithChildren];
[root setAccessibilityElementsHidden:YES];
// Enumeration should be empty.
NSArray *actualElements = [self accessibilityElementsInTree:root];
XCTAssertEqual([actualElements count], (NSUInteger)0);
}
- (void)testGTXAccessibilityTreeSkipsEmptyFrameElements {
UIView *root = [self newTestElementWithChildren];
// Enumeration should be empty for zero width.
root.accessibilityFrame = CGRectMake(0, 0, 0, 1);
root.frame = CGRectMake(0, 0, 0, 1);
NSArray *actualElements = [self accessibilityElementsInTree:root];
XCTAssertEqual([actualElements count], (NSUInteger)0);
// Enumeration should be empty for zero height.
root.accessibilityFrame = CGRectMake(0, 0, 1, 0);
root.frame = CGRectMake(0, 0, 1, 0);
actualElements = [self accessibilityElementsInTree:root];
XCTAssertEqual([actualElements count], (NSUInteger)0);
// Enumeration should be empty for zero rect.
root.accessibilityFrame = CGRectZero;
root.frame = CGRectZero;
actualElements = [self accessibilityElementsInTree:root];
XCTAssertEqual([actualElements count], (NSUInteger)0);
}
- (void)testGTXAccessibilityTreeNotNonEmptyFrameElements {
UIView *root = [self newTestElementWithChildren];
// Enumeration should not be empty if frame is non-empty.
CGRect nonZeroRect = CGRectMake(0, 0, 1, 1);
root.accessibilityFrame = CGRectZero;
root.frame = nonZeroRect;
NSArray *actualElements = [self accessibilityElementsInTree:root];
XCTAssertNotEqual([actualElements count], (NSUInteger)0);
// Enumeration should not be empty if accessibilityFrame is non-empty.
root.accessibilityFrame = nonZeroRect;
root.frame = CGRectZero;
actualElements = [self accessibilityElementsInTree:root];
XCTAssertNotEqual([actualElements count], (NSUInteger)0);
}
- (void)testGTXAccessibilityTreeSkipsChildrenOfAccessibilityHiddenElements {
// Accessibility element which provide same elements via element.accessibilityElements and
// element.accessibilityElementAtIndex: are considered consistent.
GTXTestAccessibilityElementFull *root = [[GTXTestAccessibilityElementFull alloc] init];
id element1 = [self newUIElementWithAccessibility:YES];
id element2 = [self newUIElementWithAccessibility:YES];
root.accessibilityElementsOveride = @[element1, element2];
root.accessibilityElementsAtIndexOveride = @[element2, element1];
root.isAccessibilityElementOveride = NO;
[self assertGTXAccessibilityTreeWithRootElements:@[root]
yields:@[root, element1, element2]];
}
- (void)testGTXAccessibilityTreeSkipsChildrenOfHiddenElements {
UIView *root = [self newTestElementWithChildren];
UIView *subTreeView = root.subviews[0];
[subTreeView setHidden:YES];
NSArray *actualElements = [self accessibilityElementsInTree:root];
XCTAssertFalse([actualElements containsObject:subTreeView.subviews[0]]);
XCTAssertFalse([actualElements containsObject:subTreeView.subviews[1]]);
}
- (void)testGTXAccessibilityTreeFailsForInConsistentTrees {
GTXTestAccessibilityElementFull *root = [[GTXTestAccessibilityElementFull alloc] init];
root.accessibilityElementsOveride = @[[self newUIElementWithAccessibility:YES]];
root.accessibilityElementsAtIndexOveride = @[[self newUIElementWithAccessibility:YES]];
root.isAccessibilityElementOveride = NO;
XCTAssertThrows([[[GTXAccessibilityTree alloc] initWithRootElements:@[root]] nextObject]);
}
- (void)testGTXAccessibilityTreeWorksForConsistentTrees {
// Accessibility element which provide same elements via element.accessibilityElements and
// element.accessibilityElementAtIndex: are considered consistent.
GTXTestAccessibilityElementFull *root = [[GTXTestAccessibilityElementFull alloc] init];
id element1 = [self newUIElementWithAccessibility:YES];
id element2 = [self newUIElementWithAccessibility:YES];
root.accessibilityElementsOveride = @[element1, element2];
root.accessibilityElementsAtIndexOveride = @[element2, element1];
root.isAccessibilityElementOveride = NO;
[self assertGTXAccessibilityTreeWithRootElements:@[root]
yields:@[root, element1, element2]];
}
- (void)testGTXAccessibilityTreeWorksWithAccessibilityElements {
GTXTestAccessibilityElementA *root = [[GTXTestAccessibilityElementA alloc] init];
root.isAccessibilityElementOveride = NO;
id element = [self newUIElementWithAccessibility:YES];
root.accessibilityElementsOveride = @[element];
NSArray *elements = @[root, element];
[self assertGTXAccessibilityTreeWithRootElements:@[root]
yields:elements];
}
- (void)testGTXAccessibilityTreeWorksWithAccessibilityElementsAtIndex {
GTXTestAccessibilityElementB *root = [[GTXTestAccessibilityElementB alloc] init];
root.isAccessibilityElementOveride = NO;
id element1 = [self newUIElementWithAccessibility:YES];
id element2 = [self newUIElementWithAccessibility:YES];
root.accessibilityElementsAtIndexOveride = @[element1, element2];
NSArray *elements = @[root, element1, element2];
[self assertGTXAccessibilityTreeWithRootElements:@[root]
yields:elements];
}
#pragma mark - Private
- (void)assertGTXAccessibilityTreeWithRootElements:(NSArray *)rootElements
yields:(NSArray *)expectedElements {
NSMutableArray *actualElemets = [[NSMutableArray alloc] init];
for (id element in [[GTXAccessibilityTree alloc] initWithRootElements:rootElements]) {
[actualElemets addObject:element];
}
XCTAssertEqualObjects(expectedElements, actualElemets);
}
- (id)newTestElementWithChildren {
UIView *leftSubTreeRoot = [self newUIElementWithAccessibility:NO];
[leftSubTreeRoot addSubview:[self newUIElementWithAccessibility:NO]];
[leftSubTreeRoot addSubview:[self newUIElementWithAccessibility:NO]];
UIView *rightSubTreeRoot = [self newUIElementWithAccessibility:NO];
[rightSubTreeRoot addSubview:[self newUIElementWithAccessibility:NO]];
[rightSubTreeRoot addSubview:[self newUIElementWithAccessibility:NO]];
UIView *root = [self newUIElementWithAccessibility:NO];
[root addSubview:leftSubTreeRoot];
[root addSubview:rightSubTreeRoot];
return root;
}
- (id)newUIElementWithAccessibility:(BOOL)isAccessibilityElement {
UIView *element = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 1, 1)];
[element setIsAccessibilityElement:isAccessibilityElement];
return element;
}
- (NSArray *)accessibilityElementsInTree:(id)root {
NSMutableArray *accessibilityElementsArray = [[NSMutableArray alloc] init];
for (id element in [[GTXAccessibilityTree alloc] initWithRootElements:@[root]]) {
[accessibilityElementsArray addObject:element];
}
return accessibilityElementsArray;
}
@end