require 'watir'
ie = Watir::Browser.new
ie.goto "http://www.wallpapers.com/windows/Wallpapers/Animals/Dogs"
ie.select(:id, "ctl00_CPH1_ctl00_ddlSortExpression").flash
ie.select(:id, "ctl00_CPH1_ctl00_ddlSortExpression").set("Newest")
C:/Ruby193/lib/ruby/gems/1.9.1/gems/watir-classic-3.0.0/lib/watir-classic/element.rb:433:in `method_missing': undefined method `set' for #<Watir::SelectList:0x31be0b8> (NoMethodError)
from sample.rb:9:in `<main>'
also tried with same result:
ie.select(:id, "ctl00_CPH1_ctl00_ddlSortExpression").to_subtype.set("Newest")
Use .select() instead:
ie.select(:id, "ctl00_CPH1_ctl00_ddlSortExpression").select("Newest")
In Watir 3.0, .set() no longer exists for select lists. Not sure if it is a bug or removed on purpose.
Related
Variant creation stucked. Console shows:
Uncaught (in promise) TypeError: (intermediate value).map is not a function
Degging deeper with the debugger variantRestrictions is broken in some way.
In the database product.variant_restrictions is an empty JSON array []. If I change it to NULL it worked again.
You can fix it like this:
UPDATE product SET variant_restrictions = NULL WHERE variant_restrictions = '[]';
Using Watir 6.0.3, page object 2.0.0 and Ruby 2.1.9
As per latest watir and page-object changes changed below code to
wait_until(DEFAULT_WAIT_TIME.to_i, 'Login button not found when waiting for the login page to load') do
login_element.visible?
end
to
message = "Login button not found when waiting for the login page to load"
login_element.wait_until(timeout: timeout, message: message, &:visible?)
but getting undefined method 'zero?' for #<Hash:0x4991340> (NoMethodError)error.
however if I get rid of page-object locator shown below Watir 'wait_until'works as expected.
message = "Login button not found when waiting for the login page to load"
browser.button(name: 'login').wait_until(timeout: 10, message: message, &:visible?)
The Element#wait_until method is defined as:
def wait_until(timeout=::PageObject.default_element_wait, message=nil, &block)
Object::Watir::Wait.until(timeout: timeout, message: message, &block)
end
Notice that timeout and message are normal parameters rather than keyword arguments. As a result, the usage needs to be:
login_element.wait_until(timeout, message, &:visible?)
That said, Element#wait_until is still broken. The way that Object::Watir::Wait.until is called will result in a NoMethodError due to object being nil in the Watir method. Until a fix is released, you can monkey patch Page-Object using (included after you require 'page-object'):
module PageObject
module Platforms
module WatirWebDriver
module Element
def wait_until(timeout=::PageObject.default_element_wait, message=nil, &block)
element.wait_until(timeout: timeout, message: message, &block)
end
end
end
end
end
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
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.
I'm using page-object gem with watir and RSpec to test my web application.
Here is my page object.
require 'page-object'
class UserEditPage
include PageObject
page_url "#{$context}/user/edit?id=#{#params[:id]}"
text_field :user_id, name: 'userName'
text_field :pw, name: 'password'
text_field :pw_retype, name: 'password2'
# snip uninteresting stuff
button :submit, index: 0
end
I would like to parameterize :id in page_url via PageObject::PageFactory like this:
visit UserEditPage, using_params: {id: 1000} do |page|
# operation on page
end
This document implies that above usage is possible, but I couldn't understand how exactly this is achieved.
Question: how can I pass parameter id from visit method to UserEditPage?
Running code results in
***/user/edit_page.rb:8:in `<class:UserEditPage>': undefined method `[]' for nil:NilClass (NoMethodError)
from ***/user/edit_page.rb:5:in `<top (required)>'
probably because #params is nil when evaluating page_url.
Changing using_params: {id: 1000} to id: 1000 with no luck.
The page_url needs to be:
page_url "#{$context}/user/edit?id=<%=params[:id]%>"
Note how the parameters need to be included differently - ie <%=params[:id]%> instead of #{params[:id]}.
The problem is that the page_url is evaluated when the page object class is evaluated. This means that when the class is evaluated, params[:id] must already exist. This is not going to be true when you want to include the parameters dynamically.
The page object gem uses ERB to allow you to create a template, which allows substitution of the params later - ie when calling visit.
In summary, when creating a page_url:
Use string interpolation if the value is known when the page object class is evaluated.
Use ERB if the value is to be dynamically specified on visit.
Working Example
Below is a working example of the dynamic parameters.
require 'watir-webdriver'
require 'page-object'
$context = 'http://testurl.com'
class UserEditPage
include PageObject
page_url "#{$context}/user/edit?id=<%=params[:id]%>"
end
include PageObject::PageFactory
#browser = Watir::Browser.new
visit UserEditPage, using_params: {id: 1000} do |page|
p page.current_url
#=> "http://testurl.com/user/edit?id=1000"
end