XPATH Testing string value of child and parent has empty string value - selenium

I have html that I am searching against in a Selenium test where I want to find the child by its text only if the parent has no text:
Here's the HTML:
<ul>
<li>
<div>
"4"
<span>630</span>
</div>
</li>
<li>
<div>
<span>630</span>
</div>
</li>
<li>
<div>
"6"
<span>630</span>
</div>
</li>
</ul>
Selecting for the text string '630' yields three results using "//span[.='630']" or "//span[text()='630']", but I only want that middle one with an empty parent. I've tried a whole lot of constructions that don't work "//span[.='630' and parent::div[.='']]" or "//span[text()='630' and parent::div[text='']]" and even "//div[text()='']/*[1] | //span[text()='630']" but these all result in either 3 results or none.
Note that while "//span[text()='630'] and .//div[contains(text(),'')]" detects the text, it returns true, and I need it to return the element so that I can click it.

//span[text()='630']/parent::div[not(text())]
try this.

This worked for me:
//div[#innertext='']/span[text()='630']

Related

Materialize: Cannot set property 'tabIndex' of null at Dropdown._makeDropdownFocusable

I am trying to test my vuejs component via jest that contains materialize select.
When performing a component test, I get the following error in materialize.js:
TypeError: Cannot set property 'tabIndex' of null at Dropdown._makeDropdownFocusable
How fix this error?
This problem can happen when the input field is not wrapped inside a div with the class input-field:
<div class="input-field">
<input type="text" class="autocomplete"></input>
</div>
Adding a div with the class "input-field might solve this problem.
use id selector instead class selector. for example call dropdown like this :
html :
<a class='dropdown-trigger' id="dropdowner" href='#' data-target='dropdown1'>Drop Me!</a>
<!-- Dropdown Structure -->
<ul id='dropdown1' class='dropdown-content'>
<li>one</li>
<li>two</li>
<li class="divider" tabindex="-1"></li>
<li>three</li>
<li><i class="material-icons">view_module</i>four</li>
<li><i class="material-icons">cloud</i>five</li>
</ul>
js:
$('#dropdowner').dropdown();
Can only be used once.
data-target="name_target" must not be repeated
Exam1.❌
<nav>
<div class="nav-wrapper">
<ul class="right hide-on-med-and-down">
<li><a class="dropdown-trigger" href="#!" data-target="name_target1">Dropdown<i class="material-icons right">arrow_drop_down</i></a></li>
<li><a class="dropdown-trigger" href="#!" data-target="name_target1">Dropdown<i class="material-icons right">arrow_drop_down</i></a></li>
</ul>
</div>
</nav>
<!-- Dropdown Structure -->
<ul id="name_target1" class="dropdown-content">
<li>one</li>
<li>two</li>
</ul>
Exam2.✔️
<nav> <div class="nav-wrapper">
Logo
<ul class="right hide-on-med-and-down">
<li><a class="dropdown-trigger" href="#!" data-target="name_target2">Dropdown<i enter code here class="material-icons right">arrow_drop_down</i></a></li>
</ul> </div> </nav> <ul id="name_target2" class="dropdown-content"> <li>one</li> <li>two</li> </ul>
When I ran into this issue I was trying to create the whole dropdown list dynamically in JS. The fix for me was creating the list and any default list elements in HTML:
<div id="select1" class=\"input-field col s12\">
<select>
<option value="" selected>Default</option>
</select>
<label>Test</label>
</div>
Then appending any dynamic values in JS:
contents.forEach(function(content) {
var buffer = "<option></option>";
var template = $(buffer);
$(template).text(content);
$("select1").find("select").append(template);
});
$("select").formSelect();
pre 1.0.0 you would use data-activates, if data-target is not specified you will get this error
My problem was, that jQuery object was not attached to the DOM yet, so inner materialise code could not init element due to inability to find element by ID:
// materializecss initing dropdown (in my case for input autocomplete), where `t` is the input element
i.id = M.getIdFromTrigger(t),
i.dropdownEl = document.getElementById(i.id),
i.$dropdownEl = h(i.dropdownEl),
M.getIdFromTrigger(t) returned some random ID (not the one I provided) and dropdownEl was inited with null, and later method _makeDropdownFocusable failed on using it `this.dropdownEl.tabIndex = 0
So my problem code looked like this:
let root = $('#root'); // root in the DOM already
let wrapper = $('<div>'); // wrapper is just created and NOT attached to the DOM yet
let input = $('<input>').appendTo(wrapper); // creating input and attaching to the wrapper, but still not in DOM
initAutocomplete(input) // M.Autocomplete.init logic here FAILS
root.append(wrapper) // too late, error above
So the quick fix is to append elements first and only than do M.Autocomplete.init
I just stumbled this issue too while using Materializecss for my Vue project. As mentioned by sajjad, using id selector instead of class works. However, this is problem for initializing multiple dropdown, since each dropdown must have unique ID.
The way I solve this is just by selecting all the elements with the '.dropdown-trigger' class, and initialize every each of those. It works for me.
$.each($('.dropdown-trigger'), function(index, value) {
$(value).dropdown();
});

How to do AND or OR in XPATH on combined divs

I would like to get a DIV based on two conditions in children DIVs.
//div//[child::div[text()="Administrator"] and //child::div[text='No card']]
But and condition appears to be working on properties of a single element.
Kindly advise how to achieve something like above, using either Xpath or CSSSelector
HTML:
<div>
<div class="src-containers-Quo-SimpleCard-components-styles-index__carHolderRow-" style="transition: s;">
<h4 class="-shared-react-components1Lsp1">Mr.</h4>
<div class="src-containers-Quo-SimpleCard-components-styles-index__carDetails--3xMqU">
<div class="src-containers-Quo-SimpleCard-components-1bGot">bla</div>
<div class="src-containers-Quo-SimpleCard-components--1bGot">Administrator</div>
<div><button class="src-containers-Quo-simpleCard-" type="button">Edit</button><button class="src-containers-Quo-SimpleCard-" type="button">Delete</button></div>
</div>
</div>
</div>
Many thanks
Basically if you want to select div by text values of two child div elements, you can do
//div[div="Administrator" and div="No card"]
Let me know (update your question) if you faced with another issue
P.S. Note that //div[//child::div[text='No card']] means something like return FIRST div if there is a div with text 'No card' somewhere in DOM, but not what you expect

robot framework selenium get all names in a list

I'm fairly new to selenium. Please bear with me.
I have a html code as shown below. I'm producing only the relevant port.
<div id="id1" style="display: block;">
<ul>
<li id="id2" title="title1">
<ins class="icon"> </ins>
<a href="#" class="">
<ins class="icon"> </ins>
row1
</a>
</li>
<li id="id3" title="title2">
<ins class="icon"> </ins>
<a href="#" class="">
<ins class="icon"> </ins>
row2
</a>
</li>
.
.
.
</ul>
</div>
Using Robot framework selenium library, I have to display the names of the rows [row1, row2 etc...].
I am unable to find a suitable keyword which does this.
(note: the answer here refers to the original question. It was edited to ask something completely different so this answer no longer applies to the question in its present form)
You can use Get element count.
Using the html in the question as an example, it would look like this:
${count}= get element count //div[#id='id1']//li
That xpath says to find a div with the id "id1", then find any "li" elements anywhere under that div.

Find my span text using xpath

<body>
...
<div class="first-class">
<ul class="container-class>
<li>
<a><span>Not it</span></a>
</li>
<li>
<a><span>Target</span</a>
</li>
I want to create an Xpath to find the word "target". The number of list elements can vary so I can't use the id because it will change dynamically.
Here's what I've tried:
".//*[#class='first-class']/ul[li a//(text)[contains(.,'Target')]]"
You can try below XPath:
//a[.="Target"]
or
//a[span="Target"]
//a[contains(#span,'Target')]
Should be all it takes.

How to allow nested accordions but manage top level as accordion (and not collapsable) with materializecss?

I'm using nested accordions with Materializecss. I want to be able to have nested accordions, but to let each level to only have 1 item of the accordion opened (as of data-collapsible='accordion').
I can't get it to work: if I set data-collapsible='accordion' I cannot open nested accordions, and if I set data-collapsible='collapsible', I can open any number of items per accordion.
Any workaround?
Thanks!
If you are managing the inner elements of the collapsibles dinamically, then you need to "initialize" them using a jquery method included in "materialize.js". This is written in the "materializecss" documentation here.
I'll provide a practical example.
Given the next HTML:
...
<ul class="collapsible" data-collapsible="accordion">
<li>
<div class="collapsible-header">
My nested collapsible
</div>
<div class="collapsible-body">
<ul class="nested collapsible" data-collapsible="accordion">
<!-- No data initially -->
</ul>
</div>
</li>
<li>
<div class="collapsible-header">Second</div>
<div class="collapsible-body">
<p>Normal data...</p>
</div>
</li>
</ul>
...
I suppose the problem comes because you are appending data into the ".nested" div, and it's not working as an accordion as expected.
You should then do something like:
// ... Your handler code ...
// ... Data appended into $('.nested')
$('.nested').collapsible({accordion: true});
// ...
The {accordion: true} option is not mandatory, as it will be treated as an accordion by default.
It should work in this case. Good luck.