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.
Files changed (54) hide show
  1. checksums.yaml +4 -4
  2. data/assets/live-tools/instructions.html +17 -0
  3. data/assets/live-tools/tools.css +16 -0
  4. data/assets/live-tools/tools.js +41 -47
  5. data/assets/live-tools/welcome.html +18 -0
  6. data/lib/crabfarm/adapters/browser/abstract_webdriver.rb +19 -16
  7. data/lib/crabfarm/adapters/browser/phantom_js.rb +11 -11
  8. data/lib/crabfarm/assertion/fields.rb +8 -0
  9. data/lib/crabfarm/base_navigator.rb +4 -11
  10. data/lib/crabfarm/base_reducer.rb +5 -1
  11. data/lib/crabfarm/cli.rb +13 -13
  12. data/lib/crabfarm/context.rb +15 -3
  13. data/lib/crabfarm/factories/context.rb +24 -0
  14. data/lib/crabfarm/factories/decorable.rb +71 -0
  15. data/lib/crabfarm/factories/navigator.rb +14 -0
  16. data/lib/crabfarm/factories/reducer.rb +14 -0
  17. data/lib/crabfarm/factories/snapshot_reducer.rb +14 -0
  18. data/lib/crabfarm/http_client.rb +2 -5
  19. data/lib/crabfarm/live/context.rb +21 -0
  20. data/lib/crabfarm/live/controller.rb +20 -72
  21. data/lib/crabfarm/live/interactable.rb +6 -2
  22. data/lib/crabfarm/live/manager.rb +90 -18
  23. data/lib/crabfarm/live/navigator_runner.rb +43 -13
  24. data/lib/crabfarm/live/navigator_runner_direct.rb +39 -0
  25. data/lib/crabfarm/live/navigator_runner_rspec.rb +111 -0
  26. data/lib/crabfarm/live/reducer_runner.rb +61 -10
  27. data/lib/crabfarm/live/reducer_runner_direct.rb +41 -0
  28. data/lib/crabfarm/live/reducer_runner_rspec.rb +23 -0
  29. data/lib/crabfarm/live/watcher.rb +21 -7
  30. data/lib/crabfarm/modes/console.rb +1 -1
  31. data/lib/crabfarm/modes/live.rb +7 -4
  32. data/lib/crabfarm/modes/recorder/memento.rb +1 -5
  33. data/lib/crabfarm/modes/recorder/snapshot.rb +2 -2
  34. data/lib/crabfarm/modes/shared/interactive_decorator.rb +0 -1
  35. data/lib/crabfarm/modes/shared/snapshot_decorator.rb +17 -22
  36. data/lib/crabfarm/rspec/navigator_spec_helpers.rb +56 -0
  37. data/lib/crabfarm/rspec/reducer_spec_helpers.rb +29 -0
  38. data/lib/crabfarm/rspec/reducer_spy.rb +36 -0
  39. data/lib/crabfarm/rspec/reducer_spy_manager.rb +38 -0
  40. data/lib/crabfarm/rspec.rb +22 -66
  41. data/lib/crabfarm/support/phantom_runner.rb +77 -0
  42. data/lib/crabfarm/templates/Gemfile.erb +1 -0
  43. data/lib/crabfarm/transition_service.rb +3 -48
  44. data/lib/crabfarm/utils/console.rb +77 -0
  45. data/lib/crabfarm/utils/naming.rb +4 -3
  46. data/lib/crabfarm/utils/resolve.rb +39 -0
  47. data/lib/crabfarm/utils/rspec_runner.rb +54 -0
  48. data/lib/crabfarm/{live/helpers.rb → utils/webdriver.rb} +3 -3
  49. data/lib/crabfarm/version.rb +1 -1
  50. data/lib/crabfarm.rb +24 -3
  51. metadata +23 -6
  52. data/lib/crabfarm/context_factory.rb +0 -32
  53. data/lib/crabfarm/global_state.rb +0 -22
  54. 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
- base_path = File.join CF_PATH, 'app'
30
- @listener = Listen.to(base_path) do |modified, added, removed|
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
- class_from_path path[base_path.length..-1]
33
- end.reject &:nil?
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 = class_name.constantize rescue nil
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 PATH_RGX
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
- TransitionService.with_navigator_decorator Shared::SnapshotDecorator do
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
@@ -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 => e
22
- puts "Fatal error: #{e.to_s}".color Console::Colors::ERROR
23
- puts e.backtrace
24
+ rescue Exception => exc
25
+ Utils::Console.error "Fatal error!"
26
+ Utils::Console.exception exc
24
27
  ensure
25
- puts 'Exiting'
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
- service.with_navigator_decorator Shared::SnapshotDecorator do
18
+ Factories::Reducer.with_decorator Shared::SnapshotDecorator do
19
19
  if _query.nil?
20
- service.with_navigator_decorator Shared::InteractiveDecorator do
20
+ Factories::Navigator.with_decorator Shared::InteractiveDecorator do
21
21
  service.transition _context, _navigator
22
22
  end
23
23
  else
@@ -61,7 +61,6 @@ module Crabfarm
61
61
  @i_params ||= InteractiveHash.new.merge! @params
62
62
  end
63
63
 
64
- _navigator
65
64
  end
66
65
 
67
66
  end
@@ -10,33 +10,28 @@ module Crabfarm
10
10
  include Crabfarm::Modes::Console::Colors
11
11
  end
12
12
 
13
- def self.decorate(_navigator)
14
-
15
- def _navigator.execute_reducer(_reducer)
16
- loop do
17
- name = Ask.input "-- Name for #{_reducer.class.to_s} snapshot (blank to skip)".color Colors::QUESTION
18
- if name.empty?
19
- puts "-- Skipping snapshot".color Colors::WARNING
20
- break
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
- file_path = _reducer.class.snapshot_path name
23
-
24
- if File.exist? file_path
25
- puts "-- Could not save snapshot, file already exist!".color Colors::ERROR
26
- else
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
- _navigator
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
@@ -1,76 +1,32 @@
1
- module Crabfarm
2
- module RSpec
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
- if example.metadata[:reducing] || example[:reducing_with_params]
67
- @reducer = reduce example.metadata[:reducing], example.metadata[:reducing_with_params] || {}
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::ContextFactory.with_context example.metadata[:navigating] do |ctx|
72
- @context = ctx
73
- example.run
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
@@ -12,5 +12,6 @@ gem "selenium-webdriver", "~> 2.45"
12
12
  gem "watir-webdriver"
13
13
 
14
14
  group :test do
15
+ gem "rspec", "~> 3.2.0"
15
16
  gem "rspec-nc"
16
17
  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(_name, _params={})
28
- navigator_class = if _name.is_a? String or _name.is_a? Symbol
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 = navigator_class.new @context, _params
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