pincers 0.6.0 → 0.7.0

Sign up to get free protection for your applications and to get access to all the features.
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