What is the difference between 'page_source' and 'find_element_by_tag_name("body").text'? - python-3.x

Trying to find whether a text is present on UI login page (web-page).
I could verify it by 'driver.page_source()' and driver.find_element_by_tag_name("body").text
driver.page_source()
text = "abcd"
page_source = driver.execute_script("return document.body.innerHTML;")
if text in page_source:
return True
else:
return False
driver.find_element_by_tag_name("body").text
text = "abcd"
value = text in self.browser.find_element_by_tag_name("body").text
if value:
return True
else:
return False
What's the difference between method1 and method2 ?
Which one is preferred to do the required task ?
Which is faster ?
Or anySelenium-UI methods to be used ?
Any help would be appreciated. Looking for valuable inputs.
Any idea on this ? Any help here ?

Page source will give all the text including HTML tags, styles etc. as you have written yourself in execute script to return the innerHTML. So, all HTML code will be returned which obviously will contain the text too. You can also get the whole html with selenium too instead of using JavaScript executor by browser.page_source.
On the other hand, browser.find_element_by_tag_name("body").text will return all the text you see on the page without html tags.
To me, the 2nd method should be preferred and faster because you will have string of smaller length(without un-necessary html tags) and the actual text you are interested in.

Related

Can't acess dynamic element on webpage

I can't acess a textbox on a webpage box , it's a dynamic element. I've tried to filter it by many attributes on the xpath but it seems that the number that changes on the id and name is the only unique part of the element's xpath. All the filters I try show at least 3 element. I've been trying for 2 days, really need some help here.
from selenium import webdriver
def click_btn(submit_xpath): #clicks on button
submit_box = driver.find_element_by_xpath(submit_xpath)
submit_box.click()
driver.implicitly_wait(7)
return
#sends text to text box
def send_text_to_box(box_xpath, text):
box = driver.find_element_by_xpath(box_xpath)
box.send_keys(text)
driver.implicitly_wait(3)
return
descr = 'Can't send this text'
send_text_to_box('//*[#id="textfield-1285-inputEl"]', descr)' #the number
#here is the changeable part on the xpath
:
edit: it worked now with the following xpath //input[contains(#id, 'textfield') and contains(#aria-readonly, 'false') and contains (#class, 'x-form-invalid-field-default')] . Hopefully I found something specific on this element:
You can use partial string to find the element instead of an exact match. That is, in place of
send_text_to_box('//*[#id="textfield-1285-inputEl"]', descr)' please try send_text_to_box('//*[contains(#id,"inputEl")]', descr)'
In case if there are multiple elements that have string 'inputE1' in id, you should look for something else that remains constant(some other property may be). Else, try finding some other element and then traverse to the required input.

how to get the data in url using groovy code?

i want to get defect id from the url using groovy code (To build custom code in tasktop).
for example: I will have an dynamic url generated say www.xyz.com/abc/defect_123/ now I want to retrieve that letter that always starts from 17th position. and return the string
Please help..
Thanks in advance
Here are two possibilities. Please note that the "substring" option is very strict and will always start from the 16th position (what happens if the domain changes from www.xyz.com to www.xyzw.com?)
def str = 'www.xyz.com/abc/defect_123/';
def pieces = str.tokenize('/'); // prints defect_123
def from16 = str.substring(16); // prints defect_123/
println from16;
println pieces.last();
You should define this as dynamic url in UrlMappings.groovy file:
"www.xyz.com/abc/$defect_id" (controller: 'YourController', action: 'method_name')
and you can access the defect_id variable from YourController using params.defect_id

Groovy XmlParser / XmlSlurper: node.localText() position?

I have a follow-up question for this question: Groovy XmlSlurper get value of the node without children.
It explains that in order to get the local inner text of a (HTML) node without recursively get the nested text of potential inner child nodes as well, one has to use #localText() instead of #text().
For instance, a slightly enhanced example from the original question:
<html>
<body>
<div>
Text I would like to get1.
extra stuff
Text I would like to get2.
link to example
Text I would like to get3.
</div>
<span>
extra stuff
Text I would like to get2.
link to example
Text I would like to get3.
</span>
</body>
</html>
with the solution applied:
def tagsoupParser = new org.ccil.cowan.tagsoup.Parser()
def slurper = new XmlSlurper(tagsoupParser)
def htmlParsed = slurper.parseText(stringToParse)
println htmlParsed.body.div[0].localText()[0]
would return:
[Text I would like to get1., Text I would like to get2., Text I would like to get3.]
However, when parsing the <span> part in this example
println htmlParsed.body.span[0].localText()
the output is
[Text I would like to get2., Text I would like to get3.]
The problem I am facing now is that it's apparently not possible to pinpoint the location ("between which child nodes") of the texts. I would have expected the second invocation to yield
[, Text I would like to get2., Text I would like to get3.]
This would have made it clear: Position 0 (before child 0) is empty, position 1 (between child 0 and 1) is "Text I would like to get2.", and position 2 (between child 1 and 2) is "Text I would like to get3." But given the API works as it does, there is apparently no way to determine whether the text returned at index 0 is actually positioned at index 0 or at any other index, and the same is true for all the other indices.
I have tried it with both XmlSlurper and XmlParser, yielding the same results.
If I'm not mistaken here, it's as a consequence also impossible to completely recreate an original HTML document using the information from the parser because this "text index" information is lost.
My question is: Is there any way to find out those text positions? An answer requiring me to change the parser would also be acceptable.
UPDATE / SOLUTION:
For further reference, here's Will P's answer, applied to the original code:
def tagsoupParser = new org.ccil.cowan.tagsoup.Parser()
def slurper = new XmlParser(tagsoupParser)
def htmlParsed = slurper.parseText(stringToParse)
println htmlParsed.body.div[0].children().collect {it in String ? it : null}
This yields:
[Text I would like to get1., null, Text I would like to get2., null, Text I would like to get3.]
One has to use XmlParser instead of XmlSlurper with node.children().
I don't know jsoup, and i hope it is not interfering with the solution, but with a pure XmlParser you can get an array of children() which contains the raw string:
html = '''<html>
<body>
<div>
Text I would like to get1.
extra stuff
Text I would like to get2.
link to example
Text I would like to get3.
</div>
<span>
extra stuff
Text I would like to get2.
link to example
Text I would like to get3.
</span>
</body>
</html>'''
def root = new XmlParser().parseText html
root.body.div[0].children().with {
assert get(0).trim() == 'Text I would like to get1.'
assert get(0).getClass() == String
assert get(1).name() == 'a'
assert get(1).getClass() == Node
assert get(2) == '''
Text I would like to get2.
'''
}

Pyramid Chameleon Tal:condition 'Not' issue

I am trying to display conditional text in a Pyramid Chameleon template. Basically, checking if the dictionary key 'maxed_out_alerts' is empty (false) or has a string 'yes' in it.
<p tal:condition="not:maxed_out_alerts"><h3>Maxed Out.</h3></p>
<p tal:condition="maxed_out_alerts"><h3>Not Maxed Out</h3></p>
When 'maxed_out_alerts' is an empty string, 'Maxed Out' is only displayed (correctly). However, If 'maxed_out_alerts' contains 'yes' string both 'Maxed Out' and "Not Maxed Out' are displayed (incorrectly).
It seems that the NOT is always evaluated to a true condition. It should display one or the other messages not both. What am I doing wrong? thanks
For TAL conditionals in python you can say python: and then use a python syntax conditional
<p tal:condition="python:len(maxed_out_alerts) > 0"><h3>Maxed Out.</h3></p>
It could help if you save boolean state in a boolean variable. By storing this information in a string you run into such problems you are facing right now. That's what builtin python types are made for - use them.
As a pyramid developer I would advice to move the logic to evaluate the current value of maxed_out_alerts into a string into a view method and pass the computed string in a dictionary to the renderer/template. This way you can even create tests for the view logic - any pyramid tutorial, simple or advanced shows you how to do that.
A good start for any simple logic - imagine logic gets more complicated or you even have to translate the text for the template.
#view_config(name="yourname", renderer='templates/yourtemplate.pt')
def myview(request):
"""
#get boolean state from model
#could be that you want to have it the other way round
#or do it by using python ternary operator - a if test else b
if model['maxed_out_alerts'] == True:
maxed_out_alerts = 'Maxed Out'
else:
maxed_out_alerts = 'Not Maxed Out'
return dict(maxed_out_alerts = maxed_out_alerts)
In your Template
<h3 tal:content="maxed_out_alerts">text for maxed out alerts</h3>
or
<h3>${maxed_out_alerts}</h3>

In Watir, how to get the full text, from a portion of text?

I have a portion of HTML that looks similar to:
<table><tbody><tr>
<td><div> Text Goes Here </div></td>
<td> ... rest of table
There are no IDs, no Titles, no descriptors of any kind to easily identify the div that contains the text.
When an error occurs on the page, the error is inserted into the location where "Text Goes Here" is at (no text is present unless an error occurs). Each error contains the word "valid".
Examples: "The form must contain a valid name" or "Invalid date range selected"
I currently have the Watir code looking like this:
if browser.frame(:index => 0).text.includes? "valid"
msg = # need to get full text of message
return msg
else
return true
end
Is there any way to get the full text in a situation like this?
Basically: return the full text of the element that contains the text "valid" ?
Using: Watir 2.0.4 , Webdriver 0.4.1
Given the structure you provided, since divs are so often used I would be inclined to look for the table cell using a regular expression as Dave shows in his answer. Unless you have a lot of nested tables, it is more likely to return just the text you want.
Also if 'valid' may appear elsewhere then you might want to provide a slightly larger sample of the text to look for
. browser(:cell => /valid/).text
Try this
return browser.div(:text => /valid/).text
or
return browser.table.div(:text => /valid/).text
if the valid is not found, it should return nil.

Resources