how to click by attribute in selenium? - selenium

HTML structure:
<g class="bars">
<rect class="bar selected" x="81" y="79" width="66" height="126">
<rect class="bar selected" x="169" y="79" width="66" height="126">
<rect class="bar selected" x="257" y="60" width="66" height="145">
</g>
I need to click in bar selected with attribute x=81.
How to do this?
Thank you

Find the element by xpath. Example (using python bindings):
element = driver.find_element_by_xpath('//g[#class="bars"]/rect[#x="81"]')
element.click()
There are certainly multiple ways to find that element. For instance, you can get the first rect out of the g tag:
//g[#class="bars"]/rect[1]
Or, you can additionally check the class attribute:
//g[#class="bars"]/rect[#class="bar selected"][1]
Or, you can combine the options I've mentioned and make your own xpath. It really depends on the uniqueness of the element and it's attributes across the page. Difficult to say without seeing the complete HTML source of the page.

Related

webdriverio findelements and $$ options are returning a Typescript error getText is not a function

I have the below html tag generated as part of highchart
<g class="highcharts-axis-labels highcharts-xaxis-labels " data-z-index="7">
<text x="332.3333333333367" style="color:#666666;cursor:default;font-size:13;fill:#666666;" text-anchor="middle" transform="translate(0,0)" y="246" opacity="1">60</text>
<text x="886.9999999999668" style="color:#666666;cursor:default;font-size:13;fill:#666666;" text-anchor="middle" transform="translate(0,0)" y="246" opacity="1">65</text>
<text x="1441.6666666666667" style="color:#666666;cursor:default;font-size:13;fill:#666666;" text-anchor="middle" transform="translate(0,0)" y="246" opacity="1">70</text>
</g>
I am trying to extract all the text values in it and used the below command
xAxis = $('.highcharts-xaxis-labels').$$('text').getText();
I tried the browser.findelements using the XPATH as well. But with both I am getting the error message
TypeError: $(...).$$(...).getText is not a function
The problem here is that $$ (an alias for getElements) returns an array of elements, not just one element. An element has a getText() method, but an array doesn't have that.
If you want to get a list of all the values, you need to map the list of elements to each element's value:
$('.highcharts-xaxis-labels').$$('text').map(textElement => textElement.getText());

Selenium Xpath works sometimes, does not work the following time

I'm trying to make an application to automate job applying on linkedin with selenium.
When I find an xpath for an element on the webpage and tell my code to locate the element, it found it and clicked it with no issue.
However when I run the same exact code later on
alpha = driver.find_element_by_xpath("//*[#id='ember2350']/form/button")
I'm greeted with a no such element exception, why does this happen?
Edit:
Here's the HTML of the button I'm trying to get to
<button aria-expanded="false" aria-controls="linkedin-features-facet-values" class="search-s-facet__name-wrap search-s-facet__name-wrap--pill button-secondary-medium-muted" data-is-animating-click="true">
<div class="search-s-facet__name-wrap-container search-s-facet__name-wrap-container--pill">
<div class="search-s-facet__name">
<span class="visually-hidden">Expand LinkedIn Features facet</span>
<h3 class="search-s-facet__name Sans-17px-black-55%-semibold">LinkedIn Features</h3>
</div>
<span class="search-s-facet__svg-icon svg-icon-wrap"><li-icon aria-hidden="true" type="caret-filled-down-icon" size="small"><svg viewBox="0 0 24 24" width="24px" height="24px" x="0" y="0" preserveAspectRatio="xMinYMin meet" class="artdeco-icon" focusable="false"><path d="M8.8,10.66L14,5.12A0.07,0.07,0,0,0,13.93,5H2.07A0.07,0.07,0,0,0,2,5.12L7.2,10.66A1.1,1.1,0,0,0,8.8,10.66Z" class="small-icon" style="fill-opacity: 1"></path></svg></li-icon></span>
</div>
</button>
On LinkedIn #id are dynamic values, so you shouldn't use them to locate elements. Try below instead:
driver.find_element_by_xpath("//button[.//span='Expand LinkedIn Features facet']").click()
It seems that the Id - "ember2350" is dynamic and the numeric is changing so that's why it is not working as it is changing everytime.
Use this xpath :
//span[normalize-space()='Easy Apply']

How to Select a checbox by its corresponding label name

I am relatively new to xpath and I'm having an issue with Selecting a checkbox.
The following expression works fine
:xpath=//div/label[#for='chkCat2']
But I need to select a checkbox based on its label name (Music in this case)
Unfortunately, this -
xpath=.//div[label[contains(text(),'Music')]
is clicking on the label, not on the checkbox.
How is it possible to do that? I also tried this one but its not able to locate the element:
xpath=.//div[label[contains(text(),'Music')]/preceding-sibling::label]
That's the sample of the code:
<input name="ctl00$cphContent$ThreeMedia$categoriesRepeater$ctl01$ctl00"
data-bind="attr:{'id': 'chkCat' + id, 'data-id': id}, checked: selected" id="chkCat2" data-id="2" type="checkbox">
<label data-bind="attr:{'for': 'chkCat' + id}" for="chkCat2" class=" firepath-matching-node"></label>
<label class="chkbox-content margin-bottom-0" data-bind="text: name">Music</label>
Thanks for the help
But I need to select a checkbox based on its label name (Music in this case)
Assuming div is the parent element of the provided checkbox element, try using below xpath :-
.//div[normalize-space(.)='Music']/input
or more specific
.//div[normalize-space(.)='Music']/input[#type='checkbox']
one more
.//div[label[text() = 'Music']]/input
Try this below mentioned xpath
//label[text()= 'Music']/..//preceding-sibling::input[#id='chkCat2']
Explanation of xpath:- Use text method along with <label> tag and move ahead with <input> tag using preceding-sibling keyword.

RML Test of Page Number

Moin Moin,
I'm working on Openerp 7 and there pdf's get created with rml.
Problem is: I need Page Numbers, but just starting of the second Page.
I tried some rml if clause statements, but Page 1 gets printed all the time and the things that get printet are pretty wierd.
<header>
<pageTemplate id="second">
<frame id="second" x1="2.2cm" y1="2.5cm" width="16.9cm" height="22.3cm"/>
<pageGraphics>
<image file="images/isatech_water_header_medium.jpg" x="0.0cm" y="24.4cm" width="19.0cm" height="6.0cm"/>
<image file="images/isatech_water_footer.jpg" x="0.0cm" y="-0.5cm" width="16.9cm" height="2.6cm"/>
</pageGraphics>
</pageTemplate>
<pageTemplate id="first">
<frame id="first" x1="2.2cm" y1="2.5cm" width="16.9cm" height="22.3cm"/>
<pageGraphics>
<image file="images/isatech_water_header.jpg" x="0.0cm" y="24.4cm" width="19.0cm" height="6.0cm"/>
<image file="images/isatech_water_footer.jpg" x="0.0cm" y="-0.5cm" width="16.9cm" height="2.6cm"/>
[[ <pageNumber/> != '1' and <drawCentredString x="10cm" y="0.3cm"><pageNumber/></drawCentredString> ]]
</pageGraphics>
</pageTemplate>
</header>
What gets printed on the pdf is:
]] 1(2,3,...)
The pageTemplate second is for printing different header after page 1. I hope to get that straigt after the page numbers.
I really have no idea why the code behaves like he does. Different solutions are also welcome.
mfg Chris
I found a different way to do it.
It is not a good Idea to check the pageNumber in RML.
If I got it right, then the pageNumber is processed as one of the last steps. (Same goes for PageCount where it makes sense as you can't know the pageCount until the end of building your document)
Even if you call a python function with a pageNumber it gets handled as a String. I can just imagine it is the same reason.
I helped myself with a <setNextTemplate name="pageTemplate id"/>
Uncheck Add RML header in Settings > Actions > Reports > "Your Report"
Change your RML File and define the different pageTemplates
<template title="Sales Order" author="OpenERP S.A.(sales#openerp.com)" allowSplitting="20" showBoundary="0">
<pageTemplate id="first">
<frame id="first" x1="2.2cm" y1="2.5cm" width="16.9cm" height="22.3cm"/>
<pageGraphics>
<image file="images/header_page_1.jpg" x="0.8cm" y="24.7cm" width="16,9cm" height="4cm"/>
<image file="images/footer_page_1.jpg" x="0.4cm" y="-0.4cm" width="16.9cm" height="2.3cm"/>
</pageGraphics>
</pageTemplate>
<pageTemplate id="second">
<frame id="first" x1="2.2cm" y1="2.5cm" width="16.9cm" height="22.3cm"/>
<pageGraphics>
<image file="images/header_page_2.jpg" x="0.8cm" y="24.7cm" width="16,9cm" height="4cm"/>
<image file="images/header_page_2.jpg" x="0.4cm" y="-0.4cm" width="16.9cm" height="2.3cm"/>
</pageGraphics>
</pageTemplate>
Somewhere on page x add <setNextTemplate name="pageTemplate id"/>
or <setNextTemplate name="pageTemplate id"/>
<nextFrame/> to change the pageTemplate of page x+1
<setNextTemplate name="pageTemplate id"/> simply defines the pageTemplate of the next page and
<nextFrame/> additionaly end the current page.
Edit(Multi-Company-Header): I kind of forgot that we have multi Company Headers. Still I use this method. I just copy the .rml for every Company and hardcode the different company logos. Then in the reports setting page for every company(database) I specific the right .rml file.
I's very redundant, but I didn't found a better solution.
VG Chris

Click checkbox with Nested Elements in Watir

I'll try to keep it simple.
I have a list of similar rows like this:
HTML code:
<li ...>
<div ... >
<some elements here>
</div>
<input id="121099" class="containerMultiSelect" type="checkbox" value="121099" name="NodeIds">
<a ...>
<div ... />
<div ... >
<h2>Identified Text</h2>
<h3>...</h3>
</div>
</a>
</li>
I want to click the checkbox with a certain text, but I can't use any of its elements, because they are the same for all the list, and id is generated automatically. The only thing can be differentiated is the h2 text. I tried :
browser.h2(:text => /Identified/).checkbox(:name => "NodeIds").set
and I got UnknownException which is obvious because checkbox is not nested with a tag.
What can I do in this case?
Thanks
The h2 and checkbox are related by the li, which is a common ancestor. Therefore, to find the checkbox, you can look for the li that contains the h2 element. I find the most readable approach to doing this is by using the find method of the element collection. The find method basically allows you to make custom locators.
The code would be:
parent_li = browser.lis.find do |li|
li.h2(:text => 'Identified Text').present?
end
parent_li.checkbox.set
Notes:
browser.lis creates a collection of all li elements.
find iterates through the lis and returns the first element that has the block evaluate as true - ie the first li where an h2 with the specified text is present.
First have a look at this explanation
http://jkotests.wordpress.com/2012/12/20/finding-a-parent-element-that-matches-a-specific-criteria/
Now following a similar approach,
First locate the element that has a unique identifier
parent=#browser.h2(:text=>"Identified Text")
Now we have to iterate over to the parent element which contains both the checkbox and text against it.
parent=parent.parent until parent.tag_name=="li"
Once the control is on the li element, simple click on the checkbox using.
parent.checkbox.click