While running a cucumber-based test, I used the -b commend to get more information on the error. Now it seems that my webdriver will not go back to quiet mode.
Here's my support file:
require 'capybara'
require 'capybara/cucumber'
require 'rspec'
require 'selenium/webdriver'
#require 'capybara/rails'
def snore(location)
x = 0
timeout = 120
while (page.has_css?(location) == false) && (x < timeout)
sleep(1)
x = x + 1
puts x
puts page.has_css?(location)
end
end
def eventday
now = Time.now
today = 0
if now.day.to_i > 27
today = 15
else
today = now.day.to_s
end
return today.to_s
end
def monthup
now = Time.now
monthtime = 0
if now.day.to_i > 27
monthtime = 1500000
else
monthtime = 3000000
end
return monthtime.to_i
end
caps = Selenium::WebDriver::Remote::Capabilities.chrome #chrome|firefox|internet_explorer
#caps.version = "8"
#caps.platform = :WINDOWS
Capybara.server_port = 3001
Capybara.app_host = "http://www.google.com"
Capybara.default_driver = :selenium
Capybara.ignore_hidden_elements = true
Capybara.register_driver :selenium do |app|
Capybara::Selenium::Driver.new(app,
:browser => :chrome #chrome|firefox|internet_explorer
#,
#:url => "localhost:4444/wd/hub",
#:desired_capabilities => ("chrome.binary", "/usr/lib/chromium-browser/chromium-browser")
)
end
Here's some of the output I'm seeing:
[8.261][INFO]: received WebDriver request: POST /session/1bdb4fe1ae6d3bef1f6e4299c3b3/url
"url": "http://example.org"
}
[8.267][INFO]: waiting for pending navigations...
[8.283][INFO]: done waiting for pending navigations
[8.377][INFO]: waiting for pending navigations...
[0703/152133:ERROR:gl_surface_egl.cc(479)] Error: surface has zero area 0 x 0
[0703/152133:ERROR:gl_surface_egl.cc(547)] Failed to resize pbuffer.
[10.866][INFO]: done waiting for pending navigations
[10.866][INFO]: sending WebDriver response: 200 {
"sessionId": "1bdb4fe1ae6d3bef1f6e4299c3b3",
"status": 0,
"value": null
Related
Goal: Download photos from iCloud Shared web album via script: https://www.icloud.com/sharedalbum/#B0Q5oqs3qGtDCal
I have following script from here: https://github.com/dsboulder/icloud-shared-album-download/blob/master/download_album.rb
(I have taken out the image resize)
Problem: Photos seem to download, however they all look all like this (script output further below):
#!/usr/bin/env ruby
# C:\Users\Win10IE11\Desktop\icloud-shared-album-download-master\download_album2.rb B0Q5oqs3qGtDCal
require 'selenium-webdriver'
require 'fileutils'
require 'yaml'
album_name = ARGV[0]
options = Selenium::WebDriver::Chrome::Options.new(args: ['headless'])
driver = Selenium::WebDriver.for(:chrome, options: options)
puts "Downloading album ID #{album_name}:"
dir = "C:/Users/Win10IE11/Downloads/#{album_name}"
movies_dir = "/home/pi/Videos"
FileUtils.mkdir_p(dir)
urls_seen = Set.new
files_seen = Set.new
driver.get("https://www.icloud.com/sharedalbum/##{album_name}")
puts " Navigated to index page: #{driver.current_url}"
sleep 2
driver.find_element(css: "[role=button]").click
sleep 5
c = 0
current_url = driver.current_url
seen_first = false
exit_early = false
until urls_seen.include?(current_url) or c >= 200 or exit_early do
retries = 0
begin
current_url = driver.current_url
puts " Navigated to: #{current_url}"
urls_seen.add(current_url)
i = driver.find_element(css: "img")
puts " Downloading image #{c}: #{i["src"]}"
u = URI.parse(i["src"])
ext = u.path.split(".").last.downcase
filename = "#{current_url.split(";").last}.#{ext}".downcase
path = "#{dir}/#{filename}"
if File.exist?(path)
if c == 0
seen_first = true
puts " Already seen first image, going backwards now"
elsif seen_first and c == 1
exit_early = true
puts " Already seen last image, we're probably done!"
else
puts " Skipping already downloaded file #{path}"
end
else
r = Net::HTTP.get_response(u)
puts " #{r.inspect}"
File.write(path, r.body)
puts " Wrote file of length #{r.body.length} to #{path}"
videos = driver.find_elements(css: ".play-button")
if videos.length > 0
puts " Found video!!!"
videos.first.click
video_src = driver.find_element(css: "video > source")["src"]
u = URI.parse(video_src)
ext = u.path.split(".").last.downcase
filename = "#{current_url.split("#").last.gsub(";", "_")}.#{ext}".downcase
path = "#{movies_dir}/#{filename}"
puts " Downloading from #{video_src} to #{path}"
driver.navigate.refresh
r = Net::HTTP.get_response(u)
File.write(path, r.body)
puts " Wrote #{r.body.length} bytes of video to #{path}"
end
end
c += 1
sleep 1
driver.find_element(css: "body").send_keys(seen_first ? :arrow_left : :arrow_right)
sleep 1
current_url = driver.current_url
rescue => e
puts "Error: #{e.inspect}"
retries += 1
if retries < 4
driver.quit rescue nil
puts "RETRY ##{retries}"
system "pkill -f chromedriver"
driver = Selenium::WebDriver.for(:chrome, options: options)
driver.get(current_url)
sleep 5
retry
end
end
end
puts " Finished #{c} photos in album #{album_name}!"
driver.quit
***Output:
Navigated to: https://www.icloud.com/sharedalbum/#B0Q5oqs3qGtDCal;64D46E01-D439-4FB3-9234-EEADFD92B4B8
Downloading image 22: https://cvws.icloud-content.com/S/AZmmX4aAk6O2XpXCavO3rA4XSNms/IMG_0023.JPG?o=AtHCwB51UajcHVvLEboQsSvM4hK5ZHb25DMLu5rjLgMs&v=1&z=https%3A%2F%2Fp26-content.icloud.com%3A443&x=1&a=BqocZLbrD6m1lXeHN6LXov32oNLDA-UfRgEAAAMxH0Y&e=1538045095&r=900d8d25-0a15-43e5-be59-2a4c9267cfaf-36&s=C3ee21ErkyHFKzq-JWjZkKXpah4
#<Net::HTTPOK 200 OK readbody=true>
Wrote file of length 1248141 to C:/Users/Win10IE11/Downloads/B0Q5oqs3qGtDCal/64d46e01-d439-4fb3-9234-eeadfd92b4b8.jpg
Swapped the function with "open-uri" function, doc found here: https://cobwwweb.com/download-collection-of-images-from-url-using-ruby.html
Swapped old code:
File.write(path, r.body)
with:
File.open(dest, 'wb') { |f| f.write(u.read) }
Here is the fixed code:
#!/usr/bin/env ruby
# C:\Users\Win10IE11\Desktop\icloud-shared-album-download-master\dl5.rb B0Q5oqs3qGtDCal
require 'selenium-webdriver'
require 'fileutils'
require 'yaml'
require 'open-uri'
album_name = ARGV[0]
options = Selenium::WebDriver::Chrome::Options.new(args: ['headless'])
driver = Selenium::WebDriver.for(:chrome, options: options)
puts "Downloading album ID #{album_name}:"
dir = "C:/Users/Win10IE11/Downloads/#{album_name}"
movies_dir = dir
FileUtils.mkdir_p(dir)
urls_seen = Set.new
files_seen = Set.new
driver.get("https://www.icloud.com/sharedalbum/##{album_name}")
puts " Navigated to index page: #{driver.current_url}"
sleep 1
driver.find_element(css: "[role=button]").click
sleep 1
c = 0
current_url = driver.current_url
seen_first = true
exit_early = false
def download_image(url, dest)
open(url) do |u|
File.open(dest, 'wb') { |f| f.write(u.read) }
puts "Saved #{url} to #{dest}"
end
end
until urls_seen.include?(current_url) or c >= 200 or exit_early do
retries = 0
begin
current_url = driver.current_url
puts " Navigated to: #{current_url}"
urls_seen.add(current_url)
i = driver.find_element(css: "img")
# C:\Users\Win10IE11\Desktop\icloud-shared-album-download-master\dl5.rb B0Q5oqs3qGtDCal
puts " count #{c}"
videos = driver.find_elements(css: ".play-button")
if videos.length > 0
#puts " Found video!!!"
videos.first.click
i = driver.find_element(css: "video > source")
url = "#{i["src"]}"
local1 = "#{url.split('/').last}"
local = "#{c}_#{local1.split('?').first}"
download_image(url, "#{dir}/#{local}")
driver.navigate.refresh
sleep 1
else
#puts " not video!!!"
url = "#{i["src"]}"
local1 = "#{url.split('/').last}"
local = "#{c}_#{local1.split('?').first}"
download_image(url, "#{dir}/#{local}")
end
c += 1
sleep 0.1
driver.find_element(css: "body").send_keys(seen_first ? :arrow_left : :arrow_right)
sleep 0.1
current_url = driver.current_url
rescue => e
puts "Error: #{e.inspect}"
retries += 1
if retries < 4
driver.quit rescue nil
puts "RETRY ##{retries}"
system "pkill -f chromedriver"
driver = Selenium::WebDriver.for(:chrome, options: options)
driver.get(current_url)
sleep 1
retry
end
end
end
puts " Finished #{c} photos in album #{album_name}!"
driver.quit
I'm having a difficulty with processing resque tasks which were enqueued.
The whole enqueuing part goes well - I can see it in Redis and also Resque.info shows the pending tasks number incrementing as it should.
If I run the perform method of the Job class explicitly - everything works fine.
Once the worker come alive - all the tasks fail.
This is the Job class:
class TestJob
#queue = :test1_queue
def self.perform(str)
begin
f = open('/tmp/test.txt', 'a')
f.write("#{Time.now.to_s} #{str} in self.perform\n")
rescue Exception => e
f.write("#{Time.now.to_s} #{str} in self.perform\n#{e.message}\n#{e.backtrace}\n")
ensure
f.close
end
end
end
The resque.rb initializer:
require 'resque'
require 'redis'
Dir['../../jobs'].each { |file| require file }
Resque.redis = $resque_redis
Resque.logger.level = Logger::WARN
Resque.after_fork do |_|
$resque_redis.client.reconnect
end
Redis initializer:
require 'redis'
$resque_redis = Redis.new(:host => REDIS_BITMAP_HOST, :port => REDIS_PORT, :db => 0, :timeout => 30)
config file to start the worker with god:
require_relative './common.rb'
watch_resque_process('test1', 1)
God definitions:
$home_dir = ENV["HOME"]
$rack_env = ENV["ETL_ENV"] || "development"
def create_deafult_monitoring_scheme(watch)
# Restart if memory is above 150 Megabytes or CPU is above 50% for 5 consecutive intervals
watch.restart_if do |restart|
restart.condition(:memory_usage) do |c|
c.above = 150.megabytes
c.times = [3, 5] # 3 out of 5 intervals
end
restart.condition(:cpu_usage) do |c|
c.above = 50.percent
c.times = 5
end
end
# The :flapping condition guards against the edge case wherein god rapidly starts or restarts your application.
# If this watch is started or restarted five times withing 5 minutes, then unmonitor it for 10 minutes.
# After 10 minutes, monitor it again to see if it was just a temporary problem; if the process is seen to be flapping five times within two hours, then give up completely.
watch.lifecycle do |on|
on.condition(:flapping) do |c|
c.to_state = [:start, :restart]
c.times = 5
c.within = 5.minute
c.transition = :unmonitored
c.retry_in = 10.minute
c.retry_times = 5
c.retry_within = 30.minute
end
end
end
def watch_resque_process(resque_process_name, worker_count=8)
God.watch do |w|
w.name = "resque_work-#{resque_process_name}"
w.start = "cd #{$home_dir}/rtb-etl && COUNT=#{worker_count} QUEUE='#{resque_process_name}_queue' RACK_ENV=#{$rack_env} rake resque:workers"
w.interval = 30.seconds
w.log = File.join($home_dir, 'logs', 'resque', "resque_#{resque_process_name}.log")
w.err_log = File.join($home_dir, 'logs', 'resque', "resque_#{resque_process_name}.log")
w.env = { 'PIDFILE' => "#{$home_dir}/pids/#{w.name}.pid" }
# Check if the process is still up every 5 seconds
w.start_if do |start|
start.condition(:process_running) do |c|
c.interval = 5.seconds
c.running = false
end
end
create_deafult_monitoring_scheme(w)
end
end
def watch_rake_task(rake_task_name, interval=30.seconds)
God.watch do |w|
w.name = "rake_#{rake_task_name}"
# w.start = "cd #{$home_dir}/rtb-etl && RACK_ENV=#{$rack_env} bundle exec rake #{rake_task_name}"
w.start = "cd #{$home_dir}/rtb-etl && RACK_ENV=#{$rack_env} rake #{rake_task_name}"
w.interval = interval
w.log = File.join($home_dir, 'logs', 'resque', "rake_#{rake_task_name}.log")
w.err_log = File.join($home_dir, 'logs', 'resque', "rake_#{rake_task_name}.log")
w.env = { 'PIDFILE' => "#{$home_dir}/pids/#{w.name}.pid" }
# Check if the process is still up every 30 seconds
w.start_if do |start|
start.condition(:process_running) do |c|
c.interval = interval
c.running = false
end
end
create_deafult_monitoring_scheme(w)
end
end
when I run the follwoing:
irb(main):004:0> Resque.enqueue(TestJob, 'foo')
=> true
In order to check what went wrong, I run in irb the following:
Resque::Failure.all(0,20).each { |job|
puts "#{job["exception"]} #{job["backtrace"]}"
}
and get this result:
[{"failed_at"=>"2015/08/26 17:35:00 UTC",
"payload"=>{"class"=>"TestJob", "args"=>["foo"]},
"exception"=>"NoMethodError",
"error"=>"undefined method `client' for nil:NilClass",
"backtrace"=>[], "worker"=>"ip-172-31-11-211:5006:test1_queue",
"queue"=>"test1_queue"}]
Any ideas ?
I'm trying to run this code in Red Hat Linux, and it won't launch a browser. The only way I can get it to work is if i ALSO launch a browser OUTSIDE of the thread, which makes no sense to me. Here is what I mean:
require 'watir-webdriver'
$alphabet = ["A", "B", "C"]
$alphabet.each do |z|
puts "pshaw"
Thread.new{
Thread.current["testPuts"] = "ohai " + z.to_s
Thread.current["myBrowser"] = Watir::Browser.new :ff
puts Thread.current["testPuts"] }
$browser = Watir::Browser.new :ff
end
the output is:
pshaw
(launches browser)
ohai A
(launches browser)
pshaw
(launches browser)
ohai B
(launches browser)
pshaw
(launches browser)
ohai C
(launches browser)
However, if I remove the browser launch that is outside of the thread, as so:
require 'watir-webdriver'
$alphabet = ["A", "B", "C"]
$alphabet.each do |z|
puts "pshaw"
Thread.new{
Thread.current["testPuts"] = "ohai " + z.to_s
Thread.current["myBrowser"] = Watir::Browser.new :ff
puts Thread.current["testPuts"] }
end
The output is:
pshaw
pshaw
pshaw
What is going on here? How do I fix this so that I can launch a browser inside a thread?
EDIT TO ADD:
The solution Justin Ko provided worked on the psedocode above, but it's not helping with my actual code:
require 'watir-webdriver'
require_relative 'Credentials'
require_relative 'ReportGenerator'
require_relative 'installPageLayouts'
require_relative 'PackageHandler'
Dir[(Dir.pwd.to_s + "/bmx*")].each {|file| require_relative file } #this includes all the files in the directory with names starting with bmx
module Runner
def self.runTestCases(orgType, *caseNumbers)
$testCaseArray = Array.new
caseNumbers.each do |thisCaseNum|
$testCaseArray << thisCaseNum
end
$allTestCaseResults = Array.new
$alphabet = ["A", "B", "C"]
#count = 0
#multiOrg = 0
#peOrg = 0
#eeOrg = 0
#threads = Array.new
$testCaseArray.each do |thisCase|
$alphabet[#count] = Thread.new {
puts "working one"
Thread.current["tBrowser"] = Watir::Browser.new :ff
puts "working two"
if ((thisCase.declareOrg().downcase == "multicurrency") || (thisCase.declareOrg().downcase == "mc"))
currentOrg = $multicurrencyOrgArray[#multiOrg]
#multiOrg += 1
elsif ((thisCase.declareOrg().downcase == "enterprise") || (thisCase.declareOrg().downcase == "ee"))
currentOrg = $eeOrgArray[#eeOrg]
#eeOrg += 1
else #default to single currency PE
currentOrg = $peOrgArray[#peOrg]
#peOrg += 1
end
setupOrg(currentOrg, thisCase.testCaseID, currentOrg.layoutDirectory)
runningTest = thisCase.actualTest()
if runningTest.crashed != "crashed" #changed this to read the attr_reader isntead of the deleted caseStatus method from TestCase.rb
cleanupOrg(thisCase.testCaseID, currentOrg.layoutDirectory)
end
#threads << Thread.current
}
#count += 1
end
#threads.each do |thisThread|
thisThread.join
end
writeReport($allTestCaseResults)
end
def self.setupOrg(thisOrg, caseID, layoutPath)
begin
thisOrg.logIn
pkg = PackageHandler.new
basicInstalled = "false"
counter = 0
until ((basicInstalled == "true") || (counter == 5))
pkg.basicInstaller()
if Thread.current["tBrowser"].text.include? "You have attempted to access a page"
thisOrg.logIn
else
basicInstalled = "true"
end
counter +=1
end
if !((caseID.include? "bmxb") || (caseID.include? "BMXB"))
moduleInstalled = "false"
counter2 = 0
until ((moduleInstalled == "true") || (counter == 5))
pkg.packageInstaller(caseID)
if Thread.current["tBrowser"].text.include? "You have attempted to access a page"
thisOrg.logIn
else
moduleInstalled = "true"
end
counter2 +=1
end
end
installPageLayouts(layoutPath)
rescue
$allTestCaseResults << TestCaseResult.new(caseID, caseID, 1, "SETUP FAILED!" + "<p>#{$!}</p><p>#{$#}</p>").hashEmUp
writeReport($allTestCaseResults)
end
end
def self.cleanupOrg(caseID, layoutPath)
begin
uninstallPageLayouts(layoutPath)
pkg = PackageHandler.new
pkg.packageUninstaller(caseID)
Thread.current["tBrowser"].close
rescue
$allTestCaseResults << TestCaseResult.new(caseID, caseID, 1, "CLEANUP FAILED!" + "<p>#{$!}</p><p>#{$#}</p>").hashEmUp
writeReport($allTestCaseResults)
end
end
end
The output it's generating is:
working one
working one
working one
It's not opening a browser or doing any of the subsequent code.
It looks like the code is having the problem mentioned in the Thread class documentation:
If we don't call thr.join before the main thread terminates, then all
other threads including thr will be killed.
Basically your main thread is finishing pretty instantaneously. However, the threads, which create browsers, take a lot longer than that. As result the threads get terminated before the browser opens.
By adding a long sleep at the end, you can see that your browsers can be opened by your code:
require 'watir-webdriver'
$chunkythread = ["A", "B", "C"]
$chunkythread.each do |z|
puts "pshaw"
Thread.new{
Thread.current["testwords"] = "ohai " + z.to_s
Thread.current["myBrowser"] = Watir::Browser.new :ff
puts Thread.current["testwords"] }
end
sleep(300)
However, for more reliability, you should join all the threads at the end:
require 'watir-webdriver'
threads = []
$chunkythread = ["A", "B", "C"]
$chunkythread.each do |z|
puts "pshaw"
threads << Thread.new{
Thread.current["testwords"] = "ohai " + z.to_s
Thread.current["myBrowser"] = Watir::Browser.new :ff
puts Thread.current["testwords"] }
end
threads.each { |thr| thr.join }
For the actual code example, putting #threads << Thread.current will not work. The join will be evaluating like #threads is empty. You could try doing the following:
$testCaseArray.each do |thisCase|
#threads << Thread.new {
puts "working one"
Thread.current["tBrowser"] = Watir::Browser.new :ff
# Do your other thread stuff
}
$alphabet[#count] = #threads.last
#count += 1
end
#threads.each do |thisThread|
thisThread.join
end
Note that I am not sure why you want to store the threads in $alphabet. I put in the $alphabet[#count] = #threads.last, but could be removed if not in use.
I uninstalled Watir 5.0.0 and installed Watir 4.0.2, and now it works fine.
http://demos.telerik.com/aspnet-ajax/combobox/examples/functionality/checkboxes/defaultcs.aspx
I am able to get total number of options but not able to get text.
Try with following. It's working at my end:
require 'selenium-webdriver'
driver = Selenium::WebDriver.for :firefox
driver.get "http://demos.telerik.com/aspnet-ajax/combobox/examples/functionality/checkboxes/defaultcs.aspx"
el = driver.find_element(:id, "ctl00_ContentPlaceHolder1_RadComboBox1_Arrow")
el.click
list = driver.find_element(:xpath, "//ul[#class='rcbList']")
options = list.find_elements(:xpath, ".//li/label")
options.each do |option|
puts option.text
end
Works fine for me with or without using Selenium::WebDriver::Wait.
Here is the complete code (I commented out the version without using WebDriverWait, both versions should work anyway):
require 'selenium-webdriver'
driver = Selenium::WebDriver.for :firefox
driver.get('http://demos.telerik.com/aspnet-ajax/combobox/examples/functionality/checkboxes/defaultcs.aspx')
wait = Selenium::WebDriver::Wait.new(:timeout => 10) # seconds
# without wait
# combo = driver.find_element(:id => 'ctl00_ContentPlaceHolder1_RadComboBox1_Input')
# combo.click
# with wait
combo = wait.until { driver.find_element(:id => "ctl00_ContentPlaceHolder1_RadComboBox1_Input") }
combo.click
# without wait
# all_labels = driver.find_elements(:css => '#ctl00_ContentPlaceHolder1_RadComboBox1_DropDown .rcbItem label')
# with wait
all_labels = wait.until { driver.find_elements(:css => '#ctl00_ContentPlaceHolder1_RadComboBox1_DropDown .rcbItem label') }
all_labels.each do |label|
puts label.text
end
puts all_labels.count
I've got a ruby script
#!/usr/bin/ruby
require 'rubygems'
require 'mechanize'
require 'nokogiri'
require 'highline/import'
require 'stringio'
#Change based on Semester
$term = '09'
$year = '2012'
$frequency = 4 #Number of Seconds between check requests
$agent = Mechanize.new
$agent.redirect_ok = true
$agent.user_agent = "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_6_8) AppleWebKit/535.19 (KHTML, like Gecko) Chrome/18.0.1025.11 Safari/535.19"
$agent.verify_mode = OpenSSL::SSL::VERIFY_NONE
#Uber simway to colorize outputin
class String
def color(c)
colors = {
:black => 30,
:red => 31,
:green => 32,
:yellow => 33,
:blue => 34,
:magenta => 35,
:cyan => 36,
:white => 37
}
return "\e[#{colors[c] || c}m#{self}\e[0m"
end
end
#Logins, Gets the Courses, Returns Courses Obj with Name/URL/Tools for each
def login(username, password)
#Login to the system!
page = $agent.get("https://auth.vt.edu/login?service=https://webapps.banner.vt.edu/banner-cas-prod/authorized/banner/SelfService")
login = page.forms.first
login.set_fields({
:username => username,
:password => password
})
if (login.submit().body.match(/Invalid username or password/)) then
return false
else
return true
end
end
#Gets Course Information
def getCourse(crn)
begin
courseDetails = Nokogiri::HTML( $agent.get(
"https://banweb.banner.vt.edu/ssb/prod/HZSKVTSC.P_ProcComments?CRN=#{crn}&TERM=#{$term}&YEAR=#{$year}"
).body)
rescue
return false #Failed to get course
end
#Flatten table to make it easier to work with
course = {}
dataSet = false
course[:title] = courseDetails.css('td.title').last.text.gsub(/-\ +/, '')
course[:crn] = crn
courseDetails.css('table table tr').each_with_index do |row|
#If we have a dataSet
case dataSet
when :rowA
[ :i, :days, :end, :begin, :end, :exam].each_with_index do |el, i|
if row.css('td')[i] then
course[el] = row.css('td')[i].text
end
end
when :rowB
[ :instructor, :type, :status, :seats, :capacity ].each_with_index do |el, i|
course[el] = row.css('td')[i].text
end
end
dataSet = false
#Is there a dataset?
row.css('td').each do |cell|
case cell.text
when "Days"
dataSet = :rowA
when "Instructor"
dataSet = :rowB
end
end
end
return course
end
#Registers you for the given CRN, returns true if successful, false if not
def registerCrn(crn)
#Follow Path
$agent.get("https://banweb.banner.vt.edu/ssb/prod/twbkwbis.P_GenMenu?name=bmenu.P_MainMnu")
reg = $agent.get("https://banweb.banner.vt.edu/ssb/prod/hzskstat.P_DispRegStatPage")
dropAdd = reg.link_with(:href => "/ssb/prod/bwskfreg.P_AddDropCrse?term_in=#{$year}#{$term}").click
#Fill in CRN Box and Submit
crnEntry = dropAdd.form_with(:action => '/ssb/prod/bwckcoms.P_Regs')
crnEntry.fields_with(:id => 'crn_id1').first.value = crn
crnEntry['CRN_IN'] = crn
add = crnEntry.submit(crnEntry.button_with(:value => 'Submit Changes')).body
if add =~ /#{crn}/ && !(add =~ /Registration Errors/) then
return true
else
return false
end
end
#Main loop that checks the availaibility of each courses and fires to registerCrn on availaibility
def checkCourses(courses)
requestCount = 0
startTime = Time.new
loop do
system("clear")
requestCount += 1
nowTime = Time.new
puts "Checking Availaibility of CRNs".color(:yellow)
puts "--------------------------------\n"
puts "Started:\t#{startTime.asctime}".color(:magenta)
puts "Now: \t#{nowTime.asctime}".color(:cyan)
puts "Request:\t#{requestCount} (Once every #{$frequency} seconds)".color(:green)
puts "--------------------------------\n\n"
courses.each_with_index do |c, i|
puts "#{c[:crn]} - #{c[:title]}".color(:blue)
course = getCourse(c[:crn])
next unless course #If throws error
puts "Availaibility: #{course[:seats]} / #{course[:capacity]}".color(:red)
if (course[:seats] =~ /Full/) then
else
if (registerCrn(c[:crn])) then
puts "CRN #{c[:crn]} Registration Sucessfull"
courses.slice!(i)
else
puts "Couldn't Register"
end
end
print "\n"
end
sleep $frequency
end
end
#Add courses to be checked
def addCourses
crns = []
loop do
system("clear")
puts "Your CRNs:".color(:red)
crns.each do |crn|
puts " -> #{crn[:title]} (CRN: #{crn[:crn]})".color(:magenta)
end
#Prompt for CRN
alt = (crns.length > 0) ? " (or just type 'start') " : " "
input = ask("\nEnter a CRN to add it#{alt}".color(:green) + ":: ") { |q| q.echo = true }
#Validate CRN to be 5 Digits
if (input =~ /^\d{5}$/) then
#Display CRN Info
c = getCourse(input.to_s)
puts "\nCourse: #{c[:title]} - #{c[:crn]}".color(:red)
puts "--> Time: #{c[:begin]}-#{c[:end]} on #{c[:days]}".color(:cyan)
puts "--> Teacher: #{c[:instructor]}".color(:cyan)
puts "--> Type: #{c[:type]} || Status: #{c[:status]}".color(:cyan)
puts "--> Availability: #{c[:seats]} / #{c[:capacity]}\n".color(:cyan)
#Add Class Prompt
add = ask("Add This Class? (yes/no)".color(:yellow) + ":: ") { |q| q.echo = true }
crns.push(c) if (add =~ /yes/)
elsif (input == "start") then
checkCourses(crns)
end
end
end
def main
system("clear")
puts "Welcome to CourseAdd by mil".color(:blue)
username = ask("PID ".color(:green) + ":: ") { |q| q.echo = true }
password = ask("Password ".color(:green) + ":: " ) { |q| q.echo = "*" }
system("clear")
if login(username, password) then
addCourses
else
puts "Invalid PID/Password"
exit
end
end
main
but when I run ruby Untitled.rb it give me this error.
/System/Library/Frameworks/Ruby.framework/Versions/1.8/usr/lib/ruby/1.8/rubygems/custom_require.rb:31:in `gem_original_require': no such file to load -- mechanize (LoadError)
from /System/Library/Frameworks/Ruby.framework/Versions/1.8/usr/lib/ruby/1.8/rubygems/custom_require.rb:31:in `require'
from /Users/user/Desktop/Untitled.rb:3
What does this mean and how can I fix it? I'm not sure if I need to be doing this through an IDE or if terminal works. I'm brand new to ruby so I honestly have not a clue what the issue could be.
You need to install mechanize. In your terminal, type:
gem install mechanize
Retry your script when it finishes installing. If you have other gems that are missing, you can use the same command to install them.
gem install <gem name>