XPath to select following-sibling - selenium

This is the code that I currently have:
<div>
<ul class="nav nav-pills nav-stacked">
<li>
<li>
<li>
<li>
<li>
<section>
<span name="merchant">ABZ</span>
</section>
<section>
<span class="glyphicon glyphicon-pencil" name="edit"></span>
<span class="glyphicon glyphicon-remove" name="delete"></span>
</section>
</li>
<li>
<li>
<li>
<li>
</ul>
<div class="add-item bottom" name="new-merchant">
</div>
I have tried the following:
xpath=//span[contains(.,'ABZ')]/following-sibling::section/span[#name='edit']
xpath=//span[contains(.,'ABZ')]/following-sibling::span[1]
I am using selenium, and I want it to click on the edit button that is right after the ABZ span.

This xpath worked for me in Chrome, using your html:
//span[contains(text(), 'ABZ')]/../following-sibling::section/span[#name='edit']
Edit
The .. means to go up a level. The .. takes the selector from span to section. Then the following-sibling finds the section after the parent section of your matching span.
Your original selector was matching span, then looking for a following-sibling to span.

Adding to the answer above, both the expressions below will work well.
//span[contains(text(), 'ABZ')]/following::section/span[#name='edit']
OR
//span[contains(text(), 'ABZ')]/../following-sibling::section/span[#name='edit']
Notably, the axis following will pick each node following the context node while the axis following-sibling will only pick the sibling nodes to the context node.

Related

How to write xpath for li content for breadcrumb items

I want to write an xpath for verify the Custom Report text without index.
HTML:
<ol>
<li>
Lw2_0702230135
</li>
<li>
Report
</li>
<li>
Custom Report
</li>
</ol>
You can use the following xpath:
//ol/li[contains(text(), "Custom Report")]
Given the HTML:
<ol>
<li>
Lw2_0702230135
</li>
<li>
Report
</li>
<li>
Custom Report
</li>
</ol>
To identify the element with text Custom Report you can use the following xpath based locator strategy:
//ol/li[last()]
Code (Python):
element = driver.find_element(By.XPATH, "//ol/li[last()]")

Wrapper element for for loop

I'm currently expanding my horizon by trying out Vuejs.
I'm creating a navigation with data coming from my Vue instance, and I have the following code:
<ul class="nav">
<li class="nav-item" v-for="navLink in navLinks" :key="navLink.id">
<a class="nav-link" :href="navLink.url">{{ navLink.name }}</a>
</li>
</ul>
Now even though this works perfectly fine, I have seen the following two examples in videos instead:
<ul class="nav">
<template v-for="navLink in navLinks">
<li class="nav-item">
<a class="nav-link" :href="navLink.url">{{ navLink.name }}</a>
</li>
</template>
</ul>
<ul class="nav">
<div v-for="navLink in navLinks" :key="navLink.id">
<li class="nav-item">
<a class="nav-link" :href="navLink.url">{{ navLink.name }}</a>
</li>
</div>
</ul>
I'm asking myself which one of these is best practice.
Now from what I've learned, one should always (if possible) set a :key in a for loop. This is not possible on the tag, therefore I would think this option is the worse.
But what about option 3 and mine? Is there any difference? Is it just personal preference or is there an actual reason on why to choose one or the other.
Ty
The only difference I spot between the first and the third options is that you'd wrap each list item in an additional div. You don't need those wrappers unless you want to use this nesting for styling purposes.
Your example is perfectly fine. Just make sure ids you use for keys are unique.
Also avoid using v-if and v-for on the same element and rather add v-if on the parent
I think you should always put a key property in your for loop.
Say you have nothing to work with for an ID (some item.name could potentially be duplicated?) just use this:
<div v-for="(item, index) in items)" :key="index">
{{ item.name }}
</div>
index in this case is just the index of the items array.
So yours will be rendered like:
<ul class="nav">
<li class="nav-item" :key="navLink.id">
<a class="nav-link" :href="navLink.url">{{ navLink.name }}</a>
</li>
...
<li class="nav-item" :key="navLink.id">
<a class="nav-link" :href="navLink.url">{{ navLink.name }}</a>
</li>
</ul>
Whereas the third one will be:
<ul class="nav">
<div :key="navLink.id">
<li class="nav-item">
<a class="nav-link" :href="navLink.url">{{ navLink.name }}</a>
</li>
</div>
...
<div :key="navLink.id">
<li class="nav-item">
<a class="nav-link" :href="navLink.url">{{ navLink.name }}</a>
</li>
</div>
</ul>
I would say it's a bit verbose to wrap a <li> inside a <div> in each one of them.
Yours is fine, all of them indeed are going to work well, but the third one may have problems with custom css, since it's a wrapper for the tag.
The template is an alternative as it is stated in the docs.
You've set the key at the li tag, as long as you're following the guide for mantaining state with keys, it's fine.

Selenium - How to click on this span?

I've tried using cssSelector and xpath. I can't use class=chips__text as it is not unique. How can I click on the span with text Nou?
<ul id="targetparam17" class="chipschoice fleft">
<li class="hidden">
<a href="#" class="is-selected">
<span class="chips__text">Alege</span>
<span class="value"></span>
</a>
</li>
<li class="">
<a href="#" class="">
<span class="chips__text">Utilizat</span>
<span class="value">used</span>
</a>
</li>
<li class="">
<a href="#" class="">
<span class="chips__text">Nou</span>
<span class="value">new</span>
</a>
</li>
</ul>
Find the element with respect to the desired text i.e. "Nou" and then click on it. xpath for it is //span[text()='Nou']. In case if you with to use different texts to click on different spans, you can manipulate the xpath using string manipulation techniques. Hope it helps :)
ExpectedConditions.elementToBeClickable means to selenium to be clickable is that it is visible & enabled. See Here
So you should check whether webElement isDisplayed() & isEnabled().
Or alternatively you can use ExpectedConditions.visibilityOf(WebElement)
I've used //span[contains(.,'Nou')] and it works perfectly
Try below xpath :
driver.find_element_by_xpath("//ul[#id='targetparam17']//li//a//span[contains(.,'Nou')")

Can I use v-if and v-for outside HTML tag?

The point is that if the condition is satisfied I should assign whole list to a variable, otherwise I need to iterate through list and assign element by element.
<ul>
<li v-if="flag = true">
<myVueComponent
v-bind:list="LIST">
</myVueComponent>
<v-else v-for="item in LIST">
<a v-else :href="url+item.name">#{{item.name}}</a>
</li>
</ul>
If this is not valid code, then could I use v-if inside one <li> tag and v-else inside another <li> tag? In that case I would also use v-for in that tag.
Basically, yes, you could use it inside v-if inside one list element and v-else inside another:
<ul>
<li v-if="flag">
<myVueComponent
v-bind:list="LIST">
</myVueComponent>
</li>
<li v-else v-for="item in LIST">
<a :href="url+item.name">#{{item.name}}</a>
</li>
</ul>

Find titles of Anchor tags using Selenium

I need to find number of anchor tags and their titles in code mentioned below. I am using web driver, java, Selenium.
<div>
<div>
<div>
<div>
<ul>
<li>
<a></a>
</li>
<li>
<a></a>
</li>
</ul>
<ul>
<li>
<a></a>
</li>
<li>
<a></a>
</li>
</ul>
<ul>
<li>
<a></a>
</li>
<li>
<a></a>
</li>
</ul>
</div>
</div>
</div>
</div>
What will be the best way to find it?
Thanks in advance.
I assume that by 'title' you meant the text between the anchor tags.
Use the following code:-
//find the div tag
WebElement divTag = driver.findElement(By.xpath("//div/div/div/div"));
//find all the a tags in the div tag
List<WebElement> allAnchors = divTag.findElements(By.tagName("a"));
//print number of anchor tag
System.out.println("Number of Anchor tags = " + allAnchors.size());
//print text within each anchor tag
int count=0
For(WebElement anchor : allAnchors) {
System.out.println("Text within anchor"+ (++count) + "="+ anchor.getText());
}
Let me know if this helps you.