Setting input text field with watir-jquery - watir

I am trying to set the value of a text input using watir-jquery selectors. I find that it only works with watir's text_field selector. My questions are:
How to set input fields using watir-jquery
What is watir's text_field selector, and why does its result have different methods than the same field found by the input selector?
The relevant code follows:
require 'watir'
require 'watir-jquery'
browser = Watir::Browser.new
browser.goto 'www.yandex.com'
jq_inp = browser.jq('input#searchInput')
jq_inp.value = 'Vlad the Impaler'
NoMethodError: undefined method `value=' for #<Watir::Input:0x007fd7f3c3cee0>
from gems/ruby-2.0.0-p247/gems/watir-webdriver-0.6.4/lib/watir-webdriver/elements/element.rb:553:in `method_missing'
wt_inp = browser.input(:id, 'searchInput')
wt_inp.value = 'Vlad the Impaler'
NoMethodError: undefined method `value=' for #<Watir::Input:0x007fd7f3c97b60>
from gems/ruby-2.0.0-p247/gems/watir-webdriver-0.6.4/lib/watir-webdriver/elements/element.rb:553:in `method_missing'
wt_tf = browser.text_field(:id, 'searchInput')
wt_tf.value = 'Vlad the Impaler' # This works!
# So, let us try text_field with jquery
jq_tf = browser.jq('text_field#searchInput')
=> nil
# No search thing as text_field in jquery

Watir has a TextField object that is a subtype of Input, which supports set. So both
browser.jq('input#searchInput').to_subtype.set
and
browser.input(:id, 'searchInput').to_subtype.set
work.

Related

SimpleAttribute instead of Attribute in Rapidminer script?

I am trying to extract an Attribute from an ExampleSet in a RapidMiner 'Execute script' like this:
ExampleSet exSet = input[0];
Attributes attrs = exSet.getAttributes();
Attribute attr = attrs.getAttribute("h_area");
but then I get an error and it says that attrs is not a Attributes but a SimpleAttributes object.
This works:
Attribute[] attrs2 = exSet.createRegularAttributeArray();
Attribute attr2 = attrs2.getAt(1);
What is the correct way to get an Attribute from an ExampleSet?
From these docs, it looks like the getAttributes() call will return an object implementing the Attributes abstract class, which SimpleAttributes is, so it looks pretty fair at this stage. However, the getAttribute() method doesn't look like it's defined in either object. I can't test this here and now, but have you tried the following:
ExampleSet exSet = input[0];
Attributes attrs = exSet.getAttributes();
Attribute attr = attrs.get("h_area");

Is `#browser` the obligatory name for the ChromeDriver object when using Watir/Chrome?

I want to change the name of the #browser variable because I'm tired of typing it.
In env.rb:
before do
#b = Watir::Browser.new :chrome
end
This throws error:
Unable to pick a platform for the provided browser or element: nil.
nil was passed to the PageObject constructor instead of a valid browser or element object. (RuntimeError)
before do
#browser = Watir::Browser.new :chrome
end
works as expected.
#browser = Watir::Browser.new :chrome
#b = #browser
doesn't work either. Is there any way to modify this variable name?
In general, you can store your browser instance in a variable of any name. Watir-Webdriver does not care, nor does Cheezy's page objects. The initialization of the page object only cares what the actual object passed in is - ie it must be a Watir::Browser or Watir::Element (or the Selenium-WebDriver equivalents).
However, this is not true when using the PageObject::PageFactory. In the on_page method, and implicitly visit_page and if_page, the code is hard-coded to look for a #browser variable.
def on_page(page_class, params={:using_params => {}}, visit=false, &block)
page_class = class_from_string(page_class) if page_class.is_a? String
return super(page_class, params, visit, &block) unless page_class.ancestors.include? PageObject
merged = page_class.params.merge(params[:using_params])
page_class.instance_variable_set("#merged_params", merged) unless merged.empty?
#current_page = page_class.new(#browser, visit)
block.call #current_page if block
#current_page
end
The initialization of the page object is always done with #browser. When you stored the browser instance in #b, it meant that #browser was nil. This then led to the exception you saw. If you want to use the PageFactory as written, you will need to stick to #browser.
If the variable really bothers you, there is always the option for monkey patching. Simply re-define the on_page and on method to use whatever variable you like. The following redefines the method to use #b:
require 'page-object'
module PageObject
module PageFactory
def on_page(page_class, params={:using_params => {}}, visit=false, &block)
page_class = class_from_string(page_class) if page_class.is_a? String
return super(page_class, params, visit, &block) unless page_class.ancestors.include? PageObject
merged = page_class.params.merge(params[:using_params])
page_class.instance_variable_set("#merged_params", merged) unless merged.empty?
#current_page = page_class.new(#b, visit)
block.call #current_page if block
#current_page
end
alias_method :on, :on_page
end
end
The issue is somewhere else in your code. If you run just the line you provided (after requiring watir)
require 'watir-webdriver'
#b = Watir::Browser.new :chrome
in a IRB session it will work just fine..
Some other code dependency (page objects library perhaps) needs a browser object and is expecting a specific name, is getting a nill (un-initialized) object instead and complaining.
Also, unless you want the overhead of opening and closing the browser for each test (can add a ton of time) you may want to initialize the browser earlier, such as in a before_all hook, or early in the startup of your test code. Then just do something like clear cache and cookies in the before hook

Get element Id from a found element

I'm using the Chrome driver and Selenium tools in my CodedUI tests. I can find the element I need using the SearchProperties and a Contains operator however I need the full Id for subsequent searches.
For example I need to find an input element with Id "pm_modal_28".
This is easy enough by doing a search where Id contains "pm_modal".
I then need to parse the value "28" out of the Id that was found so I can search for the next nested element which has an Id of "dp_28".
When I use the Id property of HtmlDiv I get a NotSupportedException. Is there anyway I can get all of the Html attributes from an Element or get the Id from an element after it has been found?
Not sure if this what you are after, once the control is identified, you would have all its properties to play around with.
For example
var control = new HtmlDiv ();
control.SearchProperties.Add("Id", "MyDiv_28");
if (!control.TryFind()) return;
var newControl = new HtmlDiv();
newControl.SearchProperties.Add("Id", control.Id.Split('_')[1]);
newControl.TryFind();
HtmlDiv myDiv = new HtmlDiv(browser);
//Add the search logic u want !
myDiv.SearchProperties.Add("class", "ClassName");
string onewayforID = myDiv.Id;
string anotherWay = myDiv.GetProperty(HtmlDiv.PropertyNames.Id).ToString(); // Or u can simpy pass "Id"
See if that Works !

Passing a string variable into a marquee

Please help, I am trying to pass a string that exists in a variable I created. It is todo with weather info I am grabbing with an API. This is the variable I am creating;
success : function(parsed_json) {
var temp_f = parsed_json['current_observation']['temp_f'];
var wind_kph = parsed_json['current_observation']['wind_kph'];
var wind_gust_kph = parsed_json['current_observation']['wind_gust_kph'];
var wind_string = parsed_json['current_observation']['wind_string'];
alert(wind_string);
gauge3 = wind_gust_kph
gauge4 = wind_kph
The alert works and prints my string. Now I want to pass it into a
<td><div><marquee behavior="scroll" direction="left">("wind_string")</marquee></div></td>
I have tried many options and can only get what I type and not the actually string inside the variable.
Hope that is clear!
Add an id - "wind", as you suggested - to the marquee element to make it more searchable:
<marquee id="wind" behavior="scroll" direction="left"></marquee>
Get the marquee element with getElementById and assign the string you want to its innerHTML:
var wind_string = parsed_json['current_observation']['wind_string'];
//alert(wind_string);
document.getElementById('wind').innerHTML = wind_string;
Note: the marquee element became obsolete in HTML5.

What is the purpose of the SvgElement.tag(String tag) constructor?

There is no documentation in the API doc for the constructors. I would like to understand the purpose/use cases for SvgElement.tag() .
The SvgElement.tag(String tag) constructor creates a new SvgElement for a corresponding tag value.
For example:
var foo = new SvgElement.tag('view');
print(foo is ViewElement); // prints 'true'
would create a new SvgElement specified by the <view> tag.
This means that the above code is the same as:
var bar = new ViewElement();
print(bar is ViewElement); // prints 'true'
See also the tag constructor from the superclass Element.
Use cases for this constructor are places where you get the value of the tag from text and want to generate a new element of that tag value.
You might get the tag from parsing the DOM, or maybe from a different API. The tag constructor is a way to write DOM code in a "Darty" way (with objects and classes) while being able to work with DOM elements via text.
In many cases, it is preferable to create this Element object instead of say, using innerHtml to set the DOM inside of another Element.
Compare:
var someTagName = 'view';
var someDomNode = query('#id');
// BAD
someDomNode.innerHtml = '<$someTagName> ... </$someTagName>';
// GOOD
var myElement = new SvgElement.tag(someTagName);
someDomNode.append(myElement);

Resources