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(scrollTo): raise if scroll view element is not hittable. #3115

Merged
merged 20 commits into from
Dec 6, 2021

Conversation

asafkorem
Copy link
Contributor

@asafkorem asafkorem commented Nov 29, 2021

Description

This pull request addresses the issue described here: #2834.

In this pull request, I have reproduced the bug from the issue, by adding more tests to the test-app. Apparently, only the scrollTo didn't work as expected because we don't assert if the called element is hidden by another view or window.

This fixes the bug as we did in all other UI interaction actions (taps, long-presses, date-picking), by raising an assertion when the view is not hittable.

Similar failed tests could be achieved by hiding the scroll view with another view, but I still decided to implement them with UIWindow ("overlay") since it is not tested anywhere in our test suite, and that's an iOS-specific behaviour (in Android we touch the visible screen, and not the window behind the element).

Also, in addition to this fix, I rewrote the mechanism of assertions before interacting with a view (for any UI gesture).

@@ -0,0 +1,46 @@
const { expectToThrow } = require('./utils/custom-expects');

describe(':ios: Overlay', () => {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'll run tomorrow, thanks!

@noomorph
Copy link
Collaborator

@asafkorem maybe I'll mention the obvious, but this change should pass pre-release lifecycle on our Wix internal projects, I guess. Nightly RCs for all the projects.

@asafkorem asafkorem changed the title fix(scrollTo): raise if element is hidden. fix(scrollTo): raise if scroll view element is not hittable. Nov 29, 2021
@asafkorem asafkorem changed the title fix(scrollTo): raise if scroll view element is not hittable. fix(scrollTo): raise if scroll view element is not visible. Nov 29, 2021
Comment on lines 269 to 270
[self dtx_assertVisibleWithPercent:@1];

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't like this.
However, I don't like the current approach also (>=75% visible), what we use in other views actions (see for example), since the view can be half visible and still accessible..

Also, the normalizedStartingPoint is undefined in many cases and then we use some almost-arbitrary point (from one of the edges). Theoretically I could use this point to check whether it's hittable on that point, but then it might result in breakage of tests (where this points are hidden but the view is partially visible, like in 03.actions-scroll.test.js).

Copy link
Contributor Author

@asafkorem asafkorem Nov 29, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It might be the best we can offer for this fix, without breaking the current API much. Of course, I'd like to hear more thoughts..

Copy link
Collaborator

@d4vidi d4vidi Dec 1, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I agree that adding the ≥75 assertion offhand would be reckless, and also will not make sense as long as the percentage cannot be specified by the user.

As for the idea you suggested - checking hittability, I wouldn't get it off the table altogether. But in any case, on Android we essentially do something quite similar to your change with respect to visibility -- asserting the view is non-empty (which means it may actually make sense).

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done ✔️ we will now check hittability instead of visibility.
There's a lot of changes in the new implementation, so this may be effective to review them face to face.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

of course, we should also test it with the latest changes as broadly as possible using the internal wix projects. especially when it adds more assertions to touch actions.

@asafkorem
Copy link
Contributor Author

@wix/detox-team I'll appreciate if one of you can review this change :)

it('should be intractable when overlay is not shown', async () => {
await verticalScrollView.scrollTo('bottom');
await expect(showOverlayButton).not.toBeVisible();
});
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think is not necessary because it is tested in the actions suite

Copy link
Contributor Author

@asafkorem asafkorem Dec 1, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Basically you are right but not really, since I'm testing the whole screen, in this test I made sure that we start from the desired initial state (where the button disappears after scrolling). This covers the case where the scroll view might be not-scrollable (for example, too few items on some screen).

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Still kind of sounds like this:

it('should scroll to edge', async () => {

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I disagree, I'm not testing the functionality of a scroll view, but the expectation from the initial state of this screen. Let's discuss about this f2f?

overlayWindow = [[UIWindow alloc] initWithFrame:screenBounds];

[overlayWindow setWindowLevel:UIWindowLevelStatusBar];
[overlayWindow setBackgroundColor:[UIColor.grayColor colorWithAlphaComponent:0.5]];
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would it make sense to challenge further and use a 0 alpha?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Holy s**t, that's an excellent question!
If the overlying view has a transparent background (or, clearColor), we consider the underlying view as visible. So in this case the views are considered as "visible" but they are not tappable / scrollable.

So it makes a lot of sense, but the tests will break, but we need to cover these cases also since they shouldn't (touch gestures should not pass).

We must have some better mechanism here than just asserting on visibility.

@asafkorem
Copy link
Contributor Author

asafkorem commented Dec 2, 2021

@d4vidi fixed and squashed. I rewrote the mechanism of is-hittable check on iOS.

The guiding logic is:

  • If not point was given, finds a visible point of the view (otherwise the view is not hittable).
  • Finds the topmost window, tries to tap on the visible point, on the topmost window using hitTest.
  • Checks whether the hitted view is the view itself / descendent of the tested view.

The problems that were in the previous check (of is-hittable, which also weren't even in use in some actions):

  • It checked the visibility of the point only, at the given point or on the central point of the visible bounds of the view.
  • It didn't checked whether it passes the hits to another view (for example, a tappable subview).
  • It didn't considered transparent views (with clear-color), as overlying views that can block the hit from getting to the target view.

Some tests are still failing: I'm investigating the reasons. Pushed the current changes for visibility, in case you want to start looking.

As a side note, XCUITest already provide API for isHittable, so when we'll use XCUIT we'll get a much more accurate check.

@asafkorem asafkorem force-pushed the feature/rnn-overlay branch 2 times, most recently from 6af218c to 9ce9eae Compare December 4, 2021 10:44
@asafkorem asafkorem changed the title fix(scrollTo): raise if scroll view element is not visible. fix(scrollTo): raise if scroll view element is not hittable. Dec 4, 2021
// Copyright © 2021 Wix. All rights reserved.
//

#import "UIResponder+First.h"
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ref stackoverflow

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

v

@d4vidi
Copy link
Collaborator

d4vidi commented Dec 5, 2021

  • Descriptive error for when default start point is not hittable (i.e. use offset arg + ref the docs)
  • Add missing assertions in scrolling test with offsets
  • Add expect-to-fail scroll test -- when overlay is shown, in 03.actions.test.js
  • UIScreen etc.

@asafkorem
Copy link
Contributor Author

Changes pushed

Descriptive error for when default start point is not hittable (i.e. use offset arg + ref the docs)

Done ✔️

Add missing assertions in scrolling test with offsets

Done ✔️

Add expect-to-fail scroll test -- when overlay is shown, in 03.actions.test.js

Done ✔️

@asafkorem asafkorem force-pushed the feature/rnn-overlay branch 2 times, most recently from 8d4c744 to e6c4341 Compare December 6, 2021 10:15
Replaces this error message: `View “<RCTView: 0x7fa3020598b0>” is not visible:
View is clipped by one or more of its superviews' bounds and does not pass
visibility percent threshold (7,500)`,

With this error message: `View “<RCTView: 0x7fa3020598b0>” is not visible:
View is clipped by one or more of its superviews' bounds and does not pass
visibility percent threshold (75)`.
Comment on lines 170 to 173
if (device.getPlatform() === 'ios') {
// TODO: investigate why this assertion fails on Android
await expect(element(by.text('Text1'))).not.toBeVisible(1);
}
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This was already TODOed here:

if (device.getPlatform() === 'ios') {
// TODO: investigate why this assertion fails on Android
await expect(element(by.text('Text1'))).not.toBeVisible();
}

@jonathanmos / @d4vidi FYI

Copy link
Contributor Author

@asafkorem asafkorem Dec 6, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actually, it's related to an issue that was reported very recently 😄 , and Amit has reported on that long ago in a RN issue: #3105 (comment), facebook/react-native#23870

@asafkorem asafkorem merged commit b146425 into wix:master Dec 6, 2021
@asafkorem asafkorem deleted the feature/rnn-overlay branch December 6, 2021 16:12
asafkorem added a commit that referenced this pull request Dec 27, 2021
…3115)"

This reverts commit b146425, reversing
changes made to d95b5e7.

# Conflicts:
#	detox/package.json
#	detox/test/package.json
#	examples/demo-native-android/package.json
#	examples/demo-native-ios/package.json
#	examples/demo-react-native-detox-instruments/package.json
#	examples/demo-react-native-jest/package.json
#	examples/demo-react-native/package.json
#	lerna.json
#	package.json

(Resolved by using the current files)
asafkorem added a commit that referenced this pull request Nov 7, 2022
This change reverts #3150, and adds the following changes (hit-test):
- #3149
- #3145
- #3115

Those changes resolves this issue #2834.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Interactive touch outside React-Native-Navigation Overlay when detox run
4 participants