At start i want to say sorry about my English skill. I write automated test for the hybrid Android application. GUI of this app is written in HTML5/JS/CSS3 (with angularJS framework). I want to test any data form. Form is filled with some data on the start (received from server). To enter new data I have to clear current value and enter the new one. For enter new text i use:
By element = By.cssSelector("...");
solo.waitForWebElement(element);
solo.typeTextInWebElement(element, "foo", 0);
and it works well. I have got problems with data clear. In the Robotium documentation i found method:
solo.clearTextInWebElement(item);
This method cannot get index parameter (I don't know why), it only use the "By" object to catch specified element. I decided to use code like:
By item = By.cssSelector("input:nth-child(3)");
this.solo.waitForWebElement(item);
this.solo.sleep(3000);
this.solo.clearTextInWebElement(item);
but still doesn't work too. I don't know how to test web inputs by Robotium.
If the web elements have name or id attributes then you can use By.id("elementId") or By.name("elementName") to access them.
Your question will be easier to answer if you post more sample code, particularly the html of the elements you're trying to test.
Related
I am developing an Ionic 4 based app with Angular 8 and have a strange situation that has developed. I am using this calendar.
It seems to be similar to this issue... and you will see I have commented there asking how they solved it to no avail.
It works fine on the browser using ionic -serve and WAS working fine on my android device (I haven't gotten to iOS yet).
There was an andoid update to my phone last week and since then, the calendar page doesnt work any longer.
I have stripped out most of the code and simplified it to the extent that it (almost) works now but I have to remove the datasource object.
This leads me to believe there is something wrong with the data in the datasource which I had found before when incorrectly formatted. However, I am uncertain if this is the issue.
The startTime and endTimes come from the server and are converted from ISO strings like this:
fixAppointmentTimesFromServer(appointment: Appointment) {
appointment.startTime = new Date(appointment.StartTimeServer);
appointment.endTime = new Date(appointment.EndTimeServer);
}
If I log out the type of object in the appoinmtents array like this:
this.userService.appointments.forEach( appt => {
console.log(appt.startTime);
console.log(typeof (appt.startTime));
console.log(appt.endTime);
console.log(typeof (appt.endTime));
});
it shows the start/endTimes as strings so I was wondering if this could be the issue, or if thats just more of the mystery that is JS Date objects..?
Or if anyone can tell me how to actually find and get into the Calendar module to debug it, then that might help?
I've added an additional:
this.platform.ready().then( res => {
...
at the start of the ngOninit().
The whole start/end time thing could just be a red herring...
Any thoughts at all? Thanks
I am answering my own question here since I don't want others to have the same issues I had tracking this down.
The way I was fixing up the date for the ionic2 calendar wasn't adequate (apparently) as it needs a millisecond based Date Object to work properly. Different browser versions seem to operate differently.
So, the way I fix up the dates from the server now is as follows:
fixAppointmentTimesFromServer(appointment: Appointment) {
const start = new Date(appointment.StartTimeServer);
const end = new Date(appointment.EndTimeServer);
appointment.startTime = new Date(Date.UTC(start.getFullYear(), start.getMonth(),
start.getDate(), start.getHours(), start.getMinutes()));
appointment.endTime = new Date(Date.UTC(end.getFullYear(), end.getMonth(), end.getDate(), end.getHours(), end.getMinutes()));
}
This converts first to a string and then converts again to get a UTC (millisecond) based Date object. Which does work.
A word of caution however:
I found that when I wasn't getting the data from the server, but using the already converted data from out of Ionic Storage, it broke again. This needing me to reconvert the data when getting it out of storage. So, this wasn't some 'funny date on the server' to JS thing, moreover a perfect example of how completely ******* up Javascript actually is!
I am trying to display the first document in a view using the "UnpBootFormViewer".
What I have currently done is include the "UnpBootFlatView" control that references a view which contains only one (1) document (app settings in this instance). I have it in a "" with the style set to "display: none;".
This works great on a computer using a standard browser, but when the same app is opened on a mobile device (Nexus 5) it does nto work.
Is there a better/easier way to do what I'm trying?
I assume you use native document data source. To initialize it with first document from some view you must provide UNID of that document. Example:
var v:View = database.getView("view name");
var vec:ViewEntryCollection = v.getAllEntries();
var ve:ViewEntry = vec.getFirstEntry();
var unid = ve.getUniversalID();
return unid;
I recommend to use your preferred error catching technique (try/catch, OpenLog...)
Why so complicated - ViewEntryCollection and ViewNavigator collections keep documents sorted as in view. Common beginner's mistake is to use view.getFirstDocument() - this document is the first from internal list of documents so it need not to be the first document shown in the view.
I think what you are trying to do is possible and I think it's demostrated in this page from the sample app provided by Teamstudio
My Activities Page
This uses the UnpBootFlatView to look up the activities based you your username. It then uses the UnpBootFormViewer to display the first document in the view.
The XPage to reference is MyActivities
The documentations also points out that from release 1.3 of the XControls 'openfirstdocument' is defaulted to 'yes'. If you have this set to anything else the first document in the view will not load.
Flat View Documentation
If that's all fine on the standard browser as you suggest and it just doesn't work on the Android device, then I'd suggest contacting Teamstudio Support.
Tim C. ;o)
[Disclosure] Tim Clark works for Teamstudio
I'm new to automatization, Android, Selenium, Appium and xpath, too. I know it's suck a great beggining.
I write tests for Android devices, but the application I have to test have a lot of costum views. I found out the best way to interact with these custom items is to put an "android:contentDescription" field in the Views. My only question is how to get access to the element with have a specified contentDescription? This is az android specific question, I'm not even sure that the content-desc is the field I'm looking for.
I have the hierarchy provided by Android UI Animator Viewer:
http://i.imgur.com/NUGc56o.png
The ways i've tried:
xpath: //*[contains(#android:contentDescription,'example text')]
I was able to get access by finding them as an ImageView, but as I mentioned I need to work with custom Views
My code looks like somtihng like this:
driver.findElementByXPath("//*[constains(#content-desc,'Login')]").click();
Thanks for the help!
You could also try using Accessibility labels or the UIAutomator locator strategy.
Here's Appium's documentation on those.
Your xpath is incorrect. It should be: "//android.widget.ImageView[#content-desc='Login']"
Here's some pseudocode of what you should do:
login_image = driver.findElementByXPath("//android.widget.ImageView[#content-desc='Login']"); // Gets you the WebElement
print login_image.getClass(); // Just for debugging, make sure it's not nil/null
login_image.click(); // Click on it!
When running calabash-android and outputting to HTML format, I am getting intermittent exceptions as per the below (typically within the first step of the app). I am using Xamarin and MVVMCross libraries.
Timeout waiting for elements: * marked:'Terms of Use'
(Calabash::Android::WaitHelpers::WaitError)
./features/step_definitions/calabash_steps.rb:4:in `/^User has accepted the Terms of Use$/'
features\registration.feature:8:in `Given User has accepted the Terms of Use'
2
3Given /^User has accepted the Terms of Use$/ do
4 #current_page=page(TermsOfUse).await
5 #current_page.tap_accept_button
6end
7# gem install syntax to get syntax highlighting
The screenshots generated show the UI element is present on the screen, and the same errors never occur when I exclude the html format option and simply write the detail out to the console. Does anybody else have any experience of this?
Most likely the view's text has some formatting information in it.
It's a good practice to use id instead of text for identifying elements. If you have an id, use that:
query("* id:'terms_of_use_id'")
If you don't have an id try to add one.
If that is not possible try to query the whole UI with:
query("*")
Find the element and see what's in it's text property.
I'm working on a project for my university about customizing an Android application on runtime.
Is it possible to include layout XML files that are actually not in the \res\layout\ folder of my android project but on an external webserver?
The idea behind this is to give me an opportunity to customize the xml-file on my webserver, e.g. adding new fields, without having to re-install/update the app.
I'll try to explain my idea with the following example:
Let's say I got an application to save and display addresses. All addresses are stored in a database. I got the fields 'name' and 'surname' in my database and displayed in the app when saving or displaying the addresses.
Now I would like to add a third field 'email' where I can enter email addresses.
My idea is to create this field in my database and add it to my layout-xml-file which is on my webserver. So I can 'link' the xml file within the app and the new field appears after refreshing the app.
Hope you guys can give me some information about how to customize my input forms on runtime, my research on the internet didnt help me out at all..
Greetz
You can't use external XML files to dynamically adjust the layout.
The documentation of LayoutInflater#inflate(XmlPullParser, ViewGroup) explains why:
Important For performance reasons, view inflation relies heavily on pre-processing of XML files that is done at build time. Therefore, it is not currently possible to use LayoutInflater with an XmlPullParser over a plain XML file at runtime.
But you can create your layout dynamically in code, see e.g. Android Runtime Layout Tutorial
So you could put a file on the server that holds layout information, fetch it in your app, parse it and create the layout dynamically. It is going to be a lot of work since you would basically replicate Android's LayoutInflater. You can obviously simplify the format to just the basics that you need but it's still a lot of work that is IMHO not required.
Let's assume your layout info is just a plain text file that has name of fields
name
surname
email
You can then read it line by line and create a simple EditText for each in a way like
private View getDynamicLayout(ArrayList<String> lines) {
LinearLayout ll = new LinearLayout(this);
for (String line : lines) {
EditText et = new EditText(this);
// fill it with some text
et.setText(line);
ll.addView(ll);
}
return ll;
}
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
ArrayList<String> layoutConfig = readConfigFromFile();
View layout = getDynamicLayout(layoutConfig);
setContentView(layout);
}
But unless you really need that, I would suggest that you update the app the regular way. It is also faster to use preprocessed layouts instead of building that info on your own.
Also take care not do heavy disk / any network access in the UI thread like in above example (reading the file). That should be done in a background task.
Thanks a lot for your help. I'll try to get through this.
The reason I can't just update the app is that the app I'm talking about is actually a CRM system used by many different companies. They all have to download the same app from the google play store.
The goal of my work is that every company can customize their input forms on their own, so there could be many different input forms (each for every company) but all using the same app.
I thought about a server that stores a file with the layout information which can be accessed by the app on runtime.
btw, since I'm not a software engineer, I don't have to write any code, I only have to describe the concept in an abstract way.. :)