diff --git a/Integration Tests/Tests/SLNavigationBarTests.m b/Integration Tests/Tests/SLNavigationBarTests.m new file mode 100644 index 0000000..2117613 --- /dev/null +++ b/Integration Tests/Tests/SLNavigationBarTests.m @@ -0,0 +1,49 @@ +// +// SLNavigationBarTests.m +// Subliminal +// +// Created by Jordan Zucker on 4/4/14. +// Copyright (c) 2014 Inkling. All rights reserved. +// + +#import "SLIntegrationTest.h" + +@interface SLNavigationBarTests : SLIntegrationTest +@end + +@implementation SLNavigationBarTests + ++ (NSString *)testCaseViewControllerClassName { + return @"SLNavigationBarTestsViewController"; +} + +- (void)testRightButtonBroadMatching { + SLButton *rightButton = [SLButton elementWithAccessibilityLabel:@"Right"]; + SLAssertTrue([UIAElement(rightButton) isValidAndVisible], @"Right button didn't appear"); + + [UIAElement(rightButton) tap]; +} + +- (void)testRightButtonWithNewMethod +{ + SLNavigationBar *navBar = [SLNavigationBar elementWithAccessibilityIdentifier:@"NavigationBar"]; + SLLogAsync(@"navBar is %@", navBar); + SLAssertTrue([UIAElement(navBar) isValidAndVisible], @"Couldn't find nav bar matching specifications"); + SLButton *rightButton = [navBar childElementMatching:[SLButton elementWithAccessibilityLabel:@"Right"]]; + SLAssertTrue([UIAElement(rightButton) isValidAndVisible], @"Couldn't find right button bar"); + + [UIAElement(rightButton) tap]; +} + +- (void)testTitleLabel +{ + SLNavigationBar *navBar = [SLNavigationBar elementWithAccessibilityIdentifier:@"NavigationBar"]; + SLLogAsync(@"navBar is %@", navBar); + SLAssertTrue([UIAElement(navBar) isValidAndVisible], @"Couldn't find nav bar matching specifications"); + SLElement *title = [navBar childElementMatching:[SLElement elementWithAccessibilityLabel:@"Testing" value:nil traits:UIAccessibilityTraitStaticText]]; + SLAssertTrue([UIAElement(title) isValidAndVisible], @"title isn't valid and visible"); + SLLogAsync(@"title is %@", title.label); + SLAssertTrue([UIAElement(title.label) isEqualToString:@"Testing"], @"title doesn't match expected string"); +} + +@end diff --git a/Integration Tests/Tests/SLNavigationBarTestsViewController.m b/Integration Tests/Tests/SLNavigationBarTestsViewController.m new file mode 100644 index 0000000..e4b7d52 --- /dev/null +++ b/Integration Tests/Tests/SLNavigationBarTestsViewController.m @@ -0,0 +1,67 @@ +// +// SLNavigationBarTestsViewController.m +// Subliminal +// +// Created by Jordan Zucker on 4/4/14. +// Copyright (c) 2014 Inkling. All rights reserved. +// + +#import "SLTestCaseViewController.h" + +#import + +@interface SLNavigationBarTestsViewController : SLTestCaseViewController + +@end + +@interface SLNavigationBarTestsViewController () +// Connect IBOutlets here. +@property (nonatomic, weak) IBOutlet UINavigationBar *navBar; +@end + +@implementation SLNavigationBarTestsViewController + ++ (NSString *)nibNameForTestCase:(SEL)testCase { + return @"SLNavigationBarTestsViewController"; +} + +- (void)viewDidLoad { + [super viewDidLoad]; + + // Do any additional setup after loading the view from its nib. + // Test case specific configuration is best done using app hooks + // triggered from -[SLNavigationBarTests setUpTestCaseWithSelector:]. + UIBarButtonItem *rightButton = [[UIBarButtonItem alloc] initWithTitle:@"Right" style:UIBarButtonItemStylePlain target:self action:@selector(tapRightButton:)]; + rightButton.accessibilityLabel = @"Right"; + _navBar.topItem.rightBarButtonItem = rightButton; + + _navBar.accessibilityIdentifier = @"NavigationBar"; + + _navBar.topItem.title = @"Testing"; + _navBar.topItem.title.isAccessibilityElement = YES; + _navBar.topItem.title.accessibilityLabel = _navBar.topItem.title; +} + +- (IBAction)tapRightButton:(id)sender +{ + NSLog(@"hey"); +} + +- (instancetype)initWithTestCaseWithSelector:(SEL)testCase { + self = [super initWithTestCaseWithSelector:testCase]; + if (self) { + // Register for app hooks, e.g. + // [[SLTestController sharedTestController] registerTarget:<#(id)#> forAction:<#(SEL)#>]; + } + return self; +} + +// Deregister for app hooks, if any +//- (void)dealloc { +// [[SLTestController sharedTestController] deregisterTarget:self]; +//} + +//#pragma mark - App hooks +// Put any app hooks below here + +@end diff --git a/Integration Tests/Tests/SLNavigationBarTestsViewController.xib b/Integration Tests/Tests/SLNavigationBarTestsViewController.xib new file mode 100644 index 0000000..518af47 --- /dev/null +++ b/Integration Tests/Tests/SLNavigationBarTestsViewController.xib @@ -0,0 +1,33 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Integration Tests/Tests/SLTableViewCellChildElementsTest.m b/Integration Tests/Tests/SLTableViewCellChildElementsTest.m new file mode 100644 index 0000000..330ef55 --- /dev/null +++ b/Integration Tests/Tests/SLTableViewCellChildElementsTest.m @@ -0,0 +1,144 @@ +// +// SLTableViewCellChildElementsTest.m +// Subliminal +// +// Created by Jordan Zucker on 3/20/14. +// Copyright (c) 2014 Inkling. All rights reserved. +// + +#import "SLIntegrationTest.h" + +@interface SLTableViewCellChildElementsTest : SLIntegrationTest + +@end + +@implementation SLTableViewCellChildElementsTest + ++ (NSString *)testCaseViewControllerClassName { + return @"SLTableViewCellChildElementsTestViewController"; +} + +- (void)testTapBroadMatchingTableViewCellButton { + [[SLDevice currentDevice] captureScreenshotWithFilename:@"start"]; + + SLButton *favoriteButton = [SLButton elementWithAccessibilityLabel:@"Favorite"]; + SLAssertTrue([UIAElement(favoriteButton.value) isEqualToString:@"off"], @"favorite button is not originally off"); + SLAssertTrue([UIAElement(favoriteButton) isValidAndVisible], @"Favorite button is not valid and visible"); + [favoriteButton captureScreenshotWithFilename:@"fb: starting"]; + + [UIAElement(favoriteButton) tap]; + + [self wait:1]; + [[SLDevice currentDevice] captureScreenshotWithFilename:@"after tap"]; + [favoriteButton captureScreenshotWithFilename:@"fb: after first tap"]; + + SLAssertTrue([UIAElement(favoriteButton) isValidAndVisible], @"favorite button is not valid and visible after first time tapping"); + SLAssertTrue([UIAElement(favoriteButton.value) isEqualToString:@"on"], @"Favorite button does not has ax value of on"); + [UIAElement(favoriteButton) tap]; + + [self wait:1]; + + SLAssertTrue([UIAElement(favoriteButton.value) isEqualToString:@"off"], @"favorite button is not off at end of test"); + SLAssertTrue([UIAElement(favoriteButton) isValidAndVisible], @"Favorite button is not valid and visible"); + [favoriteButton captureScreenshotWithFilename:@"fb: ending"]; + + + [[SLDevice currentDevice] captureScreenshotWithFilename:@"end of test"]; +} + +- (void)testMatchingTableViewCellByMatchingTableViewCellAndTableView +{ + [[SLDevice currentDevice] captureScreenshotWithFilename:@"start"]; + SLButton *favoriteButton = [SLButton elementMatching:^BOOL(NSObject *obj) { + + if ([obj.accessibilityLabel isEqualToString:@"Favorite"]) { + + id accessibilityParent = [obj slAccessibilityParent]; + + while (accessibilityParent && ![[accessibilityParent accessibilityLabel] isEqualToString:@"Cell 2"]) { + + accessibilityParent = [accessibilityParent slAccessibilityParent]; + + } + + + id doubleAccessibilityParent = [accessibilityParent slAccessibilityParent]; + + while (doubleAccessibilityParent && ![doubleAccessibilityParent isKindOfClass:[UITableView class]]) { + doubleAccessibilityParent = [doubleAccessibilityParent slAccessibilityParent]; + } + + if (doubleAccessibilityParent) { + return YES; + } + else { + return NO; + } + + + } + + return NO; + + } withDescription:@"searching for favoritebutton"]; + + SLAssertTrue([UIAElement(favoriteButton.value) isEqualToString:@"off"], @"favorite button is not originally off"); + SLAssertTrue([UIAElement(favoriteButton) isValidAndVisible], @"Favorite button is not valid and visible"); + [favoriteButton captureScreenshotWithFilename:@"fb: starting"]; + + [UIAElement(favoriteButton) tap]; + + [self wait:1]; + [[SLDevice currentDevice] captureScreenshotWithFilename:@"after tap"]; + [favoriteButton captureScreenshotWithFilename:@"fb: after first tap"]; + + SLAssertTrue([UIAElement(favoriteButton) isValidAndVisible], @"favorite button is not valid and visible after first time tapping"); + SLAssertTrue([UIAElement(favoriteButton.value) isEqualToString:@"on"], @"Favorite button does not has ax value of on"); + [UIAElement(favoriteButton) tap]; + + [self wait:1]; + + SLAssertTrue([UIAElement(favoriteButton.value) isEqualToString:@"off"], @"favorite button is not off at end of test"); + SLAssertTrue([UIAElement(favoriteButton) isValidAndVisible], @"Favorite button is not valid and visible"); + [favoriteButton captureScreenshotWithFilename:@"fb: ending"]; + + + [[SLDevice currentDevice] captureScreenshotWithFilename:@"end of test"]; +} + +- (void)testMatchingTableViewCellWithAccessibilityContainerMethod +{ + [[SLDevice currentDevice] captureScreenshotWithFilename:@"start"]; + SLTableViewCell *tableViewCell = [SLTableViewCell elementWithAccessibilityLabel:@"Cell 2"]; + SLAssertTrue([UIAElement(tableViewCell) isValidAndVisible], @"table view cell matching cell 2 not valid and visible"); + SLButton *favoriteButton = [tableViewCell childElementMatching:[SLButton elementWithAccessibilityLabel:@"Favorite"]]; + + SLLogAsync(@"favoriteButton.value is %@", UIAElement(favoriteButton.value)); + + SLAssertTrue([UIAElement(favoriteButton.value) isEqualToString:@"off"], @"favorite button is not originally off"); + SLAssertTrue([UIAElement(favoriteButton) isValidAndVisible], @"Favorite button is not valid and visible"); + [favoriteButton captureScreenshotWithFilename:@"fb: starting"]; + + [UIAElement(favoriteButton) tap]; + + [self wait:1]; + [[SLDevice currentDevice] captureScreenshotWithFilename:@"after tap"]; + [favoriteButton captureScreenshotWithFilename:@"fb: after first tap"]; + + [UIAElement(favoriteButton) isValidAndVisible]; + + SLAssertTrue([UIAElement(favoriteButton) isValidAndVisible], @"favorite button is not valid and visible after first time tapping"); + SLAssertTrue([UIAElement(favoriteButton.value) isEqualToString:@"on"], @"Favorite button does not has ax value of on"); + [UIAElement(favoriteButton) tap]; + + [self wait:1]; + + SLAssertTrue([UIAElement(favoriteButton.value) isEqualToString:@"off"], @"favorite button is not off at end of test"); + SLAssertTrue([UIAElement(favoriteButton) isValidAndVisible], @"Favorite button is not valid and visible"); + [favoriteButton captureScreenshotWithFilename:@"fb: ending"]; + + + [[SLDevice currentDevice] captureScreenshotWithFilename:@"end of test"]; +} + +@end diff --git a/Integration Tests/Tests/SLTableViewCellChildElementsTestViewController.m b/Integration Tests/Tests/SLTableViewCellChildElementsTestViewController.m new file mode 100644 index 0000000..fc7da0e --- /dev/null +++ b/Integration Tests/Tests/SLTableViewCellChildElementsTestViewController.m @@ -0,0 +1,109 @@ +// +// SLTableViewCellChildElementsTestViewController.m +// Subliminal +// +// Created by Jordan Zucker on 3/20/14. +// Copyright (c) 2014 Inkling. All rights reserved. +// + +#import "SLTestCaseViewController.h" + +#import + +@interface SLTableViewCellChildElementsTestViewController : SLTestCaseViewController + +@end + +@interface SLTableViewCellChildElementsTestViewController () +@property (nonatomic, weak) IBOutlet UITableView *tableView; +@property (nonatomic, strong) NSArray *tableViewElements; +@property (nonatomic, strong) NSMutableArray *tableViewFavorites; +@end + +@implementation SLTableViewCellChildElementsTestViewController + ++ (NSString *)nibNameForTestCase:(SEL)testCase { + return @"SLTableViewCellChildElementsTestViewController"; +} + +- (void)viewDidLoad { + [super viewDidLoad]; + + _tableViewElements = @[@"Cell 0", @"Cell 1", @"Cell 2", @"Cell 3"]; + _tableViewFavorites = [[NSMutableArray alloc] initWithObjects:@(NO), @(NO), @(NO), @(NO), nil]; +} + +- (instancetype)initWithTestCaseWithSelector:(SEL)testCase { + self = [super initWithTestCaseWithSelector:testCase]; + if (self) { + } + return self; +} + +//#pragma mark - App hooks +// Put any app hooks below here + +#pragma mark - UIButton method + +- (IBAction)pressButton:(id)sender +{ + UIButton *favoriteButton = (UIButton *)sender; + NSNumber *oldFavoriteBool = [_tableViewFavorites objectAtIndex:favoriteButton.tag]; + [self setFavoriteButton:favoriteButton withFavoriteStatus:(![oldFavoriteBool boolValue])]; +} + +- (void) setFavoriteButton:(UIButton *)favoriteButton withFavoriteStatus:(BOOL)favoriteBool +{ + NSString *updatedFavoriteButtonAccessibilityValue; + UIImage *updatedFavoriteButtonImage; + if (favoriteBool == YES) { + updatedFavoriteButtonAccessibilityValue = @"on"; + updatedFavoriteButtonImage = [UIImage imageNamed:@"heart_icon&32.png"]; + + } + else { + updatedFavoriteButtonAccessibilityValue = @"off"; + updatedFavoriteButtonImage = [UIImage imageNamed:@"heart_empty_icon&32.png"]; + } + [_tableViewFavorites setObject:@(favoriteBool) atIndexedSubscript:favoriteButton.tag]; + favoriteButton.accessibilityValue = updatedFavoriteButtonAccessibilityValue; + [favoriteButton setImage:updatedFavoriteButtonImage forState:UIControlStateNormal]; +} + +#pragma mark - UITableViewDataSource + +- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView +{ + return 1; +} + +- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section +{ + return [_tableViewElements count]; +} + +- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath +{ + static NSString *CellIdentifier = @"Cell"; + UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier]; + if (cell == nil) { + cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier]; + } + + cell.textLabel.text = [_tableViewElements objectAtIndex:indexPath.row]; + UIButton *favoriteButton = [UIButton buttonWithType:UIButtonTypeCustom]; + favoriteButton.accessibilityLabel = @"Favorite"; + favoriteButton.tag = indexPath.row; + + favoriteButton.frame = CGRectMake(160.0f, 5.0f, 32.0f, 32.0f); + [self setFavoriteButton:favoriteButton withFavoriteStatus:[[_tableViewFavorites objectAtIndex:indexPath.row] boolValue]]; + [favoriteButton addTarget:self action:@selector(pressButton:) forControlEvents:UIControlEventTouchUpInside]; + [cell addSubview:favoriteButton]; + + cell.accessibilityLabel = cell.textLabel.text; + cell.accessibilityValue = cell.textLabel.text; + + return cell; +} + +@end diff --git a/Integration Tests/Tests/SLTableViewCellChildElementsTestViewController.xib b/Integration Tests/Tests/SLTableViewCellChildElementsTestViewController.xib new file mode 100644 index 0000000..4483677 --- /dev/null +++ b/Integration Tests/Tests/SLTableViewCellChildElementsTestViewController.xib @@ -0,0 +1,34 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Integration Tests/Tests/heart_empty_icon&32.png b/Integration Tests/Tests/heart_empty_icon&32.png new file mode 100755 index 0000000..9c324dc Binary files /dev/null and b/Integration Tests/Tests/heart_empty_icon&32.png differ diff --git a/Integration Tests/Tests/heart_icon&32.png b/Integration Tests/Tests/heart_icon&32.png new file mode 100755 index 0000000..ba444e8 Binary files /dev/null and b/Integration Tests/Tests/heart_icon&32.png differ diff --git a/Sources/Classes/UIAutomation/User Interface Elements/NSObject+SLAccessibilityHierarchy.m b/Sources/Classes/UIAutomation/User Interface Elements/NSObject+SLAccessibilityHierarchy.m index bae1799..dee2a89 100644 --- a/Sources/Classes/UIAutomation/User Interface Elements/NSObject+SLAccessibilityHierarchy.m +++ b/Sources/Classes/UIAutomation/User Interface Elements/NSObject+SLAccessibilityHierarchy.m @@ -376,6 +376,9 @@ @implementation UITableViewCell (SLAccessibilityHierarchy) - (BOOL)classForcesPresenceOfMockingViewsInAccessibilityHierarchy { return YES; } +- (BOOL)classForcesPresenceInAccessibilityHierarchy { + return YES; +} @end diff --git a/Sources/Classes/UIAutomation/User Interface Elements/SLElement.h b/Sources/Classes/UIAutomation/User Interface Elements/SLElement.h index d20be7c..4e9e6ee 100644 --- a/Sources/Classes/UIAutomation/User Interface Elements/SLElement.h +++ b/Sources/Classes/UIAutomation/User Interface Elements/SLElement.h @@ -133,6 +133,21 @@ */ + (instancetype)anyElement; +#pragma mark - Hierarchy + +/** + Allows the caller to return a child object matching the specificed `SLElement`. + + Superclass method assumes element and view are both direct descendants. This + will need to be overriden in `SLTableViewCell`, amongst others. + + @param childElement A `SLElement` with your provided specifications. + + @return `instancetype` matching specifications of the parameter and appearing as an + accessibilityChild of the caller. If there are no accessibilityChildren then it returns nil + */ +- (id)childElementMatching:(SLElement *)childElement; + #pragma mark - Gestures and Actions /// ------------------------------------------ /// @name Gestures and Actions diff --git a/Sources/Classes/UIAutomation/User Interface Elements/SLElement.m b/Sources/Classes/UIAutomation/User Interface Elements/SLElement.m index f97859f..1ed7bf6 100644 --- a/Sources/Classes/UIAutomation/User Interface Elements/SLElement.m +++ b/Sources/Classes/UIAutomation/User Interface Elements/SLElement.m @@ -303,6 +303,20 @@ - (void)examineMatchingObject:(void (^)(NSObject *))block timeout:(NSTimeInterva if (examinationException) @throw examinationException; } +- (id) childElementMatching:(SLElement *)childElement +{ + if ([self accessibilityElementCount] == 0) { + return nil; + } + return [SLElement elementMatching:^BOOL(NSObject *obj) { + if ([childElement matchesObject:obj]) { + id accessibilityParent = [obj slAccessibilityParent]; + return [self matchesObject:accessibilityParent]; + } + return NO; + } withDescription:@"nav bar child"]; +} + - (BOOL)isValid { // isValid evaluates the current state, no waiting to resolve the element SLAccessibilityPath *accessibilityPath = [self accessibilityPathWithTimeout:0.0]; diff --git a/Sources/Classes/UIAutomation/User Interface Elements/SLNavigationBar.h b/Sources/Classes/UIAutomation/User Interface Elements/SLNavigationBar.h new file mode 100644 index 0000000..fcde3fd --- /dev/null +++ b/Sources/Classes/UIAutomation/User Interface Elements/SLNavigationBar.h @@ -0,0 +1,20 @@ +// +// SLNavigationBar.h +// Subliminal +// +// Created by Jordan Zucker on 4/24/14. +// Copyright (c) 2014 Inkling. All rights reserved. +// + +#import "SLElement.h" +#import "SLUIAElement+Subclassing.h" + +/** + `SLNavigationBar` matches against instances of `UINavigationBar`. + + Will find an element matching the parameters that appears inside + a navigationBar. + */ +@interface SLNavigationBar : SLElement + +@end diff --git a/Sources/Classes/UIAutomation/User Interface Elements/SLNavigationBar.m b/Sources/Classes/UIAutomation/User Interface Elements/SLNavigationBar.m new file mode 100644 index 0000000..8ab4348 --- /dev/null +++ b/Sources/Classes/UIAutomation/User Interface Elements/SLNavigationBar.m @@ -0,0 +1,19 @@ +// +// SLNavigationBar.m +// Subliminal +// +// Created by Jordan Zucker on 4/24/14. +// Copyright (c) 2014 Inkling. All rights reserved. +// + +#import "SLNavigationBar.h" +#import "NSObject+SLAccessibilityHierarchy.h" + +@implementation SLNavigationBar + +- (BOOL)matchesObject:(NSObject *)object +{ + return [super matchesObject:object] && [object isKindOfClass:[UINavigationBar class]]; +} + +@end diff --git a/Sources/Classes/UIAutomation/User Interface Elements/SLTableViewCell.h b/Sources/Classes/UIAutomation/User Interface Elements/SLTableViewCell.h new file mode 100644 index 0000000..5de9afb --- /dev/null +++ b/Sources/Classes/UIAutomation/User Interface Elements/SLTableViewCell.h @@ -0,0 +1,19 @@ +// +// SLTableViewCell.h +// Subliminal +// +// Created by Jordan Zucker on 4/24/14. +// Copyright (c) 2014 Inkling. All rights reserved. +// + +#import "SLElement.h" + +/** + `SLTableViewCell` matches against instances of `UITableViewCell`. + + Will find an element matching the parameters that appears inside + a table view. + */ +@interface SLTableViewCell : SLElement + +@end diff --git a/Sources/Classes/UIAutomation/User Interface Elements/SLTableViewCell.m b/Sources/Classes/UIAutomation/User Interface Elements/SLTableViewCell.m new file mode 100644 index 0000000..bd450da --- /dev/null +++ b/Sources/Classes/UIAutomation/User Interface Elements/SLTableViewCell.m @@ -0,0 +1,62 @@ +// +// SLTableViewCell.m +// Subliminal +// +// Created by Jordan Zucker on 4/24/14. +// Copyright (c) 2014 Inkling. All rights reserved. +// + +#import "SLTableViewCell.h" +#import "NSObject+SLAccessibilityHierarchy.h" +#import "SLUIAElement+Subclassing.h" + +@implementation SLTableViewCell + +- (BOOL)matchesObject:(NSObject *)object +{ + if (![super matchesObject:object]) { + return NO; + } + // When we are matching for corresponding `UITableViewCell` instances for + // isVisible checking and such, we need to take iOS version into account. + // On iOS 6 `UITableViewCell` is a direct descendant of `UITableView`. + // On iOS 7, there is a `UITableViewWrapperView` between `UITableView` + // and `UITableViewCell`. + id accessibilityParent = [object slAccessibilityParent]; + if (accessibilityParent && [accessibilityParent isKindOfClass:[UITableView class]]) { + return YES; + } + if (kCFCoreFoundationVersionNumber > kCFCoreFoundationVersionNumber_iOS_6_1) { + id doubleAccessibilityParent = [accessibilityParent slAccessibilityParent]; + return [doubleAccessibilityParent isKindOfClass:[UITableView class]]; + } + + return NO; +} + +- (id)childElementMatching:(SLElement *)childElement +{ + return [SLElement elementMatching:^BOOL(NSObject *obj) { + if ([childElement matchesObject:obj]) { + id objAccessibilityParent = [obj slAccessibilityParent]; + // On iOS 6, views and accessibility mock views are + // direct children of `UITableViewCell`. + // On iOS 7, there is a `UITableViewCellScrollView` that is + // a child of `UITableViewCell` and all views contained therein + // are children of that `UITableViewCellScrollView`, which is + // a hidden class + if ([self matchesObject:objAccessibilityParent]) { + return YES; + } + if (kCFCoreFoundationVersionNumber > kCFCoreFoundationVersionNumber_iOS_6_1) { + // UITableViewCellScrollView + id doubleAccessibilityParent = [objAccessibilityParent slAccessibilityParent]; + return [self matchesObject:doubleAccessibilityParent]; + } + return NO; + } + return NO; + } withDescription:@"container child"]; +} + +@end diff --git a/Sources/Subliminal.h b/Sources/Subliminal.h index 2942072..55b17ab 100644 --- a/Sources/Subliminal.h +++ b/Sources/Subliminal.h @@ -29,6 +29,8 @@ #import "NSObject+SLAccessibilityDescription.h" #import "NSObject+SLAccessibilityHierarchy.h" #import "SLStaticElement.h" +#import "SLTableViewCell.h" +#import "SLNavigationBar.h" #import "SLAlert.h" #import "SLButton.h" #import "SLKeyboard.h" diff --git a/Subliminal.xcodeproj/project.pbxproj b/Subliminal.xcodeproj/project.pbxproj index 4199fc4..cca2192 100644 --- a/Subliminal.xcodeproj/project.pbxproj +++ b/Subliminal.xcodeproj/project.pbxproj @@ -41,6 +41,18 @@ 50F2B7C818E9C0D700F21635 /* SLDispatchTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 50F2B7C718E9C0D700F21635 /* SLDispatchTests.m */; }; 50F3E18C1783A5CB00C6BD1B /* SLGeometry.h in Headers */ = {isa = PBXBuildFile; fileRef = 50F3E18A1783A5CB00C6BD1B /* SLGeometry.h */; settings = {ATTRIBUTES = (Public, ); }; }; 50F3E18E1783A60100C6BD1B /* SLGeometry.m in Sources */ = {isa = PBXBuildFile; fileRef = 50F3E18B1783A5CB00C6BD1B /* SLGeometry.m */; }; + 9764EF6D1909715E009E6B68 /* SLNavigationBarTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 9764EF6A1909715E009E6B68 /* SLNavigationBarTests.m */; }; + 9764EF6E1909715F009E6B68 /* SLNavigationBarTestsViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 9764EF6B1909715E009E6B68 /* SLNavigationBarTestsViewController.m */; }; + 9764EF6F1909715F009E6B68 /* SLNavigationBarTestsViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = 9764EF6C1909715E009E6B68 /* SLNavigationBarTestsViewController.xib */; }; + 9764EF751909716B009E6B68 /* heart_empty_icon&32.png in Resources */ = {isa = PBXBuildFile; fileRef = 9764EF701909716B009E6B68 /* heart_empty_icon&32.png */; }; + 9764EF761909716B009E6B68 /* heart_icon&32.png in Resources */ = {isa = PBXBuildFile; fileRef = 9764EF711909716B009E6B68 /* heart_icon&32.png */; }; + 9764EF771909716B009E6B68 /* SLTableViewCellChildElementsTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 9764EF721909716B009E6B68 /* SLTableViewCellChildElementsTest.m */; }; + 9764EF781909716B009E6B68 /* SLTableViewCellChildElementsTestViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 9764EF731909716B009E6B68 /* SLTableViewCellChildElementsTestViewController.m */; }; + 9764EF791909716B009E6B68 /* SLTableViewCellChildElementsTestViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = 9764EF741909716B009E6B68 /* SLTableViewCellChildElementsTestViewController.xib */; }; + 9764EF7E19097353009E6B68 /* SLTableViewCell.h in Headers */ = {isa = PBXBuildFile; fileRef = 9764EF7C19097353009E6B68 /* SLTableViewCell.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 9764EF7F19097353009E6B68 /* SLTableViewCell.m in Sources */ = {isa = PBXBuildFile; fileRef = 9764EF7D19097353009E6B68 /* SLTableViewCell.m */; }; + 9764EF8519099714009E6B68 /* SLNavigationBar.h in Headers */ = {isa = PBXBuildFile; fileRef = 9764EF8319099714009E6B68 /* SLNavigationBar.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 9764EF8619099714009E6B68 /* SLNavigationBar.m in Sources */ = {isa = PBXBuildFile; fileRef = 9764EF8419099714009E6B68 /* SLNavigationBar.m */; }; CA75E78216697A1200D57E92 /* SLDevice.h in Headers */ = {isa = PBXBuildFile; fileRef = CA75E78016697A1200D57E92 /* SLDevice.h */; settings = {ATTRIBUTES = (Public, ); }; }; CA75E78516697C0000D57E92 /* SLDevice.m in Sources */ = {isa = PBXBuildFile; fileRef = CA75E78116697A1200D57E92 /* SLDevice.m */; }; CAC388051641CD7500F995F9 /* SLStringUtilities.h in Headers */ = {isa = PBXBuildFile; fileRef = CAC388031641CD7500F995F9 /* SLStringUtilities.h */; settings = {ATTRIBUTES = (Public, ); }; }; @@ -274,6 +286,18 @@ 50F2B7C718E9C0D700F21635 /* SLDispatchTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SLDispatchTests.m; sourceTree = ""; }; 50F3E18A1783A5CB00C6BD1B /* SLGeometry.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SLGeometry.h; sourceTree = ""; }; 50F3E18B1783A5CB00C6BD1B /* SLGeometry.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SLGeometry.m; sourceTree = ""; }; + 9764EF6A1909715E009E6B68 /* SLNavigationBarTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SLNavigationBarTests.m; sourceTree = ""; }; + 9764EF6B1909715E009E6B68 /* SLNavigationBarTestsViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SLNavigationBarTestsViewController.m; sourceTree = ""; }; + 9764EF6C1909715E009E6B68 /* SLNavigationBarTestsViewController.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = SLNavigationBarTestsViewController.xib; sourceTree = ""; }; + 9764EF701909716B009E6B68 /* heart_empty_icon&32.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "heart_empty_icon&32.png"; sourceTree = ""; }; + 9764EF711909716B009E6B68 /* heart_icon&32.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "heart_icon&32.png"; sourceTree = ""; }; + 9764EF721909716B009E6B68 /* SLTableViewCellChildElementsTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SLTableViewCellChildElementsTest.m; sourceTree = ""; }; + 9764EF731909716B009E6B68 /* SLTableViewCellChildElementsTestViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SLTableViewCellChildElementsTestViewController.m; sourceTree = ""; }; + 9764EF741909716B009E6B68 /* SLTableViewCellChildElementsTestViewController.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = SLTableViewCellChildElementsTestViewController.xib; sourceTree = ""; }; + 9764EF7C19097353009E6B68 /* SLTableViewCell.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SLTableViewCell.h; sourceTree = ""; }; + 9764EF7D19097353009E6B68 /* SLTableViewCell.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SLTableViewCell.m; sourceTree = ""; }; + 9764EF8319099714009E6B68 /* SLNavigationBar.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SLNavigationBar.h; sourceTree = ""; }; + 9764EF8419099714009E6B68 /* SLNavigationBar.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SLNavigationBar.m; sourceTree = ""; }; CA75E78016697A1200D57E92 /* SLDevice.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SLDevice.h; sourceTree = ""; }; CA75E78116697A1200D57E92 /* SLDevice.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SLDevice.m; sourceTree = ""; }; CAC388031641CD7500F995F9 /* SLStringUtilities.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SLStringUtilities.h; sourceTree = ""; }; @@ -518,6 +542,28 @@ name = "SLGeometry Tests"; sourceTree = ""; }; + 9764EF6519097135009E6B68 /* SLTableViewCell Tests */ = { + isa = PBXGroup; + children = ( + 9764EF701909716B009E6B68 /* heart_empty_icon&32.png */, + 9764EF711909716B009E6B68 /* heart_icon&32.png */, + 9764EF721909716B009E6B68 /* SLTableViewCellChildElementsTest.m */, + 9764EF731909716B009E6B68 /* SLTableViewCellChildElementsTestViewController.m */, + 9764EF741909716B009E6B68 /* SLTableViewCellChildElementsTestViewController.xib */, + ); + name = "SLTableViewCell Tests"; + sourceTree = ""; + }; + 9764EF6919097141009E6B68 /* SLNavigationBar Tests */ = { + isa = PBXGroup; + children = ( + 9764EF6A1909715E009E6B68 /* SLNavigationBarTests.m */, + 9764EF6B1909715E009E6B68 /* SLNavigationBarTestsViewController.m */, + 9764EF6C1909715E009E6B68 /* SLNavigationBarTestsViewController.xib */, + ); + name = "SLNavigationBar Tests"; + sourceTree = ""; + }; CAC388011641CD4800F995F9 /* Internal */ = { isa = PBXGroup; children = ( @@ -782,6 +828,10 @@ F0C07A371703F95B00C93F93 /* SLAlert.m */, F0C07A451703FEF600C93F93 /* SLButton.h */, F0C07A461703FEF600C93F93 /* SLButton.m */, + 9764EF7C19097353009E6B68 /* SLTableViewCell.h */, + 9764EF7D19097353009E6B68 /* SLTableViewCell.m */, + 9764EF8319099714009E6B68 /* SLNavigationBar.h */, + 9764EF8419099714009E6B68 /* SLNavigationBar.m */, 2CE9AA4A17E3A747007EF0B5 /* SLSwitch.h */, 2CE9AA4B17E3A747007EF0B5 /* SLSwitch.m */, F0C07A511704011300C93F93 /* SLKeyboard.h */, @@ -896,6 +946,8 @@ F0AC80BE16BB542400C5D5C0 /* Tests */ = { isa = PBXGroup; children = ( + 9764EF6919097141009E6B68 /* SLNavigationBar Tests */, + 9764EF6519097135009E6B68 /* SLTableViewCell Tests */, DB2627D817B96704009DA3A6 /* SLStatusBar Tests */, 50A59BD317848CEE002A863A /* SLGeometry Tests */, F07DA31F16E439B7004C2282 /* SLAlert Tests */, @@ -1016,6 +1068,7 @@ F0CEDA3116BF5FA5005FE8B9 /* SLTest+Internal.h in Headers */, F016493D16D42E3C000AEB50 /* SLTestController+Internal.h in Headers */, F0C07A381703F95B00C93F93 /* SLAlert.h in Headers */, + 9764EF8519099714009E6B68 /* SLNavigationBar.h in Headers */, F0C07A3F1703F9A900C93F93 /* SLUIAElement+Subclassing.h in Headers */, F0C07A471703FEF600C93F93 /* SLButton.h in Headers */, F0C07A4B1704002100C93F93 /* SLTextField.h in Headers */, @@ -1035,6 +1088,7 @@ F04346A7175AD10200D91F7F /* NSObject+SLVisibility.h in Headers */, F0A3F63417A715AE007529C3 /* SLTextView.h in Headers */, DB501DC917B9669A001658CB /* SLStatusBar.h in Headers */, + 9764EF7E19097353009E6B68 /* SLTableViewCell.h in Headers */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -1205,10 +1259,13 @@ 068D3E4D16DE9008004E7E28 /* SLTableViewChildElementMatchingTestViewController.xib in Resources */, 0696BA5A16E013D600DD70CF /* SLElementDraggingTestViewController.xib in Resources */, F01EBC9E1701429400FF6A7C /* SLWebTextField.html in Resources */, + 9764EF6F1909715F009E6B68 /* SLNavigationBarTestsViewController.xib in Resources */, F077D70F16D9D77900908FF5 /* SLElementVisibilityTestCovered.xib in Resources */, F090AE7016D9E01D000F0B6F /* SLElementVisibilityTestHidden.xib in Resources */, F090AE7116D9E01D000F0B6F /* SLElementVisibilityTestLowAlpha.xib in Resources */, + 9764EF761909716B009E6B68 /* heart_icon&32.png in Resources */, F090AE7216D9E01D000F0B6F /* SLElementVisibilityTestOffscreen.xib in Resources */, + 9764EF791909716B009E6B68 /* SLTableViewCellChildElementsTestViewController.xib in Resources */, F090AE7416D9E1D1000F0B6F /* SLElementVisibilityTestSuperviewHidden.xib in Resources */, F0E80D8816DB2CEB00945D25 /* SLElementVisibilityTestElementContainerHidden.xib in Resources */, F0E80D8916DB2CEB00945D25 /* SLElementVisibilityTestElementCovered.xib in Resources */, @@ -1222,6 +1279,7 @@ 064B6FC7173DCE9A004AB1BF /* SLElementVisibilityWithSubviews.xib in Resources */, F0C27CDF1741694900335A41 /* SLElementStateTestMidpointCovered.xib in Resources */, F0C27CE917416EC400335A41 /* SLElementStateTestCompletelyCovered.xib in Resources */, + 9764EF751909716B009E6B68 /* heart_empty_icon&32.png in Resources */, F00800C9174B3349001927AC /* SLButtonTestViewController.xib in Resources */, F00F3B5E1778E05100119580 /* SLElementTapTestScrollViewCases.xib in Resources */, F00F3B6717790B4C00119580 /* SLStaticElementTestScrollView.xib in Resources */, @@ -1297,9 +1355,11 @@ F0271B00162E0B950098F5F2 /* SLTestController+AppHooks.m in Sources */, F02DF30917EC064F00BE28BF /* UIScrollView+SLProgrammaticScrolling.m in Sources */, CAC388061641CD7500F995F9 /* SLStringUtilities.m in Sources */, + 9764EF7F19097353009E6B68 /* SLTableViewCell.m in Sources */, CAC388401643503C00F995F9 /* NSObject+SLAccessibilityHierarchy.m in Sources */, CA75E78516697C0000D57E92 /* SLDevice.m in Sources */, F0C07A391703F95B00C93F93 /* SLAlert.m in Sources */, + 9764EF8619099714009E6B68 /* SLNavigationBar.m in Sources */, F0C07A481703FEF600C93F93 /* SLButton.m in Sources */, F0C07A4C1704002100C93F93 /* SLTextField.m in Sources */, F0C07A501704009E00C93F93 /* SLWindow.m in Sources */, @@ -1327,6 +1387,7 @@ F0AC80A416BB299500C5D5C0 /* SLIntegrationTestsAppDelegate.m in Sources */, F0AC80BD16BB50FF00C5D5C0 /* SLTestsViewController.m in Sources */, F0AC80C416BC355D00C5D5C0 /* SLTerminalTest.m in Sources */, + 9764EF6E1909715F009E6B68 /* SLNavigationBarTestsViewController.m in Sources */, F0AC80C116BB559F00C5D5C0 /* SLIntegrationTest.m in Sources */, F0AC80C816BC367E00C5D5C0 /* SLTestViewController.m in Sources */, F078C04A1808BF24000767D2 /* SLWebViewTestViewController.m in Sources */, @@ -1358,13 +1419,16 @@ F05D2B071746B55C0089DB9E /* SLStaticElementTestViewController.m in Sources */, F00800C7174B3349001927AC /* SLButtonTest.m in Sources */, F00800C8174B3349001927AC /* SLButtonTestViewController.m in Sources */, + 9764EF781909716B009E6B68 /* SLTableViewCellChildElementsTestViewController.m in Sources */, F00800E2174C2E0A001927AC /* SLPopoverTest.m in Sources */, F00800E3174C2E0A001927AC /* SLPopoverTestViewController.m in Sources */, 0640035A178FDE7800479173 /* SLElementTouchAndHoldTestViewController.m in Sources */, F0A3F63D17A7172E007529C3 /* SLTextViewTest.m in Sources */, F0A3F63E17A7172E007529C3 /* SLTextViewTestViewController.m in Sources */, + 9764EF6D1909715E009E6B68 /* SLNavigationBarTests.m in Sources */, DB2627DE17B96727009DA3A6 /* SLStatusBarTest.m in Sources */, F078C0491808BF24000767D2 /* SLWebViewTest.m in Sources */, + 9764EF771909716B009E6B68 /* SLTableViewCellChildElementsTest.m in Sources */, DB2627DF17B96727009DA3A6 /* SLStatusBarTestViewController.m in Sources */, 50A59BD81784908D002A863A /* SLGeometryTest.m in Sources */, 50A59BDB178490C2002A863A /* SLGeometryTestViewController.m in Sources */,