Does SC have a built-in library that I can call which will give me a list of all elements on a page?
Announcement
Collapse
No announcement yet.
X
-
If you mean DOM elements, no. That's actually built-in to all modern browsers (getElementsByTagName), although we'd recommend using a wrapper library such as JQuery for anything you might do with the elements along the lines of detecting sizes or retrieving various attributes.
-
Currently the scLocators are based from the Smartclient object's ID field that we've set. And the ID field we currently set are formed from their hierarchical path. For example, if there is a layout with name="myLayout" and it contains another layout with name="myLowerLayout" and in turn "myLowerLayout" contains a text field with name="myTextField" then the ID for the text field is something like myLayout$myLowerLayout$myTextField. As a result, myLayout$myLowerLayout$myTextField is also the generated scLocator for that field.
We currently have an issue when we move the "myTextField" directly under "myLayout" since then its ID becomes "myLayout$myTextField" and the Selenium test will fail. We want to implement a smart lookup where the locator is simply "myTextField". Then the Selenium locator search should find any element with id that ends with "$myTextField". Can you recommend a way we can accomplish this?
I'm don't know how the Selenium extension code you guys provide work exactly. Is it taking the scLocator as well as the user action, such as a "click" into your internal code to find the element and perform the click, or, is it returning the DOM element to Selenium and allowing Selenium to generate the click event on the DOM element, and your sc object merely listen to the click event to perform the click?
Comment
-
We currently have an issue when we move the "myTextField" directly under "myLayout" since then its ID becomes "myLayout$myTextField" and the Selenium test will fail. We want to implement a smart lookup where the locator is simply "myTextField". Then the Selenium locator search should find any element with id that ends with "$myTextField". Can you recommend a way we can accomplish this?
I'm don't know how the Selenium extension code you guys provide work exactly. Is it taking the scLocator as well as the user action, such as a "click" into your internal code to find the element and perform the click, or, is it returning the DOM element to Selenium and allowing Selenium to generate the click event on the DOM element, and your sc object merely listen to the click event to perform the click?
Comment
-
We understand your point of not embedding object hierarchy in the component's ID. But for our case, we actually have to generate our UI dynamically so we use this method to guarantee uniqueness of the ids. For Selenium play back, we do not worry too much about the efficiency or the matching of the wrong widget. If we find more than one object that matches the locator, we can always say we expect the 2nd or 4th one. We also think about adding additional attribute to the objects specifically for Selenium other than using the ID attribute. Then we can add our own Selenium extension and do the matching ourselves. Two things prevent us from doing this: first we need a way to obtain all SmartClient objects so we can iterate through them. Secondly, when we find the right SmartClient object, we need a way to obtain its associated DOM object to return to Selenium. Also, as you mentioned that you have to do "special" things in order for Selenium to perform actions correctly. We need to do the same thing in our extension. Would you be able to provide a solution to the problems we have?
Comment
-
You need to articulate an actual, real-world testing scenario that you are trying to solve before we can suggest a solution.
You mentioned the ability to match components by a suffix of an ID instead of an ID - but this capability appears be redundant with, and entirely worse than, the approaches and capabilities our product already provides.
As far as writing your own Selenium extensions - this is extremely complicated and we would advise you, in the strongest possible terms, not to go down this path - this will lead to total failure after a huge amount of effort. Not to mention, you'd be getting into the internal DOM of SmartClient components, which by necessity is undocumented and subject to change at any time.
Comment
-
The driver for the questions we have posed to you is that currently our Selenium test cases are extremely brittle and prone to breaking with every new release of SmartClient we upgrade to. Unlike traditional web application UI, our UI is generated at runtime. This means that we cannot assign unique IDs to every element on a particular screen because I do not know what can potentially be on screen. I have to generate the unique IDs and I have to generate them in a way that it's the same with every run of the application. What we have is an hierarchy of objects in the UI, and we know the name of each object in the hierarchy. We have a restriction that name of each object under the same parent have to be unique. Naturally, the path of each element in the hierarchy is unique and we use that as the ID. The downside is the the IDs are potentially very long and any changes in the hierarchy breaks the test due to inability to find the object. We want the ability to search for an element through Selenium using both the ID we generate, and the name of the element. Using only the name of the element can cause the problem that multiple element with the same name can be located, but we are fine with that since in those cases we can specify the n-th element in the list. The problem is that your code only deals with IDs as the locator, there is no way for us to say: don't use IDs as the scLocator, use this "myLocator" attribute as the scLocator. Or, here is this partial scLocator, do a pattern matching on it and return all elements whose ID matches the pattern. Either of these would help us achieve what we need.
Comment
-
So again, our advice, which is right there in the Using Selenium docs, is:
Use setID() selectively to avoid this problem. Generally, it makes sense to use setID() on all top-level (parentless) widgets - at this point, locators for children that do not have a unique ID will be based on the parent's ID plus a relative path. This relative path will not incorporate auto-generated IDs and will generally continue to work even if the interior layout of the parent is significantly rearranged (such as adding a new intervening container widget).
If you would just follow our best practices, your scripts would not break.
Comment
Comment