Simple way to find and interact with elements

Hi, I am fairly new to Katalon/Selenium, having worked mostly with Cypress in the past. In cypress finding elements is pretty straight forward and I am trying to use Katalon in a similar way but I often find that an element cannot be found.

For this element for instance (an email verification button after a new user has been created), the xpath constantly changes due to a random user ID being added to the href:

href="http://localhost:3500/email-verification/a63a2b24-b785-4b18-b104-83283670b920?email=test%40aurem.ae"

In cypress I could easily click the button with following code:

cy.findAllByRole("link", { name: /Verify email/i })
        .eq(0)
        .should("be.visible");

cy.findAllByRole("link", { name: /Verify email/i }).click();

How can I achieve something similar with Katalon?

1 Like

Hi there,

Thank you very much for your topic. Please note that it may take a little while before a member of our community or from Katalon team responds to you.

Thanks!

I don’t understand your Cypress bit of “{name: ‘Verify email/i’ }” but otherwise, I might do something like:

import org.openqa.selenium.WebDriver as WebDriver
import org.openqa.selenium.WebElement as WebElement
import com.kms.katalon.core.webui.driver.DriverFactory as DriverFactory
import com.kms.katalon.core.webui.keyword.WebUiBuiltInKeywords as WebUI

WebDriver driver = DriverFactory.getWebDriver();

WebElement element = driver.findElement(By.xpath("//button[contains(@href,'/email-verification/') and contains(@href, 'email=test')]"));
assertTrue (element.isDisplayed())
WebUI.verifyMatch(element.isDisplayed().toString(), "true", false)
element.click()

Edit: if there is a <name> attribute somewhere in your HTML that you did not show, then you might be able to use that to find a unique pathway to your element.

Basically with Cypress (and a plugin called test library) I can easily fetch elements by their role and name, so things like:

    cy.findByRole("button", { name: /Sign Up/i }).click();
    cy.findByRole("heading", { name: /Create an account/i }).should(
      "have.text",
      "Create an account",
    );

and when a unique ID is present just like:

    cy.get('[data-e2e-id="signUp__input__email"]').clear().type(adminEmail);
    cy.get('[data-e2e-id="signUp__input__password"]')
      .clear()
      .type(adminPassword);
    cy.get('[data-e2e-id="signUp__button__submit"]').click();

I think searching by xpath using contains I should be able to fetch unique elements.

I’m just wondering, do i always have to call WebElement element = driver.findElement? I suppose this is only needed if you do not use the Object Repository.

1 Like

If you use the Object Repository, then you will be dealing with Test Objects and you can just drag-and-drop from the OR into your Test Case, such as below.
WebUI.click(findTestObject('myPage/button_EmailVerification'))

In my post above, as you surmised, I created a WebElement.

Edit: you can also make a Test Object without using the Object Repository by either using the below Keyword or its contents inline of your code:

import com.kms.katalon.core.testobject.TestObject
import com.kms.katalon.core.testobject.ConditionType

	/**
	 * Utility to create an instance of TestObject with XPath
	 * @param xpath
	 * @return TestObject
	 */
	public static TestObject makeTO(String xpath) {
		TestObject to = new TestObject(xpath)
		to.addProperty("xpath", ConditionType.EQUALS, xpath)

		return to
	}

you can rename the method to whatever you want, but the idea is to use the contents of the method or as a Keyword to create a Test Object. So, if you want to use the Keyword and perform your task, it could look like:

myItem = com.Tools.makeTO("//button[contains(@href,'/email-verification/') and contains(@href, 'email=test')]")
WebUI.verifyElementVisible(myItem)
WebUI.click(myItem)