1

During locator failure, I want to pass a newly generated locator on the fly. I'm aware of the QAF's inbuilt multiple locator strategy but in my case locator may change during the run so I will not get new locator info before the run.

user861594
  • 5,733
  • 3
  • 29
  • 45
Renish
  • 165
  • 6

1 Answers1

0

with qaf 3.0.1 you can set by in QAFExtendedWebElement. Best way is to use element listener. For example

@Override
public void onFailure(QAFExtendedWebElement element, CommandTracker commandTracker) {
    //By newBy = <do needful>;
    element.setBy(newBy);
    commandTracker.setRetry(true);
}

qaf 3.0.1b is released, you can try that.

EDIT: to handle find element failure you can use driver listener. For example:

   private static final Map<String, Object> byToString = JSONUtil.toMap(
            "{'ByCssSelector':'css selector','ByClassName':'class name','ByXPath':'xpath','ByPartialLinkText':'partial link text','ById':'id','ByLinkText':'link text','ByName':'name'}");

    @Override
    public void onFailure(QAFExtendedWebDriver driver, CommandTracker commandTracker) {

        Map<String, Object> parameters = commandTracker.getParameters();
        if (parameters != null && parameters.containsKey("using") && parameters.containsKey("value")) {
            By actaulBy = LocatorUtil.getBy(String.format("%s=%s", parameters.get("using"), parameters.get("value")));
            By newBy = <do the needful>
            commandTracker.getParameters().putAll(toParams(newBy));
            commandTracker.setRetry(true);
        }
    }

    private static Map<String, String> toParams(By by) {
        Map<String, String> map = new HashMap<String, String>();
        String val = by.toString().split(":", 2)[1].trim();
        map.put("using", byToString.get(by.getClass().getSimpleName()).toString());
        map.put("value", val);

        return map;

    }
user861594
  • 5,733
  • 3
  • 29
  • 45
  • I got the onFailure function to trigger with QAF 3.0.1b, but was not able to pass the new locator for the step. I tried following: By newBy = By.xpath("//*[@id='txtPassword']"); element.setBy(newBy); commandTracker.setRetry(true); Also tried another: @FindBy(locator = "id=txtPassword"); By newBy = LocatorUtil.getBy(locator); element.setBy(newBy); commandTracker.setRetry(true); – Renish Sep 25 '21 at 18:52
  • Can I update the existing locator using getBundle().setProperty("loc.id.2", "['id=txtPassword']"); and trigger commandTracker.setRetry(true); ? – Renish Sep 25 '21 at 18:59
  • refer updated answer. Find element failure will not trigger element onFailure listener, it can be handled through driver onFailure. – user861594 Sep 27 '21 at 15:39
  • Thanks for the prompt reply and extended help. Since I'm new to Java, can you please help me how to pass a new locator to By newBy = . Eg: my old locator is "xpath=//loc" but new loc is "xpath=//locnew". Note: When my locator was failing webelement listener was getting triggered, but I was not able to pass the new locator. – Renish Sep 27 '21 at 18:50
  • `LocatorUtil.getBy("xpath=//locnew")` or `By.xpath("//locnew")` – user861594 Sep 27 '21 at 20:42
  • Thanks a lot.. it worked... LocatorUtil.getBy("xpath://locnew") – Renish Sep 28 '21 at 04:37
  • Any reason why the test is starting from the start again not continuing from the element it has failed? – Renish Sep 28 '21 at 07:18
  • the best way to find the reason is running in debug mode. you can run testng test/suite in debug mode. – user861594 Sep 28 '21 at 15:49