crabfarm 0.4.2 → 0.5.1
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.
- 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
|