Waiting for an element without throwing an exception if timed out - ruby

I know of the method Element#wait_until_present(t), but if this method times out it throws a timeOut exception.
Is there a method that just waits for t seconds and then returns true if the element became present or false otherwise?
I know it can be done with a simple begin..rescue..end statement, but I'm looking for something that doesn't use exceptions.

You can write a short-hand rescue clause like this:
element_present = browser.element.wait_until_present rescue false
puts "element not present" unless element_present
This does however result in a false value on any Exception at all and not just with TimeoutError. I still prefer to use it since if there's any Exception at all then it would be safer to assume that the element was not present.

Looks like there is no other method that will do what i'm looking for ,
so here is the simplest method to achieve this :
#check method for Element#wait_until_present(t)
def check_if_present(element,t)
raise ArgumentError, 't must be a number ' unless t.is_a? Numeric
begin
element.wait_until_present(t)
true
rescue Watir::Wait::TimeoutError
false
rescue
raise "Something wrong with the element"
end
end

If you do not want an exception the below code can be handy:
sleep 'your time here' eg: sleep 20 - this will wait for 20 secs.
then check for your element now:
'your element'.exists? -this will return true/false
you will not get an exception this way.
Another best way is to write your wait_for_load method based on your needs.

Related

How to test a simple rescue block in ruby

I have a custom fact in ruby that goes like this:
Facter.add(:some_random_fact) do
setcode do
output = execute_some_method
if !output.nil? then
begin
pruned_output = output.split("\n")
result = true
rescue
result = false
end
else
result = false
end
end
end
How do I write a unit test using rspec for the rescue block to raise an Exception?
EDIT: Please let me know if the below test is the correct way to test it
it "return fact as false when begin block raises exception" do
output = double(:output)
allow(output).to receive(:split).with(true).and_raise(RuntimeError.new("error occured"))
expect(Facter.fact(:some_random_fact).vallue).to eq(false)
end
The code you've shown here is weird and I get the feeling we're missing context, but in general you can stub out a method to raise an error like so:
expect(output).to receive(:split).with("\n").and_raise(RuntimeError.new("some error"))
but this is sort of an ugly way to go about things. If the error is raised conditionally depending the type of output, then it's better to find a way to set that variable to an error-producing value. How to do that, I can't tell you without seeing the test of your code.
For example, say you wrapped all this code in a def add_fact(output) - then from your tests you could intentionally pass an error-causing value for the output, and you no longer need to stub split (which is a wierd thing to do). This pattern is known as "dependency injection".

Is there a Way To Exit Two Loops by Single Command In Ruby?

Here is the Sample code,
while true
while true
exit all loops when condition true
end
end
Can someone tell me if is it possible here to exit first loop when second loop breaks, but then I want to use only one break command and no raise.
You know what's better than using only one break? Not using any at all! :)
Little-used throw/catch is good here
catch(:done) do
while cond1
while cond2
throw :done if condition
end
end
end
For more information, see the docs on throw and catch.
Alright, so apparently boolean flags are a no-go. Oops.
The other thing that pops to mind is catching an error, but you said you don't want to do that, or wrap it in a method and return. Honestly, there doesn't seem to be a way, but here's the simplest I could come up with:
catch (:exit) do
while true
while true
throw :exit if condition
end
end
end
You could also throw an exception, but that seems dirty. Here's the code to do it, though:
begin
while true
while true
raise "Exiting loops" if condition
end
end
rescue
#Code to go after the loop
end
Lastly, you could wrap the whole thing in a method and return from that method:
def my_descriptive_method_name()
while true
while true
return if condition
end
end
end

Why is negative specific exception expectation deprecated in RSpec?

Seems like I am permitted to specify exception class for .to but not for .not_to?
What are exact reasons of this?
Failure/Error: expect{ smth }.not_to raise_exception SomeExceptionClass
ArgumentError:
`expect { }.not_to raise_error(SpecificErrorClass)` is not valid, use `expect { }.not_to raise_error` (with no args) instead
To expand on Nakilon's answer a little:
This is a design decision on their part. It would appear that they think this is not a good test to specify, because if you expect that a certain error not be raised, then the test will pass if:
no error is raised
some other error is raised
...which is at least, imprecise. Probably your code only wants to do one of these things.
That appears to be the reasoning, anyway -- I wouldn't like to say how fair it was.
From the changelog:
Make expect { }.to_not raise_error(SomeSpecificClass, message), expect { }.to_not raise_error(SomeSpecificClass) and expect { }.to_not raise_error(message) invalid, since they are prone to hiding failures.
Instead, use expect { }.to_not raise_error (with no args). (Sam
Phippen)
Seems like they realised that there was no reason to deprecate the exception class parameter, so it currently works: https://www.relishapp.com/rspec/rspec-expectations/v/3-5/docs/built-in-matchers/raise-error-matcher
For example, in Selenium, after checking for some condition to become true:
Selenium::WebDriver::Wait.new(
message: message,
timeout: timeout,
).until do
f() == x
end
it's now easy to also wait that it does not become false in next seconds by negating the timeout exception:
begin
Selenium::WebDriver::Wait.new(
timeout: timeout,
).until do
f() != x
end
raise message
rescue Selenium::WebDriver::Error::TimeOutError
end

Ruby skips items from list tasks

I am trying to make an app which if give the option to type, it types false then it skips the certain element from the list and it jumps to the next executing the same task.
That is the basic idea of the following code:
string["items"].each do |item|
p continue.to_s + "<- item"
begin
Anemone.crawl("http://" + item["displayLink"] + "/") do |anemone|
anemone.on_every_page do |page|
if continue.chomp.to_bool == false
raise "no more please"
end
request = Typhoeus::Request.new(page.url, followlocation: true)
response = request.run
email = /[-0-9a-zA-Z.+_]+#[-0-9a-zA-Z.+_]+\.[a-zA-Z]{2,4}/.match(response.body)
if email.nil?
else
p email
begin
continue = Timeout::timeout(2) do
p "insert now false/nothing"
gets
end
rescue Timeout::Error
continue = "true"
end
end
end
end
rescue
continue = true
next
end
p "---------------------------------------------------------"
end
As the code shows, if the user types false when prompted the app should skip the item and go to the next one. However what it does is: when the user types false the app skips the current item and then doesn't execute any of the code that should be executed for all of the other items except the printing ( the second line of code );
Here is how the output looks like:
$ruby main.rb
"1"
"true<- item"
#<MatchData "support#keycreative.com">
"insert now false/nothing"
false
"true<- item"
"true<- item"
"true<- item"
As I'm doing my best to show after false is entered the code does skip the certain item from the list but it also never ever executes code for the other items as it should since it is an each loop
First I thought that maybe the continue is false however as you can see from the output the continue is true which makes me wonder why does ruby skip my code?
UPDATE
Here is where the to_bool method comes from:
class String
def to_bool()
return true if self == "true"
return false if self == "false"
return nil
end
end
In your last rescue statement add:
rescue => e
puts e.message
continue = true
next
end
and inspect the output. Most likely your code is throwing an exception other than "no more please" (I expect undefined method to_bool for true:TrueClass). Note that using exception for skipping the loop element is a terrible idea. Why can't you just get rid of this rescue and do:
if continue.chomp.to_bool == false
continue = true
next
end
There are a lot of things in this code which makes it very un-ruby-like. If you want to improve it please paste it to StackExchange CodeReview page. (link in the comment).
UPDATE:
My bad, you are in nested loop, so the if statement won't work. You might look at sth similar to raise/rescue bit, namely throw/catch, see example here: How to break from nested loops in Ruby?. I still think you should post it to codereview though for refactoring advises.
As to your actual code (without refactoring). You are calling to_bool method on continue, and in your rescue block you assign true instead of 'true'. Hence your to_bool method raises exception which is then rescued same way as 'no more please' exception.

Difference between $! versus a variable with rescue

When rescuing from an exception, there are two ways to refer to the raised exception:
begin
...
rescue Exception => e
handle_the_error(e)
end
and
begin
...
rescue Exception
handle_the_error($!)
end
I believe they are interchangeable, but are they? Is there any situation where one should be used over the other?
I also think these snippets are interchangeable. But you should always prefer explicit variables to thread-global magic.
One case where $! magic var is handy:
result_or_error = perform_some_operation() rescue $!
For those who don't know that this line means:
It's so called "inline rescue". Format is this:
<expr1> rescue <expr2>
First, expr1 is evaluated. If no exception was raised, its value is returned. But if there was an exception, then expr2 is evaluated and its value returned.
So, in this case, if perform_some_operation() raised an exception, variable result_or_error would be set to an instance of that exception (because $! returns last error).

Resources