undefined method error in ruby selenium - ruby

I am using ruby with selenium and my code is as follows:
$num=1
def isElementPresent(xpathExpression)
allElements=#driver.find_elements(:xpath,xpathExpression)
if (allElements.size==0)
return true
end
else
return false
end
while Demo.isElementPresent(str1+$num.to_s+str2)
text=#driver.find_element(:xpath,str1+$num.to_s+str2).text
$num+=1
puts "text is:#{text}"
#driver.find_element(:xpath,str1+$num.to_s+str2).click
puts #driver.title
#driver.navigate.back
end
end
I'm getting an undefined method error for while Demo.isElementPresent(str1+$num.to_s+str2).
Any help is appreciated

As per my understanding, Your condition should be:
if (allElements.size>0)
return true
As if size is 0. That means no element is present.
Also, in this case your function definition should end before you are calling it.
Try following code:
$num=1
def isElementPresent(xpathExpression)
allElements=#driver.find_elements(:xpath,xpathExpression)
if (allElements.size>0)
return true
end
else
return false
end
end
while isElementPresent(str1+$num.to_s+str2) do
text=#driver.find_element(:xpath,str1+$num.to_s+str2).text
$num+=1
puts "text is:#{text}"
#driver.find_element(:xpath,str1+$num.to_s+str2).click
puts #driver.title
#driver.navigate.back
end
Here I have made two changes: First, for the condition I explained about and Second, Ending the definition of function before your loop.
Please let me know if it works as intended.

Related

Is multiple include?() arguments in ruby possible?

def coffee_drink?(drink_list)
drink_list.include?("coffee") ? true : drink_list.include?("espresso") ? true : false
end
I am learning Ruby with TOP and am looking to check for more than a single argument with the include function. I don't think my solution is too bad but surely there is a better solution I am just unable to find.
e.g. include?("ABC", "CBA) and include?("ABC" || "CBA") wont work.
def coffee_drink?(drink_list)
%w(coffee espresso).any? { |drink| drink_list.include?(drink) }
end
or
def coffee_drink?(drink_list)
(%w(coffee espresso) & drink_list).any?
end
note that your version could be rewritten like this
def coffee_drink?(drink_list)
drink_list.include?("coffee") || drink_list.include?("espresso")
end

How do I check that the value of a param is a number in a certain range

I am trying to write a test suite for a method that sends a POST request with a parameter 'target' that has to be between 0 and 10
My Ruby class:
class ClassName
before_action :must_have_valid_target
def create
target = params[:target]
. . .
end
def must_have_valid_target
return if params.key?(:target)
error_response(422, 'error message')
end
end
My Rspec
it 'cannot create request with negative target' do
post(:create, {target: -1})
assert_response(422) # actual result is: Expected 422, Actual 200
end
I tried:
def must_have_valid_target
valid = params[:target].between?(0,10)
end
but this does not work. How do I check that the symbol has a value between the range so I can give the correct response afterwards?
This is not homework, I am trying to add additional tests to the codebase at my workplace but I am still very new to RSpec and Ruby.
params[:target] is a string, cast to integer prior to the comparison,
def must_have_valid_target
params[:target].present? && params[:target].to_i.between?(0,10)
end

Using variable declared in one method to open webpage in another method

I am working on a CLI Project and trying to open up a web page by using url variable declared in another method.
def self.open_deal_page(input)
index = input.to_i - 1
#deals = PopularDeals::NewDeals.new_deals
#deals.each do |info|
d = info[index]
#product_url = "#{d.url}"
end
#product_url.to_s
puts "They got me!"
end
def self.deal_page(product_url)
#self.open_deal_page(input)
deal = {}
html = Nokogiri::HTML(open(#product_url))
doc = Nokogiri::HTML(html)
deal[:name] = doc.css(".dealTitle h1").text.strip
deal[:discription] = doc.css(".textDescription").text.strip
deal[:purchase] = doc.css("div a.button").attribute("href")
deal
#binding.pry
end
but I am receiving this error.
`open': no implicit conversion of nil into String (TypeError)
any possible solution? Thank you so much in advance.
Try returning your #product_url within your open_deal_page method, because now you're returning puts "They got me!", and also note that your product_url is being created inside your each block, so, it won't be accessible then, try creating it before as an empty string and then you can return it.
def open_deal_page(input)
...
# Create the variable
product_url = ''
# Assign it the value
deals.each do |info|
product_url = "#{info[index].url}"
end
# And return it
product_url
end
In your deal_page method tell to Nokogiri to open the product_url that you're passing as argument.
def deal_page(product_url)
...
html = Nokogiri::HTML(open(product_url))
...
end

Is it possible to write a spec for infinite-loop issues using Rspec?, Ruby

Listen I've an interesting question here, the other day I ran into an "infinite-loop" problem using Rspec, Rspec couldn't even go through the spec related to other methods inside the loop and even the comp was almost crashing. Very funny.
I'd like to test my future loops (While-loop in this case) against infinite loop-code.
How I can test this while-loop and catch up this problem like this one and make the proper correction?
Thanks!
This is my code from other day:
i = 0
while i <= Video.all.count do
if ( #sampler = Video.find_next_sampler(#samplers[-1].end_time, #samplers[-1].end_point) )
#samplers << #sampler
else
flash[:error] = 'There is not any more match for this video-sampler'
end
i + 1 #Now Here is the bug!! IT should be: i += 1
end
require 'timeout'
it 'should not take too long' do
Timeout.timeout(20) do
... blah ...
end
end
Or even
# spec_helper.rb
require 'timeout'
RSpec.configure do |c|
c.around(:example, finite: true) do |example|
Timeout.timeout(20) do
example.run
end
end
end
# my_spec.rb
it "should work really fast", finite: true do
... blah ...
end
In this particular example is doesn't make sense to run the loop more often that the total number of all videos in the database.
Therefore I would try something like this:
let(:videos_count) { Video.count }
before do
allow(Video).to receive(:find_next_sampler).and_call_original
end
it 'is not an infinite loop' do
except(Video).to receive(:find_next_sampler).at_most(videos_count).times
# call your method
end

NoMethodError: undefined method `hours' for "1":String

I am getting this error all the time
#<NoMethodError: undefined method `hours' for "1":String>
UPDATE: I am getting errors for any number not just "1"
and here is the code that I am returning hours. i am using this method
def check_hours(most_recent_snooze)
if most_recent_snooze.duration.nil?
return 0.hours
else
return most_recent_snooze.duration.hours
end
end
and these code uses check_hours(most_recent_snooze) method
def snoozing?
if most_recent_snooze = Snooze.find_by_sensor_id(self.id)
if most_recent_snooze && !(most_recent_snooze.created_at + check_hours(most_recent_snooze) < Time.now)
# snooze is active
return true
else
most_recent_snooze.destroy
return false
end
end
return false
#self.snoozes.active.present? ? true : false
end
def snooze_minutes_remaining
# (60 - (Time.now - self.snoozes.last.created_at)/60).to_i + 1
most_recent_snooze = Snooze.find_by_sensor_id(self.id)
distance_of_time_in_words(Time.now, most_recent_snooze.created_at + check_hours(most_recent_snooze)) if most_recent_snooze
end
Please let me know on where did I go wrong on this code?
UPDATE:
Inside schema.rb, duration is integer
create_table "snoozes", :force => true do |t|
.......
........
.........
t.integer "duration"
end
ActiveSupport's time methods can be applied to Fixnums only, and it seems that some data you are passing in is a string. Perhaps you have a database column in an incorrect format?
A good way to handle this is to use an explicit to_i conversion in your method:
def check_hours(most_recent_snooze)
most_recent_snooze.duration.to_i.hours
end
nil.to_i returns 0, so you don't need the nil check in this case.
Your most_recent_snooze's duration, for some reason is a string. If you can't fix that, try this in check_hours:
def check_hours(most_recent_snooze)
if most_recent_snooze.duration.nil?
return 0.hours
else
return most_recent_snooze.duration.to_i.hours
end
end

Resources