webpilot 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -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: