webpilot 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1 @@
1
+ Gemfile.lock
data/Gemfile ADDED
@@ -0,0 +1,6 @@
1
+ source "http://rubygems.org"
2
+
3
+ gem 'headless'
4
+ gem 'log4r'
5
+ gem 'rspec'
6
+ gem 'selenium-webdriver'
@@ -0,0 +1,7 @@
1
+ require 'rspec/core/rake_task'
2
+
3
+ desc 'Default: Run specs'
4
+ task :default => :spec
5
+
6
+ desc 'Run specs'
7
+ RSpec::Core::RakeTask.new
@@ -0,0 +1,133 @@
1
+ require 'bundler/setup'
2
+ require 'headless'
3
+ require 'log4r'
4
+ require 'selenium-webdriver'
5
+
6
+ $LOAD_PATH << File.expand_path(File.dirname(__FILE__))
7
+
8
+ class WebPilot
9
+ include Log4r
10
+ attr_reader :driver, :logger
11
+
12
+ extend Forwardable
13
+ def_delegators :@driver, :close, :current_url, :execute_script, :navigate,
14
+ :page_source, :quit, :switch_to, :window_handle, :window_handles
15
+ def_delegators :@logger, :debug, :info, :warn, :error, :fatal
16
+
17
+ def initialize(options={})
18
+ @browser = options[:browser] || :firefox
19
+ @is_headless = options[:is_headless]
20
+ @pause_time = options[:pause_time] || 0.3
21
+ @screenshot_dir = options[:screenshot_dir]
22
+ @timeout = options[:timeout] || 8
23
+
24
+ case
25
+ when options[:logger].nil?
26
+ @logger = Logger.new 'debug_log'
27
+ null_outputter = IOOutputter.new 'null', File.open('/dev/null', 'w')
28
+ when options[:logger].is_a?(Logger)
29
+ @logger = options[:logger]
30
+ when options[:logger] == 'STDOUT'
31
+ @logger = Logger.new 'debug_log'
32
+ @logger.outputters = Outputter.stdout
33
+ @logger.level = DEBUG
34
+ when options[:logger] == 'STDERR'
35
+ @logger = Logger.new 'debug_log'
36
+ @logger.outputters = Outputter.stderr
37
+ @logger.level = DEBUG
38
+ end
39
+
40
+ if @is_headless
41
+ @headless = Headless.new
42
+ @headless.start
43
+ end
44
+
45
+ @driver = Selenium::WebDriver.for @browser
46
+ end
47
+
48
+ # Close all windows that have a current url of "about:blank". Must follow this with a call to
49
+ # `#switch_to`, so that you know what window you're on.
50
+ def close_blank_windows
51
+ @driver.window_handles.each do |handle|
52
+ @driver.switch_to.window(handle)
53
+ @driver.close if @driver.current_url == 'about:blank'
54
+ end
55
+ end
56
+
57
+ # Enlargens the text of an element, using `method` and `locator`, by changing the `font-size`
58
+ # in the style to be `3em`. It uses the following Javascript:
59
+ #
60
+ # hlt = function(c) { c.style.fontSize='3em'; }; return hlt(arguments[0]);
61
+ def enlargen(method, locator)
62
+ @logger.debug " enlargen: Waiting up to #{@timeout} seconds to find_element(#{method}, #{locator})..."
63
+ wait = Selenium::WebDriver::Wait.new(:timeout => @timeout)
64
+ wait.until { find_element(method, locator) }
65
+ element = find_element(method, locator)
66
+ execute_script("hlt = function(c) { c.style.fontSize='3em'; }; return hlt(arguments[0]);", element)
67
+ end
68
+
69
+ def find_element(method, selector, options={})
70
+ retries = 4
71
+ sleep 0.1 # based on http://groups.google.com/group/ruby-capybara/browse_thread/thread/5e182835a8293def fixes "NS_ERROR_ILLEGAL_VALUE"
72
+ begin
73
+ @driver.find_element(method, selector)
74
+ rescue Selenium::WebDriver::Error::NoSuchElementError, Selenium::WebDriver::Error::TimeOutError => e
75
+ return nil if options[:no_raise]
76
+ raise e
77
+ rescue Selenium::WebDriver::Error::InvalidSelectorError => e
78
+ raise e if retries == 0
79
+ @logger.info "Caught a Selenium::WebDriver::Error::InvalidSelectorError: #{e}"
80
+ @logger.info "Retrying..."
81
+ pause 2
82
+ retries -= 1
83
+ retry
84
+ end
85
+ end
86
+
87
+ def highlight(method, locator, ancestors=0)
88
+ wait = Selenium::WebDriver::Wait.new(:timeout => @timeout)
89
+ wait.until { find_element(method, locator) }
90
+ element = find_element(method, locator)
91
+ execute_script("hlt = function(c) { c.style.border='solid 1px rgb(255, 16, 16)'; }; return hlt(arguments[0]);", element)
92
+ parents = ""
93
+ red = 255
94
+
95
+ ancestors.times do
96
+ parents << ".parentNode"
97
+ red -= (12*8 / ancestors)
98
+ execute_script("hlt = function(c) { c#{parents}.style.border='solid 1px rgb(#{red}, 0, 0)'; }; return hlt(arguments[0]);", element)
99
+ end
100
+ pause
101
+ end
102
+
103
+ def pause(time = nil)
104
+ @logger.debug " breathing..."
105
+ sleep (time || @pause_time)
106
+ end
107
+
108
+ def quit
109
+ @driver.quit
110
+ @headless.destroy if @is_headless
111
+ end
112
+
113
+ # Deselect all `<option>s` within a `<select>`, suppressing any `UnsupportedOperationError`
114
+ # that Selenium may throw
115
+ def safe_deselect_all(el)
116
+ el.deselect_all
117
+ rescue Selenium::WebDriver::Error::UnsupportedOperationError
118
+ end
119
+
120
+ # Select a frame by its `id`
121
+ def select_frame(id)
122
+ @driver.switch_to().frame(id)
123
+ pause
124
+ end
125
+
126
+ # Create and execute a `Selenium::WebDriver::Wait` for finding an element by `method` and `selector`
127
+ def wait_for(method, locator)
128
+ @logger.debug " wait_for: Waiting up to #{@timeout} seconds to find_element(#{method}, #{locator})..."
129
+ wait = Selenium::WebDriver::Wait.new(:timeout => @timeout)
130
+ sleep 0.1 # based on http://groups.google.com/group/ruby-capybara/browse_thread/thread/5e182835a8293def fixes "NS_ERROR_ILLEGAL_VALUE"
131
+ wait.until { driver.find_element(method, locator) }
132
+ end
133
+ end
@@ -0,0 +1,19 @@
1
+ require File.join(File.dirname(File.expand_path(__FILE__)), 'spec_helper')
2
+
3
+ describe "WebPilot" do
4
+ before(:each) do
5
+ @driver = WebPilot.new(:is_headless => true)
6
+ end
7
+
8
+ after(:each) do
9
+ @driver.quit
10
+ end
11
+
12
+ it "should do some basics" do
13
+ @driver.navigate.to "http://www.google.com"
14
+ @driver.find_element(:css, '#gbqfq').send_keys('mwrc ruby')
15
+ @driver.find_element(:css, '#gbqfb').click
16
+ @driver.wait_for(:xpath, "//ol[@id='rso']/li//a")
17
+ @driver.find_element(:xpath, "//ol[@id='rso']/li//a").click
18
+ end
19
+ end
@@ -0,0 +1,62 @@
1
+ require File.join(File.dirname(File.expand_path(__FILE__)), 'spec_helper')
2
+
3
+ describe "WebPilot" do
4
+ context "default" do
5
+ before(:each) do
6
+ @driver = WebPilot.new(:is_headless => true)
7
+ end
8
+
9
+ after(:each) do
10
+ @driver.quit
11
+ end
12
+
13
+ it "should launch firefox by default" do
14
+ @driver.navigate.to "http://www.google.com"
15
+ ps_firefox = `ps -ef | grep "[f]irefox"`
16
+ ps_firefox['foreground'].should_not == nil
17
+ end
18
+ end
19
+
20
+ context "firefox" do
21
+ before(:each) do
22
+ @driver = WebPilot.new(:browser => :firefox, :is_headless => true)
23
+ end
24
+
25
+ after(:each) do
26
+ @driver.quit
27
+ end
28
+
29
+ it "should launch firefox when specified" do
30
+ @driver.navigate.to "http://www.google.com"
31
+ ps_firefox = `ps -ef | grep "[f]irefox"`
32
+ ps_firefox['foreground'].should_not == nil
33
+ end
34
+ end
35
+
36
+ context "chrome" do
37
+ before(:each) do
38
+ begin
39
+ @driver = WebPilot.new(:browser => :chrome, :is_headless => true)
40
+ rescue Selenium::WebDriver::Error::WebDriverError => e
41
+ @driver = nil
42
+ @pending = true
43
+ @exception = e
44
+ end
45
+ end
46
+
47
+ after(:each) do
48
+ @driver.quit unless @driver.nil?
49
+ end
50
+
51
+ it "should launch chrome when specified" do
52
+ if @driver.nil? and @pending
53
+ pending(@exception)
54
+ else
55
+ @driver.navigate.to "http://www.google.com"
56
+ sleep 5
57
+ ps_chrome = `ps -ef | grep "[c]hrom"`
58
+ ps_chrome['foreground'].should_not == nil
59
+ end
60
+ end
61
+ end
62
+ end
@@ -0,0 +1,5 @@
1
+ require 'bundler/setup'
2
+ require 'rspec'
3
+
4
+ $LOAD_PATH << File.join(File.dirname(File.expand_path(__FILE__)), '..', 'lib')
5
+ require 'webpilot'
metadata ADDED
@@ -0,0 +1,57 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: webpilot
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Sam Rawlins
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2012-03-26 00:00:00.000000000 Z
13
+ dependencies: []
14
+ description: WebPilot is a wrapper for Selenium::WebDriver that makes the library
15
+ more ruby-esque. Rather than inherit from Selenium::WebDriver, an instance of WebPilot
16
+ has a Selenium::WebDriver as an attribute. It serves other functions rather than
17
+ just extending Selenium::WebDriver, so it also wraps a logger, saves screenshots,
18
+ etc.
19
+ email:
20
+ - katt-core@listserv.arizona.edu
21
+ executables: []
22
+ extensions: []
23
+ extra_rdoc_files: []
24
+ files:
25
+ - .gitignore
26
+ - Gemfile
27
+ - Rakefile
28
+ - lib/webpilot.rb
29
+ - spec/basic_spec.rb
30
+ - spec/browsers_spec.rb
31
+ - spec/spec_helper.rb
32
+ homepage:
33
+ licenses: []
34
+ post_install_message:
35
+ rdoc_options: []
36
+ require_paths:
37
+ - lib
38
+ required_ruby_version: !ruby/object:Gem::Requirement
39
+ none: false
40
+ requirements:
41
+ - - ! '>='
42
+ - !ruby/object:Gem::Version
43
+ version: '0'
44
+ required_rubygems_version: !ruby/object:Gem::Requirement
45
+ none: false
46
+ requirements:
47
+ - - ! '>='
48
+ - !ruby/object:Gem::Version
49
+ version: '0'
50
+ requirements: []
51
+ rubyforge_project:
52
+ rubygems_version: 1.8.17
53
+ signing_key:
54
+ specification_version: 3
55
+ summary: A facade for Selenium::WebDriver to make the library more ruby-esque.
56
+ test_files: []
57
+ has_rdoc: