trailblazer-operation 0.0.13 → 0.4.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 (60) hide show
  1. checksums.yaml +5 -5
  2. data/.travis.yml +5 -3
  3. data/CHANGES.md +100 -0
  4. data/Gemfile +4 -2
  5. data/Rakefile +8 -6
  6. data/lib/trailblazer/operation.rb +80 -13
  7. data/lib/trailblazer/operation/callable.rb +42 -0
  8. data/lib/trailblazer/operation/class_dependencies.rb +25 -0
  9. data/lib/trailblazer/operation/deprecated_macro.rb +19 -0
  10. data/lib/trailblazer/operation/heritage.rb +30 -0
  11. data/lib/trailblazer/operation/inject.rb +36 -0
  12. data/lib/trailblazer/operation/inspect.rb +79 -0
  13. data/lib/trailblazer/operation/public_call.rb +55 -0
  14. data/lib/trailblazer/operation/railway.rb +32 -0
  15. data/lib/trailblazer/operation/railway/fast_track.rb +13 -0
  16. data/lib/trailblazer/operation/railway/macaroni.rb +23 -0
  17. data/lib/trailblazer/operation/railway/normalizer.rb +58 -0
  18. data/lib/trailblazer/operation/railway/task_builder.rb +37 -0
  19. data/lib/trailblazer/operation/result.rb +6 -4
  20. data/lib/trailblazer/operation/trace.rb +46 -0
  21. data/lib/trailblazer/operation/version.rb +1 -1
  22. data/test/call_test.rb +27 -8
  23. data/test/callable_test.rb +147 -0
  24. data/test/class_dependencies_test.rb +16 -0
  25. data/test/docs/doormat_test.rb +189 -0
  26. data/test/docs/macaroni_test.rb +33 -0
  27. data/test/docs/operation_test.rb +23 -0
  28. data/test/docs/wiring_test.rb +559 -0
  29. data/test/dry_container_test.rb +4 -0
  30. data/test/fast_track_test.rb +197 -0
  31. data/test/gemfiles/Gemfile.ruby-2.0 +1 -2
  32. data/test/gemfiles/Gemfile.ruby-2.0.lock +40 -0
  33. data/test/inheritance_test.rb +1 -1
  34. data/test/inspect_test.rb +43 -0
  35. data/test/introspect_test.rb +51 -0
  36. data/test/macro_test.rb +60 -0
  37. data/test/operation_test.rb +94 -0
  38. data/test/result_test.rb +14 -8
  39. data/test/ruby-2.0.0/operation_test.rb +61 -0
  40. data/test/ruby-2.0.0/step_test.rb +136 -0
  41. data/test/skill_test.rb +66 -48
  42. data/test/step_test.rb +228 -0
  43. data/test/task_wrap_test.rb +97 -0
  44. data/test/test_helper.rb +37 -0
  45. data/test/trace_test.rb +57 -0
  46. data/test/wire_test.rb +113 -0
  47. data/test/wiring/defaults_test.rb +197 -0
  48. data/test/wiring/subprocess_test.rb +70 -0
  49. data/trailblazer-operation.gemspec +3 -5
  50. metadata +68 -37
  51. data/lib/trailblazer/operation/1.9.3/option.rb +0 -36
  52. data/lib/trailblazer/operation/generic.rb +0 -12
  53. data/lib/trailblazer/operation/option.rb +0 -54
  54. data/lib/trailblazer/operation/pipetree.rb +0 -142
  55. data/lib/trailblazer/operation/skill.rb +0 -41
  56. data/lib/trailblazer/skill.rb +0 -70
  57. data/test/2.0.0-pipetree_test.rb +0 -100
  58. data/test/2.1.0-pipetree_test.rb +0 -100
  59. data/test/operation_skill_test.rb +0 -89
  60. data/test/pipetree_test.rb +0 -185
@@ -11,6 +11,10 @@ class DryContainerTest < Minitest::Spec
11
11
  class Create < Trailblazer::Operation
12
12
  end
13
13
 
14
+ it "allows 2.2 call style" do
15
+ Create.({}, my_container)["user_repository"].must_equal Object
16
+ end
17
+
14
18
  it { Create.({}, {}, my_container)["user_repository"].must_equal Object }
15
19
  it { Create.({}, {}, my_container)["contract.create"].must_equal Array }
16
20
  # also allows our own options PLUS containers.
@@ -0,0 +1,197 @@
1
+ require "test_helper"
2
+
3
+ class FastTrackTest < Minitest::Spec
4
+ # #failure fails fast.
5
+ # class Create < Trailblazer::Operation
6
+ # step ->(options, *) { options["x"] = options["dont_fail"] }
7
+ # failure ->(options, *) { options["a"] = true; options["fail_fast"] }, fail_fast: true
8
+ # failure ->(options, *) { options["b"] = true }
9
+ # step ->(options, *) { options["y"] = true }
10
+ # end
11
+
12
+ # puts Create["pipetree"].inspect
13
+
14
+ # require "trailblazer/diagram/bpmn"
15
+ # puts Trailblazer::Diagram::BPMN.to_xml(Create["pipetree"])
16
+
17
+ # it { Create.("fail_fast" => true, "dont_fail" => true ).inspect("x", "a", "b", "y").must_equal %{<Result:true [true, nil, nil, true] >} }
18
+ # it { Create.("fail_fast" => true ).inspect("x", "a", "b", "y").must_equal %{<Result:false [nil, true, nil, nil] >} }
19
+ # it { Create.("fail_fast" => false ).inspect("x", "a", "b", "y").must_equal %{<Result:false [nil, true, nil, nil] >} }
20
+
21
+ # #success passes fast.
22
+ class Retrieve < Trailblazer::Operation
23
+ pass ->(options, **) { options["x"] = options["dont_fail"] }, pass_fast: true
24
+ fail ->(options, **) { options["b"] = true }
25
+ step ->(options, **) { options["y"] = true }
26
+ end
27
+ it { Retrieve.("dont_fail" => true ).inspect("x", "b", "y").must_equal %{<Result:true [true, nil, nil] >} }
28
+ it { Retrieve.("dont_fail" => false ).inspect("x", "b", "y").must_equal %{<Result:true [false, nil, nil] >} }
29
+
30
+ # #step fails fast if option set and returns false.
31
+ class Update < Trailblazer::Operation
32
+ step ->(options, *) { options["x"] = true }
33
+ step ->(options, *) { options["a"] = options["dont_fail"] }, fail_fast: true # only on false.
34
+ failure ->(options, *) { options["b"] = true }
35
+ step ->(options, *) { options["y"] = true }
36
+ end
37
+
38
+ it { Update.("dont_fail" => true).inspect("x", "a", "b", "y").must_equal %{<Result:true [true, true, nil, true] >} }
39
+ it { Update.({} ).inspect("x", "a", "b", "y").must_equal %{<Result:false [true, nil, nil, nil] >} }
40
+
41
+ # #step passes fast if option set and returns true.
42
+ class Delete < Trailblazer::Operation
43
+ step ->(options, *) { options["x"] = true }
44
+ step ->(options, *) { options["a"] = options["dont_fail"] }, pass_fast: true # only on true.
45
+ fail ->(options, *) { options["b"] = true }
46
+ step ->(options, *) { options["y"] = true }
47
+ end
48
+
49
+ it { Delete.("dont_fail" => true).inspect("x", "a", "b", "y").must_equal %{<Result:true [true, true, nil, nil] >} }
50
+ it { Delete.({} ).inspect("x", "a", "b", "y").must_equal %{<Result:false [true, nil, true, nil] >} }
51
+ end
52
+
53
+ class FailBangTest < Minitest::Spec
54
+ class Create < Trailblazer::Operation
55
+ step ->(options, *) { options["x"] = true; Railway.fail! }
56
+ step ->(options, *) { options["y"] = true }
57
+ failure ->(options, *) { options["a"] = true }
58
+ end
59
+
60
+ it { Create.().inspect("x", "y", "a").must_equal %{<Result:false [true, nil, true] >} }
61
+ end
62
+
63
+ class PassBangTest < Minitest::Spec
64
+ class Create < Trailblazer::Operation
65
+ step ->(options, *) { options["x"] = true; Railway.pass! }
66
+ step ->(options, *) { options["y"] = true }
67
+ failure ->(options, *) { options["a"] = true }
68
+ end
69
+
70
+ it { Create.().inspect("x", "y", "a").must_equal %{<Result:true [true, true, nil] >} }
71
+ end
72
+
73
+ class FailFastBangTest < Minitest::Spec
74
+ class Create < Trailblazer::Operation
75
+ step ->(options, *) { options["x"] = true; Railway.fail_fast! }
76
+ step ->(options, *) { options["y"] = true }
77
+ failure ->(options, *) { options["a"] = true }
78
+ end
79
+
80
+ # without proper configuration, emitting a FastTrack signal is illegal.
81
+ it { assert_raises(Trailblazer::Circuit::IllegalSignalError) { Create.().inspect("x", "y", "a").must_equal %{<Result:false [true, nil, nil] >} } }
82
+
83
+ class Update < Trailblazer::Operation
84
+ step ->(options, *) { options["x"] = true; Railway.fail_fast! }, fast_track: true
85
+ step ->(options, *) { options["y"] = true }
86
+ failure ->(options, *) { options["a"] = true }
87
+ end
88
+
89
+ it { Update.().inspect("x", "y", "a").must_equal %{<Result:false [true, nil, nil] >} }
90
+ end
91
+
92
+ class PassFastBangTest < Minitest::Spec
93
+ class Create < Trailblazer::Operation
94
+ step ->(options, *) { options["x"] = true; Railway.pass_fast! }, fast_track: true
95
+ step ->(options, *) { options["y"] = true }
96
+ failure ->(options, *) { options["a"] = true }
97
+ end
98
+
99
+ it { Create.().inspect("x", "y", "a").must_equal %{<Result:true [true, nil, nil] >} }
100
+ end
101
+
102
+ #-
103
+ class NestedFastTrackTest < Minitest::Spec
104
+ #- The ::step DSL method automatically connects the nested's End.fail_fast/End.pass_fast to Update's End.fail_fast/End.pass_fast.
105
+ #
106
+ # Edit has fast-tracked steps, so it has outputs :success/:failure/:pass_fast/:fail_fast.
107
+ class Edit < Trailblazer::Operation
108
+ step :a, fast_track: true # task is connected to End.pass_fast and End.fail_fast.
109
+
110
+ def a(options, edit_return:, **)
111
+ options["a"] = 1
112
+ edit_return # End.success, End.pass_fast, etc.
113
+ end
114
+ end
115
+
116
+ module Steps
117
+ def b(options, a:, **)
118
+ options["b"] = a+1
119
+ end
120
+
121
+ def f(options, **)
122
+ options["f"] = 3
123
+ end
124
+ end
125
+
126
+ describe "Nested, fast_track: true and all its outputs given" do
127
+ let(:update) do
128
+ Class.new(Trailblazer::Operation) do
129
+ step task: Trailblazer::Operation::Callable( Edit, call: :call_with_circuit_interface ), id: "Callable/",
130
+ outputs: Edit.outputs ,
131
+ fast_track: true
132
+ step :b
133
+ fail :f
134
+
135
+ include Steps
136
+ end
137
+ end
138
+
139
+ # Edit returns End.success
140
+ it { update.(edit_return: true).inspect("a", "b", "f").must_equal %{<Result:true [1, 2, nil] >} }
141
+ # Edit returns End.failure
142
+ it { update.(edit_return: false).inspect("a", "b", "f").must_equal %{<Result:false [1, nil, 3] >} }
143
+ # Edit returns End.pass_fast
144
+ it { update.(edit_return: Trailblazer::Operation::Railway.pass_fast!).inspect("a", "b", "f").must_equal %{<Result:true [1, nil, nil] >} }
145
+ # Edit returns End.fail_fast
146
+ it { update.(edit_return: Trailblazer::Operation::Railway.fail_fast!).inspect("a", "b", "f").must_equal %{<Result:false [1, nil, nil] >} }
147
+ end
148
+
149
+ describe "Nested, no :fast_track option but all its outputs given" do
150
+ let(:update) do
151
+ Class.new(Trailblazer::Operation) do
152
+ include Steps
153
+
154
+ step task: Trailblazer::Operation::Callable( Edit, call: :call_with_circuit_interface ), id: "Callable/",
155
+ outputs: Edit.outputs # all outputs given means it "works"
156
+ step :b
157
+ fail :f
158
+ end
159
+ end
160
+
161
+ # Edit returns End.success
162
+ it { update.(edit_return: true).inspect("a", "b", "f").must_equal %{<Result:true [1, 2, nil] >} }
163
+ # Edit returns End.failure
164
+ it { update.(edit_return: false).inspect("a", "b", "f").must_equal %{<Result:false [1, nil, 3] >} }
165
+ # Edit returns End.pass_fast
166
+ it { update.(edit_return: Trailblazer::Operation::Railway.pass_fast!).inspect("a", "b", "f").must_equal %{<Result:true [1, nil, nil] >} }
167
+ # Edit returns End.fail_fast
168
+ it { update.(edit_return: Trailblazer::Operation::Railway.fail_fast!).inspect("a", "b", "f").must_equal %{<Result:false [1, nil, nil] >} }
169
+ end
170
+
171
+ describe "2.0 behavior: no :fast_track option, all outputs given, but we rewire fast_track" do
172
+ let(:update) do
173
+ Class.new(Trailblazer::Operation) do
174
+ include Steps
175
+
176
+ step({task: Trailblazer::Operation::Callable( Edit, call: :call_with_circuit_interface ), id: "Callable/",
177
+ outputs: Edit.outputs },
178
+ {Output(:pass_fast) => Track(:success), Output(:fail_fast) => Track(:failure)} )# manually rewire the fast-track outputs to "conventional" railway ends.
179
+
180
+ step :b
181
+ fail :f
182
+ end
183
+ end
184
+
185
+ # it { puts Trailblazer::Activity::Introspect.Cct(update.instance_variable_get(:@process)) }
186
+ it { update.to_h }
187
+ # Edit returns End.success
188
+ it { update.(edit_return: true).inspect("a", "b", "f").must_equal %{<Result:true [1, 2, nil] >} }
189
+ # Edit returns End.failure
190
+ it { update.(edit_return: false).inspect("a", "b", "f").must_equal %{<Result:false [1, nil, 3] >} }
191
+ # Edit returns End.pass_fast, but behaves like :success.
192
+ it { update.(edit_return: Trailblazer::Operation::Railway.pass_fast!).inspect("a", "b", "f").must_equal %{<Result:true [1, 2, nil] >} }
193
+ # Edit returns End.fail_fast, but behaves like :failure.
194
+ it { update.(edit_return: Trailblazer::Operation::Railway.fail_fast!).inspect("a", "b", "f").must_equal %{<Result:false [1, nil, 3] >} }
195
+ end
196
+ end
197
+
@@ -1,6 +1,5 @@
1
1
  source 'https://rubygems.org'
2
2
  gemspec path: "../../"
3
3
 
4
- gem "declarative"
5
- gem "pipetree"
6
4
  gem "dry-container"
5
+ gem "minitest-line"
@@ -0,0 +1,40 @@
1
+ PATH
2
+ remote: ../..
3
+ specs:
4
+ trailblazer-operation (0.1.0)
5
+ declarative
6
+ trailblazer-activity (>= 0.1.3, < 0.2.0)
7
+
8
+ GEM
9
+ remote: https://rubygems.org/
10
+ specs:
11
+ concurrent-ruby (1.0.2)
12
+ declarative (0.0.9)
13
+ dry-configurable (0.4.0)
14
+ concurrent-ruby (~> 1.0)
15
+ dry-container (0.6.0)
16
+ concurrent-ruby (~> 1.0)
17
+ dry-configurable (~> 0.1, >= 0.1.3)
18
+ hirb (0.7.3)
19
+ minitest (5.10.2)
20
+ minitest-line (0.6.3)
21
+ minitest (~> 5.0)
22
+ raise (0.0.2)
23
+ rake (12.0.0)
24
+ trailblazer-activity (0.1.3)
25
+ hirb
26
+
27
+ PLATFORMS
28
+ ruby
29
+
30
+ DEPENDENCIES
31
+ bundler
32
+ dry-container
33
+ minitest
34
+ minitest-line
35
+ raise
36
+ rake
37
+ trailblazer-operation!
38
+
39
+ BUNDLED WITH
40
+ 1.15.3
@@ -23,6 +23,6 @@ class InheritanceTest < Minitest::Spec
23
23
  it do
24
24
  Update["a"].must_equal "A"
25
25
  Update["b"].must_equal "B"
26
- Update["c"].must_equal nil
26
+ Update["c"].must_be_nil
27
27
  end
28
28
  end
@@ -0,0 +1,43 @@
1
+ require "test_helper"
2
+
3
+
4
+ class InspectTest < Minitest::Spec
5
+ # Test: #to_table
6
+ class Create < Trailblazer::Operation
7
+ step :decide!
8
+ pass :wasnt_ok!
9
+ pass :was_ok!
10
+ fail :return_true!
11
+ fail :return_false!
12
+ step :finalize!
13
+ end
14
+
15
+ #---
16
+ #- to_table
17
+
18
+ # pp Create.instance_variable_get(:@builder)
19
+
20
+ it do
21
+ Trailblazer::Operation.introspect(Create).must_equal %{[>decide!,>>wasnt_ok!,>>was_ok!,<<return_true!,<<return_false!,>finalize!]}
22
+ end
23
+
24
+ it do
25
+ Trailblazer::Operation::Inspect.call(Create, style: :rows).must_equal %{
26
+ 0 ==============================>decide!
27
+ 1 ===========================>>wasnt_ok!
28
+ 2 =============================>>was_ok!
29
+ 3 <<return_true!========================
30
+ 4 <<return_false!=======================
31
+ 5 ============================>finalize!}
32
+ end
33
+
34
+ describe "step with only one output (happens with Nested)" do
35
+ class Present < Trailblazer::Operation
36
+ pass :ok!, outputs: {:success => Trailblazer::Activity::Output("signal", :success)}
37
+ end
38
+
39
+ it do
40
+ Trailblazer::Operation.introspect(Present).must_equal %{[>>ok!]}
41
+ end
42
+ end
43
+ end
@@ -0,0 +1,51 @@
1
+ require "test_helper"
2
+
3
+ class IntrospectTest < Minitest::Spec
4
+ A = ->(*args) { [ Activity::Right, *args ] }
5
+ B = ->(*args) { [ Activity::Right, *args ] }
6
+ C = ->(*args) { [ Activity::Right, *args ] }
7
+ D = ->(*args) { [ Activity::Right, *args ] }
8
+
9
+ let(:activity) do
10
+ nested = bc
11
+
12
+ Class.new(Trailblazer::Operation) do
13
+ step A
14
+ step nested, Output(nested.outputs.keys.first, :success) => :success
15
+ step D, id: "D"
16
+ end
17
+ end
18
+
19
+ let(:bc) do
20
+ Class.new(Trailblazer::Operation) do
21
+ step B
22
+ step C
23
+ end
24
+ end
25
+
26
+ describe "#collect" do
27
+ it "iterates over each task element in the top activity" do
28
+ skip
29
+ all_tasks = Activity::Introspect.collect(activity) do |task, connections|
30
+ task
31
+ end
32
+
33
+ # pp all_tasks
34
+
35
+ all_tasks.size.must_equal 8
36
+ # all_tasks[1..3].must_equal [A, bc, D]
37
+ # TODO: test start and end!
38
+ end
39
+
40
+ it "iterates over all task elements recursively" do
41
+ skip
42
+ all_tasks = Activity::Introspect.collect(activity, recursive: true) do |task, connections|
43
+ task
44
+ end
45
+
46
+ all_tasks.size.must_equal 9
47
+ all_tasks[1..2].must_equal [A, bc]
48
+ all_tasks[4..5].must_equal [B, C]
49
+ end
50
+ end
51
+ end
@@ -0,0 +1,60 @@
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
@@ -0,0 +1,94 @@
1
+ require "test_helper"
2
+
3
+ class DeclarativeApiTest < Minitest::Spec
4
+ #---
5
+ #- step, pass, fail
6
+
7
+ # Test: step/pass/fail
8
+ # * do they deviate properly?
9
+ class Create < Trailblazer::Operation
10
+ step :decide!
11
+ pass :wasnt_ok!
12
+ pass :was_ok!
13
+ fail :return_true!
14
+ fail :return_false!
15
+
16
+ def decide!(options, decide:raise, **)
17
+ options["a"] = true
18
+ decide
19
+ end
20
+
21
+ def wasnt_ok!(options, **)
22
+ options["y"] = false
23
+ end
24
+
25
+ def was_ok!(options, **)
26
+ options["x"] = true
27
+ end
28
+
29
+ def return_true! (options, **); options["b"] = true end
30
+ def return_false!(options, **); options["c"] = false end
31
+ end
32
+
33
+ it { Create.(decide: true).inspect("a", "x", "y", "b", "c").must_equal %{<Result:true [true, true, false, nil, nil] >} }
34
+ it { Create.(decide: false).inspect("a", "x", "y", "b", "c").must_equal %{<Result:false [true, nil, nil, true, false] >} }
35
+
36
+ #---
37
+ #- trace
38
+
39
+ it do
40
+
41
+ end
42
+
43
+ #---
44
+ #- empty class
45
+ class Noop < Trailblazer::Operation
46
+ end
47
+
48
+ it { Noop.().inspect("params").must_equal %{<Result:true [nil] >} }
49
+
50
+ #---
51
+ #- pass
52
+ #- fail
53
+ class Update < Trailblazer::Operation
54
+ pass ->(options, **) { options["a"] = false }
55
+ step ->(options, params:raise, **) { options["b"] = params[:decide] }
56
+ fail ->(options, **) { options["c"] = true }
57
+ end
58
+
59
+ it { Update.("params" => {decide: true}).inspect("a", "b", "c").must_equal %{<Result:true [false, true, nil] >} }
60
+ it { Update.("params" => {decide: false}).inspect("a", "b", "c").must_equal %{<Result:false [false, false, true] >} }
61
+
62
+ #---
63
+ #- inheritance
64
+ class Upsert < Update
65
+ step ->(options, **) { options["d"] = 1 }
66
+ end
67
+
68
+ class Unset < Upsert
69
+ step ->(options, **) { options["e"] = 2 }
70
+ end
71
+
72
+ it "allows to inherit" do
73
+ Upsert.("params" => {decide: true}).inspect("a", "b", "c", "d", "e").must_equal %{<Result:true [false, true, nil, 1, nil] >}
74
+ Unset. ("params" => {decide: true}).inspect("a", "b", "c", "d", "e").must_equal %{<Result:true [false, true, nil, 1, 2] >}
75
+ end
76
+
77
+ describe "Activity::Interface" do
78
+ class Edit < Trailblazer::Operation
79
+ step :a
80
+ step :b, fast_track: true
81
+ end
82
+
83
+ it "provides #outputs" do
84
+ Activity::Introspect.Outputs(Edit.outputs).must_equal %{success=> (#<Trailblazer::Operation::Railway::End::Success semantic=:success>, success)
85
+ failure=> (#<Trailblazer::Operation::Railway::End::Failure semantic=:failure>, failure)
86
+ pass_fast=> (#<Trailblazer::Operation::Railway::End::PassFast semantic=:pass_fast>, pass_fast)
87
+ fail_fast=> (#<Trailblazer::Operation::Railway::End::FailFast semantic=:fail_fast>, fail_fast)}
88
+ end
89
+
90
+ it "is an Interface" do
91
+ Edit.is_a?( Activity::Interface ).must_equal true
92
+ end
93
+ end
94
+ end