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.
@@ -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
- @driver = case driver_name.to_sym
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(_force_reset=false)
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 _force_reset or @anonymous # reset bucket if required
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 < StandardError; end
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 { |b| b.unbind(force_reset) }
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 _opt.fetch(:on_exit, :release) == :discard
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 first element.
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
- raise EmptySetError.new if empty?
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
- load_driver
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
- # return the current page title
66
- def title
67
- load_driver.title
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
- load_driver(retries > 0).get(_url)
91
+ driver(retries > 0).get(_url)
78
92
  @stack = [] # clear stack after successfull navigation
79
93
  break
80
- rescue Timeout::Error, Selenium::WebDriver::Error::UnknownError
81
- trace "Error when opening #{_url}!"
82
- raise if retries >= @max_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 unecesary...
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 || [load_driver]
143
+ @stack.last || [driver]
142
144
  end
143
145
 
144
146
  def observe
@@ -1,3 +1,3 @@
1
1
  module SeleniumSurfer
2
- VERSION = "0.0.2"
2
+ VERSION = "0.0.3"
3
3
  end
@@ -11,7 +11,9 @@ module SeleniumSurfer
11
11
  @@config = {
12
12
  :webdriver => nil,
13
13
  :remote_host => 'http://localhost:8080',
14
- :remote_timeout => 120
14
+ :remote_timeout => 120,
15
+ :window_width => 1500,
16
+ :window_height => 1000
15
17
  }
16
18
 
17
19
  # Configure through hash
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.2
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-13 00:00:00.000000000 Z
12
+ date: 2013-08-14 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: selenium-webdriver