selenium_surfer 0.0.2 → 0.0.3
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.
- 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
|