pincers 0.6.0 → 0.7.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.
Files changed (37) hide show
  1. checksums.yaml +4 -4
  2. data/lib/pincers/chenso/backend.rb +162 -0
  3. data/lib/pincers/chenso/browsing_context.rb +76 -0
  4. data/lib/pincers/chenso/browsing_manager.rb +67 -0
  5. data/lib/pincers/chenso/factory.rb +27 -0
  6. data/lib/pincers/chenso/html_form_request.rb +7 -0
  7. data/lib/pincers/chenso/html_page_request.rb +27 -0
  8. data/lib/pincers/{backend/base.rb → core/base_backend.rb} +18 -8
  9. data/lib/pincers/{factories/base.rb → core/base_factory.rb} +2 -2
  10. data/lib/pincers/core/helpers/form.rb +106 -0
  11. data/lib/pincers/core/{query.rb → helpers/query.rb} +3 -4
  12. data/lib/pincers/core/replicas/form.rb +43 -0
  13. data/lib/pincers/core/replicas/link.rb +18 -0
  14. data/lib/pincers/core/root_context.rb +25 -6
  15. data/lib/pincers/core/search_context.rb +24 -3
  16. data/lib/pincers/errors.rb +4 -1
  17. data/lib/pincers/extension/labs.rb +3 -0
  18. data/lib/pincers/factory.rb +9 -4
  19. data/lib/pincers/http/base_document.rb +20 -0
  20. data/lib/pincers/http/client.rb +134 -0
  21. data/lib/pincers/{support → http}/cookie.rb +1 -1
  22. data/lib/pincers/{support → http}/cookie_jar.rb +4 -3
  23. data/lib/pincers/http/errors.rb +26 -0
  24. data/lib/pincers/http/request.rb +62 -0
  25. data/lib/pincers/http/response_document.rb +24 -0
  26. data/lib/pincers/http/session.rb +99 -0
  27. data/lib/pincers/http/utils.rb +43 -0
  28. data/lib/pincers/nokogiri/backend.rb +151 -0
  29. data/lib/pincers/{factories/nokogiri.rb → nokogiri/factory.rb} +5 -5
  30. data/lib/pincers/version.rb +1 -1
  31. data/lib/pincers/{backend/webdriver.rb → webdriver/backend.rb} +22 -31
  32. data/lib/pincers/{factories/webdriver.rb → webdriver/factory.rb} +5 -5
  33. data/lib/pincers/webdriver/http_document.rb +23 -0
  34. metadata +42 -13
  35. data/lib/pincers/backend/nokogiri.rb +0 -66
  36. data/lib/pincers/core/download.rb +0 -14
  37. data/lib/pincers/support/http_client.rb +0 -123
@@ -1,3 +1,3 @@
1
1
  module Pincers
2
- VERSION = "0.6.0"
2
+ VERSION = "0.7.0"
3
3
  end
@@ -1,18 +1,19 @@
1
- require "selenium-webdriver"
2
- require "pincers/backend/base"
3
- require "pincers/support/http_client"
4
- require "pincers/core/download"
1
+ require 'selenium-webdriver'
2
+ require 'pincers/core/base_backend'
3
+ require 'pincers/http/client'
4
+ require 'pincers/webdriver/http_document'
5
5
 
6
- module Pincers::Backend
7
-
8
- class Webdriver < Base
6
+ module Pincers::Webdriver
7
+ class Backend < Pincers::Core::BaseBackend
9
8
 
10
9
  DOM_PROPERTIES = [:selected, :disabled, :checked, :value, :required]
11
10
 
12
- alias :driver :document
11
+ attr_reader :driver
12
+
13
+ alias :document :driver
13
14
 
14
15
  def initialize(_driver)
15
- super _driver
16
+ @driver = _driver
16
17
  end
17
18
 
18
19
  def javascript_enabled?
@@ -143,6 +144,11 @@ module Pincers::Backend
143
144
  actions.drag_and_drop(_element, _on).perform
144
145
  end
145
146
 
147
+ def submit_form(_element)
148
+ _element = ensure_element _element
149
+ _element.submit
150
+ end
151
+
146
152
  def switch_to_frame(_element)
147
153
  driver.switch_to.frame _element
148
154
  end
@@ -151,10 +157,13 @@ module Pincers::Backend
151
157
  driver.switch_to.default_content
152
158
  end
153
159
 
154
- def fetch_resource(_url)
155
- url = URI::join(driver.current_url, _url)
156
- response = as_http_client.get url
157
- Pincers::Core::Download.from_http_response response
160
+ def as_http_client
161
+ session = Pincers::Http::Session.new
162
+ session.headers['User-Agent'] = user_agent
163
+ session.proxy = proxy_address
164
+ driver.manage.all_cookies.each { |c| session.cookie_jar.set c }
165
+
166
+ Pincers::Http::Client.new session, HttpDocument.new(self)
158
167
  end
159
168
 
160
169
  private
@@ -200,16 +209,6 @@ module Pincers::Backend
200
209
  _element
201
210
  end
202
211
 
203
- def as_http_client
204
- Pincers::Support::HttpClient.new({
205
- proxy: proxy_address,
206
- cookies: cookie_jar,
207
- headers: {
208
- 'User-Agent' => user_agent
209
- }
210
- })
211
- end
212
-
213
212
  def user_agent
214
213
  driver.execute_script("return navigator.userAgent;")
215
214
  end
@@ -218,13 +217,5 @@ module Pincers::Backend
218
217
  proxy = driver.capabilities.proxy
219
218
  proxy.nil? ? nil : (proxy.http || proxy.ssl)
220
219
  end
221
-
222
- def cookie_jar
223
- jar = Pincers::Support::CookieJar.new
224
- driver.manage.all_cookies.each { |c| jar.set c }
225
- jar
226
- end
227
-
228
220
  end
229
-
230
221
  end
@@ -1,8 +1,8 @@
1
- require 'pincers/factories/base'
2
- require 'pincers/backend/webdriver'
1
+ require 'pincers/core/base_factory'
2
+ require 'pincers/webdriver/backend'
3
3
 
4
- module Pincers::Factories
5
- class Webdriver < Base
4
+ module Pincers::Webdriver
5
+ class Factory < Pincers::Core::BaseFactory
6
6
 
7
7
  DEFAULT_SETUP = {
8
8
  page_timeout: 60000
@@ -17,7 +17,7 @@ module Pincers::Factories
17
17
  setup_driver driver, _options
18
18
  end
19
19
 
20
- ::Pincers::Backend::Webdriver.new driver
20
+ Pincers::Webdriver::Backend.new driver
21
21
  end
22
22
 
23
23
  private
@@ -0,0 +1,23 @@
1
+ require 'pincers/http/utils'
2
+
3
+ module Pincers::Webdriver
4
+ class HttpDocument
5
+
6
+ def initialize(_backend)
7
+ @backend = _backend
8
+ end
9
+
10
+ def uri
11
+ Pincers::Http::Utils.parse_uri @backend.document_url
12
+ end
13
+
14
+ def content_type
15
+ 'text/html'
16
+ end
17
+
18
+ def content
19
+ @backend
20
+ end
21
+
22
+ end
23
+ end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: pincers
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.6.0
4
+ version: 0.7.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Ignacio Baixas
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2015-09-13 00:00:00.000000000 Z
11
+ date: 2015-10-21 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: nokogiri
@@ -206,6 +206,20 @@ dependencies:
206
206
  - - ~>
207
207
  - !ruby/object:Gem::Version
208
208
  version: '1.6'
209
+ - !ruby/object:Gem::Dependency
210
+ name: webmock
211
+ requirement: !ruby/object:Gem::Requirement
212
+ requirements:
213
+ - - ~>
214
+ - !ruby/object:Gem::Version
215
+ version: '1.22'
216
+ type: :development
217
+ prerelease: false
218
+ version_requirements: !ruby/object:Gem::Requirement
219
+ requirements:
220
+ - - ~>
221
+ - !ruby/object:Gem::Version
222
+ version: '1.22'
209
223
  description: Web automation DSL on top of webdriver and nokogiri
210
224
  email:
211
225
  - ignacio@platan.us
@@ -214,12 +228,19 @@ extensions: []
214
228
  extra_rdoc_files: []
215
229
  files:
216
230
  - lib/pincers.rb
217
- - lib/pincers/backend/base.rb
218
- - lib/pincers/backend/nokogiri.rb
219
- - lib/pincers/backend/webdriver.rb
231
+ - lib/pincers/chenso/backend.rb
232
+ - lib/pincers/chenso/browsing_context.rb
233
+ - lib/pincers/chenso/browsing_manager.rb
234
+ - lib/pincers/chenso/factory.rb
235
+ - lib/pincers/chenso/html_form_request.rb
236
+ - lib/pincers/chenso/html_page_request.rb
237
+ - lib/pincers/core/base_backend.rb
238
+ - lib/pincers/core/base_factory.rb
220
239
  - lib/pincers/core/cookies.rb
221
- - lib/pincers/core/download.rb
222
- - lib/pincers/core/query.rb
240
+ - lib/pincers/core/helpers/form.rb
241
+ - lib/pincers/core/helpers/query.rb
242
+ - lib/pincers/core/replicas/form.rb
243
+ - lib/pincers/core/replicas/link.rb
223
244
  - lib/pincers/core/root_context.rb
224
245
  - lib/pincers/core/search_context.rb
225
246
  - lib/pincers/css/parser.rb
@@ -228,16 +249,24 @@ files:
228
249
  - lib/pincers/extension/actions.rb
229
250
  - lib/pincers/extension/labs.rb
230
251
  - lib/pincers/extension/queries.rb
231
- - lib/pincers/factories/base.rb
232
- - lib/pincers/factories/nokogiri.rb
233
- - lib/pincers/factories/webdriver.rb
234
252
  - lib/pincers/factory.rb
253
+ - lib/pincers/http/base_document.rb
254
+ - lib/pincers/http/client.rb
255
+ - lib/pincers/http/cookie.rb
256
+ - lib/pincers/http/cookie_jar.rb
257
+ - lib/pincers/http/errors.rb
258
+ - lib/pincers/http/request.rb
259
+ - lib/pincers/http/response_document.rb
260
+ - lib/pincers/http/session.rb
261
+ - lib/pincers/http/utils.rb
262
+ - lib/pincers/nokogiri/backend.rb
263
+ - lib/pincers/nokogiri/factory.rb
235
264
  - lib/pincers/support/configuration.rb
236
- - lib/pincers/support/cookie.rb
237
- - lib/pincers/support/cookie_jar.rb
238
- - lib/pincers/support/http_client.rb
239
265
  - lib/pincers/support/xpath_builder.rb
240
266
  - lib/pincers/version.rb
267
+ - lib/pincers/webdriver/backend.rb
268
+ - lib/pincers/webdriver/factory.rb
269
+ - lib/pincers/webdriver/http_document.rb
241
270
  homepage: https://github.com/platanus/pincers
242
271
  licenses:
243
272
  - MIT
@@ -1,66 +0,0 @@
1
- require 'pincers/backend/base'
2
-
3
- module Pincers::Backend
4
-
5
- class Nokogiri < Base
6
-
7
- BOOL_PROPERTIES = [:selected, :disabled, :checked, :required]
8
-
9
- def document_root
10
- [document]
11
- end
12
-
13
- def document_title
14
- document.title
15
- end
16
-
17
- def close_document
18
- # no closing needed
19
- end
20
-
21
- def search_by_css(_element, _selector, _limit)
22
- # nokogiri does not do any query level optimization when searching just one node
23
- _element.css _selector
24
- end
25
-
26
- def search_by_xpath(_element, _selector, _limit)
27
- # nokogiri does not do any query level optimization when searching just one node
28
- _element.xpath _selector
29
- end
30
-
31
- def extract_element_tag(_element)
32
- _element.name
33
- end
34
-
35
- def extract_element_text(_element)
36
- _element.content
37
- end
38
-
39
- def extract_element_html(_element)
40
- _element.to_html
41
- end
42
-
43
- def extract_element_attribute(_element, _name)
44
- _name = _name.to_sym
45
- value = _element[_name]
46
-
47
- if BOOL_PROPERTIES.include? _name
48
- value = !value.nil?
49
- elsif _name == :value
50
- value = checkbox_value_fix _element, value
51
- end
52
-
53
- value
54
- end
55
-
56
- private
57
-
58
- def checkbox_value_fix(_element, _value)
59
- if _value.nil? and _element.name.downcase == 'input' and ['checkbox', 'radio'].include? _element[:type].downcase
60
- 'on'
61
- else _value end
62
- end
63
-
64
- end
65
-
66
- end
@@ -1,14 +0,0 @@
1
- module Pincers::Core
2
-
3
- class Download < Struct.new(:mime, :data)
4
-
5
- def self.from_http_response(_response)
6
- self.new _response['Content-Type'] || 'text/plain', _response.body
7
- end
8
-
9
- def store(_path)
10
- File.write _path, data
11
- end
12
-
13
- end
14
- end
@@ -1,123 +0,0 @@
1
- require "uri"
2
- require "pincers/support/cookie_jar"
3
-
4
- module Pincers::Support
5
- class HttpClient
6
-
7
- class HttpRequestError < StandardError
8
- extend Forwardable
9
-
10
- def_delegators :@response, :code, :body
11
-
12
- attr_reader :response
13
-
14
- def initialize(_response)
15
- @response = _response
16
- super _response.message
17
- end
18
- end
19
-
20
- class MaximumRedirectsError < StandardError
21
- def initialize
22
- super 'Redirection loop detected!'
23
- end
24
- end
25
-
26
- attr_reader :proxy_addr, :proxy_port, :cookies
27
-
28
- def initialize(_options={})
29
- if _options[:proxy]
30
- @proxy_addr, @proxy_port = _options[:proxy].split ':'
31
- end
32
-
33
- @cookies = if _options[:cookies]
34
- _options[:cookies].copy
35
- else
36
- CookieJar.new
37
- end
38
-
39
- @default_headers = _options[:headers]
40
- end
41
-
42
- def get(_url, _query={}, _headers={})
43
- # TODO: append query string?
44
- perform_request Net::HTTP::Get, URI(_url), _headers
45
- end
46
-
47
- def post(_url, _data, _headers={})
48
- perform_request Net::HTTP::Post, URI(_url), _headers do |req|
49
- req.body = prepare_data(_data)
50
- end
51
- end
52
-
53
- def put(_url, _data, _headers={})
54
- perform_request Net::HTTP::Put, URI(_url), _headers do |req|
55
- req.body = prepare_data(_data)
56
- end
57
- end
58
-
59
- def delete(_url)
60
- perform_request Net::HTTP::Delete, URI(_url), _headers
61
- end
62
-
63
- private
64
-
65
- def perform_request(_req_type, _uri, _headers, _limit=10)
66
-
67
- raise MaximumRedirectsError.new if _limit == 0
68
-
69
- request = _req_type.new(_uri.request_uri.empty? ? '/' : _uri.request_uri)
70
- build_headers(request, _headers)
71
- set_cookies(request, _uri)
72
- yield request if block_given?
73
-
74
- response = build_client(_uri).request request
75
-
76
- case response
77
- when Net::HTTPSuccess then
78
- update_cookies(_uri, response)
79
- response
80
- when Net::HTTPRedirection then
81
- location = response['location']
82
- perform_request(_req_type, URI.parse(location), _headers, _limit - 1)
83
- else
84
- handle_error_response response
85
- end
86
- end
87
-
88
- def build_client(uri)
89
- client = Net::HTTP.new uri.host, uri.port || 80, proxy_addr, proxy_port
90
- client.use_ssl = true if uri.scheme == 'https'
91
- client.verify_mode = OpenSSL::SSL::VERIFY_NONE
92
- client
93
- end
94
-
95
- def handle_error_response(_response)
96
- raise HttpRequestError.new _response
97
- end
98
-
99
- def prepare_data(_data)
100
- if _data.is_a? Hash
101
- _data.keys.map { |k| "#{k}=#{_data[k]}" }.join '&'
102
- else _data end
103
- end
104
-
105
- def build_headers(_request, _headers)
106
- copy_headers _request, @default_headers if @default_headers
107
- copy_headers _request, _headers
108
- end
109
-
110
- def set_cookies(_request, _uri)
111
- _request['Cookie'] = @cookies.for_origin_as_header _uri
112
- end
113
-
114
- def update_cookies(_uri, _response)
115
- cookies = _response.get_fields('set-cookie')
116
- cookies.each { |raw| @cookies.set_raw _uri, raw } if cookies
117
- end
118
-
119
- def copy_headers(_request, _headers)
120
- _headers.keys.each { |k| _request[k] = _headers[k] }
121
- end
122
- end
123
- end