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

Unable to select value from picker #798

Closed
matthewrfindley opened this issue Jun 27, 2018 · 10 comments
Closed

Unable to select value from picker #798

matthewrfindley opened this issue Jun 27, 2018 · 10 comments

Comments

@matthewrfindley
Copy link
Contributor

Description

Using detox to select a value from a picker appears to be broken on IOS. Using a testID on a Picker or using UIPickerView have different results as seen below. This could be a result of any number of things going wrong in the dependency chain, but I figured the detox community may know the answer. I've added a spec to the e2e tests to isolate the issue. You can find the branch here.

Steps to Reproduce

Detox, Node, Device, Xcode and macOS Versions

  • Detox: 7.4.3
  • React Native: 0.51 (in detox repo)
  • Node: 8.11.1
  • Device: iPhone 8 Plus - 11.4
  • Xcode: 9.4.1
  • macOS: 10.13.5

Device and verbose Detox logs

✗ :ios: Picker picker should trigger change handler correctly using testID
 ● :ios: Picker › picker should trigger change handler correctly using testID

    Error: Cannot find UI element.
    Exception with Action: {
      "Action Name" : "Set picker column 0 to value 'Bar'",
      "Element Matcher" : "(((respondsToSelector(accessibilityIdentifier) && accessibilityID('FooPicker')) && !(kindOfClass('RCTScrollView'))) || (kindOfClass('UIScrollView') && ((kindOfClass('UIView') || respondsToSelector(accessibilityContainer)) && ancestorThatMatches(((respondsToSelector(accessibilityIdentifier) && accessibilityID('FooPicker')) && kindOfClass('RCTScrollView'))))))",
      "Recovery Suggestion" : "Check if the element exists in the UI hierarchy printed below. If it exists, adjust the matcher so that it accurately matches element."
    }

    Error Trace: [
      {
        "Description" : "Interaction cannot continue because the desired element was not found.",
        "Error Domain" : "com.google.earlgrey.ElementInteractionErrorDomain",
        "Error Code" : "0",
        "File Name" : "GREYElementInteraction.m",
        "Function Name" : "-[GREYElementInteraction matchedElementsWithTimeout:error:]",
        "Line" : "124"
      }
    ]

      71 |     // when this test run fails, we want a stack trace from up here where the
      72 |     // $callee is still available, and not inside the catch block where it isn't
    > 73 |     const potentialError = new Error()
      74 |
      75 |     try {
      76 |       await this.sendAction(new actions.Invoke(invocation));

      at Client.execute (../../src/client/Client.js:73:28)
      at InvocationManager.execute (../../src/invoke.js:11:33)
      at ActionInteraction.execute (../../src/ios/expect.js:178:29)
      at Element.setColumnToValue (../../src/ios/expect.js:306:86)
      at Object.it (20.picker.test.js:10:39)
send: {"type":"invoke","params":{"target":{"type":"Invocation","value":{"target":{"type":"EarlGrey","value":"instance"},"method":"detox_selectElementWithMatcher:","args":[{"type":"Invocation","value":{"target":{"type":"Class","value":"GREYMatchers"},"method":"matcherForAccessibilityID:","args":[{"type":"NSString","value":"FooPicker"}]}}]}},"method":"performAction:","args":[{"type":"Invocation","value":{"target":{"type":"Class","value":"GREYActions"},"method":"actionForSetPickerColumn:toValue:","args":[{"type":"NSInteger","value":0},{"type":"NSString","value":"Bar"}]}}]},"messageId":3}
 onMessage: {"type":"testFailed","messageId":3,"params":{"details":"Cannot find UI element.\nException with Action: {\n  \"Action Name\" : \"Set picker column 0 to value 'Bar'\",\n  \"Element Matcher\" : \"(((respondsToSelector(accessibilityIdentifier) && accessibilityID('FooPicker')) && !(kindOfClass('RCTScrollView'))) || (kindOfClass('UIScrollView') && ((kindOfClass('UIView') || respondsToSelector(accessibilityContainer)) && ancestorThatMatches(((respondsToSelector(accessibilityIdentifier) && accessibilityID('FooPicker')) && kindOfClass('RCTScrollView'))))))\",\n  \"Recovery Suggestion\" : \"Check if the element exists in the UI hierarchy printed below. If it exists, adjust the matcher so that it accurately matches element.\"\n}\n\nError Trace: [\n  {\n    \"Description\" : \"Interaction cannot continue because the desired element was not found.\",\n    \"Error Domain\" : \"com.google.earlgrey.ElementInteractionErrorDomain\",\n    \"Error Code\" : \"0\",\n    \"File Name\" : \"GREYElementInteraction.m\",\n    \"Function Name\" : \"-[GREYElementInteraction matchedElementsWithTimeout:error:]\",\n    \"Line\" : \"124\"\n  }\n]"}}
✗ :ios: Picker picker should trigger change handler correctly using type
 ● :ios: Picker › picker should trigger change handler correctly using type

    Error: An action failed. Please refer to the error trace below.
    Exception with Action: {
      "Action Name" : "Set picker column 0 to value 'Bar'",
      "Element Matcher" : "((kindOfClass('UIPickerView') && !(kindOfClass('RCTScrollView'))) || (kindOfClass('UIScrollView') && ((kindOfClass('UIView') || respondsToSelector(accessibilityContainer)) && ancestorThatMatches((kindOfClass('UIPickerView') && kindOfClass('RCTScrollView'))))))"
    }

    Error Trace: [
      {
        "Description" : "UIPickerView does not contain desired value!",
        "Error Domain" : "com.google.earlgrey.ElementInteractionErrorDomain",
        "Error Code" : "2",
        "File Name" : "GREYPickerAction.m",
        "Function Name" : "-[GREYPickerAction perform:error:]",
        "Line" : "120"
      }
    ]

      71 |     // when this test run fails, we want a stack trace from up here where the
      72 |     // $callee is still available, and not inside the catch block where it isn't
    > 73 |     const potentialError = new Error()
      74 |
      75 |     try {
      76 |       await this.sendAction(new actions.Invoke(invocation));

      at Client.execute (../../src/client/Client.js:73:28)
      at InvocationManager.execute (../../src/invoke.js:11:33)
      at ActionInteraction.execute (../../src/ios/expect.js:178:29)
      at Element.setColumnToValue (../../src/ios/expect.js:306:86)
      at Object.it (20.picker.test.js:18:44)
send: {"type":"invoke","params":{"target":{"type":"Invocation","value":{"target":{"type":"EarlGrey","value":"instance"},"method":"detox_selectElementWithMatcher:","args":[{"type":"Invocation","value":{"target":{"type":"Class","value":"GREYMatchers"},"method":"detoxMatcherForClass:","args":[{"type":"NSString","value":"UIPickerView"}]}}]}},"method":"performAction:","args":[{"type":"Invocation","value":{"target":{"type":"Class","value":"GREYActions"},"method":"actionForSetPickerColumn:toValue:","args":[{"type":"NSInteger","value":0},{"type":"NSString","value":"Bar"}]}}]},"messageId":6}
 onMessage: {"type":"testFailed","messageId":6,"params":{"details":"An action failed. Please refer to the error trace below.\nException with Action: {\n  \"Action Name\" : \"Set picker column 0 to value 'Bar'\",\n  \"Element Matcher\" : \"((kindOfClass('UIPickerView') && !(kindOfClass('RCTScrollView'))) || (kindOfClass('UIScrollView') && ((kindOfClass('UIView') || respondsToSelector(accessibilityContainer)) && ancestorThatMatches((kindOfClass('UIPickerView') && kindOfClass('RCTScrollView'))))))\"\n}\n\nError Trace: [\n  {\n    \"Description\" : \"UIPickerView does not contain desired value!\",\n    \"Error Domain\" : \"com.google.earlgrey.ElementInteractionErrorDomain\",\n    \"Error Code\" : \"2\",\n    \"File Name\" : \"GREYPickerAction.m\",\n    \"Function Name\" : \"-[GREYPickerAction perform:error:]\",\n    \"Line\" : \"120\"\n  }\n]"}}
@rotemmiz
Copy link
Member

Did you try to inspect the view hierarchy and see what's going on ?

@matthewrfindley
Copy link
Contributor Author

I will have a look at the view hierarchy and report back.

@matthewrfindley
Copy link
Contributor Author

matthewrfindley commented Jun 29, 2018

TBH, I am not sure what would be helpful for debugging here.

Both have a hierarchy of UIPickerView with 1 or more UIPickerColumnView.s I would expect executing await element(by.type('UIPickerView')).setColumnToValue(0, 'Bar'); would work for Picker as it does for choosing a time in a date picker as follows (which works) expect targeting a different column.

  await element(by.type('UIPickerView')).setColumnToValue(2, minute)
  await element(by.type('UIPickerView')).setColumnToValue(1, hour)
  await element(by.type('UIPickerView')).setColumnToValue(3, meridiem)

@matthewrfindley
Copy link
Contributor Author

master...matthewrfindley:failing-e2e-picker-test

This is a simple test to reproduce the issue.

@rotemmiz
Copy link
Member

It may be possible that react native doesn't pass testID to native view hierarchy on one of them, but does on the other.
It may also be possible that the testID is not being added at the same hierarchy path (it me set on a wrong view, like a wrapper view).
Anyway, different UI element implementation may have different behavior. It's best to understand the native layout hierarchy with the inspector

@matthewrfindley
Copy link
Contributor Author

The test attempts 2 ways to find the element. by.id causes the test to fail because if does not find the element. This makes sense if the testID is not passed to a native element. by.type fails because it is unable to select the value in the picker. Given that it finds the element and the values are present I'd figure there is something else going on.

@rotemmiz
Copy link
Member

Can you check the accessibility properties of the view you're trying to match? Let's see the value in the picker

@matthewrfindley matthewrfindley changed the title Unable to select value picker value Unable to select value from picker Jul 3, 2018
@matthewrfindley
Copy link
Contributor Author

These are not from the test, but are built using the same react-native Picker and have the same problem outlined in the test. Using setColumnToValue(0, '2') or setColumnToValue(0, 'Week') will produce the same error "UIPickerView does not contain desired value!". There does not appear to be anything out of the ordinary to me.

screen shot 2018-07-03 at 9 38 47 am

screen shot 2018-07-03 at 9 38 54 am

screen shot 2018-07-03 at 9 39 05 am

@stale
Copy link

stale bot commented Aug 17, 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 17, 2018
@stale
Copy link

stale bot commented Aug 24, 2018

The issue has been closed for inactivity.

@stale stale bot closed this as completed Aug 24, 2018
@lock lock bot locked as resolved and limited conversation to collaborators Aug 27, 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

3 participants