trailblazer-operation 0.4.1 → 0.5.0

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 (49) hide show
  1. checksums.yaml +4 -4
  2. data/.rubocop.yml +8 -0
  3. data/.rubocop_todo.yml +223 -0
  4. data/.travis.yml +6 -7
  5. data/CHANGES.md +2 -14
  6. data/Gemfile +4 -2
  7. data/README.md +13 -2
  8. data/Rakefile +2 -2
  9. data/lib/trailblazer/operation.rb +53 -67
  10. data/lib/trailblazer/operation/class_dependencies.rb +1 -1
  11. data/lib/trailblazer/operation/container.rb +14 -0
  12. data/lib/trailblazer/operation/deprecated_macro.rb +2 -2
  13. data/lib/trailblazer/operation/inspect.rb +17 -27
  14. data/lib/trailblazer/operation/public_call.rb +16 -18
  15. data/lib/trailblazer/operation/railway.rb +2 -3
  16. data/lib/trailblazer/operation/railway/macaroni.rb +2 -2
  17. data/lib/trailblazer/operation/result.rb +14 -1
  18. data/lib/trailblazer/operation/trace.rb +5 -8
  19. data/lib/trailblazer/operation/version.rb +4 -2
  20. data/test/benchmark/skill_resolver_benchmark.rb +8 -9
  21. data/test/call_test.rb +56 -30
  22. data/test/callable_test.rb +147 -147
  23. data/test/class_dependencies_test.rb +6 -7
  24. data/test/docs/doormat_test.rb +13 -12
  25. data/test/docs/macaroni_test.rb +7 -9
  26. data/test/docs/operation_test.rb +69 -4
  27. data/test/docs/wiring_test.rb +98 -53
  28. data/test/dry_container_test.rb +4 -3
  29. data/test/fast_track_test.rb +24 -44
  30. data/test/inheritance_test.rb +13 -12
  31. data/test/inspect_test.rb +6 -7
  32. data/test/introspect_test.rb +6 -6
  33. data/test/operation_test.rb +17 -25
  34. data/test/result_test.rb +4 -4
  35. data/test/ruby-2.0.0/operation_test.rb +9 -9
  36. data/test/ruby-2.0.0/step_test.rb +17 -16
  37. data/test/step_test.rb +47 -42
  38. data/test/test_helper.rb +6 -13
  39. data/test/trace_test.rb +26 -26
  40. data/test/wiring/defaults_test.rb +29 -33
  41. data/trailblazer-operation.gemspec +7 -6
  42. metadata +26 -18
  43. data/lib/trailblazer/operation/heritage.rb +0 -30
  44. data/lib/trailblazer/operation/inject.rb +0 -36
  45. data/lib/trailblazer/operation/railway/fast_track.rb +0 -13
  46. data/lib/trailblazer/operation/railway/normalizer.rb +0 -58
  47. data/lib/trailblazer/operation/railway/task_builder.rb +0 -37
  48. data/test/macro_test.rb +0 -60
  49. data/test/task_wrap_test.rb +0 -97
@@ -4,11 +4,11 @@ require 'trailblazer/operation/version'
4
4
 
5
5
  Gem::Specification.new do |spec|
6
6
  spec.name = "trailblazer-operation"
7
- spec.version = Trailblazer::Operation::VERSION
7
+ spec.version = Trailblazer::Version::Operation::VERSION
8
8
  spec.authors = ["Nick Sutterer"]
9
9
  spec.email = ["apotonick@gmail.com"]
10
- spec.description = %q{Trailblazer's operation object.}
11
- spec.summary = %q{Trailblazer's operation object with railway flow and integrated error handling.}
10
+ spec.description = %q(Trailblazer's operation object.)
11
+ spec.summary = %q(Trailblazer's operation object with railway flow and integrated error handling.)
12
12
  spec.homepage = "http://trailblazer.to"
13
13
  spec.license = "MIT"
14
14
 
@@ -17,12 +17,13 @@ Gem::Specification.new do |spec|
17
17
  spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
18
18
  spec.require_paths = ["lib"]
19
19
 
20
- spec.add_dependency "trailblazer-activity", ">= 0.7.1", "< 0.8.0"
20
+ spec.add_dependency "trailblazer-activity-dsl-linear", ">= 0.1.5", "< 1.0.0"
21
21
  spec.add_dependency "trailblazer-context", ">= 0.1.1", "< 0.3.0"
22
22
 
23
23
  spec.add_development_dependency "bundler"
24
- spec.add_development_dependency "rake"
25
24
  spec.add_development_dependency "minitest"
25
+ spec.add_development_dependency "rake"
26
+ spec.add_development_dependency "rubocop"
26
27
 
27
- spec.required_ruby_version = '>= 2.0.0'
28
+ spec.required_ruby_version = ">= 2.1.0"
28
29
  end
metadata CHANGED
@@ -1,35 +1,35 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: trailblazer-operation
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.4.1
4
+ version: 0.5.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Nick Sutterer
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2018-06-18 00:00:00.000000000 Z
11
+ date: 2019-06-16 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
- name: trailblazer-activity
14
+ name: trailblazer-activity-dsl-linear
15
15
  requirement: !ruby/object:Gem::Requirement
16
16
  requirements:
17
17
  - - ">="
18
18
  - !ruby/object:Gem::Version
19
- version: 0.7.1
19
+ version: 0.1.5
20
20
  - - "<"
21
21
  - !ruby/object:Gem::Version
22
- version: 0.8.0
22
+ version: 1.0.0
23
23
  type: :runtime
24
24
  prerelease: false
25
25
  version_requirements: !ruby/object:Gem::Requirement
26
26
  requirements:
27
27
  - - ">="
28
28
  - !ruby/object:Gem::Version
29
- version: 0.7.1
29
+ version: 0.1.5
30
30
  - - "<"
31
31
  - !ruby/object:Gem::Version
32
- version: 0.8.0
32
+ version: 1.0.0
33
33
  - !ruby/object:Gem::Dependency
34
34
  name: trailblazer-context
35
35
  requirement: !ruby/object:Gem::Requirement
@@ -64,6 +64,20 @@ dependencies:
64
64
  - - ">="
65
65
  - !ruby/object:Gem::Version
66
66
  version: '0'
67
+ - !ruby/object:Gem::Dependency
68
+ name: minitest
69
+ requirement: !ruby/object:Gem::Requirement
70
+ requirements:
71
+ - - ">="
72
+ - !ruby/object:Gem::Version
73
+ version: '0'
74
+ type: :development
75
+ prerelease: false
76
+ version_requirements: !ruby/object:Gem::Requirement
77
+ requirements:
78
+ - - ">="
79
+ - !ruby/object:Gem::Version
80
+ version: '0'
67
81
  - !ruby/object:Gem::Dependency
68
82
  name: rake
69
83
  requirement: !ruby/object:Gem::Requirement
@@ -79,7 +93,7 @@ dependencies:
79
93
  - !ruby/object:Gem::Version
80
94
  version: '0'
81
95
  - !ruby/object:Gem::Dependency
82
- name: minitest
96
+ name: rubocop
83
97
  requirement: !ruby/object:Gem::Requirement
84
98
  requirements:
85
99
  - - ">="
@@ -100,6 +114,8 @@ extensions: []
100
114
  extra_rdoc_files: []
101
115
  files:
102
116
  - ".gitignore"
117
+ - ".rubocop.yml"
118
+ - ".rubocop_todo.yml"
103
119
  - ".travis.yml"
104
120
  - CHANGES.md
105
121
  - Gemfile
@@ -108,16 +124,12 @@ files:
108
124
  - lib/trailblazer/operation.rb
109
125
  - lib/trailblazer/operation/callable.rb
110
126
  - lib/trailblazer/operation/class_dependencies.rb
127
+ - lib/trailblazer/operation/container.rb
111
128
  - lib/trailblazer/operation/deprecated_macro.rb
112
- - lib/trailblazer/operation/heritage.rb
113
- - lib/trailblazer/operation/inject.rb
114
129
  - lib/trailblazer/operation/inspect.rb
115
130
  - lib/trailblazer/operation/public_call.rb
116
131
  - lib/trailblazer/operation/railway.rb
117
- - lib/trailblazer/operation/railway/fast_track.rb
118
132
  - lib/trailblazer/operation/railway/macaroni.rb
119
- - lib/trailblazer/operation/railway/normalizer.rb
120
- - lib/trailblazer/operation/railway/task_builder.rb
121
133
  - lib/trailblazer/operation/result.rb
122
134
  - lib/trailblazer/operation/trace.rb
123
135
  - lib/trailblazer/operation/version.rb
@@ -138,14 +150,12 @@ files:
138
150
  - test/inheritance_test.rb
139
151
  - test/inspect_test.rb
140
152
  - test/introspect_test.rb
141
- - test/macro_test.rb
142
153
  - test/operation_test.rb
143
154
  - test/result_test.rb
144
155
  - test/ruby-2.0.0/operation_test.rb
145
156
  - test/ruby-2.0.0/step_test.rb
146
157
  - test/skill_test.rb
147
158
  - test/step_test.rb
148
- - test/task_wrap_test.rb
149
159
  - test/test_helper.rb
150
160
  - test/trace_test.rb
151
161
  - test/wire_test.rb
@@ -164,7 +174,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
164
174
  requirements:
165
175
  - - ">="
166
176
  - !ruby/object:Gem::Version
167
- version: 2.0.0
177
+ version: 2.1.0
168
178
  required_rubygems_version: !ruby/object:Gem::Requirement
169
179
  requirements:
170
180
  - - ">="
@@ -194,14 +204,12 @@ test_files:
194
204
  - test/inheritance_test.rb
195
205
  - test/inspect_test.rb
196
206
  - test/introspect_test.rb
197
- - test/macro_test.rb
198
207
  - test/operation_test.rb
199
208
  - test/result_test.rb
200
209
  - test/ruby-2.0.0/operation_test.rb
201
210
  - test/ruby-2.0.0/step_test.rb
202
211
  - test/skill_test.rb
203
212
  - test/step_test.rb
204
- - test/task_wrap_test.rb
205
213
  - test/test_helper.rb
206
214
  - test/trace_test.rb
207
215
  - test/wire_test.rb
@@ -1,30 +0,0 @@
1
- module Trailblazer
2
- # This is copied from the Declarative gem. This might get removed in favor of a real heritage gem.
3
- class Operation
4
- class Heritage < Array
5
- # Record inheritable assignments for replay in an inheriting class.
6
- def record(method, *args, &block)
7
- self << { method: method, args: args, block: block }
8
- end
9
-
10
- # Replay the recorded assignments on inheritor.
11
- # Accepts a block that will allow processing the arguments for every recorded statement.
12
- def call(inheritor, &block)
13
- each { |cfg| call!(inheritor, cfg, &block) }
14
- end
15
-
16
- private
17
- def call!(inheritor, cfg)
18
- yield cfg if block_given? # allow messing around with recorded arguments.
19
-
20
- inheritor.send(cfg[:method], *cfg[:args], &cfg[:block])
21
- end
22
-
23
- module Accessor
24
- def heritage
25
- @heritage ||= Heritage.new
26
- end
27
- end
28
- end
29
- end
30
- end
@@ -1,36 +0,0 @@
1
- module Trailblazer
2
- module Operation::Wrap
3
- module Inject
4
- # Returns an Alteration wirings that, when applied, inserts the {ReverseMergeDefaults} task
5
- # before the {Wrap::Call} task. This is meant for macros and steps that accept a dependency
6
- # injection but need a default parameter to be set if not injected.
7
- # @returns ADDS
8
- def self.Defaults(default_dependencies)
9
- Module.new do
10
- extend Activity::Path::Plan()
11
-
12
- task ReverseMergeDefaults.new( default_dependencies ),
13
- id: "ReverseMergeDefaults#{default_dependencies}",
14
- before: "task_wrap.call_task"
15
- end
16
- end
17
-
18
- # @api private
19
- # @returns Task
20
- # @param Hash list of key/value that should be set if not already assigned/set before (or injected from the outside).
21
- class ReverseMergeDefaults
22
- def initialize(defaults)
23
- @defaults = defaults
24
- end
25
-
26
- def call((wrap_ctx, original_args), **circuit_options)
27
- ctx = original_args[0][0]
28
-
29
- @defaults.each { |k, v| ctx[k] ||= v }
30
-
31
- return Activity::Right, [ wrap_ctx, original_args ]
32
- end
33
- end
34
- end # Inject
35
- end
36
- end
@@ -1,13 +0,0 @@
1
- module Trailblazer
2
- module Operation::Railway
3
- def self.fail! ; Activity::Left end
4
- def self.pass! ; Activity::Right end
5
- def self.fail_fast!; Activity::FastTrack::FailFast end
6
- def self.pass_fast!; Activity::FastTrack::PassFast end
7
-
8
- module End
9
- FailFast = Class.new(Operation::Railway::End::Failure)
10
- PassFast = Class.new(Operation::Railway::End::Success)
11
- end
12
- end
13
- end
@@ -1,58 +0,0 @@
1
- module Trailblazer
2
- module Operation::Railway
3
- # The {Normalizer} is called for every DSL call (step/pass/fail etc.) and normalizes/defaults
4
- # the user options, such as setting `:id`, connecting the task's outputs or wrapping the user's
5
- # task via {TaskBuilder} in order to translate true/false to `Right` or `Left`.
6
- #
7
- # The Normalizer sits in the `@builder`, which receives all DSL calls from the Operation subclass.
8
- module Normalizer
9
- Pipeline = Activity::Magnetic::Normalizer::Pipeline.clone
10
-
11
- Pipeline.module_eval do
12
- # Handle the :override option which is specific to Operation.
13
- def self.override(ctx, task:, options:, sequence_options:, **)
14
- options, locals = Activity::Magnetic::Options.normalize(options, [:override])
15
- sequence_options = sequence_options.merge( replace: options[:id] ) if locals[:override]
16
-
17
- ctx[:options], ctx[:sequence_options] = options, sequence_options
18
- end
19
-
20
- # TODO remove in 2.2
21
- def self.deprecate_macro_with_two_args(ctx, task:, **)
22
- return true unless task.is_a?(Array) # TODO remove in 2.2
23
-
24
- ctx[:options] = Operation::DeprecatedMacro.( *task )
25
- end
26
-
27
- # TODO remove in 2.2
28
- def self.deprecate_name(ctx, local_options:, connection_options:, **)
29
- connection_options, deprecated_options = Activity::Magnetic::Options.normalize(connection_options, [:name])
30
- local_options, _deprecated_options = Activity::Magnetic::Options.normalize(local_options, [:name])
31
-
32
- deprecated_options = deprecated_options.merge(_deprecated_options)
33
-
34
- local_options = local_options.merge( name: deprecated_options[:name] ) if deprecated_options[:name]
35
-
36
- local_options, locals = Activity::Magnetic::Options.normalize(local_options, [:name])
37
- if locals[:name]
38
- warn "[Trailblazer] The :name option for #step, #success and #failure has been renamed to :id."
39
- local_options = local_options.merge(id: locals[:name])
40
- end
41
-
42
- ctx[:local_options], ctx[:connection_options] = local_options, connection_options
43
- end
44
-
45
- def self.raise_on_missing_id(ctx, local_options:, **)
46
- raise "No :id given for #{local_options[:task]}" unless local_options[:id]
47
- true
48
- end
49
-
50
- # add more normalization tasks to the existing Magnetic::Normalizer::Pipeline
51
- task Activity::TaskBuilder::Binary( method(:deprecate_macro_with_two_args) ), before: "split_options"
52
- task Activity::TaskBuilder::Binary( method(:deprecate_name) )
53
- task Activity::TaskBuilder::Binary( method(:override) )
54
- task Activity::TaskBuilder::Binary( method(:raise_on_missing_id) )
55
- end
56
- end # Normalizer
57
- end
58
- end
@@ -1,37 +0,0 @@
1
- module Trailblazer
2
- module Operation::Railway
3
- # every step is wrapped by this proc/decider. this is executed in the circuit as the actual task.
4
- # Step calls step.(options, **options, flow_options)
5
- # Output direction binary: true=>Right, false=>Left.
6
- # Passes through all subclasses of Direction.~~~~~~~~~~~~~~~~~
7
- module TaskBuilder
8
- def self.call(user_proc)
9
- Task.new( Trailblazer::Option::KW( user_proc ), user_proc )
10
- end
11
-
12
- # Translates the return value of the user step into a valid signal.
13
- # Note that it passes through subclasses of {Signal}.
14
- def self.binary_direction_for(result, on_true, on_false)
15
- result.is_a?(Class) && result < Activity::Signal ? result : (result ? on_true : on_false)
16
- end
17
- end
18
-
19
- class Task
20
- def initialize(task, user_proc)
21
- @task = task
22
- @user_proc = user_proc
23
- freeze
24
- end
25
-
26
- def call( (options, *args), **circuit_args )
27
- # Execute the user step with TRB's kw args.
28
- result = @task.( options, **circuit_args ) # circuit_args contains :exec_context.
29
-
30
- # Return an appropriate signal which direction to go next.
31
- direction = TaskBuilder.binary_direction_for( result, Activity::Right, Activity::Left )
32
-
33
- [ direction, [ options, *args ], **circuit_args ]
34
- end
35
- end
36
- end
37
- end
data/test/macro_test.rb DELETED
@@ -1,60 +0,0 @@
1
- require "test_helper"
2
- #- test
3
- # macro [ task, {name} ]
4
- # macro [ task, {name}, { alteration: } ] # see task_wrap_test.rb
5
- # macro [ task, {name}, { alteration: }, {task_outputs} ] # for eg. nested
6
-
7
- class MacroTest < Minitest::Spec
8
- MacroB = ->(( options, *args ), **) do
9
- options[:B] = true # we were here!
10
-
11
- [ options[:MacroB_return], [ options, *args ] ]
12
- end
13
-
14
- it "raises exception when macro doesn't provide :id" do
15
- assert_raises do
16
-
17
- Class.new(Trailblazer::Operation) do
18
- step( task: "<some macro>" )
19
- end
20
-
21
- end.message.must_equal %{No :id given for <some macro>}
22
- end
23
-
24
-
25
- class Create < Trailblazer::Operation
26
- step :a
27
- step task: MacroB, id: :MacroB, outputs: { :success => Activity::Output("Allgood", :success), :failure => Activity::Output("Fail!", :failure), :pass_fast => Activity::Output("Winning", :pass_fast) }
28
- step :c
29
-
30
- def a(options, **); options[:a] = true end
31
- def c(options, **); options[:c] = true end
32
- end
33
-
34
- # MacroB returns Allgood and is wired to the :success edge (right track).
35
- it { Create.( {}, MacroB_return: "Allgood" ).inspect(:a, :B, :c).must_equal %{<Result:true [true, true, true] >} }
36
- # MacroB returns Fail! and is wired to the :failure edge (left track).
37
- it { Create.( {}, MacroB_return: "Fail!" ).inspect(:a, :B, :c).must_equal %{<Result:false [true, true, nil] >} }
38
- # MacroB returns Winning and is wired to the :pass_fast edge.
39
- it { Create.( {}, MacroB_return: "Winning" ).inspect(:a, :B, :c).must_equal %{<Result:true [true, true, nil] >} }
40
-
41
- #- user overrides :plus_poles
42
- class Update < Trailblazer::Operation
43
- macro = { task: MacroB, id: :MacroB, outputs: { :success => Activity::Output("Allgood", :success), :failure => Activity::Output("Fail!", :failure), :pass_fast => Activity::Output("Winning", :pass_fast) } }
44
-
45
- step :a
46
- step macro, outputs: { :success => Activity::Output("Fail!", :success), :fail_fast => Activity::Output("Winning", :fail_fast), :failure => Activity::Output("Allgood", :failure) }
47
- # plus_poles: Test.plus_poles_for("Allgood" => :failure, "Fail!" => :success, "Winning" => :fail_fast)
48
- step :c
49
-
50
- def a(options, **); options[:a] = true end
51
- def c(options, **); options[:c] = true end
52
- end
53
-
54
- # MacroB returns Allgood and is wired to the :failure edge.
55
- it { Update.( {}, MacroB_return: "Allgood" ).inspect(:a, :B, :c).must_equal %{<Result:false [true, true, nil] >} }
56
- # MacroB returns Fail! and is wired to the :success edge.
57
- it { Update.( {}, MacroB_return: "Fail!" ).inspect(:a, :B, :c).must_equal %{<Result:true [true, true, true] >} }
58
- # MacroB returns Winning and is wired to the :fail_fast edge.
59
- it { Update.( {}, MacroB_return: "Winning" ).inspect(:a, :B, :c).must_equal %{<Result:false [true, true, nil] >} }
60
- end
@@ -1,97 +0,0 @@
1
- require "test_helper"
2
-
3
- require "trailblazer/operation/inject" # an optional feature.com.
4
-
5
- class TaskWrapTest < Minitest::Spec
6
- MyMacro = ->( (options, *args), *) do
7
- options["MyMacro.contract"] = options[:contract]
8
- [ Trailblazer::Activity::Right, [options, *args] ]
9
- end
10
-
11
- class Create < Trailblazer::Operation
12
- step :model!
13
- # step [ MyMacro, { name: "MyMacro" }, { dependencies: { "contract" => :external_maybe } }]
14
- step(
15
- task: MyMacro,
16
- id: "MyMacro",
17
-
18
- Trailblazer::Activity::DSL::Extension.new(
19
- Trailblazer::Activity::TaskWrap::Merge.new(
20
- Module.new do
21
- extend Trailblazer::Activity::Path::Plan()
22
-
23
- task Trailblazer::Operation::Wrap::Inject::ReverseMergeDefaults.new( contract: "MyDefaultContract" ),
24
- id: "inject.my_default",
25
- before: "task_wrap.call_task"
26
- end
27
- )
28
- ) => true
29
- )
30
-
31
- def model!(options, **)
32
- options["options.contract"] = options[:contract]
33
- true
34
- end
35
- end
36
-
37
- # it { Create.call("adsf", options={}, {}).inspect("MyMacro.contract", "options.contract").must_equal %{} }
38
-
39
- def inspect_hash(hash, *keys)
40
- Hash[ keys.collect { |key| [key, hash[key]] } ].inspect
41
- end
42
-
43
- #-
44
- # default gets set by Injection.
45
- it do
46
- result = Create.call( {} )
47
-
48
- inspect_hash(result, "options.contract", :contract, "MyMacro.contract").
49
- must_equal %{{"options.contract"=>nil, :contract=>"MyDefaultContract", "MyMacro.contract"=>"MyDefaultContract"}}
50
- end
51
-
52
- # injected from outside, Injection skips.
53
- it do
54
- result = Create.call( { :contract=>"MyExternalContract" } )
55
-
56
- inspect_hash(result, "options.contract", :contract, "MyMacro.contract").
57
- must_equal %{{"options.contract"=>"MyExternalContract", :contract=>"MyExternalContract", "MyMacro.contract"=>"MyExternalContract"}}
58
- end
59
-
60
- #- Nested task_wraps should not override the outer.
61
- AnotherMacro = ->( (options, *args), *) do
62
- options["AnotherMacro.another_contract"] = options[:another_contract]
63
- [ Trailblazer::Activity::Right, [options, *args] ]
64
- end
65
-
66
- class Update < Trailblazer::Operation
67
- step(
68
- task: ->( (options, *args), circuit_options ) {
69
- _d, *o = Create.call( [ options, *args ], circuit_options )
70
-
71
- [ Trailblazer::Activity::Right, *o ]
72
- },
73
- id: "Create"
74
- )
75
- step(
76
- task: AnotherMacro,
77
- id: "AnotherMacro",
78
- Trailblazer::Activity::DSL::Extension.new(
79
- Trailblazer::Activity::TaskWrap::Merge.new(
80
- Module.new do
81
- extend Trailblazer::Activity::Path::Plan()
82
-
83
- task Trailblazer::Operation::Wrap::Inject::ReverseMergeDefaults.new( another_contract: "AnotherDefaultContract" ), id: "inject.my_default",
84
- before: "task_wrap.call_task"
85
- end
86
- )
87
- ) => true,
88
- )
89
- end
90
-
91
- it do
92
- result = Update.call( {} )
93
-
94
- inspect_hash(result, "options.contract", :contract, "MyMacro.contract", "AnotherMacro.another_contract").
95
- must_equal %{{"options.contract"=>nil, :contract=>"MyDefaultContract", "MyMacro.contract"=>"MyDefaultContract", "AnotherMacro.another_contract"=>"AnotherDefaultContract"}}
96
- end
97
- end