Capybara / Ruby - Trying to return to the beginning of the loop when an error shows up - ruby

I'm trying to return to the loop beginnig when an error shows up as the code below.
I'm using the command "next" when a casual error occurs but it is not coming back for the loop beginning.
describe 'Test', :test do
before(:each) do
visit '/admin'
end
it 'Adding new images' do
image = 'barcelona.jpg'
#imagem = Dir.pwd + '/spec/fixtures/' + image
produto = '1'
100.times do
visit '/admin/' + produto
if page.has_no_css?('#mensagem > h1')
within_frame(:xpath, "//*[#id='app-content']/main/div/iframe") do
find('#ctl00_Conteudo_tbxNome_txtId').set 'test_name'
find('#ctl00_Conteudo_BtnSalvar').click
if page.has_no_css?('#mensagem > h1')
find('#ctl00_Conteudo_tbxIdArquivoControle_lnkInserirArquivo').click
attach_file('ctl00_Conteudo_tbxIdArquivoControle_tbxArquivo', #imagem)
find('#ctl00_Conteudo_tbxIdArquivoControle_btnEnviar').click
if page.has_no_css?('#mensagem > h1')
find('#skuTabNavigation a[href="#tabImages"]').click
expect(page).to have_content image
puts 'Test ok'
else
puts 'Error was presented, starting over..'
next
end
else
puts 'Error was presented, starting over..'
next
end
end
else
puts 'Error was presented, starting over..'
next
end
end
end
end
I would like that every time when the system goes to "else" condition, it restart the loop.

I don't think there is a direct way to move back to the initial iteration of a loop. redo exists but it only moves you back to the current iteration.
In this case, you probably want to change the way you're looping so you can more easily control when to start/stop. For example:
i = 0
while i <= 100 do
if page.has_no_css?('#mensagem > h1')
i = 0
puts 'Error'
next
end
i += 1
end
So you don't have to reset the loop index and call puts each time you could rescue an error:
class MyError < StandardError; end
i = 0
while i <= 100 do
begin
if page.has_no_css?('#mensagem > h1')
raise MyError, 'thing was missing'
end
puts i
i += 1
rescue MyError => boom
puts "Error: #{boom.message}"
i = 0
redo
end
end

Related

Ruby "include?" method not working

I have a few commands from a Twitch chat, it works and it's awesome! People can type commands like !about and it's going to send a response. There's just one problem, if you go down to the thread and look under # // COMMANDS // COMMANDS // COMMANDS. There's a problem, there´s a few admin commands (look under # ADMIN COMMANDS // ADMIN COMMANDS). I have this: if msg.include?("!project") then msg.slice!("!project "), but it's not working like I want it to. I want to be able to type !project Then some substring here. But when a substring is attached it doesn't work, even though I can print msg and it clearly includes !project. Both the !disconnect and !project command work when it's only those commands by themselves. Meaning that something like !disconnect Hello World wouldn't work even though it clearly includes !disconnect.
# Message formatting in console
class String
def red; "\e[31m#{self}\e[0m" end
def yellow; "\e[33m#{self}\e[0m" end
def green; "\e[32m#{self}\e[0m" end
def cyan; "\e[36m#{self}\e[0m" end
def bold; "\e[1m#{self}\e[22m" end
end
# Requied packages / modules
require 'socket'
require 'logger'
require 'open-uri'
# Create logger
File.delete("log.txt") # Clear previous log
log = Logger.new("log.txt", formatter: proc {|severity, datetime, progname, msg|
"#{datetime}: #{msg}\n"})
# Required Info
load "credentials.txt"
log.info("Loading \"credentials.txt\"")
# -------- IGNORE -------- #
OAUTH.downcase!
BOTNAME.downcase!
CHANNEL.downcase!.gsub!("#", "")
# //- AGE -// #
time = Time.new
age = time.year - 2000
if time.month == 10
if time.day < 28
age -= 1
end
elsif time.month < 10
age -= 1
end
# -------- IGNORE -------- #
# Save "Preparing to connect" to "log.txt"
log.info("Preparing to connect")
# Variables
socket = TCPSocket.new('irc.chat.twitch.tv', 6667)
send = "PRIVMSG ##{CHANNEL} :" # shortcut for sending messages
running = true
content = nil
message_count = 0
message_limit = Time.now.to_i
# Commands
commands = ["!about","!uptime","!commands","!cortexio","!followed"]
api_commands = ["!followed","!uptime"]
admin_commands = ["!disconnect","!project"]
# Authorization Login
socket.puts("PASS #{OAUTH}") # Send the password(oauth) to Twitch
socket.puts("NICK #{BOTNAME}") # Send the botname to Twitch
socket.puts("JOIN ##{CHANNEL}") # Send the channel to Twitch
# Save "Connected!" to "log.txt
log.info("Joining #{CHANNEL.capitalize} as #{BOTNAME.capitalize} using OAUTH Token: #{OAUTH[6,OAUTH.length-12]}" + "*"*12)
# Thread.abort_on_exception = true
# Loop (Background Thread) for recieving Twitch chat data
Thread.start do
socket.puts(send + "Connected!") # Send "Connected!" to the Twitch channel
puts "#{BOTNAME} Joined ##{CHANNEL}" # Connection Status
puts "You should be fully connected now" # Connection Status
puts ""
puts "Type \"clear\" to clear terminal"
puts ""
while (running) do
ready = IO.select([socket])
ready[0].each do |s|
line = s.gets
# Respond to Twitch IRC "PING" Message
if line.index("PING") == 0
line.strip!
socket.puts("PONG :tmi.twitch.tv\r\n")
log.info("[IRC Message]: " + line)
log.info("[IRC Response]: PONG :tmi.twitch.tv")
puts("-".bold.red*line.length)
puts "[Twitch] ".bold.cyan + "IRC: ".bold.yellow + line.bold.green
puts "[Response] ".bold.cyan + "IRC: ".bold.yellow + "PONG :tmi.twitch.tv".bold.green
puts("-".bold.red*line.length)
end
match = line.match(/^:(.+)!(.+)PRIVMSG ##{CHANNEL} :(.+)$/)
message = match && match[3]
if message =~ /^/
message.strip!
user = match[1] # Get username
# Twitch message limit - (Max 100 messages in 30 secs - Applies to mods and above)
# Avoid global ban
if Time.now.to_i - message_limit > 30 # If more than 30 seconds has passed
message_count = 0 # Reset "message_count"
end
if message_count == 0 # If "message_count" is 0
message_limit = Time.now.to_i # Start counting to 30 again
end
message_count = message_count + 1
end
# // COMMANDS // COMMANDS // COMMANDS
if message != nil
msg = message.downcase
# ADMIN COMMANDS // ADMIN COMMANDS
if admin_commands.include?(msg) and user == CHANNEL
if msg.include?("!disconnect")
socket.puts(send + "Disconnecting") # Disconnect from the channel
socket.puts("PART ##{CHANNEL}") # Disconnect from the channel
Disconnect()
log.info("[Command] #{user}: #{message}")
elsif msg.include?("!project")
msg.slice!("!project ")
File.write("Responses/project.txt", msg)
end
user = user.capitalize # Capitalize first letter (Cuz I'm that kind of person)
elsif commands.include?(msg) and message_count < 80
puts "[Command] ".bold.cyan + "#{user}: ".bold + "#{message}".bold.cyan
# API COMMANDS // API COMMANDS
if api_commands.include?(msg)
if msg.include?("!uptime")
file = open("https://decapi.me/twitch/uptime?channel=#{CHANNEL}")
content = "#{CHANNEL} has been streaming for: " + file.read
elsif msg.include?("!followed")
file = open("https://decapi.me/twitch/followage/#{CHANNEL}/#{user}")
content = file.read
if content == "Follow not found"
content = "#{user} is not following #{CHANNEL}"
else
content = "#{user} has been following #{CHANNEL} for " + content
end
end
puts "[Response] ".bold.red + "Cortexio: ".bold + "API: ".bold.yellow + "\"#{content}\"".bold.red
else
file = open "Responses/" + msg.gsub!("!","") + ".txt" # open matching file
content = file.read
file.close
puts "[Response] ".bold.red + "Cortexio: ".bold + "File: ".bold.yellow + "\"#{msg}.txt\"".bold.red
end
file.close
log.info("[Command] #{user}: #{message}")
else
puts "[Message] ".bold.green + "#{user}: ".bold + "#{message}".bold.green
log.info("[Message] #{user}: #{message}")
if message[0] == "!" # Unrecognized command
content = "Unrecognized command: \"#{message}\" - Type !commands to see a list of available commands."
end
end
# Response handling
if content != nil
content.gsub!("USER", "##{user}")
content.gsub!("AGE", "#{age}")
content.gsub!("CHANNEL", "#{CHANNEL}")
if content.include?("COMMANDS")
content.gsub!("COMMANDS", "#{commands}")
content.gsub!("\"", "")
content.gsub!("[","")
content.gsub!("]","")
end
socket.puts(send + content) # Send response if any
content = nil # Too avoid multiple messages with the same response
end
end
end
end
end
def Disconnect() # End script
running = false
exit
end
# Loop to keep bot going
while (running) do
input = gets.chomp
if input == "clear"
system "clear" or system "cls"
end
end
The problem isn't with
if msg.include?("!project")
it's with the line before it:
admin_commands.include?(msg)
admin_commands is an array which contains the 2 strings ["!disconnect","!project"]. It does not, however, contain the string "!project Then some substring here", so you are never checking if msg.include?("!project"). You should be seeing your log messages about an unrecognized command, which means you aren't making it into your first if statement. What you'll want to be doing is something like:
if admin_commands.any? { |command| msg.include?(command) }
if msg.include?("!project")
# ...

Put contents of array all at once

I don't understand why this won't do what the title states.
#!/usr/bin/env ruby
require 'socket'
require 'timeout'
class Scanner
def initialize(host, port)
#host = host
#port = port
end
def popen
begin
array = []
sock = Socket.new(:INET, :STREAM)
sockaddr = Socket.sockaddr_in(#port, #host)
Timeout::timeout(5) do
array.push("Port #{#port}: Open") if sock.connect(sockaddr)
end
puts array
rescue Timeout::Error
puts "Port #{#port}: Filtered"
rescue Errno::ECONNREFUSED
end
end
end # end Scanner
def main
begin
p = 1
case ARGV[0]
when '-p'
eport = ARGV[1]
host = ARGV[2]
else
eport = 65535
host = ARGV[0]
end
t1 = Time.now
puts "\n"
puts "-" * 70
puts "Scanning #{host}..."
puts "-" * 70
while p <= eport.to_i do
scan = Scanner.new(host, p)
scan.popen
p += 1
end
t2 = Time.now
time = t2 - t1
puts "\nScan completed: #{host} scanned in #{time} seconds."
rescue Errno::EHOSTUNREACH
puts "This host appears to be unreachable"
rescue Interrupt
puts "onnection terminated."
end
end
main
What I'm trying to achieve is an output similar to nmap, in the way that it scans everything, and then shows all open or closed ports at the end. Instead what happens is that it prints them out as it discovers them. I figured pushing the output into an array then printing the array would achieve such an output, yet it still prints out the ports one at a time. Why is this happening?
Also, I apologize for the formatting, the code tags are a little weird.
Your loop calls popen once per iteration. Your popen method sets array = [] each time it is called, then populates it with one item, then you print it with puts. On the next loop iteration, you reset array to [] and do it all again.
You only asked "why," but – you could solve this by setting array just once in the body of main and then passing it to popen (or any number of ways).

Twitter rate limit hit while requesting friends with ruby gem

I am having trouble printing out a list of people I am following on twitter. This code worked at 250, but fails now that I am following 320 people.
Failure Description: The code request exceeds twitter's rate limit. The code sleeps for the time required for the limit to reset, and then tries again.
I think the way it's written, it just keeps retrying the same entire rejectable request, rather than picking up where it left off.
MAX_ATTEMPTS = 3
num_attempts = 0
begin
num_attempts += 1
#client.friends.each do |user|
puts "#{user.screen_name}"
end
rescue Twitter::Error::TooManyRequests => error
if num_attempts <= MAX_ATTEMPTS
sleep error.rate_limit.reset_in
retry
else
raise
end
end
Thanks!
The following code will return an array of usernames. The vast majority of the code was written by the author of: http://workstuff.tumblr.com/post/4556238101/a-short-ruby-script-to-pull-your-twitter-followers-who
First create the following definition.
def get_cursor_results(action, items, *args)
result = []
next_cursor = -1
until next_cursor == 0
begin
t = #client.send(action, args[0], args[1], {:cursor => next_cursor})
result = result + t.send(items)
next_cursor = t.next_cursor
rescue Twitter::Error::TooManyRequests => error
puts "Rate limit error, sleeping for #{error.rate_limit.reset_in} seconds...".color(:yellow)
sleep error.rate_limit.reset_in
retry
end
end
return result
end
Second gather your twitter friends using the following two lines
friends = get_cursor_results('friends', 'users', 'twitterusernamehere')
screen_names = friends.collect{|x| x.screen_name}
try using a cursor: http://rdoc.info/gems/twitter/Twitter/API/FriendsAndFollowers#friends-instance_method (for example, https://gist.github.com/kent/451413)

Retry testing sites after timeout error in Watir

I am going through a list of sites and going to each one using Watir to look for something in the source code of each page. However, after about 20 or 30 sites, the browser times out when loading a certain page and it breaks my script and I get this error:
rbuf_fill: execution expired (Timeout::Error)
I am trying to implement a way to detect when it times out and then restart testing the sites from where it left off but am having trouble.
This is my code:
ie = Watir::Browser.new :firefox, :profile => "default"
testsite_array = Array.new
y=0
File.open('topsites.txt').each do |line|
testsite_array[y] = line
y=y+1
end
total = testsite_array.length
count = 0
begin
while count <= total
site = testsite_array[count]
ie.goto site
if ie.html.include? 'teststring'
puts site + ' yes'
else
puts site + ' no'
end
rescue
retry
count = count+1
end
end
ie.close
Your loop can be:
#Use Ruby's method for iterating through the array
testsite_array.each do |site|
attempt = 1
begin
ie.goto site
if ie.html.include? 'teststring'
puts site + ' yes'
else
puts site + ' no'
end
rescue
attempt += 1
#Retry accessing the site or stop trying
if attempt > MAX_ATTEMPTS
puts site + ' site failed, moving on'
else
retry
end
end
end

While loop in Ruby Shoes GUI ToolKit

I have only been using Shoes for a few days now so maybe I am missing something. I wrote my son an little program to help him learn his multiplication tables. When he gets ten correct he's done. I can not seem to get the while loop right using SHOES.
Would some please show me a while statement. When I try; it either wipes out my flow and stack statements or Shoe crashes.
thanks in advance.
Sam
I don't know how you're using a while loop. Most likely you're trying to recreate the stack each iteration through the while loop, which is a bad idea. The two solutions that spring immediately to mind are to handle the logic on a button click and keep track of the number correct in a row, like this:
Shoes.app do
num_correct = 0
first_num = 1 + rand(10)
second_num = 1 + rand(10)
answer = first_num * second_num
stack do
#info = para 'Hi, Timmy! This program will test your ',
'multiplication tables. When you get 10 ',
'correct, you get to stop, and you get your ',
'pet hamster back!'
#question = para "What is #{first_num} x #{second_num}?"
#response = edit_line :width => 100
btn = button 'OK' do
if #response.text == ''
alert('You need to put an answer in the box, Timmy.')
elsif #response.text.to_i == answer
num_correct += 1
if num_correct == 10
#info.text = "Good job! That's #{num_correct} in a row!"
alert('You did it, Timmy! You can have your ' \
'hamster back... for now.')
exit
else
#info.text = "Good job! That's #{num_correct} in a row!"
first_num = 1 + rand(10)
second_num = 1 + rand(10)
answer = first_num * second_num
#question.text = "What is #{first_num} x #{second_num}?"
#response.text = ''
end
else
num_correct = 0
#info.text = "Wrong, Timmy. The answer is #{answer}."
first_num = 1 + rand(10)
second_num = 1 + rand(10)
answer = first_num * second_num
#question.text = "What is #{first_num} x #{second_num}?"
#response.text = ''
end
end
end
end
Or, the solution which I think is much more interesting, using url and visit:
class MyTest < Shoes
url '/', :index
url '/correct/(\d+)', :correct
url '/wrong/(\d+)', :wrong
url '/question', :question
url '/question/(\d+)', :question
url '/done', :done
def index
stack do
para 'Hi, Timmy! This program will test your ' \
'multiplication tables. When you get 10 ' \
'correct, you get to stop, and you get your ' \
'pet hamster back!'
button 'OK' do
visit '/question'
end
end
end
def question(num_correct = 0)
num_correct = num_correct.to_i
first_num = 1 + rand(10)
second_num = 1 + rand(10)
answer = first_num * second_num
stack do
para "What is #{first_num} x #{second_num}?"
flow do
response = edit_line :width => 100
button 'Answer' do
if response.text.to_i == answer
num_correct += 1
if num_correct == 10
visit '/done'
else
visit "/correct/#{num_correct}"
end
else
visit "/wrong/#{answer}"
end
end
end
end
end
def correct(num_correct)
stack do
para "Good job! That's #{num_correct} in a row!"
button "Next Question" do
visit "/question/#{num_correct}"
end
end
end
def wrong(answer)
#num_correct = 0
stack do
para "Wrong! The correct answer is #{answer}."
button "Next Question" do
visit '/question'
end
end
end
def done
stack do
para 'You did it, Timmy! You can have your ' \
'hamster back... for now.'
button 'OK' do
exit
end
end
end
end
Shoes.app

Resources