crabfarm 0.4.2 → 0.5.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/assets/live-tools/instructions.html +17 -0
- data/assets/live-tools/tools.css +16 -0
- data/assets/live-tools/tools.js +41 -47
- data/assets/live-tools/welcome.html +18 -0
- data/lib/crabfarm/adapters/browser/abstract_webdriver.rb +19 -16
- data/lib/crabfarm/adapters/browser/phantom_js.rb +11 -11
- data/lib/crabfarm/assertion/fields.rb +8 -0
- data/lib/crabfarm/base_navigator.rb +4 -11
- data/lib/crabfarm/base_reducer.rb +5 -1
- data/lib/crabfarm/cli.rb +13 -13
- data/lib/crabfarm/context.rb +15 -3
- data/lib/crabfarm/factories/context.rb +24 -0
- data/lib/crabfarm/factories/decorable.rb +71 -0
- data/lib/crabfarm/factories/navigator.rb +14 -0
- data/lib/crabfarm/factories/reducer.rb +14 -0
- data/lib/crabfarm/factories/snapshot_reducer.rb +14 -0
- data/lib/crabfarm/http_client.rb +2 -5
- data/lib/crabfarm/live/context.rb +21 -0
- data/lib/crabfarm/live/controller.rb +20 -72
- data/lib/crabfarm/live/interactable.rb +6 -2
- data/lib/crabfarm/live/manager.rb +90 -18
- data/lib/crabfarm/live/navigator_runner.rb +43 -13
- data/lib/crabfarm/live/navigator_runner_direct.rb +39 -0
- data/lib/crabfarm/live/navigator_runner_rspec.rb +111 -0
- data/lib/crabfarm/live/reducer_runner.rb +61 -10
- data/lib/crabfarm/live/reducer_runner_direct.rb +41 -0
- data/lib/crabfarm/live/reducer_runner_rspec.rb +23 -0
- data/lib/crabfarm/live/watcher.rb +21 -7
- data/lib/crabfarm/modes/console.rb +1 -1
- data/lib/crabfarm/modes/live.rb +7 -4
- data/lib/crabfarm/modes/recorder/memento.rb +1 -5
- data/lib/crabfarm/modes/recorder/snapshot.rb +2 -2
- data/lib/crabfarm/modes/shared/interactive_decorator.rb +0 -1
- data/lib/crabfarm/modes/shared/snapshot_decorator.rb +17 -22
- data/lib/crabfarm/rspec/navigator_spec_helpers.rb +56 -0
- data/lib/crabfarm/rspec/reducer_spec_helpers.rb +29 -0
- data/lib/crabfarm/rspec/reducer_spy.rb +36 -0
- data/lib/crabfarm/rspec/reducer_spy_manager.rb +38 -0
- data/lib/crabfarm/rspec.rb +22 -66
- data/lib/crabfarm/support/phantom_runner.rb +77 -0
- data/lib/crabfarm/templates/Gemfile.erb +1 -0
- data/lib/crabfarm/transition_service.rb +3 -48
- data/lib/crabfarm/utils/console.rb +77 -0
- data/lib/crabfarm/utils/naming.rb +4 -3
- data/lib/crabfarm/utils/resolve.rb +39 -0
- data/lib/crabfarm/utils/rspec_runner.rb +54 -0
- data/lib/crabfarm/{live/helpers.rb → utils/webdriver.rb} +3 -3
- data/lib/crabfarm/version.rb +1 -1
- data/lib/crabfarm.rb +24 -3
- metadata +23 -6
- data/lib/crabfarm/context_factory.rb +0 -32
- data/lib/crabfarm/global_state.rb +0 -22
- data/lib/crabfarm/phantom_runner.rb +0 -75
@@ -0,0 +1,41 @@
|
|
1
|
+
require 'benchmark'
|
2
|
+
require 'crabfarm/utils/console'
|
3
|
+
|
4
|
+
module Crabfarm
|
5
|
+
module Live
|
6
|
+
class ReducerRunnerDirect
|
7
|
+
|
8
|
+
def initialize(_manager, _snapshot, _target, _params)
|
9
|
+
@manager = _manager
|
10
|
+
@snapshot = _snapshot
|
11
|
+
@target = _target
|
12
|
+
@params = _params
|
13
|
+
end
|
14
|
+
|
15
|
+
def execute
|
16
|
+
raise ArgumentError.new 'Must provide a snapshot to execute reducer' if @snapshot.nil?
|
17
|
+
|
18
|
+
snapshot_path = @target.snapshot_path @snapshot
|
19
|
+
raise ArgumentError.new "Snapshot does not exist #{snapshot_path}" unless File.exist? snapshot_path
|
20
|
+
|
21
|
+
@reducer = Factories::SnapshotReducer.build @target, snapshot_path, (@params || {})
|
22
|
+
@elapsed = Benchmark.measure { @reducer.run }
|
23
|
+
end
|
24
|
+
|
25
|
+
def show_results
|
26
|
+
@manager.inject_web_tools
|
27
|
+
@manager.show_dialog(
|
28
|
+
:neutral,
|
29
|
+
'Reducing completed!',
|
30
|
+
"The page was parsed in #{@elapsed.real} seconds",
|
31
|
+
@reducer.to_json,
|
32
|
+
:json
|
33
|
+
)
|
34
|
+
|
35
|
+
Utils::Console.json_result @reducer
|
36
|
+
Utils::Console.info "Completed in #{@elapsed.real} s"
|
37
|
+
end
|
38
|
+
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
require 'crabfarm/utils/rspec_runner'
|
2
|
+
require 'crabfarm/live/navigator_runner_rspec'
|
3
|
+
|
4
|
+
module Crabfarm
|
5
|
+
module Live
|
6
|
+
class ReducerRunnerRSpec < NavigatorRunnerRSpec
|
7
|
+
|
8
|
+
def execute
|
9
|
+
@examples = Utils::RSpecRunner.run_spec_for spec_for(@target), live: true
|
10
|
+
end
|
11
|
+
|
12
|
+
private
|
13
|
+
|
14
|
+
def spec_for(_class)
|
15
|
+
route = Utils::Naming.route_from_constant(_class.to_s)
|
16
|
+
route = route.join(File::SEPARATOR)
|
17
|
+
route = route + '_spec.rb'
|
18
|
+
File.join('spec','reducers', route)
|
19
|
+
end
|
20
|
+
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
@@ -1,10 +1,12 @@
|
|
1
1
|
require 'listen'
|
2
|
+
require 'crabfarm/utils/console'
|
2
3
|
|
3
4
|
module Crabfarm
|
4
5
|
module Live
|
5
6
|
class Watcher
|
6
7
|
|
7
8
|
PATH_RGX = /^\/[^\/]+\/(.*?)\.rb$/i
|
9
|
+
SPEC_RGX = /^\/[^\/]+\/(.*?)_spec\.rb$/i
|
8
10
|
|
9
11
|
def initialize(_controller)
|
10
12
|
@controller = _controller
|
@@ -26,15 +28,21 @@ module Crabfarm
|
|
26
28
|
private
|
27
29
|
|
28
30
|
def start_listener
|
29
|
-
|
30
|
-
|
31
|
+
app_path = File.join CF_PATH, 'app'
|
32
|
+
spec_path = File.join CF_PATH, 'spec'
|
33
|
+
@listener = Listen.to(app_path, spec_path) do |modified, added, removed|
|
31
34
|
@candidates = (added + modified).map do |path|
|
32
|
-
|
33
|
-
|
35
|
+
if path.start_with? app_path
|
36
|
+
class_from_path path[app_path.length..-1], PATH_RGX
|
37
|
+
else
|
38
|
+
class_from_path path[spec_path.length..-1], SPEC_RGX
|
39
|
+
end
|
40
|
+
end.reject(&:nil?)
|
34
41
|
end
|
35
42
|
@listener.start
|
36
43
|
end
|
37
44
|
|
45
|
+
|
38
46
|
def stop_listener
|
39
47
|
@listener.stop if @listener
|
40
48
|
end
|
@@ -43,7 +51,13 @@ module Crabfarm
|
|
43
51
|
unless @candidates.nil?
|
44
52
|
ActiveSupport::Dependencies.clear
|
45
53
|
@candidates.each do |class_name|
|
46
|
-
target =
|
54
|
+
target = begin
|
55
|
+
class_name.constantize
|
56
|
+
rescue Exception => exc
|
57
|
+
@controller.display_external_error exc
|
58
|
+
nil
|
59
|
+
end
|
60
|
+
|
47
61
|
if target and target < Crabfarm::Live::Interactable
|
48
62
|
@controller.execute_live target
|
49
63
|
break
|
@@ -54,9 +68,9 @@ module Crabfarm
|
|
54
68
|
end
|
55
69
|
end
|
56
70
|
|
57
|
-
def class_from_path(_filename)
|
71
|
+
def class_from_path(_filename, _regexp)
|
58
72
|
_filename = _filename.gsub File::SEPARATOR, '/'
|
59
|
-
m = _filename.match
|
73
|
+
m = _filename.match _regexp
|
60
74
|
return nil if m.nil?
|
61
75
|
Utils::Naming.decode_crabfarm_uri m[1]
|
62
76
|
end
|
@@ -61,7 +61,7 @@ module Crabfarm
|
|
61
61
|
begin
|
62
62
|
puts "Navigating, waiting to hit a reducer...".color Colors::NOTICE
|
63
63
|
require 'crabfarm/modes/shared/snapshot_decorator'
|
64
|
-
|
64
|
+
Factories::Reducer.with_decorator Shared::SnapshotDecorator do
|
65
65
|
@manager.navigate _name, _params
|
66
66
|
end
|
67
67
|
puts "Navigation completed".color Colors::NOTICE
|
data/lib/crabfarm/modes/live.rb
CHANGED
@@ -1,5 +1,6 @@
|
|
1
1
|
require 'crabfarm/live/watcher'
|
2
2
|
require 'crabfarm/live/controller'
|
3
|
+
require 'crabfarm/utils/console'
|
3
4
|
|
4
5
|
module Crabfarm
|
5
6
|
module Modes
|
@@ -7,6 +8,8 @@ module Crabfarm
|
|
7
8
|
extend self
|
8
9
|
|
9
10
|
def start_watch
|
11
|
+
Utils::Console.system 'Starting crabfarm live'
|
12
|
+
|
10
13
|
begin
|
11
14
|
Crabfarm.enable_debugging!
|
12
15
|
Crabfarm.install_live_backend!
|
@@ -18,11 +21,11 @@ module Crabfarm
|
|
18
21
|
|
19
22
|
rescue SystemExit, Interrupt
|
20
23
|
# nothing
|
21
|
-
rescue Exception =>
|
22
|
-
|
23
|
-
|
24
|
+
rescue Exception => exc
|
25
|
+
Utils::Console.error "Fatal error!"
|
26
|
+
Utils::Console.exception exc
|
24
27
|
ensure
|
25
|
-
|
28
|
+
Utils::Console.system 'Exiting'
|
26
29
|
Crabfarm.live.stop rescue nil
|
27
30
|
end
|
28
31
|
end
|
@@ -9,14 +9,10 @@ module Crabfarm
|
|
9
9
|
module Memento
|
10
10
|
extend self
|
11
11
|
|
12
|
-
def memento_path(_name)
|
13
|
-
File.join(GlobalState.mementos_path, _name + '.json.gz')
|
14
|
-
end
|
15
|
-
|
16
12
|
def start(_target, _replay=false)
|
17
13
|
return puts "Must provide a recording target" unless _target.is_a? String
|
18
14
|
|
19
|
-
target_path = memento_path _target
|
15
|
+
target_path = Utils::Resolve.memento_path _target
|
20
16
|
return puts "Memento file does not exist: #{target_path}" if _replay and not File.exist? target_path
|
21
17
|
|
22
18
|
start_crabtrap _replay, target_path
|
@@ -15,9 +15,9 @@ module Crabfarm
|
|
15
15
|
|
16
16
|
begin
|
17
17
|
puts "Navigating, waiting to hit a reducer...".color(Console::Colors::NOTICE)
|
18
|
-
|
18
|
+
Factories::Reducer.with_decorator Shared::SnapshotDecorator do
|
19
19
|
if _query.nil?
|
20
|
-
|
20
|
+
Factories::Navigator.with_decorator Shared::InteractiveDecorator do
|
21
21
|
service.transition _context, _navigator
|
22
22
|
end
|
23
23
|
else
|
@@ -10,33 +10,28 @@ module Crabfarm
|
|
10
10
|
include Crabfarm::Modes::Console::Colors
|
11
11
|
end
|
12
12
|
|
13
|
-
def self.decorate(
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
13
|
+
def self.decorate(_reducer)
|
14
|
+
loop do
|
15
|
+
name = Ask.input "-- Name for #{_reducer.class.to_s} snapshot (blank to skip)".color Colors::QUESTION
|
16
|
+
if name.empty?
|
17
|
+
puts "-- Skipping snapshot".color Colors::WARNING
|
18
|
+
break
|
19
|
+
else
|
20
|
+
file_path = _reducer.class.snapshot_path name
|
21
|
+
|
22
|
+
if File.exist? file_path
|
23
|
+
puts "-- Could not save snapshot, file already exist!".color Colors::ERROR
|
21
24
|
else
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
dir_path = file_path.split(File::SEPARATOR)[0...-1]
|
28
|
-
FileUtils.mkpath dir_path.join(File::SEPARATOR) if dir_path.length > 0
|
29
|
-
File.write file_path, _reducer.raw_document
|
30
|
-
puts "-- Snapshot written to #{file_path}".color Colors::RESULT
|
31
|
-
break
|
32
|
-
end
|
25
|
+
dir_path = file_path.split(File::SEPARATOR)[0...-1]
|
26
|
+
FileUtils.mkpath dir_path.join(File::SEPARATOR) if dir_path.length > 0
|
27
|
+
File.write file_path, _reducer.raw_document
|
28
|
+
puts "-- Snapshot written to #{file_path}".color Colors::RESULT
|
29
|
+
break
|
33
30
|
end
|
34
31
|
end
|
35
|
-
|
36
|
-
_reducer.run
|
37
32
|
end
|
38
33
|
|
39
|
-
|
34
|
+
nil
|
40
35
|
end
|
41
36
|
|
42
37
|
end
|
@@ -0,0 +1,56 @@
|
|
1
|
+
require 'crabfarm/rspec/reducer_spy_manager'
|
2
|
+
|
3
|
+
module Crabfarm
|
4
|
+
module RSpec
|
5
|
+
module NavigatorSpecHelpers
|
6
|
+
|
7
|
+
def navigate(_name=nil, _params={})
|
8
|
+
ensure_context_for :navigate
|
9
|
+
|
10
|
+
if _name.is_a? Hash
|
11
|
+
_params = _name
|
12
|
+
_name = nil
|
13
|
+
end
|
14
|
+
|
15
|
+
Factories::Reducer.with_decorator spy_manager do
|
16
|
+
if _name.nil?
|
17
|
+
return nil unless described_class < BaseNavigator # TODO: maybe raise an error here.
|
18
|
+
@navigator_state = @last_state = TransitionService.transition @navigator_context, described_class, _params
|
19
|
+
else
|
20
|
+
@last_state = TransitionService.transition @navigator_context, _name, (_params || {})
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
def state
|
26
|
+
@navigator_state || navigate(@navigator_params)
|
27
|
+
end
|
28
|
+
|
29
|
+
def last_state
|
30
|
+
@last_state
|
31
|
+
end
|
32
|
+
|
33
|
+
def spy_reducer(_name_or_class)
|
34
|
+
ensure_context_for :spy_reducer
|
35
|
+
reducer_class = Utils::Resolve.reducer_class _name_or_class
|
36
|
+
spy_manager.new_spy_for reducer_class
|
37
|
+
end
|
38
|
+
|
39
|
+
def browser(_session_id=nil)
|
40
|
+
ensure_context_for :browser
|
41
|
+
@navigator_context.pool.driver _session_id
|
42
|
+
end
|
43
|
+
|
44
|
+
private
|
45
|
+
|
46
|
+
def spy_manager
|
47
|
+
@navigator_spy_manager ||= ReducerSpyManager.new
|
48
|
+
end
|
49
|
+
|
50
|
+
def ensure_context_for(_name)
|
51
|
+
raise "'#{_name}' is only available in navigator specs." if @navigator_context.nil?
|
52
|
+
end
|
53
|
+
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
module Crabfarm
|
2
|
+
module RSpec
|
3
|
+
module ReducerSpecHelpers
|
4
|
+
|
5
|
+
def reduce(_snapshot, _params={})
|
6
|
+
ensure_reducer_for :reduce
|
7
|
+
raise ArgumentError.new 'Must provide a snapshot for reducer specs' if _snapshot.nil?
|
8
|
+
|
9
|
+
snap_path = described_class.snapshot_path _snapshot
|
10
|
+
raise ArgumentError.new "Snapshot does not exist #{snap_path}" unless File.exist? snap_path
|
11
|
+
|
12
|
+
reducer = Factories::SnapshotReducer.build described_class, snap_path, (_params || {})
|
13
|
+
reducer.run
|
14
|
+
reducer
|
15
|
+
end
|
16
|
+
|
17
|
+
def reducer
|
18
|
+
@reducer_state ||= reduce @reducer_snapshot, @reducer_params
|
19
|
+
end
|
20
|
+
|
21
|
+
private
|
22
|
+
|
23
|
+
def ensure_reducer_for(_name)
|
24
|
+
raise "'#{_name}' is only available in reducer specs." unless described_class < Crabfarm::BaseReducer
|
25
|
+
end
|
26
|
+
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
@@ -0,0 +1,36 @@
|
|
1
|
+
module Crabfarm
|
2
|
+
module RSpec
|
3
|
+
class ReducerSpy
|
4
|
+
|
5
|
+
Call = Struct.new(:target, :params)
|
6
|
+
|
7
|
+
attr_reader :original, :mock, :calls
|
8
|
+
|
9
|
+
def initialize(_original)
|
10
|
+
@original = _original
|
11
|
+
@calls = []
|
12
|
+
@mock = nil
|
13
|
+
end
|
14
|
+
|
15
|
+
def register_call(_target, _params)
|
16
|
+
@calls << Call.new(_target, _params)
|
17
|
+
end
|
18
|
+
|
19
|
+
def target
|
20
|
+
raise "'#{_original.to_s}' was not invoked" if calls.size == 0
|
21
|
+
calls.first.target
|
22
|
+
end
|
23
|
+
|
24
|
+
def params
|
25
|
+
raise "'#{_original.to_s}' was not invoked" if calls.size == 0
|
26
|
+
calls.first.params
|
27
|
+
end
|
28
|
+
|
29
|
+
def mock_with(_attributes)
|
30
|
+
@mock = _attributes
|
31
|
+
self
|
32
|
+
end
|
33
|
+
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
@@ -0,0 +1,38 @@
|
|
1
|
+
require 'crabfarm/rspec/reducer_spy'
|
2
|
+
|
3
|
+
module Crabfarm
|
4
|
+
module RSpec
|
5
|
+
|
6
|
+
class ReducerSpyManager
|
7
|
+
|
8
|
+
def initialize
|
9
|
+
@spies = {}
|
10
|
+
end
|
11
|
+
|
12
|
+
def new_spy_for(_reducer_class)
|
13
|
+
@spies[_reducer_class.to_s] = ReducerSpy.new(_reducer_class)
|
14
|
+
end
|
15
|
+
|
16
|
+
# reducer decorator implementation
|
17
|
+
|
18
|
+
def prepare(_class, _target, _params)
|
19
|
+
spy = @spies[_class.to_s]
|
20
|
+
unless spy.nil?
|
21
|
+
spy.register_call _target, _params
|
22
|
+
if spy.mock
|
23
|
+
mock = _class.new _target, _params
|
24
|
+
mock.mock spy.mock
|
25
|
+
|
26
|
+
def mock.run
|
27
|
+
# do nothing
|
28
|
+
end
|
29
|
+
|
30
|
+
return mock
|
31
|
+
end
|
32
|
+
end
|
33
|
+
nil
|
34
|
+
end
|
35
|
+
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
data/lib/crabfarm/rspec.rb
CHANGED
@@ -1,76 +1,32 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
4
|
-
class Error < Crabfarm::Error; end
|
5
|
-
|
6
|
-
def reduce(_snapshot=nil, _options={})
|
7
|
-
|
8
|
-
raise Error.new "'reduce' is only available in reducer specs" unless described_class < Crabfarm::BaseReducer
|
9
|
-
|
10
|
-
if _snapshot.is_a? Hash
|
11
|
-
raise ArgumentException.new 'Invalid arguments' unless _options.nil?
|
12
|
-
_options = _snapshot
|
13
|
-
_snapshot = nil
|
14
|
-
end
|
15
|
-
|
16
|
-
snapshot_path = described_class.snapshot_path _snapshot
|
17
|
-
raise Error.new "Snapshot does not exist #{snapshot_path}" unless File.exist? snapshot_path
|
18
|
-
|
19
|
-
data = File.read snapshot_path
|
20
|
-
reducer = described_class.new data, _options
|
21
|
-
reducer.run
|
22
|
-
reducer
|
23
|
-
end
|
24
|
-
|
25
|
-
def navigate(_name=nil, _params={})
|
26
|
-
|
27
|
-
raise Error.new "'navigate' is only available in navigator specs" if @context.nil?
|
28
|
-
|
29
|
-
if _name.is_a? Hash
|
30
|
-
_params = _name
|
31
|
-
_name = nil
|
32
|
-
end
|
33
|
-
|
34
|
-
if _name.nil?
|
35
|
-
return nil unless described_class < BaseNavigator # TODO: maybe raise an error here.
|
36
|
-
@state = @last_state = TransitionService.transition @context, described_class, _params
|
37
|
-
else
|
38
|
-
@last_state = TransitionService.transition @context, _name, _params
|
39
|
-
end
|
40
|
-
end
|
41
|
-
|
42
|
-
def state
|
43
|
-
@state ||= navigate
|
44
|
-
end
|
45
|
-
|
46
|
-
def last_state
|
47
|
-
@last_state
|
48
|
-
end
|
49
|
-
|
50
|
-
def reducer
|
51
|
-
@reducer ||= reduce
|
52
|
-
end
|
53
|
-
|
54
|
-
def browser(_session_id=nil)
|
55
|
-
@context.pool.driver(_session_id)
|
56
|
-
end
|
57
|
-
|
58
|
-
end
|
59
|
-
end
|
1
|
+
require 'crabfarm/rspec/navigator_spec_helpers'
|
2
|
+
require 'crabfarm/rspec/reducer_spec_helpers'
|
60
3
|
|
61
4
|
RSpec.configure do |config|
|
62
|
-
config.include Crabfarm::RSpec
|
5
|
+
config.include Crabfarm::RSpec::NavigatorSpecHelpers
|
6
|
+
config.include Crabfarm::RSpec::ReducerSpecHelpers
|
63
7
|
|
64
8
|
config.around(:example) do |example|
|
65
9
|
if described_class < Crabfarm::BaseReducer
|
66
|
-
|
67
|
-
|
10
|
+
@reducer_snapshot = example.metadata[:reducing]
|
11
|
+
@reducer_params = example.metadata[:with_params] || {}
|
12
|
+
|
13
|
+
begin
|
14
|
+
example.run
|
15
|
+
ensure
|
16
|
+
# store result in metadata so it can be accessed by formatters/reporters
|
17
|
+
example.metadata[:result] = @reducer_state.as_json if @reducer_state
|
68
18
|
end
|
69
|
-
example.run
|
70
19
|
elsif described_class < Crabfarm::BaseNavigator
|
71
|
-
Crabfarm
|
72
|
-
@
|
73
|
-
example.
|
20
|
+
Crabfarm.with_context example.metadata[:navigating] do |ctx|
|
21
|
+
@navigator_context = ctx
|
22
|
+
@navigator_params = (example.metadata[:with_params] || {})
|
23
|
+
|
24
|
+
begin
|
25
|
+
example.run
|
26
|
+
ensure
|
27
|
+
# store result in metadata so it can be accessed by formatters/reporters
|
28
|
+
example.metadata[:result] = @navigator_state.document if @navigator_state
|
29
|
+
end
|
74
30
|
end
|
75
31
|
else
|
76
32
|
example.run
|
@@ -0,0 +1,77 @@
|
|
1
|
+
require 'timeout'
|
2
|
+
require 'crabfarm/utils/processes'
|
3
|
+
|
4
|
+
module Crabfarm
|
5
|
+
module Support
|
6
|
+
class PhantomRunner
|
7
|
+
|
8
|
+
PHANTOM_START_TM = 5 # seconds
|
9
|
+
|
10
|
+
def initialize(_config={})
|
11
|
+
@config = _config;
|
12
|
+
@process = nil
|
13
|
+
end
|
14
|
+
|
15
|
+
def port
|
16
|
+
@config[:port]
|
17
|
+
end
|
18
|
+
|
19
|
+
def start
|
20
|
+
logger.info "Starting phantomjs in port #{port}"
|
21
|
+
@process = spawn_phantomjs
|
22
|
+
logger.info "Phantomjs started (PID: #{@process.pid})"
|
23
|
+
end
|
24
|
+
|
25
|
+
def stop
|
26
|
+
unless @process.nil?
|
27
|
+
logger.info "Stopping phantomjs (PID: #{@process.pid})"
|
28
|
+
@process.stop
|
29
|
+
@process = nil
|
30
|
+
logger.info "Phantomjs stopped"
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
private
|
35
|
+
|
36
|
+
def spawn_phantomjs
|
37
|
+
proc = nil
|
38
|
+
begin
|
39
|
+
proc = Utils::Processes.start_logged_process 'phantomjs', phantomjs_cmd, logger
|
40
|
+
Timeout::timeout(PHANTOM_START_TM) { wait_for_server }
|
41
|
+
rescue ChildProcess::LaunchError
|
42
|
+
raise BinaryMissingError.new 'phantomjs', @config[:bin_path]
|
43
|
+
rescue Timeout::Error
|
44
|
+
proc.stop
|
45
|
+
raise
|
46
|
+
end
|
47
|
+
proc
|
48
|
+
end
|
49
|
+
|
50
|
+
def phantomjs_cmd
|
51
|
+
cmd = [@config[:bin_path]]
|
52
|
+
cmd << '--load-images=false' unless @config[:load_images]
|
53
|
+
cmd << "--proxy=#{@config[:proxy]}" unless @config[:proxy].nil?
|
54
|
+
cmd << "--webdriver=#{port}"
|
55
|
+
cmd << "--ssl-protocol=#{@config[:ssl]}" unless @config[:ssl].nil?
|
56
|
+
cmd << "--ignore-ssl-errors=true"
|
57
|
+
cmd << "--webdriver-loglevel=WARN"
|
58
|
+
cmd
|
59
|
+
end
|
60
|
+
|
61
|
+
def wait_for_server
|
62
|
+
loop do
|
63
|
+
begin
|
64
|
+
Net::HTTP.get_response(URI.parse("http://127.0.0.1:#{port}/status"))
|
65
|
+
break
|
66
|
+
rescue
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
def logger
|
72
|
+
Crabfarm.logger
|
73
|
+
end
|
74
|
+
|
75
|
+
end
|
76
|
+
end
|
77
|
+
end
|
@@ -1,19 +1,6 @@
|
|
1
1
|
module Crabfarm
|
2
2
|
class TransitionService
|
3
3
|
|
4
|
-
def self.with_navigator_decorator(_decorator)
|
5
|
-
@decorator = DecoratorChain.new @decorator, _decorator
|
6
|
-
begin
|
7
|
-
yield
|
8
|
-
ensure
|
9
|
-
@decorator = @decorator.base
|
10
|
-
end
|
11
|
-
end
|
12
|
-
|
13
|
-
def self.current_decorator
|
14
|
-
@decorator
|
15
|
-
end
|
16
|
-
|
17
4
|
def self.transition(_context, _name, _params={})
|
18
5
|
self.new(_context).transition(_name, _params)
|
19
6
|
end
|
@@ -24,48 +11,16 @@ module Crabfarm
|
|
24
11
|
@context = _context
|
25
12
|
end
|
26
13
|
|
27
|
-
def transition(
|
28
|
-
navigator_class =
|
29
|
-
load_class_from_uri _name
|
30
|
-
else _name end
|
14
|
+
def transition(_name_or_class, _params={})
|
15
|
+
navigator_class = Utils::Resolve.navigator_class _name_or_class
|
31
16
|
|
32
17
|
@context.prepare
|
33
|
-
@navigator =
|
34
|
-
@navigator = current_decorator.decorate @navigator unless current_decorator.nil?
|
35
|
-
|
18
|
+
@navigator = Factories::Navigator.build navigator_class, @context, _params
|
36
19
|
@document = @navigator.run
|
37
20
|
@document = @document.as_json if @document.respond_to? :as_json
|
38
21
|
|
39
22
|
self
|
40
23
|
end
|
41
24
|
|
42
|
-
private
|
43
|
-
|
44
|
-
def current_decorator
|
45
|
-
self.class.current_decorator
|
46
|
-
end
|
47
|
-
|
48
|
-
def load_class_from_uri(_uri)
|
49
|
-
class_name = Utils::Naming.decode_crabfarm_uri _uri
|
50
|
-
class_name.constantize
|
51
|
-
end
|
52
|
-
|
53
|
-
class DecoratorChain
|
54
|
-
|
55
|
-
attr_reader :base, :new
|
56
|
-
|
57
|
-
def initialize(_base, _new)
|
58
|
-
@base = _base
|
59
|
-
@new = _new
|
60
|
-
end
|
61
|
-
|
62
|
-
def decorate(_navigator)
|
63
|
-
_navigator = @new.decorate _navigator
|
64
|
-
return _navigator if @base.nil?
|
65
|
-
@base.decorate _navigator
|
66
|
-
end
|
67
|
-
|
68
|
-
end
|
69
|
-
|
70
25
|
end
|
71
26
|
end
|