crabfarm 0.2.5 → 0.3.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (54) hide show
  1. checksums.yaml +4 -4
  2. data/lib/crabfarm.rb +17 -18
  3. data/lib/crabfarm/adapters/browser/abstract_webdriver.rb +60 -0
  4. data/lib/crabfarm/adapters/browser/chrome.rb +24 -0
  5. data/lib/crabfarm/adapters/browser/firefox.rb +26 -0
  6. data/lib/crabfarm/adapters/browser/noop.rb +25 -0
  7. data/lib/crabfarm/adapters/browser/phantom_js.rb +59 -0
  8. data/lib/crabfarm/adapters/browser/remote_webdriver.rb +31 -0
  9. data/lib/crabfarm/adapters/driver_wrapper/capybara.rb +11 -0
  10. data/lib/crabfarm/adapters/driver_wrapper/surfer.rb +13 -0
  11. data/lib/crabfarm/adapters/{browser → driver_wrapper}/watir.rb +7 -3
  12. data/lib/crabfarm/adapters/parser/nokogiri.rb +17 -15
  13. data/lib/crabfarm/adapters/parser/pdf_reader.rb +14 -12
  14. data/lib/crabfarm/assertion/fields.rb +85 -0
  15. data/lib/crabfarm/base_navigator.rb +78 -0
  16. data/lib/crabfarm/base_reducer.rb +68 -0
  17. data/lib/crabfarm/base_struct.rb +17 -0
  18. data/lib/crabfarm/cli.rb +18 -8
  19. data/lib/crabfarm/configuration.rb +24 -51
  20. data/lib/crabfarm/context.rb +19 -43
  21. data/lib/crabfarm/crabtrap_context.rb +4 -11
  22. data/lib/crabfarm/driver_pool.rb +32 -0
  23. data/lib/crabfarm/dsl/surfer/surf_context.rb +5 -25
  24. data/lib/crabfarm/engines/async_state_manager.rb +1 -1
  25. data/lib/crabfarm/engines/sync_state_manager.rb +1 -1
  26. data/lib/crabfarm/forked_navigator.rb +31 -0
  27. data/lib/crabfarm/modes/console.rb +4 -4
  28. data/lib/crabfarm/modes/generator.rb +24 -11
  29. data/lib/crabfarm/rspec.rb +26 -24
  30. data/lib/crabfarm/strategies.rb +15 -9
  31. data/lib/crabfarm/templates/Crabfile.erb +21 -26
  32. data/lib/crabfarm/templates/Gemfile.erb +6 -0
  33. data/lib/crabfarm/templates/navigator.rb.erb +20 -0
  34. data/lib/crabfarm/templates/{state_spec.rb.erb → navigator_spec.rb.erb} +1 -1
  35. data/lib/crabfarm/templates/{parser.rb.erb → reducer.rb.erb} +4 -4
  36. data/lib/crabfarm/templates/{parser_spec.rb.erb → reducer_spec.rb.erb} +1 -1
  37. data/lib/crabfarm/templates/struct.rb.erb +12 -0
  38. data/lib/crabfarm/transition_service.rb +20 -7
  39. data/lib/crabfarm/version.rb +1 -1
  40. metadata +50 -48
  41. data/lib/crabfarm/adapters/browser/capybara.rb +0 -7
  42. data/lib/crabfarm/adapters/browser/surfer.rb +0 -9
  43. data/lib/crabfarm/adapters/output/hash.rb +0 -11
  44. data/lib/crabfarm/adapters/output/jbuilder.rb +0 -11
  45. data/lib/crabfarm/adapters/output/ostruct.rb +0 -14
  46. data/lib/crabfarm/base_parser.rb +0 -59
  47. data/lib/crabfarm/base_state.rb +0 -112
  48. data/lib/crabfarm/default_driver_factory.rb +0 -86
  49. data/lib/crabfarm/driver_bucket.rb +0 -42
  50. data/lib/crabfarm/driver_bucket_pool.rb +0 -26
  51. data/lib/crabfarm/forked_state.rb +0 -38
  52. data/lib/crabfarm/mocks/noop_driver.rb +0 -6
  53. data/lib/crabfarm/phantom_driver_factory.rb +0 -33
  54. data/lib/crabfarm/templates/state.rb.erb +0 -8
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: ccec565757953537736ab94a2f8a45f9abb12847
4
- data.tar.gz: 927c3fd72e63af76517b0d3e53e43a91261028d9
3
+ metadata.gz: e0b57880b14cf2f7456a2d457e9c3b9531c9ac2b
4
+ data.tar.gz: 61200983d1469d597384640d3d3457547ab486fa
5
5
  SHA512:
6
- metadata.gz: 933c56e98e7f9703756d25a379b45011292f310606886bd1d40b138e36f60a36877efb45cb730bee5208bcd364802d06ce40dcf4ac2064544124e7ac3bf59f07
7
- data.tar.gz: 2f80e480debeb2f8f39a8e44493579205269fb1f198b175b02db597c5bd531d2dfb7342214f49e2ac95eb299d05b39d9446f1bef242318bbc15367f8476f53d0
6
+ metadata.gz: 65659324efa94632a56a2da599f760ec0f79199f307efaf9399580d23344456f076987baba5631c1be7ac37ac063da41b46fd8aaf762c49911eae1439ba74d84
7
+ data.tar.gz: db9ee502e2db56b89ad0ec80dea565537cb20577b6660f27f1c3e3fbd8392da8a8ff1608b7e1c5011b7e30ddd922b2d6367bcff5630ab90fe67bc4aa7a27b766
data/lib/crabfarm.rb CHANGED
@@ -2,24 +2,21 @@ require "logger"
2
2
  require "forwardable"
3
3
  require "net/http"
4
4
  require "active_support/inflector"
5
- require "selenium-webdriver"
6
5
 
7
6
  require "crabfarm/version"
8
7
  require "crabfarm/errors"
9
8
  require "crabfarm/configuration"
10
9
  require "crabfarm/global_state"
11
- require "crabfarm/driver_bucket"
12
- require "crabfarm/driver_bucket_pool"
10
+ require "crabfarm/driver_pool"
13
11
  require "crabfarm/http_client"
14
- require "crabfarm/default_driver_factory"
15
- require "crabfarm/phantom_driver_factory"
16
12
  require "crabfarm/phantom_runner"
17
13
  require "crabfarm/state_store"
18
14
  require "crabfarm/context"
19
15
  require "crabfarm/context_factory"
20
16
  require "crabfarm/transition_service"
21
- require "crabfarm/base_state"
22
- require "crabfarm/base_parser"
17
+ require "crabfarm/base_navigator"
18
+ require "crabfarm/base_reducer"
19
+ require "crabfarm/base_struct"
23
20
  require "crabfarm/strategies"
24
21
 
25
22
  require "crabfarm/utils/port_discovery"
@@ -47,18 +44,20 @@ module Crabfarm
47
44
  end
48
45
 
49
46
  module Strategies
50
- # bundled browser dsl adapters
51
- register :browser_dsl, :surfer, 'Crabfarm::SurferBrowserDsl', 'crabfarm/adapters/browser/surfer'
52
- register :browser_dsl, :watir, 'Crabfarm::WatirBrowserDsl', 'crabfarm/adapters/browser/watir', ['watir-webdriver']
53
- register :browser_dsl, :capybara, 'Crabfarm::CapybaraBrowserDsl', 'crabfarm/adapters/browser/capybara', ['capybara']
47
+ # bundled browser adapters
48
+ register :browser, :phantomjs, 'Crabfarm::Adapters::Browser::PhantomJs', dependencies: ['selenium-webdriver']
49
+ register :browser, :firefox, 'Crabfarm::Adapters::Browser::Firefox', dependencies: ['selenium-webdriver']
50
+ register :browser, :chrome, 'Crabfarm::Adapters::Browser::Chrome', dependencies: ['selenium-webdriver']
51
+ register :browser, :remote, 'Crabfarm::Adapters::Browser::RemoteWebdriver', dependencies: ['selenium-webdriver']
52
+ register :browser, :noop, 'Crabfarm::Adapters::Browser::Noop'
53
+
54
+ # bundled webdriver dsl adapters
55
+ register :webdriver_dsl, :surfer, 'Crabfarm::Adapters::DriverWrapper::Surfer'
56
+ register :webdriver_dsl, :watir, 'Crabfarm::Adapters::DriverWrapper::Watir', dependencies: ['watir-webdriver']
57
+ register :webdriver_dsl, :capybara, 'Crabfarm::Adapters::DriverWrapper::Capybara', dependencies: ['capybara']
54
58
 
55
59
  # bundled parsers dsl adapters
56
- register :parser_engine, :nokogiri, 'Crabfarm::NokogiriAdapter', 'crabfarm/adapters/parser/nokogiri'
57
- register :parser_engine, :pdf_reader, 'Crabfarm::PdfReaderAdapter', 'crabfarm/adapters/parser/pdf_reader', ['pdf-reader']
58
-
59
- # bundled state output builders
60
- register :output_builder, :hash, 'Crabfarm::HashOutputBuilder', 'crabfarm/adapters/output/hash'
61
- register :output_builder, :ostruct, 'Crabfarm::OStructOutputBuilder', 'crabfarm/adapters/output/ostruct'
62
- register :output_builder, :jbuilder, 'Crabfarm::JbuilderOutputBuilder', 'crabfarm/adapters/output/jbuilder', ['jbuilder']
60
+ register :parser, :nokogiri, 'Crabfarm::Adapters::Parser::Nokogiri', dependencies: ['nokogiri']
61
+ register :parser, :pdf_reader, 'Crabfarm::Adapters::Parser::PdfReader', dependencies: ['pdf-reader']
63
62
  end
64
63
  end
@@ -0,0 +1,60 @@
1
+ module Crabfarm
2
+ module Adapters
3
+ module Browser
4
+ class AbstractWebdriver
5
+
6
+ attr_accessor :config
7
+
8
+ def initialize(_proxy=nil)
9
+ @config = load_driver_config
10
+ @config[:proxy] = _proxy
11
+ end
12
+
13
+ def prepare_driver_services
14
+ # Nothing by default
15
+ end
16
+
17
+ def cleanup_driver_services
18
+ # Nothing by default
19
+ end
20
+
21
+ def build_driver(_session_id)
22
+
23
+ # load driver and configure general selenium settings
24
+ driver = build_webdriver_instance
25
+ driver.manage.window.resize_to(config[:window_width], config[:window_height]) rescue nil
26
+
27
+ return wrap_driver driver
28
+ end
29
+
30
+ def release_driver(_driver)
31
+ @driver.quit rescue nil
32
+ end
33
+
34
+ private
35
+
36
+ def wrap_driver _driver
37
+ if config[:dsl].present?
38
+ Strategies.load(:webdriver_dsl, config[:dsl]).wrap _driver
39
+ else _driver end
40
+ end
41
+
42
+ def build_webdriver_instance
43
+ raise NotImplementedError.new
44
+ end
45
+
46
+ def load_driver_config
47
+ {
48
+ capabilities: Crabfarm.config.webdriver_capabilities,
49
+ remote_host: Crabfarm.config.webdriver_remote_host,
50
+ remote_timeout: Crabfarm.config.webdriver_remote_timeout,
51
+ window_width: Crabfarm.config.webdriver_window_width,
52
+ window_height: Crabfarm.config.webdriver_window_height,
53
+ dsl: Crabfarm.config.webdriver_dsl
54
+ }
55
+ end
56
+
57
+ end
58
+ end
59
+ end
60
+ end
@@ -0,0 +1,24 @@
1
+ require "crabfarm/adapters/browser/abstract_webdriver"
2
+
3
+ module Crabfarm
4
+ module Adapters
5
+ module Browser
6
+ class Chrome < AbstractWebdriver
7
+
8
+ private
9
+
10
+ def build_webdriver_instance
11
+ switches = []
12
+
13
+ if config[:proxy].present?
14
+ switches << "--proxy-server=#{config[:proxy]}"
15
+ switches << "--ignore-certificate-errors"
16
+ end
17
+
18
+ Selenium::WebDriver.for :chrome, :switches => switches
19
+ end
20
+
21
+ end
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,26 @@
1
+ require "crabfarm/adapters/browser/abstract_webdriver"
2
+
3
+ module Crabfarm
4
+ module Adapters
5
+ module Browser
6
+ class Firefox < AbstractWebdriver
7
+
8
+ private
9
+
10
+ def build_webdriver_instance
11
+ profile = Selenium::WebDriver::Firefox::Profile.new
12
+
13
+ if config.key? :proxy
14
+ profile.proxy = Selenium::WebDriver::Proxy.new({
15
+ :http => config[:proxy],
16
+ :ssl => config[:proxy]
17
+ })
18
+ end
19
+
20
+ Selenium::WebDriver.for :firefox, :profile => profile
21
+ end
22
+
23
+ end
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,25 @@
1
+ module Crabfarm
2
+ module Adapters
3
+ module Browser
4
+ class Noop
5
+
6
+ def initialize(_proxy=nil)
7
+ end
8
+
9
+ def prepare_driver_services
10
+ end
11
+
12
+ def cleanup_driver_services
13
+ end
14
+
15
+ def build_driver(_session_id)
16
+ _session_id || :noop
17
+ end
18
+
19
+ def release_driver(_driver)
20
+ end
21
+
22
+ end
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,59 @@
1
+ require "crabfarm/adapters/browser/abstract_webdriver"
2
+ require "crabfarm/phantom_runner"
3
+
4
+ module Crabfarm
5
+ module Adapters
6
+ module Browser
7
+ class PhantomJs < AbstractWebdriver
8
+
9
+ def prepare_driver_services
10
+ @phantom = load_and_start_phantom if @phantom.nil?
11
+ end
12
+
13
+ def cleanup_driver_services
14
+ @phantom.stop unless @phantom.nil?
15
+ @phantom = nil
16
+ end
17
+
18
+ private
19
+
20
+ def build_webdriver_instance
21
+ client = Selenium::WebDriver::Remote::Http::Default.new
22
+ client.timeout = config[:remote_timeout]
23
+
24
+ driver = Selenium::WebDriver.for :remote, {
25
+ :url => phantom_url,
26
+ :http_client => client,
27
+ :desired_capabilities => config[:capabilities] || Selenium::WebDriver::Remote::Capabilities.firefox
28
+ }
29
+
30
+ # TODO: not sure if this is necessary...
31
+ # driver.send(:bridge).setWindowSize(config[:window_width], config[:window_height])
32
+
33
+ return driver
34
+ end
35
+
36
+ def load_and_start_phantom
37
+ new_phantom = PhantomRunner.new phantom_config
38
+ new_phantom.start
39
+ return new_phantom
40
+ end
41
+
42
+ def phantom_config
43
+ {
44
+ load_images: Crabfarm.config.phantom_load_images,
45
+ ssl: Crabfarm.config.phantom_ssl,
46
+ bin_path: Crabfarm.config.phantom_bin_path,
47
+ proxy: config[:proxy],
48
+ port: Utils::PortDiscovery.find_available_port
49
+ }
50
+ end
51
+
52
+ def phantom_url
53
+ "http://localhost:#{@phantom.port}"
54
+ end
55
+
56
+ end
57
+ end
58
+ end
59
+ end
@@ -0,0 +1,31 @@
1
+ require "crabfarm/adapters/browser/abstract_webdriver"
2
+
3
+ module Crabfarm
4
+ module Adapters
5
+ module Browser
6
+ class RemoteWebdriver < AbstractWebdriver
7
+
8
+ private
9
+
10
+ def build_webdriver_instance
11
+ client = Selenium::WebDriver::Remote::Http::Default.new
12
+ client.timeout = config[:remote_timeout]
13
+
14
+ if config.has_key? :proxy
15
+ client.proxy = Selenium::WebDriver::Proxy.new({
16
+ :http => config[:proxy],
17
+ :ssl => config[:proxy]
18
+ })
19
+ end
20
+
21
+ Selenium::WebDriver.for(:remote, {
22
+ :url => config[:remote_host],
23
+ :http_client => client,
24
+ :desired_capabilities => config[:capabilities] || Selenium::WebDriver::Remote::Capabilities.firefox
25
+ })
26
+ end
27
+
28
+ end
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,11 @@
1
+ module Crabfarm
2
+ module Adapters
3
+ module DriverWrapper
4
+ class Capybara
5
+ def self.wrap(_driver)
6
+ raise NotImplementedError.new "Capybara adapter is not available yet"
7
+ end
8
+ end
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,13 @@
1
+ require 'crabfarm/dsl/surfer'
2
+
3
+ module Crabfarm
4
+ module Adapters
5
+ module DriverWrapper
6
+ class Surfer
7
+ def self.wrap(_driver)
8
+ Crabfarm::Dsl::Surfer::SurfContext.new _driver
9
+ end
10
+ end
11
+ end
12
+ end
13
+ end
@@ -17,9 +17,13 @@ class Watir::ElementCollection
17
17
  end
18
18
 
19
19
  module Crabfarm
20
- class WatirBrowserDsl
21
- def self.wrap(_bucket)
22
- Watir::Browser.new _bucket.original
20
+ module Adapters
21
+ module DriverWrapper
22
+ class Watir
23
+ def self.wrap(_driver)
24
+ ::Watir::Browser.new _driver
25
+ end
26
+ end
23
27
  end
24
28
  end
25
29
  end
@@ -1,21 +1,23 @@
1
- require 'nokogiri'
2
-
3
1
  module Crabfarm
4
- class NokogiriAdapter
5
- def self.format
6
- 'html'
7
- end
2
+ module Adapters
3
+ module Parser
4
+ class Nokogiri
5
+ def self.format
6
+ 'html'
7
+ end
8
8
 
9
- def self.parse(_raw)
10
- Nokogiri::HTML _raw
11
- end
9
+ def self.parse(_raw)
10
+ ::Nokogiri::HTML _raw
11
+ end
12
12
 
13
- def self.preprocess_parsing_target(_target)
14
- if _target.respond_to? :to_html
15
- _target.to_html
16
- else
17
- _target
13
+ def self.preprocess_parsing_target(_target)
14
+ if _target.respond_to? :to_html
15
+ _target.to_html
16
+ else
17
+ _target
18
+ end
19
+ end
18
20
  end
19
21
  end
20
22
  end
21
- end
23
+ end
@@ -1,17 +1,19 @@
1
- require "pdf-reader"
2
-
3
1
  module Crabfarm
4
- class PdfReaderAdapter
5
- def self.format
6
- 'pdf'
7
- end
2
+ module Adapters
3
+ module Parser
4
+ class PdfReader
5
+ def self.format
6
+ 'pdf'
7
+ end
8
8
 
9
- def self.parse(_raw)
10
- PDF::Reader.new StringIO.new _raw
11
- end
9
+ def self.parse(_raw)
10
+ PDF::Reader.new StringIO.new _raw
11
+ end
12
12
 
13
- def self.preprocess_parsing_target(_target)
14
- _target
13
+ def self.preprocess_parsing_target(_target)
14
+ _target
15
+ end
16
+ end
15
17
  end
16
18
  end
17
- end
19
+ end
@@ -0,0 +1,85 @@
1
+ require "active_support/core_ext/object/duplicable"
2
+ require 'crabfarm/assertion/context'
3
+
4
+ module Crabfarm
5
+ module Assertion
6
+ module Fields
7
+ include Context
8
+
9
+ module ClassMethods
10
+
11
+ def has_field(_name, _options={})
12
+ name = _name.to_sym
13
+
14
+ fields << name
15
+ field_defaults[name] = _options.delete :field_default
16
+
17
+ assertion = _options.delete :field_assertion
18
+ if assertion
19
+ define_method("#{name}=") { |v| field_hash[name] = assert(v).send(assertion, _options) }
20
+ elsif not _options[:field_readonly]
21
+ define_method("#{name}=") { |v| field_hash[name] = v }
22
+ end
23
+
24
+ define_method(name) { field_hash[name] }
25
+ end
26
+
27
+ def has_asserted_field(_name, _assertion, _options={})
28
+ has_field(_name, _options.merge(field_assertion: _assertion))
29
+ end
30
+
31
+ def has_array(_name)
32
+ has_field(_name, field_default: [], field_readonly: true)
33
+ end
34
+
35
+ def has_integer(_name, _options={})
36
+ has_asserted_field _name, :is_integer, _options
37
+ end
38
+
39
+ def has_float(_name, _options={})
40
+ has_asserted_field _name, :is_float, _options
41
+ end
42
+
43
+ def has_string(_name, _options={})
44
+ has_asserted_field _name, :is_string, _options
45
+ end
46
+
47
+ def has_word(_name, _options={})
48
+ has_asserted_field _name, :is_word, _options
49
+ end
50
+
51
+ def has_boolean(_name, _options={})
52
+ has_asserted_field _name, :is_boolean, _options
53
+ end
54
+
55
+ def fields
56
+ @fields ||= []
57
+ end
58
+
59
+ def field_defaults
60
+ @field_defaults ||= {}
61
+ end
62
+
63
+ end
64
+
65
+ def self.included(klass)
66
+ klass.extend ClassMethods
67
+ end
68
+
69
+ def reset_fields
70
+ klass = self.class
71
+
72
+ @field_hash = {}
73
+ klass.fields.each do |field|
74
+ value = klass.field_defaults[field]
75
+ @field_hash[field] = value.duplicable? ? value.clone : value
76
+ end
77
+ end
78
+
79
+ def field_hash
80
+ @field_hash
81
+ end
82
+
83
+ end
84
+ end
85
+ end