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

Nested ScrollView cause "Multiple UI elements match" #164

Closed
rumax opened this issue Jun 12, 2017 · 28 comments
Closed

Nested ScrollView cause "Multiple UI elements match" #164

rumax opened this issue Jun 12, 2017 · 28 comments

Comments

@rumax
Copy link

rumax commented Jun 12, 2017

Nested ScrollView cause Multiple UI elements match

Steps to reproduce

it('should be visible', async () => {
    await expect(element(by.id('vScrollView'))).toBeVisible();
});
it('should swipe', async () => {
    await element(by.id('vScrollView')).swipe('up', 'fast');
});

it('should scroll', async () => {
    await element(by.id('vScrollView')).scroll(500, 'down');
});

Actual result:

detox info 5: com.wix.demo.react.native launched 
  Example
    ✓ should have welcome screen (793ms)
    ✓ should show hello screen after tap (364ms)
    ✓ should show world screen after tap (360ms)
    1) should be visible


  3 passing (15s)
  1 failing

  1) Example should be visible:
     Error: Multiple UI elements matched for given criteria.
Exception with Assertion: {
  "Assertion Criteria" : "assertWithMatcher: matcherForSufficientlyVisible(>=0.750000)",
  "Element Matcher" : "(((respondsToSelector(accessibilityIdentifier) && accessibilityID('vScrollView')) && !kindOfClass('RCTScrollView')) || (kindOfClass('UIScrollView') && ((kindOfClass('UIView') || respondsToSelector(accessibilityContainer)) && ancestorThatMatches(((respondsToSelector(accessibilityIdentifier) && accessibilityID('vScrollView')) && kindOfClass('RCTScrollView'))))))",
  "Recovery Suggestion" : "Create a more specific matcher to narrow matched element"
}

Error Trace: [
  {
    "Description" : "Multiple elements were matched: (
    "<RCTCustomScrollView:0x7f85bb091000; AX=N; AX.frame={{0, 0}, {414, 736}}; AX.activationPoint={207, 368}; AX.traits='UIAccessibilityTraitNone'; AX.focused='N'; frame={{0, 0}, {414, 736}}; opaque; alpha=1>",
    "<RCTCustomScrollView:0x7f85ba833a00; AX=N; AX.frame={{0, 154}, {414, 100}}; AX.activationPoint={207, 204}; AX.traits='UIAccessibilityTraitNone'; AX.focused='N'; frame={{0, 0}, {414, 100}}; opaque; alpha=1>"
). Please use selection matchers to narrow the selection down to single element.",
    "Domain" : "com.google.earlgrey.ElementInteractionErrorDomain",
    "Code" : "5",
    "File Name" : "GREYElementInteraction.m",
    "Function Name" : "-[GREYElementInteraction grey_errorForMultipleMatchingElements:withMatchedElementsIndexOutOfBounds:]",
    "Line" : "910"
  }
]

Expected result

detox info 5: com.wix.demo.react.native launched 
  Example
    ✓ should have welcome screen (830ms)
    ✓ should show hello screen after tap (367ms)
    ✓ should show world screen after tap (328ms)
    ✓ should be visible (254ms)
    ✓ should swipe (471ms)
    ✓ should scroll (4822ms)


  6 passing (22s)
@abrel
Copy link

abrel commented Jul 15, 2017

I am also facing this issue with nested scrollViews. Is there any known workaround?

@rumax
Copy link
Author

rumax commented Jul 15, 2017

Is there any known workaround?

I use slow swipe

@abrel
Copy link

abrel commented Jul 16, 2017

In my case, I got the same error using scroll and swipe

@holleB
Copy link

holleB commented Aug 31, 2017

Looks like

async scroll(amount, direction = 'down') {
    // override the user's element selection with an extended matcher that looks for UIScrollView children
    this._selectElementWithMatcher(this._originalMatcher._extendToDescendantScrollViews());
    return await new ActionInteraction(this, new ScrollAmountAction(direction, amount)).execute();
}

in detox/src/ios/expect.js.

Could you explain why the matcher should descend to subviews by default? Would be nice to know if it's necessary before I try to implement something like scrollToWithoutDescendant.

@anton6
Copy link

anton6 commented Nov 27, 2017

@LeoNatan Hi. Is there any progress on this issue?

@holleB have you managed to write your custom scroller "scrollToWithoutDescendant"? Did it work?

@holleB
Copy link

holleB commented Nov 27, 2017

@anton6 No, I did try it. But I lacked the time to dive deep enough into the code to make it work.

@whiffsalot
Copy link

We had the same issue trying to scroll when selecting the outer scrollview. There was not a scrollview, but a FlatList nested within. Tried adding the fix in #458, but it didn't seem to change the error. We removed the flatlist, and just went with an array of elements in the meantime.

@LeoNatan
Copy link
Contributor

@kylemellander Could you please comment on the PR, stating your problem?

@Jhonte
Copy link

Jhonte commented Feb 24, 2018

Hm I have the same problem, but instead of nested scrollviews I have one scrollview and one textinput with multiple lines set to true.

I only state the testID on the scrollview this action:
await element(by.id('profile-scroll-view')).scrollTo('bottom')
returns
Error: Error: Multiple UI elements matched for the given criteria.

And atIndex(0) usage like this:
await element(by.id('profile-scroll-view')).atIndex(0).scrollTo('bottom')
`
does not change the behaviour at all... some tips?

@nezaidu
Copy link

nezaidu commented Mar 13, 2018

Any progress?

@LeoNatan
Copy link
Contributor

We'll look at this soon. Thanks

@compojoom
Copy link

compojoom commented Apr 18, 2018

@LeoNatan - can we set some higher priority on this? I have the same issue as @Jhonte

I have a <ScrollView testID={"scrollViewCompanyForm"}> and inside it I have a <TextInput multiple="true" /> and when I try to scroll my scrollView I get multiple elements were matched. This is strange as I'm doing a direct match by id, so I don't understand why the system would match a decending element? What I also don't understand is why is it matchin my textInput as it doesn't seem to be from type RCTSCrollView
grafik

my test code

await expect(element(by.id('companyForm'))).toBeVisible();
      await element(by.id('scrollViewCompanyForm')).scrollTo('bottom');

and here is the RN code:

<KeyboardAvoidingView style={{flex: 1}}
                            keyboardVerticalOffset={64}
                            behavior="padding"
                            testID={"companyForm"}
      >
        <ScrollView style={{flex: 1}}
                    overScrollMode={'always'}
                    testID={"scrollViewCompanyForm"}
                    keyboardShouldPersistTaps={'handled'} keyboardDismissMode="interactive"
        >

          ....
</ScrollView>
</KeyboardAvoidingView>

I've tried matching for the companyForm and then doing withDescendant. I tried matchin for scrollViewCompanyForm and then doing withAscending. I tried indexAt - it doesn't work.

If I add the changes from this PR: https://github.com/wix/detox/pull/458/files to scrollTo. basically just this.atIndex(0); -> then my view is scrolled...

@Protothor
Copy link

So, here's the hack my team used to fix this problem...
in our package.json scripts section we added a "postinstall"

scripts: {
  "postinstall": "node ./postinstall.js"
},

and then we added the fix from PR 458 into the postinstall.js

var fs = require('fs');
fs.readFile('./node_modules/detox/src/ios/expect.js', 'utf8', function (err,data) {
  if (err) {
    return console.log(err);
  }
  if (data.indexOf('this._selectElementWithMatcher(this._originalMatcher._extendToDescendantScrollViews()); this.atIndex(0);')) return;
  var result = data.replace(/this\._selectElementWithMatcher\(this\._originalMatcher\._extendToDescendantScrollViews\(\)\);/g, 'this._selectElementWithMatcher(this._originalMatcher._extendToDescendantScrollViews()); this.atIndex(0);');
  var result = result.replace(/this\._selectElementWithMatcher\(this\._originalMatcher\._avoidProblematicReactNativeElements\(\)\);/g, 'this._selectElementWithMatcher(this._originalMatcher._avoidProblematicReactNativeElements()); this.atIndex(0);');
  fs.writeFile('./node_modules/detox/src/ios/expect.js', result, 'utf8', function (err) {
     if (err) return console.log(err);
  });
});

@benadamstyles
Copy link

An alternative option is https://github.com/ds300/patch-package which automates this process of manually patching an npm package and makes it safer by committing the patch to git.

@JakeHiggins
Copy link

JakeHiggins commented May 16, 2018

@Protothor, any status on the pull request for this? it was closed 5 days ago for inactivity.

@heuism
Copy link

heuism commented May 17, 2018

@Protothor I tried the approach you put. However, It doesn't seems to be working with nested scrollview or maybe the one I am using is 1 scrollview outside and a flatlist inside? Thank you.

@moQuez
Copy link

moQuez commented May 30, 2018

I just used @Protothor approach but with @Leeds-eBooks patch-package recommendation... Works like a charm...

@adamgeoffrion
Copy link

Is there any update on a possible fix/PR for this?

@carlosvega20
Copy link

carlosvega20 commented Jun 29, 2018

I got similar log error with multiple RCTCustomScrollView:

Error: Multiple UI elements matched for given criteria.
    Exception with Assertion: {
      "Assertion Criteria" : "assertWithMatcher:matcherForSufficientlyVisible(>=0.750000)",
      "Element Matcher" : "(((respondsToSelector(accessibilityIdentifier) && accessibilityID('view_calendar')) && !(kindOfClass('RCTScrollView'))) || (kindOfClass('UIScrollView') && ((kindOfClass('UIView') || respondsToSelector(accessibilityContainer)) && ancestorThatMatches(((respondsToSelector(accessibilityIdentifier) && accessibilityID('view_calendar')) && kindOfClass('RCTScrollView'))))))",
      "Recovery Suggestion" : "Create a more specific matcher to narrow matched element"
    }

    Error Trace: [
      {
        "Description" : "Multiple elements were matched: (
        "<RCTCustomScrollView:0x7ff8328bc800; AX=N; AX.frame={{0, 128}, {414, 553}}; AX.activationPoint={207, 404.5}; AX.traits='UIAccessibilityTraitNone'; AX.focused='N'; frame={{0, 0}, {414, 553}}; opaque; alpha=1>",
        "<RCTCustomScrollView:0x7ff83287c600; AX=N; AX.frame={{0, 196}, {414, 21.333333333333343}}; AX.activationPoint={207, 206.66666666666669}; AX.traits='UIAccessibilityTraitNone'; AX.focused='N'; frame={{0, 0}, {414, 21.333333333333332}}; opaque; alpha=1>",
        "<RCTCustomScrollView:0x7ff8320bba00; AX=N; AX.frame={{0, 146}, {414, 49}}; AX.activationPoint={207, 170.5}; AX.traits='UIAccessibilityTraitNone'; AX.focused='N'; frame={{0, 0}, {414, 49}}; opaque; alpha=1>"

I am using native-base UI components. I found adding 'testID' to Component creates the issue.

My way to fixed temporally, by using other component with testID or using from react-native.

NOTE: Note sure why Content create multiple elements, pending investigation.

@stale
Copy link

stale bot commented Aug 18, 2018

This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs.
If you believe the issue is still relevant, please test on the latest Detox and report back.
Thank you for your contributions.

@stale stale bot added the 🏚 stale label Aug 18, 2018
@compojoom
Copy link

compojoom commented Aug 18, 2018

@LeoNatan would you mind commenting on this? To me it seems as a major bug that some of us are going around by applying a patch. Are you guys not running into this issue? that is the first problem I ran when I started using detox...

@LeoNatan
Copy link
Contributor

We have not run into this issue, and I am not actively working on Detox right now. If someone wants to debug this and submit a PR with a fix (or at least an analysis of where the issue lies), that would be great.

@LeoNatan
Copy link
Contributor

@compojoom Can you quickly please create a small demo project reproducing the issue?

@compojoom
Copy link

will send you a link this afternoon.

@compojoom
Copy link

@LeoNatan there you go https://github.com/compojoom/DetoxScrollBug

@LeoNatan
Copy link
Contributor

Excellent, thank you

@LeoNatan
Copy link
Contributor

Good news, we might fix this soon. See #896

LeoNatan added a commit that referenced this issue Aug 22, 2018
…896)

* Fix multiple elements matched when dealing with scrollviews.

* Remove unneeded matcher creator

* Fix oops + style

* Further refine matchers to prevent false positives in the native world.

Closes #164
@LeoNatan
Copy link
Contributor

Please test and let us know if the fix solved your problem. Thank you

@lock lock bot locked as resolved and limited conversation to collaborators Aug 26, 2018
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

No branches or pull requests