I'm new to robotium and i'm trying to write a quick and dirty script to run through all screens in an app.
The problem i have mainly with the 'home button' in the app. I've tried lots of options but i cant seem to get it to click there except with index, which is not what i want.
When i check out the button with the hierarchyviewer it looks like this:
Link
However when i try for example:
assertTrue(
"Wait for text (id: myapp.R.id.home) failed.",
solo.waitForImageById("myapp.R.id.home", 20000));
solo.clickOnImage((ImageView) solo.findViewById("myapp.R.id.home"));
solo.waitForActivity("MenuActivity");
It fails at the waitForImageByID line. Ive tried multiple options like waitForImageButton etc, but i just cant seem to get it clicked. What am i missing here?
junit.framework.AssertionFailedError: View with id: '0' is not found!
at com.jayway.android.robotium.solo.Solo.getView(Solo.java:1990)
at com.jayway.android.robotium.solo.Solo.getView(Solo.java:1970)
at com.bitbar.recorder.extensions.OtherUtils.a(OtherUtils.java:246)
at com.bitbar.recorder.extensions.OtherUtils.b(OtherUtils.java:241)
at com.bitbar.recorder.extensions.v.a(Waiter.java:71)
at com.bitbar.recorder.extensions.ExtSolo.waitForImageButtonById(ExtSolo.java:4176)
at com.example.android.apis.test.Test.testRecorded(Test.java:137)
at java.lang.reflect.Method.invokeNative(Native Method)
at android.test.InstrumentationTestCase.runMethod(InstrumentationTestCase.java:214)
at android.test.InstrumentationTestCase.runTest(InstrumentationTestCase.java:199)
at android.test.AndroidTestRunner.runTest(AndroidTestRunner.java:191)
at android.test.AndroidTestRunner.runTest(AndroidTestRunner.java:176)
at android.test.InstrumentationTestRunner.onStart(InstrumentationTestRunner.java:554)
at android.app.Instrumentation$InstrumentationThread.run(Instrumentation.java:1740)
Use the following line to press the home button in the action bar
solo.clickOnActionBarHomeButton();
The issue is that the id that it is referring is not in your application, it is in androids default R file, try android.R.id.home and it should work fine. It is worth noting though that if your application uses action bar sherlock to support the action bar pre 4.0 that this will have a different ID there and you will have to handle this in your test.
You can see this for yourself looking at: http://developer.android.com/reference/android/R.id.html
When you are using ActionBarSherlock there are two different Ids you have to check, android.R.id.home for API-Level>11 and abs__home for lower levels (provided by ActionBarSherlock):
View homeButton = activity.findViewById(android.R.id.home);
if (homeButton == null) {
homeButton = activity.findViewById(R.id.abs__home);
}
What about this code:
ArrayList<LinearLayout> ll = solo.getCurrentViews(LinearLayout.class);
//You can change 1 with the ordinal number of LinearLayout you want to click.
solo.clickOnView(ll.get(1));
or also
ArrayList<ImageView> iv = solo.getCurrentViews(ImageView.class);
//You can change 0 with the ordinal number of Image you want to click.
solo.clickOnView(iv.get(0));
I think if you identify the correct id for view or linear layout or image view it should work.
Dave C's answer was working only partially for me. The button was clicked but before the preceding screen was loaded assertions had started and thus were always false. The solution is to run "home click" on the main thread (Robotium 5.2.1):
getInstrumentation().runOnMainSync(new Runnable() {
#Override
public void run() {
solo.clickOnActionBarHomeButton();
}
});
From your question I can see that it is an image view. You can click on any view using the following piece of code.
View view = solo.getView("View_name_from_hierachy_viewer");
solo.clickOnView(view);
View_name_from_hierachy_viewer in your case will be "home".
Let me know if this does not work.
Related
how can I show a dialog to stay or leave the current page with Vaadin 23, when a user clicks back button on browser?
Regards
It depends what you wish to achieve.
See this older discussion: Vaadin onbeforeunload event
Generally: use the onBeforeUnload javascript even for this
https://www.w3schools.com/tags/ev_onbeforeunload.asp
This is executed when the user would go away from your vaadin app, but not when using the back button inside your vaadin app.
For these you can use the navigation lifecycle events as documented here
https://vaadin.com/docs/latest/routing/lifecycle
Not sure if it also catches, when a user leaves your app...
Assuming you mean, that is it possible to prevent the navigation happening, you simply can't do that. If disabling back button is important for you, the only way is to enforce your users to use the application via desktop shortcut which starts the app using --app paramater (if using Chrome). This is not a limitation in Vaadin, but a general restriction in browser behavior.
There is already a possibility to handle Browser Back Button Event on Vaadin (https://vaadin.com/docs/v14/flow/routing/tutorial-routing-lifecycle):
public class SignupForm extends Div implements BeforeLeaveObserver {
#Override
public void beforeLeave(BeforeLeaveEvent event) {
if (this.hasChanges()) {
ContinueNavigationAction action = event.postpone();
ConfirmDialog.build("Are you sure you want"+
" to leave this page?")
.ifAccept(action::proceed)
.show();
}
}
private boolean hasChanges() {
// no-op implementation
return true;
}
}
This code works once but when you click on Cancel on Confirm Dialog so that you want to stay on current page and click again on Back Button on Browser, than you don't see any Confirm Dialog again... I can not understand, why...
I have a chipgroup and some chips inside. I loop through this chipgroup, get every chip and add a checkedChangeListener for it.
for (int i = 0; i < chipGroup.getChildCount(); i++) {
final Chip chip = (Chip) chipGroup.getChildAt(i);
chip.setOnCheckedChangeListener((buttonView, isChecked) -> {
//My code
});
}
So when I open my app and click on chip, e.g. chip1, it selects it. Then when I click on that chip1 second time, it also fires the checkedChangeListener and runs my code inside it. The isChecked status is not helping, because it just changes it value like true->false->true->false on every click. But I just don't want to run my code inside onCheckedChangeListener, if the chip is already checked.
One solution I think is to save my selected chip inside fragment or ViewModel. What's your solution?
I believe you can just set a setOnCheckedChangeListener on the chipGroup instead of each individual chip. That listener will pass in an ID and isChecked as parameters. I believe using this callback on the group will be help resolve your issue. Hopefully that helps with the issue you're having.
More info on https://material.io/components/chips/android#using-chips
I tried everything to perform click on view in recyclerview item but not succesfull. Read every option on internet and tried it but still not working. Lately I used:
onView(ViewMatchers.withId(R.id.live_rw_liveMatchList))
.perform(RecyclerViewActions.actionOnItemAtPosition(2, MyViewAction.clickChildViewWithId(R.id.pick_pw_pickLeft)));
But all i get is:
android.support.test.espresso.AmbiguousViewMatcherException: 'with id:
hr.psk.android:id/ticket_list_list' matches multiple views in the
hierarchy. Problem views are marked with '****MATCHES****' below.
And it matches only one view (my recyclerview with 13 childs)
I know this should work but it is not working in my project. Tried to perform only click on recyclerviw item in other recyclerview to make it more simple like this:
onView(withId(R.id.ticket_list_list))
.perform(RecyclerViewActions.actionOnItemAtPosition(0, click()));
But it gives me the same message back -> Multiple matches problem
somebody help, I really tried everything
onView(withId(R.id.ticket_list_list))
.perform(RecyclerViewActions.actionOnItemAtPosition(0, click()));
The error you're getting means that there's another View somewhere that also uses the id ticket_list_list
Is ticket_list_list your actual list view? (the parent of the things that you want to click)
If it is then is it the only one available on the screen? if it is then use the following
onView(allOf(withId(R.id.ticket_list_list), isDisplayed()))
.perform(RecyclerViewActions.actionOnItemAtPosition(0, click()));
Adding the isDisplayed() Matcher makes the targeted View more specific by targeting only those that are displayed and ignoring those that are existing but not displayed
If there really is another matcher displayed (or the above doesn't work for you) that has the same id as the one you're trying to match then use the following
onView(allOf(withId(R.id.ticket_list_list), withParentIndex(index_of_matcher_here)))
.perform(RecyclerViewActions.actionOnItemAtPosition(0, click()));
Instead of isDisplayed() withParentIndex(some_number) should more specifically target and give you the view that has the id you're looking for along with the index of it
In the very messy instance that the above still doesn't work, maybe because all the returned Views have the same index possibly because they are the children of another View then you can get creative and do something like
onView(allOf(withId(R.id.ticket_list_list), withParent(allOf(withId(if_of_the_parent), withParentIndex(index_of_matcher_here)))))
.perform(RecyclerViewActions.actionOnItemAtPosition(0, click()));
to specify the index of the parent instead.
Just mix 'n match your way through it, just make sure to not go crazy on the Matchers and just keep things readable
Use as little as you can (make sure it's readable and maintainable too and not just made up of indexes), you're not trying to get the coordinates for a missile target- you just want the View
I also face the same problem before few days but finally got the solutions from StackOverflow.
If you want to click recycler custom item view click then implement the following code in your project
You need to write this code in java this will help you a lot and saved your time
ClickOnButtonView is control a view action happened in the list item and
UiController class helps you find custom row item
The code is written in Kotlin
#RunWith(AndroidJUnit4::class)
class CampaignFragmentTest {
#get: Rule
val activityTestRule = ActivityTestRule(TestActivity::class.java)
#Test
fun testCustomListClick() {
clickOnButtonAtRow(0)
}
}
private fun clickOnButtonAtRow(position: Int) {
Espresso.onView(ViewMatchers.withId(R.id.list)).perform(RecyclerViewActions.actionOnItemAtPosition<RecyclerView.ViewHolder>
(position, ClickOnButtonView()))
}
inner class ClickOnButtonView : ViewAction {
internal var click = ViewActions.click()
override fun getConstraints(): Matcher<View> {
return click.constraints
}
override fun getDescription(): String {
return " click on custom button view"
}
override fun perform(uiController: UiController, view: View) {
//btnClickMe -> Custom row item view button
click.perform(uiController, view.findViewById(R.id.btnClickMe))
}
}
That error means that it found multiple views with the id R.id.ticket_list_list. There should also be a view hierarchy log that follows the error message you provided, showing the views that Espresso found with that same id marked with ****MATCHES****.
So you can either change the id of the view you want to test or target the view by providing another ViewMatcher as below:
onView(allOf(withId(recyclerViewID), viewMatcher))
.perform(RecyclerViewActions.actionOnItemAtPosition(0, click()));
You Can also create your own custom click action like this :
fun customActionClickOnItemEvent(
#NonNull targetViewId: Int
): ViewAction {
return object : ViewAction {
val click = ViewActions.click()
override fun getDescription(): String = "Item clicked"
override fun getConstraints(): Matcher<View> = click.constraints
override fun perform(uiController: UiController?, view: View?) {
click.perform(uiController,view?.findViewById(targetViewId))
}
}
}
And Calling this function like this :
onView(withId(R.id.rv_products)).perform(
RecyclerViewActions.actionOnItemAtPosition<RecyclerView.ViewHolder>(
1,
customActionClickOnItemEvent(R.id.img_wish_list)
)
)
I have encountered a problem when using the the addCommand() method of the Form class along with the Native theme - other themes work fine. See the following example:
Form hi = new Form("Hi World");
hi.addComponent(new Label("Hi World"));
// with native theme - can't click on the first command in the list
hi.addCommand(new Command("Dummy1") {
public void actionPerformed(ActionEvent ev) {
Dialog.show("Dummy1 Clicked!", "You clicked the Dummy1", "OK", null);
}
});
hi.addCommand(new Command("Dummy2") {
public void actionPerformed(ActionEvent ev) {
Dialog.show("Dummy2 Clicked!", "You clicked the Dummy2", "OK", null);
}
});
hi.show();
When I create an application using the code above, a click on the second command ("Dummy2") produces the expected Dialog, but a click on the first command ("Dummy1") does nothing.
This only happens when using the Native theme. If I switch to Flat Blue, then clicking on either command produces the expected Dialog.
This behavior happens both on the Simulator and on a real Android device (don't know about iOS).
Fyi, my toolchain is NetBeans IDE v8.2, Java 1.8.0_25, with the CodenameOne plugin v3.6.0.
Has anyone else seen this? Am I missing something? If so, is there a workaround?
If the element is very narrow and very close to the top the click might be misinterpreted as a click out of bounds or on the status bar area. You need to set the styling of the SideCommand to have a sensible default as this element is very application specific. Otherwise touches might be lost.
I tried styling the SideCommand but it didn't seem to help. What worked for me was to define a style for TitleArea and simply uncheck Derived for the Padding settings (I left them all set to 0px).
I have no idea why this works - I would have thought that the derived values would have been zero in any case.
I am working with Selenium, now there is a condition:
when I hit a button in my webpage a window pop up opens up.
Now I have to click a radio button (one out of two, it will work even if we send a TAB ) and then click an OK button. I searched in the net and got to know about "driver.getWindowHandle()".
But I don't have any idea dealing with the newly opened window popup.
Need help in this.
For switching purpose u can use enhanced for loop:
for (String winHandle : objDriver.getWindowHandles()) {
objDriver.switchTo().window(winHandle);
}
So it will switch the control from one driver window to child windows.
To interact with elements on the window try to find element with whatever tool u r using and perform the required action after switching to the window.
To return back to parent window you can use the same loop or use:
driver.switchTo().defaultContent();
Check my answer in this post and also read the comments to help you understand the difference between getWindowHandle() and getWindowHandles()
Java: focus is not on pop-window during window handling
We handled this situation using AutoItX - https://www.autoitscript.com/site/ in our Windows/IE C# project:
AutoItX3 autoIt = new AutoItX3();
var handle = autoIt.WinWaitActive("[window title]", "", 20);
Assert.IsTrue(handle != 0", string.Format("Was not able to find: {0}", [window title]);
autoIt.Send("{ESCAPE}"); // tab may work as well for selection
The pop up was a Windows window, and not part of IE, therefore the WebDriver didn't know about it.
Hope this helps.