Skip to content
New issue

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

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

Already on GitHub? # to your account

Button text matching fails on Android due to default all-caps styling #1135

Closed
d4vidi opened this issue Jan 29, 2019 · 15 comments
Closed

Button text matching fails on Android due to default all-caps styling #1135

d4vidi opened this issue Jan 29, 2019 · 15 comments
Assignees

Comments

@d4vidi
Copy link
Collaborator

d4vidi commented Jan 29, 2019

Description

Starting SDK v21 (Material Design), by default, text set in native Button views appear all-caps. This is according to the guidelines, so RN doesn't provide an API to override that, and - as a matter of fact, it isn't easy to override that in native Android as well.
Therefore, looking up a button element by text using Detox API typically fails on Android while it works on iOS, since the provided text typically isn't all-caps.

Steps to Reproduce

Create a single-screen app with a single button with the text 'tap me'.
The following test code will fail:

await expect(element(by.text('tap me')).toBeVisible();

Device and verbose Detox logs

Typically error saying the element doesn't exist in the hierarchy.

@d4vidi d4vidi self-assigned this Jan 29, 2019
@rotemmiz
Copy link
Member

Yes, but, why not use id matchers?

@d4vidi
Copy link
Collaborator Author

d4vidi commented Jan 29, 2019

An id based matcher is always better, question is what to do with the by.text() api we support.
I'm inclined to say that with the fairly low cost of fixing this (solution being a case insensitive comparison when it comes to button views) we should seriously consider it.

@LeoNatan
Copy link
Contributor

This is why matching by text is a terrible that should be discouraged. Case-insensitive search might introduce the opposite, where a "DEFAULT" button and "default" text field are both matched incorrectly. I don't think this should be pushed. Whoever is using text-based matching should do the work themselves to support this behavior, or move to a proper way to match their views.

@yogeshthanvi
Copy link

In my case it is awesome when i am using app string dynamically to identify a button or label rather than hardcoing them in automation scripts

@d4vidi
Copy link
Collaborator Author

d4vidi commented Jan 31, 2019

@LeoNatan they will not be matched incorrectly, but correctly. On Android all permutations of the casing of the word "default" are the same, because what end up on the screen is "DEFAULT".
Nevertheless I will try to check whether the native Button somehow holds the original text set into it, and will compare it to it instead.

@LeoNatan
Copy link
Contributor

I mean other elements. Not all elements are caps. If you have a label with "default" and a button with "DEFAULT", you would hit both views.

@d4vidi
Copy link
Collaborator Author

d4vidi commented Jan 31, 2019

The plan is to apply this logic only to button objects, where the all-caps styling is enabled.

@LeoNatan
Copy link
Contributor

If you query a button object for its text in code, does it return the caps string or the original string?

@d4vidi
Copy link
Collaborator Author

d4vidi commented Jan 31, 2019

I suppose that if it had returned the original string out of the box we wouldn't be dealing with this issue right now.

@LeoNatan
Copy link
Contributor

LeoNatan commented Jan 31, 2019

So why not write a custom matcher that checks the original string?

@rotemmiz
Copy link
Member

The original string doesn't exist anywhere in the view object IIRC.
I suggest we won't try to solve it, and use id matchers wherever possible. If there's a usecase which is not solvable with IDs let's discuss that specifically.

@d4vidi
Copy link
Collaborator Author

d4vidi commented Jan 31, 2019

I'm willing to give it a shot. If it takes more than 1 hour, drop it.

@d4vidi
Copy link
Collaborator Author

d4vidi commented Feb 11, 2019

After putting in some effort into solving this, here are the conclusions:

  1. Creating and applying a custom matcher as discussed is easy.
  2. In react native, Button components do not map to native buttons. They are just touchables with a background. See impl. here.

All in all, this makes it really hard for the custom matcher to distinguish plaintext views from "button" views. The only lead here is the accessibility roles/traits that are inherently set to "button" on the JS side. It is likely that this info is somehow propagated to the native side, but its not trivial to find out how and thus it is not a <1hr task.

(tl;dr Won't fix)

@LeoNatan
Copy link
Contributor

Jesus, so they hardcode the uppercase string in Android. This is why RN is terrible. 🤦‍♂️

@d4vidi
Copy link
Collaborator Author

d4vidi commented Feb 11, 2019

Yes. It's VERY unfortunate.

@lock lock bot locked as resolved and limited conversation to collaborators Feb 14, 2019
# for free to subscribe to this conversation on GitHub. Already have an account? #.
Projects
None yet
Development

No branches or pull requests

4 participants