I was wonder how can I reuse an elements while I'm using appium.
An elementSerarch returns an ID which is generated by Appium , I was wonder if there a way to reuse the same element by it's id ?
If not , then what is the purpose of the element's id ?
Thanks
You can create Page Object Model (POM) is the best way for element re-usability, but these reused elements do not essentially have the same Id on different pages so you might get.
NoSuchElement Exception.
by separating out the reusable components will make your work more manageable.
Using POM You can store the elements into the variables, and pass them wherever you want.
WebElement element = driver.findElement(By.id("xyz"));
Also Preferred selector order should be : id > name > css > xpath,
id and name are often the easiest and sure way.
xpath are often brittle, css are the way to go in conjunction of id and name !
But sometimes because of Page Refresh/Loading these elements might not be available on later use so prefered way is to create Page Class and write methods to find these elements, like
public class LoginPage extends BasePage {
public void loginButton_Click() {
WebElement element = driver.findElement(By.id("xyz")).click();
}
}
Here you can list out all the methods to find the different elements on particular page, Now you just need to call the method whenever you want to use that element.
As far as Finding element by using it's Id is concern if you are using a tool such as uiautomatorviewer you will get the Developer generated Id's so you can use the same Id as many times as you want,
also if you are talking about the Id's generated by Appium such as: info: [debug] [BOOTSTRAP] [debug] Returning result: {"value":{"ELEMENT":"1"},"status":0}
Here id : 1 is internal reference for appium to act, for future actions that we call for respective element in the test code. I preferred to use driver to find the elements,
Id Of an Element
Ideally the element.getId() method can be used to return a String, representing the ID of an element, But whenever I tried to use, It always returns 1 to me, You can also use,
WebElement element = driver.findElements(By.xpath("XOXOXOXO"));
element.getAttribute("id");
Finally You need this Id to perform Click/Swipe/long click and many other events you want for your Automation Testing, basically the process is like:
Get the Id/name/xpath of an Element (By using different methods or
Tools like uiautomatorviewer)
Find that element By Name/Id/xpath etc.
Perform necessary operation
So Id is just one way to find the element, and you can reuse it by your own way.
Related
I'm using HP UFT for functional tests.
Because of dynamic id definition of ExtJS, I can't use UFT Recording feature.
I've tried many ways for assigning dynamic IDs to staticly.
I tried to change id: function() in ext-all-debug.js file.
I tried to change Components getId() function in ext-all-debug.js file.
I tried override components with afterRender method to change ids aswell.
Sometimes I achieved to change id's using component's properties (text, fieldLabel, overflowText, etc.), but for some components I couldn't achieve to assign ID's since the components properties seem empty.
Above, I listed my actions to assign static ID. So, I want to know your opinions about my actions and if you found them incorrect or not sufficient, could you offer me new approaches for using HP UFT recording feature with ExtJS6.
You can't change the dynamic id of the dom elements which represents ExtJS components. That's really bad thing and I think you would break the whole app.
The easiest way to test ExtJS app is to use already created frameworks/tools like:
Siesta by Bryntum
Sencha Test by Sencha
The Siesta is free. It has some pro features which requires the license. But you can use it for free.
If you still insists on doing it your way. You need to dynamically get the IDs of the dom elements created by ExtJS components. Basically write your own API.
You need to execute the ExtJS JS code, which will return you the ID of the component. So you need to get the ExtJS component and call getId() function on it to get the dom id.
Here is the example code:
>Ext.ComponentQuery.query('checkbox')[0].getId()
"checkbox-1047"
You will definetely need: http://docs.sencha.com/extjs/6.5.3/modern/Ext.ComponentQuery.html#method-query
And keep in mind that the query can be pretty advanced and you can use all the configs which are set on the ExtJS elements such as name, xtype, etc
You can find some other info in my other anwser https://stackoverflow.com/a/41718879/1768843
I will use robotframework to test an application that use the sencha extjs library,
my problem is that with this library the ids are generated dynamically every time
this add new components, therefore my robotframework script would change
constantly but this is a bad idea. somebody said me that other testing frameworks
it have plugins to this task but I cant found in robotframework.
thanks in advance.
There are many ways to access elements on the page, using the id is just one way. Assuming you're using Selenium2Library, you can use any of the following locators strategies (from the Selenium2Library documentation):
Strategy Example Description
--------------- --------------------------------------- ---------------------------------
identifier Click Element | identifier=my_element Matches by #id or #name attribute
id Click Element | id=my_element Matches by #id attribute
name Click Element | name=my_element Matches by #name attribute
xpath Click Element | xpath=//div[#id='my_element'] Matches with arbitrary XPath expression
dom Click Element | dom=document.images[56] Matches with arbitrary DOM express
link Click Element | link=My Link Matches anchor elements by their link text
partial link Click Element | partial link=y Lin Matches anchor elements by their partial link text
css Click Element | css=div.my_class Matches by CSS selector
jquery Click Element | jquery=div.my_class Matches by jQuery/sizzle selector
sizzle Click Element | sizzle=div.my_class Matches by jQuery/sizzle selector
tag Click Element | tag=div Matches by HTML tag name
default* Click Link | default=page?a=b Matches key attributes with value after first '='
Note that even though some examples (such as xpath) show the use of an id, an id may not be strictly required (except, obviously, for id= and identifier=). xpath is usually the strategy-of-last-resort, because you can reference pretty much anything in the document. For more about xpath you can start here: http://en.wikipedia.org/wiki/XPath
This is not a great solution, so hopefully someone else can find a plugin or something that is easy to implement. However, if you do not find a different way, you can give every one of your Ext.js elements an ID manually by setting the "id" property on every one of your elements to a unique ID yourself. It would not take too much work, and if you named them something actually related to what they are, it would make the ID's more human readable.
From the Sencha docs:
id : String
The unique id of this component instance.
It should not be necessary to use this configuration except for singleton objects in your application. Components created with an id may be >accessed globally using Ext.getCmp.
Instead of using assigned ids, use the itemId config, and ComponentQuery which provides selector-based searching for Sencha Components analogous to DOM querying. The Container class contains shortcut methods to query its descendant Components by selector.
Note that this id will also be used as the element id for the containing HTML element that is rendered to the page for this component. This allows you to write id-based CSS rules to style the specific instance of this component uniquely, and also to select sub-elements using this component's id as the parent.
Source: http://docs.sencha.com/extjs/4.1.3/#!/api/Ext.AbstractComponent-cfg-id
With the release of Selenium2Library 1.7, users are now able to create their own custom locators. You could use this to create a location scheme based on ext's component query. So long as the overall structure of the app doesn't change that much, that may suffice. For more information on custom locators see the Selenium2Library docs.
I've started an add-on library for S2L on github that you can check out for reference, but it isn't completely finished yet.
Also, Ext lets you place unique ids on components by simply specifying the id attribute. I would recommend applying ids to all elements which you want to interact with through your tests, thereby eliminating any need for complex behavior to automate the interface.
I have seen this bunch of code in a tutorial:
var searchTerm = this.$('#searchTerm').val().trim();
I would like to understand the utility of the this. in front of the selector, it's the first time i see that.
In a Backbone.View, this.$ gives a scoped version of jQuery. It is in fact equivalent to using this.$el.find which is in turn equivalent to using $(this.el).find.
Anyhow, the reason it is a good idea to use it is that it will only access html elements from within the view's element/rendered template. Thus, you don't have to worry about the rest of the html page and you will always select the element you expect to.
Imagine that you have a view that spawns sub-views and that each of these have an editable field. If you don't use the scoped version of jQuery to get the right editable field, you will have to give a unique id to each of these html elements to make sure you will select the right one when retrieving it's content. On the other hand, if you use the scoped version, you will just have to give this editable field a class attribute and selecting this class will give you a unique element, the right one.
This is the same query as this.$el.find('#searchTerm').val().trim();
You haven't given any context to that code, but assuming it's a method inside a View, this refers to the View object.
this.$ is a shortcut to access jQuery from the View object, and is equivalent to the method this.$el.find.
i need to create a component dynamically by a button click. My restrictions are:
It's going to has an Id starts with a fixed string like 'myComp_' and followed by a random number
At any time there will be only one component that has an id starts with 'myComp_xxx'
So before creating the component i have to check if there's any created before and remove it... My problem starts here. Ext.getCmp() wants the specific id. But i only have that fixed string : myComp_...
Is there any way to get the component created before???
Thanks in advance and sorry about my English.
For ExtJs 4.X use Ext.ComponentQuery.query('*[id^=myComp_xxx]');
For ExtJs 3.X you can either use the following
var el = Ext.query('*[id^=myComp_xxx]');
var cmp = Ext.getCmp(el.id);
Or (this one i haven't tried personally, but i think it should work) if the component is a child of a component that you can access, then:
var el = parentComp.find("action","btn");
and set a property called action : btn in the button config.
I think what you are looking for is DomQuery.
Ex:
Ext.query("*[id^=myComp_xxx]")
You need to use this: Ext.getCmp(id)
Ext.getCmp("myComp_xxx");
Sounds like you should be using the normal component query stuff - in general it is not a good idea to use id. You can query by xtype and by itemId (which you can assign manually).
The following
Ext.ComponentQuery.query('grid form');
would find all things with xtype grid that have forms inside them somewhere.
Ext.ComponentQuery.query('grid #okButton');
whereas the # here is saying look for grids that have something with itemId 'okButton' in them.
You can nest this to whatever level you need and use other operators to be more specific and as someone else has rightly pointed out you can use up and down on components to do this relative to the current component. Its worth noting that rather than getting an array back with all the results you just get the first one when you use up and down.
See the documentation for more information this.
Also see point 6 on this list of bad practices to avoid for more of the why
Another alternative if you know 'where' your component is going to be created is to use the up()/down() methods.
E.g. if you have a button and want to get the form it's contained within inside a click handler you can do something like this:
function myClickHandler(btn) {
var form = btn.up('form');
//do something with form
}
In our project we use ZK for webpages. There is a combobox which has lists. When selected, it fetches data from a java object through onSelect, i have given the logic.
when i select one there are 4 listboxes on that page to be filled with data according to the selection. when i select first time, no problem occurs.
But on second time i get an error pop-up like "Not Unique in the id space of Window" and showing the list box item id which have to be filled on select.
Can any one help out there?
Note: Though it shows this error i get the listboxes filled correctly according to the combo box selection. Still i cant stop this error occurring..
Your issue is a conflict of ids in ZK's id space.
A bit of background..
ZK generates ids for components at runtime, if you open up the DOM in the browser you'll see each component has some machine readable id.
However, you can also give components an id. This id does not go to the DOM but lets you reference the component in your application.
These two shouldn't be confused. The conflict you're experiencing is with the latter type of id; you are assigning a component an id in your Java code or in your ZUL file which, at runtime, is not unique.
The case you describe where it only happens the second time you click is a tell tale sign here. The content you are adding on the event has an id defined in it and you are not removing this content when you are done.
Consider the following example:
#Wire
private Window myWindow;
#Listen(Events.ON_CLICK + " = #myButton")
public void onMyButtonClicked() {
Label myLabel = new Label("sean is cool");
myLabel.setId("myLabel");
myLabel.setParent(myWindow);
}
This will work the first time you click myButton, but will throw your error on the second click. That is because the second event tries to add myLabel to myWindow but there is already a myLabel there.
There are lots of ways to resolve this depending on what you are trying to do.
Have a look through the ZK documentation on ID Spaces for more.
I also faced the same error.
My scenario is the same, only the widgets being used are different.
Hence putting my workaround here.
I have put the following piece of code in the doBeforeCompose() method of the composer:
Component widgetWithId = page.getFellowIfAny("widgetWithId");
if (widgetWithId != null) {
widgetWithId.detach();
}
Here widgetWithId is the component/widget, which is tried to be regenerated by the code, with the same Id and ZK is throwing error for it.