Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix multiple elements matched when dealing with nested scrollviews. #896

Merged
merged 4 commits into from
Aug 22, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
90 changes: 64 additions & 26 deletions detox/ios/Detox/GREYMatchers+Detox.m
Original file line number Diff line number Diff line change
Expand Up @@ -48,41 +48,79 @@ @implementation GREYMatchers (Detox)

}

+ (id<GREYMatcher>)detoxMatcherForScrollChildOfMatcher:(id<GREYMatcher>)matcher
id<GREYMatcher> detox_grey_parent(id<GREYMatcher> ancestorMatcher)
{
// find scroll views in a more robust way, either the original matcher already points to a UIScrollView
// and if it isn't look for a child under it that is a UIScrollView
return grey_anyOf(grey_allOf(grey_anyOf(grey_kindOfClass([UIScrollView class]),
grey_kindOfClass([UIWebView class]),
nil),
matcher,
nil),
grey_allOf(grey_kindOfClass([UIScrollView class]),
grey_ancestor(matcher),
MatchesBlock matches = ^BOOL(id element)
{
id parent = nil;

if ([element isKindOfClass:[UIView class]])
{
parent = [element superview];
} else {
parent = [element accessibilityContainer];
}

if (parent && [ancestorMatcher matches:parent])
{
return YES;
}

return NO;
};
DescribeToBlock describe = ^void(id<GREYDescription> description)
{
[description appendText:[NSString stringWithFormat:@"parentThatMatches(%@)",
ancestorMatcher]];
};
return grey_allOf(grey_anyOf(grey_kindOfClass([UIView class]),
grey_respondsToSelector(@selector(accessibilityContainer)),
nil),
[[GREYElementMatcherBlock alloc] initWithMatchesBlock:matches descriptionBlock:describe],
nil);
}

+ (id<GREYMatcher>)detoxMatcherForScrollChildOfMatcher:(id<GREYMatcher>)matcher
{
//No RN—Life is always good.
Class RN_RCTScrollView = NSClassFromString(@"RCTScrollView");
if (!RN_RCTScrollView)
{
return matcher;
}

//Either take scroll views or web views that match the provided matcher, or take views whose parent is a RCTScrollView subclass and the parent matches the provided matcher.
return grey_anyOf(grey_allOf(
grey_anyOf(grey_kindOfClass([UIScrollView class]),
grey_kindOfClass([UIWebView class]),
nil),
matcher,
nil),
grey_allOf(detox_grey_parent(grey_kindOfClass(RN_RCTScrollView)),
grey_kindOfClass([UIScrollView class]),
detox_grey_parent(matcher),
nil),
nil);
}

+ (id<GREYMatcher>)detoxMatcherAvoidingProblematicReactNativeElements:(id<GREYMatcher>)matcher
{
Class RN_RCTScrollView = NSClassFromString(@"RCTScrollView");
if (!RN_RCTScrollView)
{
return matcher;
}
// RCTScrollView is problematic because EarlGrey's visibility matcher adds a subview and this causes a RN assertion
// solution: if we match RCTScrollView, switch over to matching its contained UIScrollView
return grey_anyOf(grey_allOf(matcher,
grey_not(grey_kindOfClass(RN_RCTScrollView)),
//No RN—Life is always good.
Class RN_RCTScrollView = NSClassFromString(@"RCTScrollView");
if (!RN_RCTScrollView)
{
return matcher;
}
//Either take items which are not RCTScrollView subclasses and match the provided matcher, or take items whose parent is RCTScrollView and the parent matches the provided matcher.
return grey_anyOf(
grey_allOf(grey_not(grey_kindOfClass(RN_RCTScrollView)),
matcher,
nil),
grey_allOf(grey_kindOfClass([UIScrollView class]),
grey_ancestor(grey_allOf(matcher,
grey_kindOfClass(RN_RCTScrollView),
nil)),
grey_allOf(detox_grey_parent(grey_kindOfClass(RN_RCTScrollView)),
detox_grey_parent(matcher),
nil),
nil);
nil);
}

+ (id<GREYMatcher>)detoxMatcherForBoth:(id<GREYMatcher>)firstMatcher and:(id<GREYMatcher>)secondMatcher
Expand Down
6 changes: 3 additions & 3 deletions detox/test/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -37,18 +37,18 @@
"binaryPath": "ios/build/Build/Products/Debug-iphonesimulator/example.app",
"build": "set -o pipefail && xcodebuild -project ios/example.xcodeproj -scheme example_ci -configuration Debug -sdk iphonesimulator -derivedDataPath ios/build | xcpretty",
"type": "ios.simulator",
"name": "iPhone 8 Plus"
"name": "iPhone X"
},
"ios.sim.release": {
"binaryPath": "ios/build/Build/Products/Release-iphonesimulator/example.app",
"build": "set -o pipefail && export CODE_SIGNING_REQUIRED=NO && export RCT_NO_LAUNCH_PACKAGER=true && xcodebuild -project ios/example.xcodeproj -scheme example_ci -configuration Release -sdk iphonesimulator -derivedDataPath ios/build | xcpretty",
"type": "ios.simulator",
"name": "iPhone 8 Plus"
"name": "iPhone X"
},
"ios.none": {
"binaryPath": "ios",
"type": "ios.none",
"name": "iPhone 8 Plus",
"name": "iPhone X",
"session": {
"server": "ws://localhost:8099",
"sessionId": "test"
Expand Down