I am having issues to read the "value" propertie from a textarea element in a webpage.
The odd think is that the code use to work, but it stopped, apparently, after a chromedriver/chrome update.
The code line I am using to read it is:
Text = Selenium.FindElementByCss("textarea[id='some_textarea_id']").Value
But now it returns a empty string.
In the "console" tab of Chrome I can filter the text of the textarea element using the below css selector:
$$("textarea[id='some_textarea_id']")[0].value
But in Selenium VBA I fail when I try to use:
Text = Selenium.FindElementByCss("textarea[id='some_textarea_id']")[0].Value
or
Text = Selenium.FindElementByCss("textarea[id='some_textarea_id']")(0).Value
In the first case the sintax is not accepted. The line goes red and i can't run the program.
In the second case I get the error "the object does not accept this proporty or method".
The object is like these (also odd the text I am trying to read, does not appear here):
<textarea class="text sr " wrap="off" id="some_textarea_id" cols="20" maxlen="15" style="top: 0px; left: 103px; width: 132px; height: 21px; background-color: rgb(222, 224, 224);" arautocak="0" arautoctt="400" rows="1" readonly=""></textarea>
Does any one have any clue about the cause of this problem?
Problem solved. Turns out the problem was actually the chromedriver version.
I found out I was using the wrong version.
I don't know why, but there are apparently two chrome driver sites:
https://sites.google.com/a/chromium.org/chromedriver/downloads
and
https://chromedriver.chromium.org/home
In the site number 1 I only get version 91.0.4472.19 of chromedriver, that seems to have the bug I describe above.
In site number 2 I got version 91.0.4472.101 that didn't present that bug.
Note: My chrome browser version is: 91.0.4472.77.
I hope this information helps some one with the same problem. And if anyone knows why there are these two sites for chromedriver download I would love to know.
Thanks
Related
I am getting below error while executing below capybara command,
The interesting thing is the same XPath is not giving any error in I am expecting that XPath to be present.
But when I am trying to perform click on that XPath, it's throwing below error.
--------------code----------------
Then(/^I click on "([^"])" on left tree child of "([^"])"$/) do |child, parent|
within(:xpath, ".//div/span[#class='folder-nav-tree-fileroom' and text()='DND-IndexTwistyExpClps']/../../../../..", wait:5) do
find(:xpath, ".//span[contains(text(), '1 IndexTwistyLevel1')]/../../../span[#class='ui-tree-toggler fa fa-fw fa-caret-right']", wait:5).click
end
end
Error : Capybara::ElementNotFound: Unable to find visible xpath "//div[.//span[contains(text(), '1 IndexTwistyLevel1')]]/span[#class='ui-tree-toggler fa fa-fw fa-caret-right']"
Your code has a number of issues, which indicate it can't actually be working like you claim. If you fix the code and provide the HTML fragment it should be matching against we can narrow done to the issue, but for now the errors are:
Firstly, you have mismatched/non-escaped
's and )s in your XPath expressions (can't have inside a string surrounded bys so it's obvious you haven't copy/pasted your actual code)
Secondly, ::after is not valid XPath - ::after pseudo elements are purely CSS and can't be accessed from XPath, so including that in your selector isn't going to give the expected results. This should result in an invalid selector error being raised by Chrome.
Thirdly, by not starting your selectors with . you're completely defeating the within scoping block - see https://github.com/teamcapybara/capybara#beware-the-xpath--trap
Finally, using visible: false on an element you want to click makes no sense, since you can't click on an element that isn't displayed on the page.
Unfortunately its tough to tell which of these may be causing your actual issue (if any) since the code you have provided isn't valid.
within(:xpath, config['documents_obj']['FRChildTreeXpath'].sub('TEXT', parent), wait:5) do
elem = find(:xpath, config['documents_obj']['childTwistyXpath'].sub('TEXT', child), visible:false, wait:5).native
page.driver.browser.action.click(elem).perform
To avoid the error which iwas gettign what i simply did, is I used capybara action builder,
Take the native element then perform the action.
It worked perfectly in my case.
Reference : https://seleniumhq.github.io/selenium/docs/api/rb/Selenium/WebDriver/ActionBuilder.html
I am having issues with selenium using the next xpath "./preceding-sibling::text()"
I don't understand why, my first thought was that IE wasn't supporting that xpath statement but it didnt work on chrome neither.
What I am trying to do is to verify if a radio button have a certain text "near" it. For example if a radio button is like this
<div>
<label> Yes <input name='radioBtn'></input></label>
<label> No <input name='radioBtn'></input></label>
</div>
This is a simplified scenario where I need to check the "yes" radio button, so what I am doing is to search for the radiobutton and check if it preceding-sibling::text(), but selenium is cant find any element. I know the Xpath works because I test it on chrome developer tools and it returns the text "Yes".
I can't do something like 'input[1]' because I can't be sure that the first one will be always that have the Yes text.
Any idea why isn't this working on selenium? and if there is any work around?
I got to a work around but is kind of specific to the problem. But let's answer the questions 1 at the time.
Any idea why isn't this working on selenium?
It's not working because selenium don't support text elements, so even when selenium find the element it cant map it to a selenium object, i didn't see it because my code hided the selenium exception. The Exception throw is the next one:
An unhandled exception of type
'OpenQA.Selenium.InvalidSelectorException' occurred in WebDriver.dll
Additional information: invalid selector: The result of the xpath
expression "./preceding-sibling::text()" is: [object Text]. It should
be an element
Is there any work around?
Yes it is. What I did was to run a java script using the selenium IJavaScriptExecutor. With the script I revised the preceding sibling text and return it as a string so if the text was equal to the thing I was looking for (i.e Yes) trhat means that is the radio button I was looking for.
The code looks is similar to this (it can have some sintax errors since I didn't copied from the source):
string script = "function GetPrecedingText(node){"+
"var result = document.evaluate('./preceding-sibling::text()[1]', node, null, XPathResult.STRING_TYPE, null);"+
"return (result==null) ? '' : result.stringValue.trim();}"+
"return GetPrecedingText(arguments[0])";
string result = ((driver as IJavaScriptExecutor).ExecuteScript(script, SeleniumElement)).toString();
Hope someone can find this useful :) and thanks for all that tried to help me :)
I am trying to use PhantomJS as a browser to make a selenium test, but I have a problem with an input.
This input is a calendar (is not type date, is text but modified by JavaScript).
First of all, I have this using FirefoxDriver and works perfectly:
webElement.Clear();
webElement.SendKeys(date);
but, using PhantomJSDriver jumps an exception which says this:
{"errorMessage":"Element must be user-editable in order to clear it.","request":{"headers":{"Accept":"application/json, image/png","Connection":"Close","Content-Length":"0","Content-Type":"application/json;charset=utf-8","Host":"localhost:53291"},"httpVersion":"1.1","method":"POST","post":"","url":"/clear","urlParsed":{"anchor":"","query":"","file":"clear","directory":"/","path":"/clear","relative":"/clear","port":"","host":"","password":"","user":"","userInfo":"","authority":"","protocol":"","source":"/clear","queryKey":{},"chunks":["clear"]},"urlOriginal":"/session/a1e4cdb0-b901-11e4-befc-c3b28b46e8f3/element/%3Awdc%3A1424437741971/clear"}}
is very extraneous because in Firefox works perfectly,
what can I do to send the data?
Also I tried to sen this data without clear it, but the default value is 20/02/2015 and when i send something just add after the current text: 20/02/201530/03/2015 and doesn't work.
attribute .text doesn't has setter, the same for getAttribute().
thanks for all,
Ivan.
#edit1: html
<input type="text" aria-haspopup="true" title="" value="20/02/2015" name="id0" id="id0" class="bg datetime hasDatepicker">
Finally i found how to do this, probably is not the best way, but in my case works.
I send the data by JavaScript with javascriptExecutor
((IJavaScriptExecutor)_driver).ExecuteScript("document.getElementById('id0').value='" + date+ "'");
Can anyone tell me how I can identify and switch to the iframe which has only a title?
<iframe frameborder="0" style="border: 0px none; width: 100%; height: 356px; min-width: 0px; min-height: 0px; overflow: auto;" dojoattachpoint="frame" title="Fill Quote" src="https://tssstrpms501.corp.trelleborg.com:12001/teamworks/process.lsw?zWorkflowState=1&zTaskId=4581&zResetContext=true&coachDebugTrace=none">
I have tried by below code but it is not working
driver.switchTo().frame(driver.findElement(By.tagName("iframe")));
driver.switchTo().frame() has multiple overloads.
driver.switchTo().frame(name_or_id)
Here your iframe doesn't have id or name, so not for you.
driver.switchTo().frame(index)
This is the last option to choose, because using index is not stable enough as you could imagine. If this is your only iframe in the page, try driver.switchTo().frame(0)
driver.switchTo().frame(iframe_element)
The most common one. You locate your iframe like other elements, then pass it into the method.
Here locating it by title attributes seems to be the best.
driver.switchTo().frame(driver.findElement(By.cssSelector("iframe[title='Fill Quote']")));
// driver.switchTo().frame(driver.findElement(By.xpath(".//iframe[#title='Fill Quote']")));
you can use cssSelector,
driver.switchTo().frame(driver.findElement(By.cssSelector("iframe[title='Fill Quote']")));
You also can use src to switch to frame, here is what you can use:
driver.switchTo().frame(driver.findElement(By.xpath(".//iframe[#src='https://tssstrpms501.corp.trelleborg.com:12001/teamworks/process.lsw?zWorkflowState=1&zTaskId=4581&zResetContext=true&coachDebugTrace=none']")));
Make sure you switch to default content before switching to frame:
driver.switchTo().defaultContent();
driver.switchTo().frame(x);
x can be the frame number or you can do a driver.findlement and use any of the options you have available eg: driver.findElementByName("Name").
1) goto html view
2) type iframe and find your required frame and count the value and switch to it using
oASelFW.driver.switchTo().frame(2);
if it is first frame then use oASelFW.driver.switchTo().frame(0);
if it is second frame then use oASelFW.driver.switchTo().frame(1); respectively
You can use Css Selector or Xpath:
Approach 1 : CSS Selector
driver.switchTo().frame(driver.findElement(By.cssSelector("iframe[title='Fill Quote']")));
Approach 2 : Xpath
driver.switchTo().frame(driver.findElement(By.xpath("//iframe[#title='Fill Quote']")));
https://seleniumatfingertips.wordpress.com/2016/07/05/handling-frames-in-selenium-webdriver-with-java/
Easiest way of doing this is like this. If its a frame you can right click on the field and if you see the choice of "open frame in a tab" do it.
Then take the URL of the frame and that is what you put in your Python script using "driver.get (http://blah blah..)
Then Selenium can find your named element. This saved me hours of trying all the suggestions here which was learning about but didn't work. Problem with mine was it was in a frame.
I'm using Linux which gives me the right-click option of opening the frame, on its own, in another tab. I don't use Windows so don't know if you would get that option in you right-click menu.
Ganzarola
I struggled with this for a while; a particularly frustrating website had several nested frames throughout the site. I couldn't find any way to identify the frames- no name, id, xpath, css selector- nothing.
Eventually I realised that frames are numbered with the top level being frame(0) the second frame(1) etc.
As I still didn't know which frame the element I needed was sitting in, I wrote a for loop to start from 0 and cycle to 50 continually moving to the next frame and attempting to access my required element; if it failed I got it to print a message and continue.
Spent too much time on this problem for such a simple solution -_-
driver.switch_to.default_content()
for x in range(50):
try:
driver.switch_to.frame(x)
driver.find_element_by_xpath("//*[#id='23']").click()
driver.find_element_by_xpath("/html/body/form/table/tbody/tr[1]/td/ul/li[49]/a").click()
except:
print("It's not: ", x)
continue
There are three ways to switch to the frame
1)Can use id
2)Can use name of the frame
3)Can use WebElement of the frame
2->driver.switchTo().frame("name of the frame");
I think I can add something here.
Situation I faced
I cannot or not easily use the debug tools or inspection tools like firebug to see which frame I am currently at and want to go to.
The XPATH/CSS selector etc. that the inspection tool told me doesn't work since the current frame is not the target one. e.g. I need to first switch to a sub-frame to be able to access/locate the element from XPATH or any other reference.
In short, the find_element() or find_elements() method doesn't apply in my case.
Wait Wait! not exactly
unless we use some fazzy search method.
use find_elements() with contains(#id,"frame") to filter out the potential frames.
e.g.
driver.find_elements(By.XPATH,'//*[contains(#id,"frame")]')
Then use switchTo() to switch to that frame and hopefully the underlying XPATH for your target element can be accessed this time.
If you're similar unlucky like me, iteration might need to be done for the found frames and even iterate deeper in more layers.
e.g.
This is the piece I use.
try:
elf1 = mydriver.find_elements(By.XPATH,'//*[contains(#id,"rame")]')
mydriver.switch_to_frame(elf1[1])
elf2 = mydriver.find_elements(By.XPATH,'//*[contains(#id,"rame")]')
mydriver.switch_to_frame(elf2[2])
len(mydriver.page_source) ## size of source tell whether I am in the right frame
I try out different switch_to_frame(elf1[x])/switch_to_frame(elf2[x]) combinations and finally found the wanted element by the XPATH I found from the inspection tool in browser.
try:
element = WebDriverWait(mydriver, 10).until(
EC.presence_of_element_located((By.XPATH, '//*[#id="C4_W16_V17_ZSRV-HOME"]'))
)
#Click the link
element.click()
I could solve that with the following code
browser.switch_to.frame(browser.find_element_by_tag_name('iframe'))
I am using the selenium getAttribute("style") method on the following id element:-
<div id="ntsDiv_1" style="width: 250px; text-align: left; white-space: normal; top: 1090px; left: 131px; visibility: hidden;" class="mlt-pop-container">
but the API is returning only the half of the value. It is returning width: 250px; text-align: left; white-space: normal; and the remaning portion of the style is clipped.
I'm trying to extract the value of the visibility, but the method is not returning the complete value of style. Hence, i am unable to determine the correct value of visibility.
I executed System.out.println("Style is:- "+super.getElement(NEXTAG_STORES_DIV).getAttribute("style"));
NEXTAG_STORES_DIV corresponds to the xpath of the id element, and super.getElement extracts element by xpath
Please help me out!!
I just tried this with Selenium 2.30.0 and it works fine, the whole attribute is returned.
Try the following things (all the examples assume element is the WebElement you need to test):
Make really sure only a part of the attribute is returned. Aren't you just printing it into console? Many consoles have a limited line length. Try setting your console to show long lines. Check programatically the length of the returned value, or try evaluating
element.getAttribute("style").contains("visibility")
Try upgrading your Selenium library, if you can. I am not aware of any bug related to attribute getting, but there might have been some which is now (with version 2.30.0) solved.
Try it in a different browser / OS / architecture. If it works somewhere, you'll know it's an issue of a particular browser / driver / OS / architecture / whatever and you might be able to focus it down and either fix it or file a bug.
If you simply want to know whether an element is visible or not, the correct and generally preferred way is to call
element.isDisplayed()
This method takes care of all the rules you might need to inspect in order to determine whether it actually is visible or not.
If the style value changes dynamically on the page (i.e. it's not statically written in the source code of the page), WebDriver can't really see it as it doesn't pick up dynamic changes. Try accessing the value via JavaScript:
if (!driver instanceof JavascriptExecutor) {
throw new IllegalStateException("JavaScript not enabled for this driver!");
}
JavascriptExecutor js = (JavascriptExecutor)driver;
String styleAttribute = (String)js.executeScript("return arguments[0].style", element);
If you actually need to get the computed value of the CSS visibility attribute that is actually used by the browser and not the one in the style atribute (if there either isn't any or is somehow overridden), you need to use the JavaScript's getComputedStyle() method. One way (described by this article on quirksmode.org) is this:
var elem = arguments[0];
if (elem.currentStyle) {
var vis = elem.currentStyle['visibility'];
} else {
var vis = document.defaultView.getComputedStyle(elem, null).getPropertyValue('visibility');
}
return vis;
Again, this should be invoked via
String visibility = (String)js.executeScript(here_goes_the_whole_script, element);