selenium_surfer 0.0.2 → 0.0.3
Sign up to get free protection for your applications and to get access to all the features.
- data/lib/selenium_surfer/driver_bucket.rb +6 -3
- data/lib/selenium_surfer/errors.rb +13 -1
- data/lib/selenium_surfer/robot.rb +6 -2
- data/lib/selenium_surfer/search_context.rb +22 -7
- data/lib/selenium_surfer/surf_context.rb +27 -25
- data/lib/selenium_surfer/version.rb +1 -1
- data/lib/selenium_surfer.rb +3 -1
- metadata +2 -2
@@ -25,7 +25,7 @@ module SeleniumSurfer
|
|
25
25
|
driver_name = SeleniumSurfer.config[:webdriver]
|
26
26
|
raise ConfigurationError.new 'must provide a webdriver type' if driver_name.nil?
|
27
27
|
|
28
|
-
|
28
|
+
case driver_name.to_sym
|
29
29
|
when :remote
|
30
30
|
url = SeleniumSurfer.config[:remote_host]
|
31
31
|
|
@@ -36,6 +36,9 @@ module SeleniumSurfer
|
|
36
36
|
@driver = Selenium::WebDriver.for :remote, :url => url, :http_client => client
|
37
37
|
else
|
38
38
|
@driver = Selenium::WebDriver.for driver_name.to_sym
|
39
|
+
|
40
|
+
# apply browser configuration to new driver
|
41
|
+
@driver.manage.window.resize_to(SeleniumSurfer.config[:window_width], SeleniumSurfer.config[:window_height]) rescue nil
|
39
42
|
end
|
40
43
|
end
|
41
44
|
|
@@ -66,12 +69,12 @@ module SeleniumSurfer
|
|
66
69
|
end
|
67
70
|
|
68
71
|
# unbinds the currently bound context.
|
69
|
-
def unbind
|
72
|
+
def unbind
|
70
73
|
if @bound_ctx
|
71
74
|
@bound_ctx.on_unbind if @bound_ctx.respond_to? :on_unbind
|
72
75
|
@bound_ctx = nil
|
73
76
|
end
|
74
|
-
reset if
|
77
|
+
reset if @anonymous # reset bucket if required
|
75
78
|
end
|
76
79
|
end
|
77
80
|
|
@@ -9,7 +9,19 @@ module SeleniumSurfer
|
|
9
9
|
# Error thrown when a programming setup error is found
|
10
10
|
class SetupError < StandardError; end
|
11
11
|
|
12
|
+
# Base class for context errors
|
13
|
+
class ContextError < StandardError
|
14
|
+
|
15
|
+
attr_reader :context, :source
|
16
|
+
|
17
|
+
def initialize(_msg, _context)
|
18
|
+
super _msg
|
19
|
+
@context = _context
|
20
|
+
@source = _context.root_context.page_source # cache page source for future reference
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
12
24
|
# Error thrown when an element operation is attempted in an empty search result set
|
13
|
-
class EmptySetError <
|
25
|
+
class EmptySetError < ContextError; end
|
14
26
|
|
15
27
|
end
|
@@ -48,7 +48,10 @@ module SeleniumSurfer
|
|
48
48
|
raise
|
49
49
|
ensure
|
50
50
|
force_reset = session_error or !keep_sessions
|
51
|
-
@@loaded_buckets.each
|
51
|
+
@@loaded_buckets.each do |bucket|
|
52
|
+
bucket.unbind
|
53
|
+
bucket.reset if force_reset
|
54
|
+
end
|
52
55
|
@@loaded_buckets = nil
|
53
56
|
@all_buckets = temp unless keep_sessions
|
54
57
|
end
|
@@ -86,7 +89,8 @@ module SeleniumSurfer
|
|
86
89
|
begin
|
87
90
|
return _block.call ctx
|
88
91
|
ensure
|
89
|
-
bucket.unbind
|
92
|
+
bucket.unbind
|
93
|
+
bucket.reset if _opt.fetch(:on_exit, :release) == :discard
|
90
94
|
end
|
91
95
|
end
|
92
96
|
|
@@ -10,39 +10,54 @@ module SeleniumSurfer
|
|
10
10
|
include Enumerable
|
11
11
|
extend Forwardable
|
12
12
|
|
13
|
-
def initialize(_elements)
|
13
|
+
def initialize(_elements, _parent)
|
14
14
|
@elements = _elements
|
15
|
+
@parent = _parent
|
16
|
+
end
|
17
|
+
|
18
|
+
# return the context's root context
|
19
|
+
def root_context
|
20
|
+
return @parent.root_context if @parent
|
21
|
+
self
|
22
|
+
end
|
23
|
+
|
24
|
+
# return the context's parent context
|
25
|
+
def parent_context
|
26
|
+
@parent
|
15
27
|
end
|
16
28
|
|
17
29
|
# forward read-only array methods to context
|
18
30
|
def_delegators :context, :each, :[], :length, :count, :empty?, :first, :last
|
19
31
|
|
32
|
+
# yield individual SearchContext for each element contained in this result
|
20
33
|
def explode(&_block)
|
21
34
|
return enum_for(__method__) if _block.nil?
|
22
35
|
context.each do |el|
|
23
|
-
_block.call SearchContext.new([el])
|
36
|
+
_block.call SearchContext.new([el], self)
|
24
37
|
end
|
25
38
|
end
|
26
39
|
|
40
|
+
# searches for elements that match a given selector
|
27
41
|
def search(_selector=nil, _options={})
|
28
42
|
_options[:css] = _selector if _selector
|
29
|
-
SearchContext.new search_elements(_options)
|
43
|
+
SearchContext.new search_elements(_options), self
|
30
44
|
end
|
31
45
|
|
46
|
+
# clears and sends_keys to this context main element
|
32
47
|
def fill(_value)
|
33
|
-
raise EmptySetError.new if empty?
|
48
|
+
raise EmptySetError.new('Cannot call \'fill\' on an empty set', self) if empty?
|
34
49
|
context.first.clear
|
35
50
|
context.first.send_keys _value
|
36
51
|
end
|
37
52
|
|
38
|
-
# Any methods missing are forwarded to the
|
53
|
+
# Any methods missing are forwarded to the main element (first).
|
39
54
|
def method_missing(_method, *_args, &_block)
|
40
55
|
m = /^(.*)_all$/.match _method.to_s
|
41
56
|
if m then
|
42
57
|
return [] if empty?
|
43
58
|
context.map { |e| e.send(m[1], *_args, &_block) }
|
44
59
|
else
|
45
|
-
raise EmptySetError.new if empty?
|
60
|
+
raise EmptySetError.new("Cannot call '#{_method}' on an empty set", self) if empty?
|
46
61
|
context.first.send(_method, *_args, &_block)
|
47
62
|
end
|
48
63
|
end
|
@@ -54,7 +69,7 @@ module SeleniumSurfer
|
|
54
69
|
return true if empty?
|
55
70
|
context.first.respond_to? m[1], _include_all
|
56
71
|
else
|
57
|
-
|
72
|
+
return true if empty?
|
58
73
|
context.first.respond_to? _method, _include_all
|
59
74
|
end
|
60
75
|
end
|
@@ -3,6 +3,7 @@ module SeleniumSurfer
|
|
3
3
|
# ### Base class for robot contexts
|
4
4
|
#
|
5
5
|
class SurfContext < SearchContext
|
6
|
+
extend Forwardable
|
6
7
|
|
7
8
|
# add a macro attribute writer to context.
|
8
9
|
#
|
@@ -36,8 +37,10 @@ module SeleniumSurfer
|
|
36
37
|
macro_attr_accessor :max_retries
|
37
38
|
|
38
39
|
def initialize(_bucket, _macro=nil, _stack=nil)
|
40
|
+
super nil, nil
|
41
|
+
|
39
42
|
@bucket = _bucket
|
40
|
-
@macro = _macro || {}
|
43
|
+
@macro = _macro || { max_retries: 5 }
|
41
44
|
@stack = _stack || []
|
42
45
|
|
43
46
|
@bucket.bind self
|
@@ -58,13 +61,24 @@ module SeleniumSurfer
|
|
58
61
|
# ## Helpers
|
59
62
|
|
60
63
|
# retrieves the current driver being used by this context
|
61
|
-
def driver
|
62
|
-
|
64
|
+
def driver(_reset=false)
|
65
|
+
raise UnboundContextError.new if not bound?
|
66
|
+
@bucket.reset if _reset
|
67
|
+
@bucket.driver
|
63
68
|
end
|
64
69
|
|
65
|
-
#
|
66
|
-
|
67
|
-
|
70
|
+
# delegate some stuff to driver
|
71
|
+
def_delegators 'driver', :title, :current_url, :page_source
|
72
|
+
def_delegators 'driver.navigate', :back, :forward, :refresh
|
73
|
+
|
74
|
+
# return the current page url as an URI
|
75
|
+
def current_uri
|
76
|
+
URI.parse driver.current_url
|
77
|
+
end
|
78
|
+
|
79
|
+
# return the current page cookies as a hash
|
80
|
+
def cookies
|
81
|
+
driver.manage.all_cookies
|
68
82
|
end
|
69
83
|
|
70
84
|
# navigate to a given url (uses the max_retries setting)
|
@@ -74,12 +88,12 @@ module SeleniumSurfer
|
|
74
88
|
|
75
89
|
loop do
|
76
90
|
begin
|
77
|
-
|
91
|
+
driver(retries > 0).get(_url)
|
78
92
|
@stack = [] # clear stack after successfull navigation
|
79
93
|
break
|
80
|
-
rescue Timeout::Error
|
81
|
-
|
82
|
-
raise if retries >=
|
94
|
+
rescue Timeout::Error #, Selenium::WebDriver::Error::UnknownError
|
95
|
+
# TODO: log this
|
96
|
+
raise if retries >= max_retries
|
83
97
|
retries += 1
|
84
98
|
sleep 1.0
|
85
99
|
end
|
@@ -87,7 +101,7 @@ module SeleniumSurfer
|
|
87
101
|
end
|
88
102
|
|
89
103
|
# changes the context
|
90
|
-
# TODO: this method may be
|
104
|
+
# TODO: this method may be unnecesary...
|
91
105
|
def step(_selector=nil, _options={})
|
92
106
|
_options[:css] = _selector if _selector
|
93
107
|
new_context = search_elements(_options)
|
@@ -110,15 +124,9 @@ module SeleniumSurfer
|
|
110
124
|
|
111
125
|
# release and discard the current driver connection.
|
112
126
|
def quit
|
113
|
-
return false if not bound?
|
114
|
-
@bucket.unbind true
|
115
|
-
return true
|
116
|
-
end
|
117
|
-
|
118
|
-
# resets the current driver connection, does not release it.
|
119
|
-
def reset
|
120
127
|
return false if not bound?
|
121
128
|
@bucket.reset
|
129
|
+
@bucket.unbind
|
122
130
|
return true
|
123
131
|
end
|
124
132
|
|
@@ -130,15 +138,9 @@ module SeleniumSurfer
|
|
130
138
|
|
131
139
|
private
|
132
140
|
|
133
|
-
def load_driver(_reset=false)
|
134
|
-
raise UnboundContextError.new if not bound?
|
135
|
-
@bucket.reset if _reset
|
136
|
-
@bucket.driver
|
137
|
-
end
|
138
|
-
|
139
141
|
def context
|
140
142
|
raise UnboundContextError.new if not bound?
|
141
|
-
@stack.last || [
|
143
|
+
@stack.last || [driver]
|
142
144
|
end
|
143
145
|
|
144
146
|
def observe
|
data/lib/selenium_surfer.rb
CHANGED
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: selenium_surfer
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.3
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2013-08-
|
12
|
+
date: 2013-08-14 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: selenium-webdriver
|