Watir: Trouble with if statements - ruby

I spent a while looking but didn't find anything that helped much, so I decided to ask myself.
Anyways, I'm trying to make a non-malicious bot to respond to certain forum threads on a forum. However, I'm stuck on making an if statement that will detect if a thread has a certain name, and click on that thread if it does. This is what the closest I've come:
def Replies()
while true
$browser.div(:text => ':HexBot/Summon')
sleep(5)
$browser.goto <insert link here. i didn't include it for privacy reasons>
end
end
What this should do is refresh the page every 5 seconds. If it sees a thread saying ':HexBot/Summon' then it would click on that thread. However. I just get an error. I tried doing this entirely without if statements, but that also gave me an error.

I'm not completely sure I understand the question, so let me know if this isn't what you are asking for:
def Replies()
until $browser.div(:text => ':HexBot/Summon').present?
sleep(5)
$browser.goto <insert link here>
end
$browser.div(:text => ':HexBot/Summon').click
end
That should reload the page every 5 seconds (forever) until the desired text appears, at which point the text will be clicked. You could also use $browser.refresh instead of the $browser.goto statement (assuming you start on the correct page).
Lastly, you tagged this question watir. I use watir-webdriver, and there are some differences, but hopefully what I have offered here works for you.

Related

Capybara / Ruby / Cucumber - Making the command Expect to be highlighted in the evidence

I'm generating evidences every time that I run a cucumber scenario. It is working fine, however I would like to improve it a little bit more.
My idea is highlight all the "expect" commands into the evidence to make clear the result.
I'm using a hook to generate the evidence, so I think I have to do something there.
After do
shot_file = page.save_screenshot("log/screenshot.png")
shot_b64 = Base64.encode64(File.open(shot_file, "rb").read)
embed(shot_b64, "image/png", "Screenshot")
end
So, when I declare a expect command I would like to see it in the evidence highlighted.
expect(find(".nav-a.nav-a-2.nav-truncate")).to have_content "Hello, my name"
Any idea guys?
Thank you very much!
You can use the below javascript to highlight the border of the element before taking the screenshot.
element.style.border = '0.5em solid red';
Here is the sample video.

Select() method and option() method works differently

Today I have seen a question in selenium C# section where this question was posted, I try to solve that problem through WATIR coding, I have written the below code and WATIR identifies this select list as invisible.
b.goto 'http://automationpractice.com/index.php'
b.img(title: 'Faded Short Sleeve T-shirts').click
b.iframe(xpath: "//*[starts-with(#id,'fancybox-frame')]").select_list.select("L")
But If I select that same select_list through below metioned code, it works fine.
b.iframe(xpath: "//*[starts-with(#id,'fancybox-frame')]").select_list.option(text: "L").click
I don't understand what is the difference here, when I put a debug pointer, both are making a selenium call to find_element(tag_name: "select"), first one fails due to element invisible but second one passes
#Titus, #JustinKo Can you please explain me what's happening here? what's the difference?
Note: Please run it in Chrome.
Moving from a comment to an answer:
The issue is that we refactored the normal (non-select-list) way of doing it to not check for whether an element is displayed ahead of time, and put the waiting logic in the rescue block if Selenium complained. The select-list code is still checking the visibility ahead of time, and this particular select-list element is not displayed according to Selenium. Since it appears that Selenium can select options without select list showing as displayed, Watir should not be waiting for this.
I've fixed it here, and it will be working in Watir 6.13 (should be released "soon")
https://github.com/watir/watir/commit/77af164fcdecb71d8d2240110d3fb4b1dabeee4b

Trouble with greasemonkey script to refresh page

I'm downloading data from an online database using the imacros plugin for firefox. It works perfectly, except when the page times out. I've moved to downloading very small chunks of data since then the website times out much less frequently, but it still times out occasionally.
The problem is there's no way to code if statements directly into the imacros macro, so I wanted to have a greasemonkey script running along side it that will refresh the page if it timesout. The website only times out in one place for me, and when it does it shows the following:
can't open file
I never learned Java or Javascript and all of my programming experience deals with numerical methods, but I've been been piecing together code and adapting it to try and solve my problem.
The following is my base code:
var RefreshTime = '20';
var str1 = document.body.innerHTML
var str2 = "can't open file"
if (str1.search(str2) > 0) {
if (StRefTime > 0) setTimeout("location.reload(true);",RefreshTime*1000);
}
Since the browser I'm running this in is currently being used exclusively for this script I just have #include *
Basically what this is meant to do is refresh the page every 20 seconds as long "can't open file" is found the webpage. This works perfectly on other websites when I test it, but doesn't work at all on the website I need it to. It might be worth noting that when I refresh, firefox asks me to confirm resending post data - but imacros does have a function that I tested and works on this site to automatically confirm whenever the dialog is displayed.
After doing some reading I found that other people had similar problems, and I think the root of the cause is that if the page is arrived at through AJAX then greasemonkey misses it.
To address this I tried to implement the suggested solutions to those people, but I've been unsuccessful. For example I've tried putting the code I listed above into the solution given here: Run Greasemonkey script on the same page, multiple times? , for example
var RefreshTime = '20';
var str1 = document.body.innerHTML
var str2 = "can't open file"
function highlightGoodComments (jNode) {
//***** YOUR CODE HERE *****
if (/str2/i.test (jNode.text () ) ) {
if (str1.search(str2) > 0) {
if (RefreshTime > 0) setTimeout("location.reload(true);",RefreshTime*1000);
}
}
But this doesn't work either, and I've tried a couple variations of it (for example getting rid of str2 and just putting "open file" and things like that) and I've also tried and failed to make the following work https://gist.github.com/BrockA/2625891. I also tried wrapping all of my initial code in a setInterval loop with the hope that it would just check constantly for "can't open file" even without any page loading, but that didn't work either.
Unfortunately the website I'm running my script on is hidden behind a paywall, and it's hard to test my code since it times out somewhat randomly so there's no way to check if my code works outside of just waiting a long time and seeing if it failed. I know nothing about AJAX, so I'm not sure how to confirm that that is what's happening, but I still believe it to be so since my problem seemed similar to other people's - and when I enable this macro it does seem to interfere with other parts of the website but not the parts that my script works on.
I was hoping somebody could help me out, since I'm pretty stuck here and already in over my head. Even if you can't help, having some sort of AJAX website where I could test code without waiting several hours would be helpful to me trying to figure this out myself, if anybody knows of one. Thank you for reading through this, I really do appreciate any help anybody can offer.
The question is very long so I didn't bother to really read it. Since I don't use GreasMonkey I can tell you the iMacros solution.
Check if html element exists with iMacros and javascript
Here is a model how to built JS iMacros script and include if clause. You can make a testing macro that tests is t here "can't open" web page.
Also you can try to use
SET !TIMEOUT_PAGE 120
command to increase the time of page loading to 120 seconds. Try some of these if it can help.

Watir-webdriver: get same screenshot images for all failed scenarios

I've set screenshots to be taken when a scenario fails, but my html report shows the same screenshot on all failed scenarios. Can anyone help and let me know how I can get unique screenshots taken for each failed scenario.
Here is my code in my env.rb:
After do |scenario|
if scenario.failed?
#browser.driver.save_screenshot("screenshot.png")
embed("screenshot.png", "image/png")
end
You are saving the screenshot to the same file each time (ie overwriting the previous screenshot each time). The report has also linked all the images to the same place. This is why you get the same image everywhere.
You need to provide a unique name for the screenshot.
For example, you could timestamp (with date and time) the images:
After do |scenario|
if scenario.failed?
screenshot_file = "screenshot-#{Time.now.strftime('%Y%m%d-%H%M%S')}.png"
#browser.driver.save_screenshot(screenshot_file)
embed(screenshot_file, "image/png")
end
end
Justin has the answer, But while timestamps are fine, they make it harder when looking at the files to know which one was for what scenario. When I run tests while creating and debugging, I often don't even look at the html report, I just look at the generated screenshot, so in that case it is doubly useful to have more logical names.
So the code I use looks like this, and embeds using the scenario name
After do |scenario|
if scenario.failed?
screenshot = "./FAILED_#{scenario.name.gsub(' ','_').gsub(/[^0-9A-Za-z_]/, '')}.png"
#browser.driver.save_screenshot(screenshot)
encoded_img = #browser.driver.screenshot_as(:base64)
embed("data:image/png;base64,#{encoded_img}",'image/png')
end
end
An even more robust approach, dealing with scenario outlines and appending timestamp is described in this 'Two Four One' blog posting so far I've not needed to go that far, but I may pull in stuff from it to deal with scenario outlines.
for the ones using RSpec, there is a really nice implementation of HtmlFormatter in the watir-rspec project

Ruby/Watir getting stuck after using "goto"

I'm using a simple browser.goto(url) call to our Microsoft SQL Reporting pages. It does a "goto" on the first url but then just sits there. I'm currently running it via command line.
If I Ctrl+C to cancel it, the output says:
C:/Ruby/lib/ruby/gems/1.8/gems/watir-1.6.5/lib/watir/ie-class.rb:506:in `wait': Interrupt
from C:/Ruby/lib/ruby/gems/1.8/gems/watir-1.6.5/lib/watir/ie-class.rb:355:in `goto'
from screen.rb:37:in `SqlReports'
from screen.rb:35:in `each'
from screen.rb:35:in `SqlReports'
from screen.rb:45
So, I'm guessing something on the page is causing Waitr problems. I've googled the about snippets, but not come back with anything. All I want it to do is load the page, sit there for a specified time, then move to the next url (it's for a tv screen), nothing complex.
So I've tried placing a "begin/rescue" ie:
begin
$browser.goto(url)
rescue
end
No luck, it just sits on the first url. And I've tried wrapping that using the Timeout class, ie:
begin
Timeout::timeout(30) do
$browser.goto(url)
end
rescue
end
Still no luck, it crashes out. Does anyone know a fix, or how to override the implicit "wait" that Watir does when doing a goto?
My guess would be that there is something on that page that keeps IE from saying "I'm done loading everything here".
There is a $browser.click_no_wait command and a $browser.click! command, so if you had a static page that had a link to your url, you could $browser.goto that page and clcik_no_wait the link.
an excellent solution using timeouts at http://watirboy.blogspot.com/2010/07/watir-timeout-handle-browser-hangstuck.html

Resources