I am trying to read the element so that i can later use to get the id of that element. Using below code to get first the WebElement. But throws the following in console:
"[org.openqa.selenium.remote.RemoteWebElement#f76d0bdd -> unknown locator]"
WebElement ele = driver.switchTo().activeElement();
System.out.println("webelement is :"+ele);
You are seeing this because you are asking the code to essentially print ele.toString().
Which, according to the source, is going to give the exact message you see:
https://code.google.com/p/selenium/source/browse/java/client/src/org/openqa/selenium/remote/RemoteWebElement.java#375
Specifically:
public String toString() {
if (foundBy == null) {
return String.format("[%s -> unknown locator]", super.toString());
}
return String.format("[%s]", foundBy);
}
It says 'unknown locator' because one isn't explicitly set by setFoundBy.
So, I would suggest that if you want the ID of the element, you use:
ele.getAttribute("id");
Related
I am working on an Eclipse plugin which loads a URL in the SWT browser. This page rendered in the browser has hidden html attributes. The requirement is to read the values of the hidden attributes.
Browser browser = new Browser(shell, SWT.NONE);
browser.setUrl("www.<my_url>.com");
I tried to execute a query on the DOM using the statusTextListener
browser.addStatusTextListener(new StatusTextListener() {
public void changed(StatusTextEvent event) {
browser.setData("query", event.text);
}
});
browser.addProgressListener(new ProgressListener() {
public void completed(ProgressEvent event) {
boolean result = browser
.execute("window.status=document.getElementById('main').childNodes[0].nodeValue;");
if (!result) {
/* Script may fail or may not be supported on certain platforms. */
System.out.println("Script was not executed.");
return;
}
String value = (String) browser.getData("query");
System.out.println("Node value: " + value);
}
});
However this does not seem to work. It works well if I try to load HTML text in the browser instead of the URL.
Any idea how to read DOM elements from the SWT browser after the page load is complete?
Use Browser::evaluate to execute Javascript in the context of the document and return the result to the caller.
To obtain the value of the first child of the main element in your example, start like this:
String script = "<Javascript to return an array of hidden attribute names>";
Object result = browser.evaluate(script);
The supported result types, however, are limited to string, number, and boolean - and arrays of these types. Javascript that evaluates to null or undefined will return null.
Hence, you will need to adjust your Javascript that queries the DOM to return a supported type.
I'm creating a list of IWebElements to access each of elements from same type, but the test works slowly when I want to access a certain element. I came with the idea to create a dictionary of elements and access each element by it's name (text that is stored in this element). I found some topics here but was unable to make them work for me. This is the way I'm accessing elements.
public IWebElement OneElement
{
get
{
return this.Driver.FindElement(By.Id("oneElement"));
}
}
public List<IWebElement> ListOfNames
{
get
{
return this.Driver.FindElements(By.Id("name")).ToList();
}
}
You can try the following code to get element by it's text and it is fast compared the list of elements as list needs to be searched till element found. it will take time if searched element is at the last position in the list. Below code will be direct fetch of particular element. Try it and let us know.
public IWebElement GetElementByText(String text)
{
get
{
return this.Driver.FindElement(By.xpath(String.Format("//*[#id='name'][text()='{0}']",text)));
}
}
I have a drop down menu containing list elements that are sometimes static and sometimes changed. My main goal is to check that the menu contains some content [followed by outputting that content and exporting it in a report].
The function I created in my FeatureContext.php looks like this:
/**
* #Then /^I check content exists for element "([^"]*)"$/
*/
public function iCheckElementContent($locator)
{
//check element exists on page
$element=$this->assertSession()->elementExists('css', $locator);
//check element content is not empty (returns exception if true)
if ( empty($this->getPage()->find('css', $locator)->getText()) ) {
throw new Exception;
}
}
As you can notice, it is based on the reply to the other question regarding this feature. My problem however is that it doesn't seem to like the getPage() parameter. The error I get is:
PHP Fatal error: Uncaught Error: Call to undefined method FeatureContext::getPage()
I also tried changing it to getValue(), without any success. Any ideas? (bonus awesome points for also helping me with the second step of my requirements)
I think I found a solution, but I'm not sure if it passes because it works or because it's searching for nothing and finding it.
$session = $this->getSession();
$element = $session->getPage()->find('css', $locator);
//check element content is not empty (returns exception if true)
if (empty ($element->getText()) ) {
throw new Exception;
}
Can someone please code-review this?
If I have an object like Browsers.Item("iexplore") and if it has a property called IsOpen ,
how to print it in test complete log
I am using Jscript for scripting
Test complete is version 9
If you need to check whether a browser is running, you can do this in the following manner:
function test()
{
var b = Sys.WaitBrowser("iexplore");
if (b.Exists == true)
Log.Message("Internet Explorer is running");
else
Log.Message("Internet Explorer is not running");
}
To get a value of an object's property, just address this property using the dot notation: object.property. To post this value to the test log, call the Log.Message method. Use the Log.Warning and Log.Error methods to post warnings and errors correspondingly.
Log.Message(obj.MyProperty);
You could use any of these:
var yourObject = ..
console.info(yourObject);
console.log(yourObject);
console.log(yourObject.yourProperty);
Is their any way to find the object locator type, by passing the object locator alone.
for e.g. i need to click on a login button, where its id=login, classname=loginbutton or xpath=//input[#name='login']. I need to build method where i will be just passing the objectlocator (either id or name) as the input and its type(either id or name) should be decided in the method like if it contains // then type should be of xpath etc.
I need to pass the objectLocator() which returns type to the findElement()
WebElement element = driver.findElement(objectLocator());
I do not think it is available off the shelf, you would have to implement your own logic.
The only thing is, let's say you want to search by linktext. As per your usecase, you would, in your object repo specify, "this is my linktext".
Now how do you know it is an id or a name or a linktext?
For xpath you can check if it starts with /, then its an xpath. If its only id or name then you can use ByIdorName, but i think it would become tricky with css and linktext.
The one thing I can think is you can establish some sort of conventions like if it is linktext precede your lcoator definition with linktext=blah blah and then you split and consume it.
I find it very useful to store all my locators as By objects and either use the By directly or pass the By into methods as I need them. For example:
By passwordField= By.id("login");
By userNameField = By.name("username");
By submitButton = By.xpath("\\myxpath\div[2]");
public void clickLogin() {
driver.findElement(submitButton).click();
}
I also use static Bys from other classes as well:
public void clickLogin() {
driver.findElement(LoginPage.SUBMIT_BUTTON).click();
}
The modern way to do this is using PageFactory and PageObjects
The following is a quick and dirty which will adapt selenium locators strings to WebDriver locators.
public enum LocatorType {
CLASSNAME, CSS, ID, LINK, NAME, TAGNAME, XPATH ;
}
public WebElement objectLocator(LocatorType type, String ref) {
switch(type) {
case ID:
return this.webDriver.findElement(By.id(ref));
case CLASSNAME:
return this.webDriver.findElement(By.className(ref));
case XPATH:
return this.webDriver.findElement(By.xpath(ref));
case CSS:
return this.webDriver.findElement(By.cssSelector(ref));
case LINK:
return this.webDriver.findElement(By.linkText(ref));
case NAME:
return this.webDriver.findElement(By.name(ref));
case TAGNAME:
return this.webDriver.findElement(By.tagName(ref));
}
return null;
}
public WebElement objectLocator(String identifier) {
String typeString = identifier.substring(0, identifier.indexOf('='));
String ref = identifier.substring(identifier.indexOf('=')+1, identifier.length());
if (typeString.toLowerCase().contains("classname")) {
return objectLocator(LocatorType.CLASSNAME, ref);
} else if (typeString.toLowerCase().contains("css")) {
return objectLocator(LocatorType.CSS, ref);
} else if (typeString.toLowerCase().contains("id")) {
return objectLocator(LocatorType.ID, ref);
} else if (typeString.toLowerCase().contains("link")) {
return objectLocator(LocatorType.LINK, ref);
} else if (typeString.toLowerCase().contains("name")) {
return objectLocator(LocatorType.NAME, ref);
} else if (typeString.toLowerCase().contains("tagname")) {
return objectLocator(LocatorType.TAGNAME, ref);
} else if (typeString.toLowerCase().contains("xpath")) {
return objectLocator(LocatorType.XPATH, ref);
} else {
return null;
}
}
It looks like you are looking for this solution because you have an object repository maintained somewhere outside of your code in some kind of properties file or xml.
Using gui maps has lot of disadvantages like,
- maintain an external file with a list of locators
- parse locator files to read keys (you can abstract this but still an overhead)
- when writing PageObjects you need to switch back and forth from Page to gui map
- possibility of multiple duplicate locators in gui maps
- object repo grows over time and becomes impossible to maintain
- debugging is far more difficult
What you are looking for is adding one more layer of complexity which is not required in my opinion. Automating browsers is a challenge in itself and writing maintainable test automation code is utmost important.
Use PageFactory in your page objects.
- Natural place for your locators are Page Objects themselves.
- Locators easily accessible in page objects for review or correction
- No need for explicit driver.findElement, with #FindBy you get that for free
- modern Java and awesome annotations make page objects look beautiful & readable
I have used gui maps before and struggled a lot. Switching to page factory made me realize that using object repository was such a bad idea!
This should do for locating element. I have given example till 3 level deep.
public WebElement findElement(String locator){
WebElement w = null;
try{
return (driver.findElement(By.id(locator)));
}catch(Exception e1){
try{
return ( driver.findElement(By.name(locator)));
}catch(Exception e2){
try{
return (driver.findElement(By.xpath(locator)));
}catch(Exception e3){
System.out.println("Cound not find a locator");
e3.printStackTrace();
}
}
}
return(w);
}
public void type(String locator, String value){
try{
WebElement w= findElement(locator);
w.sendKeys(""+value);
Thread.sleep(sleepTime);
}catch(Exception e){
e.printStackTrace();
}
}
-Vinay