wix / Detox

Gray box end-to-end testing and automation framework for mobile apps
https://wix.github.io/Detox/
MIT License
11.15k stars 1.92k forks source link

Not able to get element from a native List view on Android #4263

Open urbanclap-admin opened 10 months ago

urbanclap-admin commented 10 months ago

What happened?

not able to find an element that is a child of ListView on native Android. the view is native only.

What was the expected behaviour?

it should be able to find the item using the text or id.

Was it tested on latest Detox?

Did your test throw out a timeout?

Help us reproduce this issue!

let address = element( by .id("location_heading") .and(by.text("Coaching Center")) );

In what environment did this happen?

Detox version: 20.13.2 React Native version: 0.67 Has Fabric (React Native's new rendering system) enabled: No Node version: v21.1.0 Device model: Pixel 4 emulator Android version: android 13 Test-runner (select one): jest

Detox logs

Detox logs ``` Test Failed: No views in hierarchy found matching: View at index #0, of those matching MATCHER((view.getTag() is "location_heading" and view has effective visibility ) and (an instance of android.widget.TextView and view.getText() with or without transformation to match: is "Coaching Center" and view has effective visibility )) If the target view is not part of the view hierarchy, you may need to use Espresso.onData to load it from one of the following AdapterViews:android.widget.ListView{a411d38 G.ED.VC.. ......I. 0,0-1080,0 #7f0a04fb app:id/location_screen_place_list aid=1073741836} ```

Device logs

Device logs ``` paste your device.log here! ```

More data, please!

have tried few variations on matchers by using type instead of id, chaining multiple matches and even tried with ancestor to find the parent listview and the child item but none of them seems to work.

urbanclap-admin commented 10 months ago

Tried chaining it with multiple ancestor matchers like below let address = element( by .id("location_heading") .withAncestor( by .id("location_heading_ll") .withAncestor( by .id("location_heading_ll_ll") .withAncestor( by .id("location_heading_ll_ll_ll") .withAncestor(by.id("location_list_parent")) ) ) ) );

this also did not work view hierarchy would looks something like this - ListView -> LinearLayout -> LinearLayout -> LinearLayout -> TextView

urbanclap-admin commented 10 months ago

@noomorph can you please help here?

noomorph commented 10 months ago

Try adb shell uiautomator dump

urbanclap-admin commented 10 months ago

Try adb shell uiautomator dump

here is the dump file

<?xml version='1.0' encoding='UTF-8' standalone='yes' ?><hierarchy rotation="0"><node index="0" text="" resource-id="" class="android.widget.FrameLayout" package="com.urbanclap.urbanclap" content-desc="" checkable="false" checked="false" clickable="false" enabled="true" focusable="false" focused="false" scrollable="false" long-clickable="false" password="false" selected="false" bounds="[0,0][1080,2138]"><node index="0" text="" resource-id="" class="android.widget.LinearLayout" package="com.urbanclap.urbanclap" content-desc="" checkable="false" checked="false" clickable="false" enabled="true" focusable="false" focused="false" scrollable="false" long-clickable="false" password="false" selected="false" bounds="[0,0][1080,2138]"><node index="0" text="" resource-id="" class="android.widget.FrameLayout" package="com.urbanclap.urbanclap" content-desc="" checkable="false" checked="false" clickable="false" enabled="true" focusable="false" focused="false" scrollable="false" long-clickable="false" password="false" selected="false" bounds="[0,136][1080,1507]"><node index="0" text="" resource-id="com.urbanclap.urbanclap:id/action_bar_root" class="android.widget.LinearLayout" package="com.urbanclap.urbanclap" content-desc="" checkable="false" checked="false" clickable="false" enabled="true" focusable="false" focused="false" scrollable="false" long-clickable="false" password="false" selected="false" bounds="[0,136][1080,1507]"><node index="0" text="" resource-id="android:id/content" class="android.widget.FrameLayout" package="com.urbanclap.urbanclap" content-desc="" checkable="false" checked="false" clickable="false" enabled="true" focusable="false" focused="false" scrollable="false" long-clickable="false" password="false" selected="false" bounds="[0,136][1080,1507]"><node index="0" text="" resource-id="" class="android.widget.FrameLayout" package="com.urbanclap.urbanclap" content-desc="" checkable="false" checked="false" clickable="false" enabled="true" focusable="false" focused="false" scrollable="false" long-clickable="false" password="false" selected="false" bounds="[0,136][1080,1507]"><node index="0" text="" resource-id="com.urbanclap.urbanclap:id/locationScreenContainerUi" class="android.view.ViewGroup" package="com.urbanclap.urbanclap" content-desc="" checkable="false" checked="false" clickable="false" enabled="true" focusable="false" focused="false" scrollable="false" long-clickable="false" password="false" selected="false" bounds="[0,136][1080,1507]"><node index="0" text="" resource-id="com.urbanclap.urbanclap:id/toolbar" class="android.widget.LinearLayout" package="com.urbanclap.urbanclap" content-desc="" checkable="false" checked="false" clickable="false" enabled="true" focusable="false" focused="false" scrollable="false" long-clickable="false" password="false" selected="false" bounds="[0,136][1080,521]"><node index="0" text="" resource-id="" class="android.widget.LinearLayout" package="com.urbanclap.urbanclap" content-desc="" checkable="false" checked="false" clickable="false" enabled="true" focusable="false" focused="false" scrollable="false" long-clickable="false" password="false" selected="false" bounds="[0,136][1080,275]"><node index="0" text="" resource-id="com.urbanclap.urbanclap:id/itv_arrow" class="android.widget.TextView" package="com.urbanclap.urbanclap" content-desc="" checkable="false" checked="false" clickable="true" enabled="true" focusable="true" focused="false" scrollable="false" long-clickable="false" password="false" selected="false" bounds="[0,136][132,275]" /><node index="1" text="" resource-id="" class="android.widget.LinearLayout" package="com.urbanclap.urbanclap" content-desc="" checkable="false" checked="false" clickable="false" enabled="true" focusable="false" focused="false" scrollable="false" long-clickable="false" password="false" selected="false" bounds="[132,169][1080,255]"><node index="0" text="" resource-id="" class="android.widget.LinearLayout" package="com.urbanclap.urbanclap" content-desc="" checkable="false" checked="false" clickable="false" enabled="true" focusable="false" focused="false" scrollable="false" long-clickable="false" password="false" selected="false" bounds="[132,169][1080,230]"><node index="0" text="Vikas Puri Cricket Coa" resource-id="com.urbanclap.urbanclap:id/et_search" class="android.widget.EditText" package="com.urbanclap.urbanclap" content-desc="" checkable="false" checked="false" clickable="true" enabled="true" focusable="true" focused="true" scrollable="false" long-clickable="true" password="false" selected="false" bounds="[132,169][964,230]" /><node index="1" text="" resource-id="com.urbanclap.urbanclap:id/itv_clear_search_text" class="android.widget.TextView" package="com.urbanclap.urbanclap" content-desc="" checkable="false" checked="false" clickable="true" enabled="true" focusable="true" focused="false" scrollable="false" long-clickable="false" password="false" selected="false" bounds="[964,172][1014,230]" /></node><node index="1" text="" resource-id="" class="android.view.View" package="com.urbanclap.urbanclap" content-desc="" checkable="false" checked="false" clickable="false" enabled="true" focusable="false" focused="false" scrollable="false" long-clickable="false" password="false" selected="false" bounds="[132,252][1014,255]" /></node></node><node index="1" text="" resource-id="" class="android.widget.LinearLayout" package="com.urbanclap.urbanclap" content-desc="" checkable="false" checked="false" clickable="false" enabled="true" focusable="false" focused="false" scrollable="false" long-clickable="false" password="false" selected="false" bounds="[14,297][1080,433]"><node index="0" text="" resource-id="com.urbanclap.urbanclap:id/uc_animation_bulb_view" class="android.widget.ImageView" package="com.urbanclap.urbanclap" content-desc="" checkable="false" checked="false" clickable="false" enabled="true" focusable="false" focused="false" scrollable="false" long-clickable="false" password="false" selected="false" bounds="[14,310][124,420]" /><node index="1" text="" resource-id="com.urbanclap.urbanclap:id/text_switcher" class="android.widget.TextSwitcher" package="com.urbanclap.urbanclap" content-desc="" checkable="false" checked="false" clickable="false" enabled="true" focusable="false" focused="false" scrollable="false" long-clickable="false" password="false" selected="false" bounds="[124,297][806,433]"><node index="0" text="eg. Marina Road or Redfern or DLF City Phase 4" resource-id="" class="android.widget.TextView" package="com.urbanclap.urbanclap" content-desc="" checkable="false" checked="false" clickable="false" enabled="true" focusable="false" focused="false" scrollable="false" long-clickable="false" password="false" selected="false" bounds="[124,345][806,384]" /></node></node></node><node index="1" text="" resource-id="" class="android.widget.LinearLayout" package="com.urbanclap.urbanclap" content-desc="" checkable="false" checked="false" clickable="false" enabled="true" focusable="false" focused="false" scrollable="false" long-clickable="false" password="false" selected="false" bounds="[0,587][1080,1061]"><node index="1" text="" resource-id="com.urbanclap.urbanclap:id/location_screen_place_list" class="android.widget.ListView" package="com.urbanclap.urbanclap" content-desc="" checkable="false" checked="false" clickable="false" enabled="true" focusable="true" focused="false" scrollable="true" long-clickable="false" password="false" selected="false" bounds="[0,587][1080,895]"><node index="0" text="" resource-id="com.urbanclap.urbanclap:id/container" class="android.widget.LinearLayout" package="com.urbanclap.urbanclap" content-desc="" checkable="false" checked="false" clickable="true" enabled="true" focusable="false" focused="false" scrollable="false" long-clickable="false" password="false" selected="true" bounds="[0,587][1080,697]"><node index="0" text="Delhi" resource-id="com.urbanclap.urbanclap:id/text1" class="android.widget.TextView" package="com.urbanclap.urbanclap" content-desc="" checkable="false" checked="false" clickable="false" enabled="true" focusable="false" focused="false" scrollable="false" long-clickable="false" password="false" selected="false" bounds="[44,626][1080,672]" /></node><node index="1" text="" resource-id="com.urbanclap.urbanclap:id/container" class="android.widget.LinearLayout" package="com.urbanclap.urbanclap" content-desc="" checkable="false" checked="false" clickable="true" enabled="true" focusable="false" focused="false" scrollable="false" long-clickable="false" password="false" selected="false" bounds="[0,697][1080,895]"><node index="0" text="" resource-id="com.urbanclap.urbanclap:id/ll_location_text_container" class="android.widget.LinearLayout" package="com.urbanclap.urbanclap" content-desc="" checkable="false" checked="false" clickable="false" enabled="true" focusable="false" focused="false" scrollable="false" long-clickable="false" password="false" selected="false" bounds="[0,697][1080,895]"><node index="0" text="" resource-id="com.urbanclap.urbanclap:id/icon_text_view" class="android.widget.TextView" package="com.urbanclap.urbanclap" content-desc="" checkable="false" checked="false" clickable="false" enabled="true" focusable="false" focused="false" scrollable="false" long-clickable="false" password="false" selected="false" bounds="[44,741][94,799]" /><node index="1" text="" resource-id="" class="android.widget.LinearLayout" package="com.urbanclap.urbanclap" content-desc="" checkable="false" checked="false" clickable="false" enabled="true" focusable="false" focused="false" scrollable="false" long-clickable="false" password="false" selected="false" bounds="[94,741][1036,851]"><node index="0" text="Vikas Puri Cricket Coaching Center" resource-id="com.urbanclap.urbanclap:id/tv_location_heading" class="android.widget.TextView" package="com.urbanclap.urbanclap" content-desc="" checkable="false" checked="false" clickable="false" enabled="true" focusable="false" focused="false" scrollable="false" long-clickable="false" password="false" selected="false" bounds="[138,741][1036,795]" /><node index="1" text="Block GG 2, Vikaspuri, New Delhi, Delhi, India" resource-id="com.urbanclap.urbanclap:id/tv_location_text" class="android.widget.TextView" package="com.urbanclap.urbanclap" content-desc="" checkable="false" checked="false" clickable="false" enabled="true" focusable="false" focused="false" scrollable="false" long-clickable="false" password="false" selected="false" bounds="[138,806][1036,851]" /></node></node></node></node><node index="2" text="" resource-id="com.urbanclap.urbanclap:id/ll_powered_by_google_container" class="android.widget.LinearLayout" package="com.urbanclap.urbanclap" content-desc="" checkable="false" checked="false" clickable="false" enabled="true" focusable="false" focused="false" scrollable="false" long-clickable="false" password="false" selected="false" bounds="[0,950][1080,1061]"><node index="0" text="" resource-id="" class="android.widget.LinearLayout" package="com.urbanclap.urbanclap" content-desc="" checkable="false" checked="false" clickable="false" enabled="true" focusable="false" focused="false" scrollable="false" long-clickable="false" password="false" selected="false" bounds="[368,1005][712,1061]"><node index="0" text="powered by" resource-id="" class="android.widget.TextView" package="com.urbanclap.urbanclap" content-desc="" checkable="false" checked="false" clickable="false" enabled="true" focusable="false" focused="false" scrollable="false" long-clickable="false" password="false" selected="false" bounds="[368,1005][560,1061]" /><node index="1" text="" resource-id="" class="android.widget.ImageView" package="com.urbanclap.urbanclap" content-desc="" checkable="false" checked="false" clickable="false" enabled="true" focusable="false" focused="false" scrollable="false" long-clickable="false" password="false" selected="false" bounds="[574,1005][712,1052]" /></node></node></node></node><node index="1" text="" resource-id="" class="android.widget.ImageView" package="com.urbanclap.urbanclap" content-desc="" checkable="false" checked="false" clickable="false" enabled="true" focusable="false" focused="false" scrollable="false" long-clickable="false" password="false" selected="false" bounds="[0,1342][1080,1507]" /></node></node></node></node></node><node index="1" text="" resource-id="android:id/statusBarBackground" class="android.view.View" package="com.urbanclap.urbanclap" content-desc="" checkable="false" checked="false" clickable="false" enabled="true" focusable="false" focused="false" scrollable="false" long-clickable="false" password="false" selected="false" bounds="[0,0][1080,136]" /><node index="2" text="" resource-id="android:id/navigationBarBackground" class="android.view.View" package="com.urbanclap.urbanclap" content-desc="" checkable="false" checked="false" clickable="false" enabled="true" focusable="false" focused="false" scrollable="false" long-clickable="false" password="false" selected="false" bounds="[0,0][0,0]" /></node></hierarchy>
noomorph commented 10 months ago

Hmm... Looks like it is tv_location_heading, you mistyped location_heading.

<node index="0" text="Vikas Puri Cricket Coaching Center"
      resource-id="com.urbanclap.urbanclap:id/tv_location_heading"
      class="android.widget.TextView"
      package="com.urbanclap.urbanclap" content-desc=""
      checkable="false" checked="false" clickable="false"
      enabled="true" focusable="false" focused="false"
      scrollable="false" long-clickable="false" password="false"
      selected="false" bounds="[138,741][1036,795]"/>
urbanclap-admin commented 10 months ago

Hmm... Looks like it is tv_location_heading, you mistyped location_heading.

<node index="0" text="Vikas Puri Cricket Coaching Center"
      resource-id="com.urbanclap.urbanclap:id/tv_location_heading"
      class="android.widget.TextView"
      package="com.urbanclap.urbanclap" content-desc=""
      checkable="false" checked="false" clickable="false"
      enabled="true" focusable="false" focused="false"
      scrollable="false" long-clickable="false" password="false"
      selected="false" bounds="[138,741][1036,795]"/>

that is the id of the view not the tag value from which detox actually fetches the view using by.id() matcher

noomorph commented 10 months ago

So, did you check that those tags (location_heading) are present in the hierarchy? Maybe you could avoid long ancestor chains and just use atIndex in case there are multiple instances (although I see only one instance, hm, then why use so specific selectors)?

element(by.id('location_heading')).atIndex(0);

Besides, you can try to inspect your hierarchy with Detox (latest Detox, 20.13.x allows that in Android) – just pick some element type that interests you and query the attributes:

console.log(await element(by.type('android.widget.TextView')).getAttributes());
urbanclap-admin commented 10 months ago

So, did you check that those tags (location_heading) are present in the hierarchy? Maybe you could avoid long ancestor chains and just use atIndex in case there are multiple instances (although I see only one instance, hm, then why use so specific selectors)?

element(by.id('location_heading')).atIndex(0);

Besides, you can try to inspect your hierarchy with Detox (latest Detox, 20.13.x allows that in Android) – just pick some element type that interests you and query the attributes:

console.log(await element(by.type('android.widget.TextView')).getAttributes());

none of the suggestions work sadly

just tried various combinations to check if something works, not sure why it is not working, would really appreciate ur help here

noomorph commented 10 months ago

And what do you see there?

console.log(await element(by.type('android.widget.TextView')).getAttributes());

urbanclap-admin commented 10 months ago
``` detox[72366] i user { elements: [ { visibility: 'visible', visible: true, label: 'Or', alpha: 1, elevation: 0, height: 55, width: 49, focused: false, enabled: true, text: 'Or', length: 2, textSize: 39 }, { visibility: 'visible', visible: true, label: '', alpha: 1, elevation: 0, height: 139, width: 132, focused: false, enabled: true, text: '', length: 1, textSize: 44 }, { visibility: 'visible', visible: true, label: 'eg. Marina Road or Redfern or DLF City Phase 4', alpha: 1, elevation: 0, height: 39, width: 682, focused: false, enabled: true, text: 'eg. Marina Road or Redfern or DLF City Phase 4', length: 46, textSize: 30 }, { visibility: 'visible', visible: true, label: '', alpha: 1, elevation: 0, height: 64, width: 55, focused: false, enabled: true, text: '', length: 1, textSize: 55 }, { visibility: 'visible', visible: true, label: 'Use current location', alpha: 1, elevation: 0, height: 53, width: 390, focused: false, enabled: true, text: 'Use current location', length: 20, textSize: 39 }, { visibility: 'visible', visible: true, label: 'powered by', alpha: 1, elevation: 0, height: 56, width: 192, focused: false, enabled: true, text: 'powered by', length: 10, textSize: 33 }, { identifier: 'search_location', visibility: 'visible', visible: true, label: 'Vikas Puri Cricket Coa', alpha: 0.8, elevation: 0, height: 61, width: 948, focused: true, enabled: true, text: 'Vikas Puri Cricket Coa', length: 22, textSize: 44, placeholder: 'Search for society, landmark, locality...' } ] } ```
noomorph commented 10 months ago

Hm, try an extended search like this:


const { elements } = await element(by.type('android.view.View')).getAttributes();
console.log(elements.filter(x => x.text.trim() || x.identifier)); // let's not overspam the results
urbanclap-admin commented 10 months ago

not sure why this works but once I do await element(by.type('android.widget.TextView')).getAttributes() I can now fetch the element just by the text matcher itself, without the attributes code this does not work, also works with atindex matcher as well

can you please explain the background behind this? my hunch is with the getAttributes call it syncs correctly with the view hierarchy I guess

stale[bot] commented 9 months ago

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!

For more information on bots in this repository, read this discussion.