1

The ultimate goal is to get the WebElement variable name for reporting purposes.

The below is the code I have.

Class A:

Class A{

      public void Click(WebElement element)
      {
            element.click();
            System.out.println("Clicked on"+ element);
      }
}

Class B:

class B extends A{

     @FindBy(xpath = "//li[@class='login-menu']//a[text()='Log In']")
     WebElement link_Log_In;

     Click(link_Log_In);
}

Desired Output:

Clicked on link_Log_In

Actual Output:

Clicked on[[ChromeDriver: chrome on XP (acc46d4d382511d7b18396d4a4dddd30)] -> xpath: //li[@class='login-menu']//a[text()='Log In']]

Also I would like to print the same Desired Output in extent report using afterClickOn(WebElement element, WebDriver driver) method in WebDriverEventListener.

I have created the framework in such a way that WebDriverEventListener results are printed in Extent Reports as required but however unable to print Desired Output as stated above.

Please advise if i'm missing something in the above code and to achieve the same in afterClickOn(WebElement element, WebDriver driver) method in WebDriverEventListener

Below is the event listener afterClickmethod

public void afterClickOn(WebElement element, WebDriver driver) {
        System.out.println("Clicked On"+element); // this is to print in console
        ExtentManager.getTest().log(Status.valueOf(element), "clicked on"); // this is to print in extent report
    }
Hari
  • 51
  • 1
  • 8
  • can u show method u r using to write webelement to extent report, basically this is happening because you are trying to write an object using a string. – Amit Jain Feb 28 '19 at 21:39
  • 1
    Possible duplicate of [Java Reflection: How to get the name of a variable?](https://stackoverflow.com/questions/744226/java-reflection-how-to-get-the-name-of-a-variable) – JeffC Mar 01 '19 at 04:11
  • No this is not duplicate of the Java Reflection: How to get the name of a variable? using Java Reflection we couldn't achieve the desired output – Hari Mar 02 '19 at 09:02
  • @AmitJain I have updated the code with afterclickmethod in event listener that would help you to answer my question. Your help is much appreciated. Actually I'm stuck because of this. – Hari Mar 02 '19 at 09:33
  • @Hari log methods accepts LogStatus and String, How are you passing WebElement, can you show what is "Status" and valueOf method u r using in param1 of log method ?? valueOf is a String class method. – Amit Jain Mar 02 '19 at 19:05
  • @AmitJain I'm doing something wrong here and i dont know how to print the webelement variable name from that. That is the reason I'm seeking help. Please guide me how to achieve that with a sample code. Thanks in advance for your help. – Hari Mar 03 '19 at 20:05

2 Answers2

0

I don't believe that there is a straightforward way to get the name that you gave to the element (like a getName() method). The closest thing I can think of is to do something like the following:

public class ElementNaming {

    //Create a hashmap that stores the name of the element as a string
    public static HashMap<WebElement, String> webElementKeys = new HashMap<>();

    public static By by = By.id("hplogo");

    public static WebElement instantiateWebElementAndName(String name, By by) {
        webElementKeys.put(driver.findElement(by), name);
        return driver.findElement(by);
    }

    public static void main(String[]args) {
        driver.get("https://www.google.com/");
        WebElement element = instantiateWebElementAndName("element", by);
        System.out.println("Element name: " + webElementKeys.get(element));
    }
}

Console Output: 
Element name: element
K. W. H.
  • 43
  • 1
  • 7
  • please help me understand how did that print "element" in the console even when you dont put the values in the hashmap? – Hari Mar 02 '19 at 09:25
  • So if you look at instantiateWebElementAndName, I'm putting the actual object returned by driver.findElement and the String name into the hashmap. The method then returns the found by object so that it can be assigned to element seen in the main method. – K. W. H. Mar 13 '19 at 15:36
0

Old question but for those who will encounter the same issue. One of the possible solutions is to extend ElementLocator (for example DefaultElementLocator) where you will log the element name in findBy() method. Like:

public class WECElementLocator extends DefaultElementLocator {

    final String UNNAMED = UUID.randomUUID().toString();
    final String elementName;

    public WECElementLocator(SearchContext searchContext, Field field) {
        super(searchContext, field);
        Name elementNameAnnotated = field.getAnnotation(Name.class);
        if (elementNameAnnotated != null){
            elementName = elementNameAnnotated.value();
        }else{
            elementName = UNNAMED;
        }
    }

    private void log(String message){
        if(!UNNAMED.equals(elementName)){
            System.out.println(message + " (for [" + elementName + "])");
        }
    }

    @Override
    public WebElement findElement() {
        try{
            log("Attempt to lookup element..");
            WebElement result = super.findElement();
            log("Element successfully located.");
            return result;
        }catch (Throwable e){
            log("Problem in locating element..");
            throw e;
        }
    }
}

You can introduce your own annotation which would assign a human-readable name to your field. Like:

public class PageObjectWithName {

    @Name("My test name")
    @FindBy(xpath = "//input[@type='button']")
    WebElement button;

    public PageObjectWithName(SearchContext context) {
        // TODO: implement page initialization
    }

    public void clickButton(){
        button.click();
    }

}

So in initialization part you will just use that custom implementation of element locator that would take the annotation and use the name from the field. No extra work with reflection will required. This will be smoothly integrated with PageFactory harness.

This is step-by-step tutorial.

Alexey R.
  • 8,057
  • 2
  • 11
  • 27