I have WebElement which I have to convert into Testobject in katalon using groovy script.
For Example
List<WebElement> WEs = WebUI.executeJavaScript("return document.querySelector('#email').parentElement", [])
Now I want to convert WEs[0] to TestObject which Katalon accepts.
Please let me know if you have an idea about this.
There is no direct way to convert WebElements to TestObjects. According to this forum question, you could create a function to get the xpath of the web element
protected String getXPathFromElement(RemoteWebElement element) {
String elementDescription = element.toString();
return elementDescription.substring(elementDescription.lastIndexOf("-> xpath: ") + 10, elementDescription.lastIndexOf("]"));
}
and then create a new test object with the given xpath:
protected TestObject fromElement(RemoteWebElement element) {
TestObject testObject = new TestObject();
testObject.addProperty("xpath", ConditionType.EQUALS, getXPathFromElement(element));
return testObject;
}
NOTE:
For other way around (Test Object -> WebElement), use
WebUiCommonHelper.findWebElement(test-object, timeout)
WebUI.convertWebElementToTestObject()
To create Test Object from any WebElement, I have developed the function as below
public static String WebElementXPath(WebElement element) {
if (element.tagName.toUpperCase() == 'HTML') return '/html';
if (element.tagName.toUpperCase() == 'BODY') return '/html/body';
// calculate position among siblings
int position = 0;
// Gets all siblings of that element.
List<WebElement> siblings = WebUI.executeJavaScript("return arguments[0].parentNode.childNodes", [element])
WebElement innerSibs
//List<WebElement> siblings = element.parentNode.childNodes;
WebElement sibling
def type,response
for(int i=0;i<siblings.size();i++){
type = WebUI.executeJavaScript("return arguments[0].nodeType", [siblings[i]])
if (type == null){
continue;
}
if(type!=1){
continue;
}
sibling = siblings[i];
// Check Siblink with our element if match then recursively call for its parent element.
if (sibling == element) {
innerSibs = WebUI.executeJavaScript("return arguments[0].parentElement", Arrays.asList(sibling))
if(innerSibs==null){
return ""
}
response = functions.WebElementXPath(innerSibs)
return response+'/'+element.tagName+'['+(position+1)+']';
}
// if it is a siblink & element-node then only increments position.
type = WebUI.executeJavaScript("return arguments[0].nodeType", [sibling])
if (type == 1 && sibling.tagName == element.tagName) position++;
}
}
And then I have created function to get test object as below as suggested by Mate Mrše
public static TestObject getTestObjectFromWebElement(WebElement element) {
TestObject object = new TestObject()
object.addProperty("xpath", ConditionType.CONTAINS, functions.WebElementXPath(element))
return object
}
Note : "Framework" folder had been created by us as inside the Keyword folder and then We had created the "functions" keyword
I hope this might help other developers.
Related
Is it possible to find out if one WebElement comes before another one in the html code?
More general, is it possible to sort a collection of WebElement objects according to their order in the html code? (note: sorting a lot of elements is not actually my intention)
/*
<html>
<body>
<div>
<div>first</div>
</div>
<div>second</div>
</body>
</html>
*/
public int compare(WebElement a, WebElement b) {
return -1; // if a=first, b=second
return 0; // I'm not really interested in corner cases
return 1; // if a=second, b=first
}
In XPath you have the preceding:: and following:: axes, but in my case I already have the WebElement objects and I want to determine their relative order.
I have not tested this and I'm coding it on-the-fly:
public WebElement firstInList(WebElement a, WebElement b) {
WebElement found = null;
List<WebElement> all = driver.findElements(By.xpath("//*");
for (WebElement test : all) {
if (test.equals(a)) {
found = a;
break;
} else if (test.equals(b)) {
found = b;
break;
}
}
return found;
}
To make it using two differents IWebElements will be a pain - is hard and will take so much time to proccess the information to discovery the html nodes and know where each one is in -> and finaly says who is the first and who is the second one.
My sugestion is using two selectors: cssSelector or Xpath. Both of they are able to mix more than one selecting condition inside itself, and when you try to return a list of IWebElements using findElements, it will return based on html order. It means that, the fiers html node will be the first element in the list.
An example (in c#, sorry, i don't know java)
public bool IsATheFirstElement(string aXPathSelector, string bXPathSelector)
{
// Creates a xpath to find both elements: A and B
var generalXPath = aXPathSelector + " | " + bXPathSelector;
// Get a list of elements containing A and B, in HTML order
var ab = _driver.FindElements(By.XPath(generalXPath));
// Get the A element
var a = _driver.FindElement(By.XPath(aXPathSelector));
// Returns a bool value that checks if a is the first element or not
return ab.First() == a;
}
This solution is rather "brute force".
It looks for all the elements after a and sees if b is in there.
public int compare(WebElement a, WebElement b) {
if(a.equals(b)){
return 0;
}
List<WebElement> afterA = a.findElements(By.xpath("descendant::* | following::*"));
if(afterA.contains(b)) {
return -1;
} else {
return 1;
}
}
this is my code
Scanner s = new Scanner(new File("ignore.txt"));
final ArrayList<String> list = new ArrayList<String>();
while (s.hasNext()){
list.add(s.next());
}
s.close();
int lengthList = list.size();
final Set<String> values = new HashSet<String>(list);
Diff myDiff1 = DiffBuilder.compare(writer1.toString()).withTest(writer.toString())
.checkForSimilar()
.checkForIdentical()
.ignoreWhitespace()
.normalizeWhitespace()
.withNodeMatcher(new DefaultNodeMatcher(ElementSelectors.byNameAndText))
.withNodeFilter(new Predicate<Node>() {
public boolean test(Node n) {
String temp = Nodes.getQName(n).getLocalPart();
//System.out.println(temp);
return !(n instanceof Element &&
values.contains(temp));
}
})
.withAttributeFilter(new Predicate<Attr>(){
public boolean test(Attr n){
javax.xml.namespace.QName attrName = Nodes.getQName(n);
//System.out.println(attrName.toString());
//QName Temp = new QName();
//System.out.println(Temp.toString()+n.toString());
Boolean temp1 = !values.contains(attrName.toString());
//Boolean temp1 =!attrName.toString().equals("answerType") ;
//System.out.println(temp1);
//return !attrName.equals(new QName("balType",null, null, "curCode"));
return temp1;
}
})
.build();
my xml file is
<ns3:CoreExceptionFault xmlns:ns3="http://core.soayodlee.com">
<faultText>com.yodlee.util.system.ycache.CobrandNotSupportedException: The CobrandCache for the cobrand 10004 is not initialized.</faultText>
</ns3:CoreExceptionFault>
I want to ignore the xmlns:ns3 attribute. The above file Ignore.txt contains all the node and attributes which i need to ignore. But when I am adding xmlns:ns3 it is not ignoring the attribute. I am using XMLunit 2.2.1
The xmlns: attributes are not "normal" attributes, you can't ignore them and XMLUnit won't report differences about them either. They are meta-attributes that apply to the element (and its children) and are usually hidden from XMLUnit by the XML parser.
In your case you seem to be comparing XML documents with elements using different namespace URIs. Be warned that two such documents will be different for any namespace aware XML parser.
If you really want to make them pass as similar, you'll have to use a DifferenceEvaluator that ignores the namespace part of the element's QNames.
Something like
.withDifferenceEvaluator(DifferenceEvaluators.chain(
DifferenceEvaluators.Default, new MyEvaluator())
with something like
class MyEvaluator implements DifferenceEvaluator {
#Override
public ComparisonResult evaluate(Comparison comparison, ComparisonResult outcome) {
if (comparison.getType() == ComparisonType.NAMESPACE_URI) {
return ComparisonResult.SIMILAR;
}
return outcome;
}
}
should work.
BTW, you should only specify one of checkForSimilar() and checkForIdentical(), they contradict each other and only the last one wins.
I am new to Java Programming. I have written a recursive procedure as follows:
public static String treeWalk2(Element element, String tofind) {
String result = "";
for ( int i = 0, size = element.nodeCount(); i < size; i++ ) {
Node node = element.node(i);
if ( node instanceof Element ) {
result = treeWalk2( (Element) node, tofind );
}
else {
if (node.asXML().toLowerCase().equals(tofind)) {
result = node.getUniquePath();
System.out.println(node.getUniquePath());
break;
}
}
}
return result;
}
I am trying to find an element in DOM Tree matching some string ("tofind" parameter in the procedure). If the type of the current node is an instance of Element then it will call itself. But when the value of the node is equal to "tofind" string then it will return the unique path of that node. I tried it with an xml file but the return value of the procedure is always "". You can see in the code I also write the unique path, if found, to the screen and it is giving me the desired result. Can anyone tell me what is wrong with my code? Thank you.
I would suggest to use return instead of break; like below
if (node.asXML().toLowerCase().equals(tofind)) {
result = node.getUniquePath();
System.out.println(node.getUniquePath());
return node.getUniquePath();
}
I am trying to use isDisplay() method in my selenium script.
While I am using this method I have found this method returns false every time.
Is there any other way to use this method or alternative of this method?
Scroll_UP is done successfully. But If element is display, Scroll_UP is not terminate.And I need return value also.
Thanks in advance.
code logic which I write
public static boolean scroll_Up_Until_FindWebe(WebElement dragEle, WebElement ele, int scrollPoint)
{
int numberOfPixelsToDragTheScrollbarUp = -10;
for (int i = scrollPoint; i > 10; i = i +numberOfPixelsToDragTheScrollbarUp)
{
if (ele.isDisplayed()) //if the tag options is displayed
{
Log4J.logp.info("Ending scroll_Up_Until_FindWebe - Element is found");
return true;
}
dragger.moveToElement(dragEle).clickAndHold().moveByOffset(0,numberOfPixelsToDragTheScrollbarUp).release().build().perform();
}
Thread.sleep(500);
return scroll_Up_Until_FindWebe(dragEle, ele, 30);
}
So my node.getValue() in the below method returns an E or generic data type.
public String toString() {
StringBuilder linkedQueueAsString = new StringBuilder();
linkedQueueAsString.append("< ");
for (Link<E> node = this.front.getNextNode(); node != null; node = node.getNextNode())
{
linkedQueueAsString.append(node.getValue()); // <=== Not working correctly
linkedQueueAsString.append(" ");
}
linkedQueueAsString.append(">");
return linkedQueueAsString.toString();
}
When I am testing it like the following my test fails:
public void setUp() {
this.queue1 = new LinkedQueue<Integer>();
this.queue2 = new LinkedQueue<Integer>();
}
public void test_enqueue3IntegersAndThenDequeueThem() {
this.queue2.enqueue(1);
this.queue2.enqueue(2);
this.queue2.enqueue(3);
assertEquals(3, this.queue2.length());
assertEquals("< 1 2 3 >", this.queue2.toString()); // <= ERROR since none of the numbers printed out
}
You can see my personal implementation of Linked Queue here.
HOW can I fix this? Thanks!
For me the problem is in this line:
for (Link<E> node = this.front.getNextNode(); node != null; node = node.getNextNode()) {
Due you call "getNextNode()" twice, you miss one element and you assertEquals will not match.