Selenium search bar protected ? " undefined local element or method" - ruby

I am using selenium trying to send a key to a search bar.
This is the code of the search bar.
<input type="text" value="XXXXXXX" onblur="ga('send', 'event',
'Search', 'Champ_de_recherche');" name="champs" id="input_search" aria-
label="Recherche XXX.com" autocapitalize="none" autocorrect="off">
I am unable to locate it with selenium using name / css / class or id selector
element = element.find_element(:id, "input_search")
element = element.find_element(:name, "champs")
both are returning "undefined local variable or method `element' for main:Object (NameError)"
any guess ?

I think it looks like an issue with your code, e.g.:
element = element.find_element
More specifically this bit:
element.find_element
Shouldn't that be:
browser.find_element
or
driver.find_element
(or similar) ?

It's saying that you don't have element defined before attempting to call those methods. If you aren't trying to find a child element from an element, use the find_element method off of your driver instance

Related

Set div value of WebElement with Selenium Webdriver

I want to set new value of div element by using Selenium FirefoxDriver in Java:
<div my-div-name="lastname">
<p>Smith</p>
</div>
I have successfully retrieved the div element (as WebElement) by use of XPATH expression and have also been able to get current value Smith by use of getText() method. However, there is no setText() method of an WebElement. So I have in stead tried to execute JavaScript:
driver.executeScript("arguments[0].value = 'Foo Bar'", element);
but nothing happens. New getText() call still returns Smith.
Any tip on how to set the value successfully?
Solution is to set innerHTML property like this:
driver.executeScript("arguments[0].innerHTML = arguments[1]", element, text);
I have tried to do this several times, but i wrote innerHtml and not innerHTML so be aware of casing when setting the property.

Can't compare expected result for <nobr> tag

There is a nobr tag with some text:
<nobr>+380</nobr>
I have described it in page-object:
elements(:txtCode, :nobr, :xpath => "//td[#id='phone_prefix']/nobr")
I need to check its value and I use following expectation:
expect(page.txtCode.text).to eql('+380')
But I'm getting the following error:
undefined method `txtCode' for #<Page:0x3071d30>
How do i describe this nobr element to bring the expect() to work?
You're defining an element collection instead of an element because you're using elements instead of element. The only method that creates on your page object is txtCode_elements. Use element instead.
element(:txtCode, :nobr, :xpath => "//td[#id='phone_prefix']/nobr")
You can read more about element collections from this blog post by Justin Ko: https://jkotests.wordpress.com/2013/06/24/defining-element-collections-using-the-page-objects-gem/

Capybara - overriding an attribute on the node

Lets say I successfully retrieve some Capybara node:
node = find("#some-element")
The element has some nasty attribute that I just want to ignore or override for the context of the given test:
node[:onClick] # "someInlineJSCrap(); return false;"
Is it possible to override an attribute on the Capybara node? I've tried ruby hash assignment syntax with no luck;
node[:onClick] = "return true;"
Edit (full error):
undefined method `[]=' for # <Capybara::Element tag="a"> (NoMethodError)
Any help would be appreciated!
i don't know if that's even possible, but i think that i have a workaround for you.
you can use page.execute_script to change the onClick value of your node via JavaScript.
that would be something like page.execute_script("$('#some-element').attr('onClick', 'return true;')")

Get all attributes or xPath of element in Webdriver

I'm trying to do simple monkey test for my web page, which get all active elements on page and click on them in random order.
When i do this I want to write a log to know, on which element my test click and on which test crashed
So I want log file to look like this
01.01.11 11.01.01 Clicked on Element <span id='myspan' class ='myclass .....>
01.01.11 11.01.01 Clicked on Element <span id='button' class ='myclass title = 'Button'.....>
or
01.01.11 11.01.01 Clicked on Element //*[#id='myspan']
01.01.11 11.01.01 Clicked on Element //*[#id='button']
Is it any way to do in Webdriver + Ruby?
I don't think there is a way but you could always do something like this (with watir-webdriver):
browser.divs.each do |div|
puts '<span ' + ['id','class','title'].map{|x| "#{x}='#{div.attribute_value(x)}'"}.join(' ') + '>'
end
WebDriver does not provide this type of functionality, you would have to get the page source and do some of your own parsing - I've done this in Html Agility Pack with C#, you would need to find a similar library for ruby (see: Options for HTML scraping?)
You can do this:
Get all elements, which are clickable
For example, find all links, find all clickable spans. Put those candidates in a list
Randomly pick a element in that candidate list
Click the very element and write some log
I tweaked #pguardiario's answer to come up with this method:
def get_element_dom_info(#e)
if #e.class != Selenium::WebDriver::Element
raise "No valid element passed: #{#e.class}"
end
#attrs = ['id', 'class', 'title', 'href', 'src', 'type', 'name']
return "<" + #e.tag_name + #attrs.map{ |x| " #{x}='#{#e.attribute(x)}'" if #e.attribute(x) && #e.attribute(x) != "" }.join('') + ">"
end
Of course, it expects that the single parameter you pass into it is an actual Selenium element. Also, it doesn't include every possible attribute, but that's the majority of them (and you can always add your extra attributes if needed).
I suppose you can integrate this via some code like this:
def clickElement(*args)
... # parse vars
#e = #driver.find_element(...)
puts get_timestamp + " Clicked on Element: " + get_element_dom_info(#e)
end
UPDATE
I recently realized that I could get the full html of the element using native javascript (d'oh!). You have to use a hack to get the "outerHTML". Here is my new method:
def get_element_dom_info(how, what)
e = #driver.find_element(how, what)
# Use native javascript to return element dom info by creating a wrapper
# that the element node is cloned to and we check the innerHTML of the parent wrapper.
return #driver.execute_script("var f = document.createElement('div').appendChild(arguments[0].cloneNode(true)); return f.parentNode.innerHTML", e)
end

Nokogiri Error: undefined method `radiobutton_with' - Why?

I try to access a form using mechanize (Ruby).
On my form I have a gorup of Radiobuttons.
So I want to check one of them.
I wrote:
target_form = (page/:form).find{ |elem| elem['id'] == 'formid'}
target_form.radiobutton_with(:name => "radiobuttonname")[2].check
In this line I want to check the radiobutton with the value of 2.
But in this line, I get an error:
: undefined method `radiobutton_with' for #<Nokogiri::XML::Element:0x9b86ea> (NoMethodError)
The problem occured because using a Mechanize page as a Nokogiri document (by calling the / method, or search, or xpath, etc.) returns Nokogiri elements, not Mechanize elements with their special methods.
As noted in the comments, you can be sure to get a Mechanize::Form by using the form_with method to find your form instead.
Sometimes, however, you can find the element you want with Nokogiri but not with Mechanize. For example, consider a page with a <select> element that is not inside a <form>. Since there is no form, you can't use the Mechanize field_with method to find the select and get a Mechanize::Form::SelectList instance.
If you have a Nokogiri element and you want the Mechanize equivalent, you can create it by passing the Nokogiri element to the constructor. For example:
sel = Mechanize::Form::SelectList.new( page.at_xpath('//select[#name="city"]') )
In your case where you had a Nokogiri::XML::Element and wanted a Mechanize::Form:
# Find the xml element
target_form = (page/:form).find{ |elem| elem['id'] == 'formid'}
target_form = Mechanize::Form.new( target_form )
P.S. The first line above is more simply achieved by target_form = page.at_css('#formid').

Resources