stepper_motor 0.1.17 → 0.1.19
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/CHANGELOG.md +12 -0
- data/lib/stepper_motor/conditional.rb +42 -0
- data/lib/stepper_motor/journey/flow_control.rb +1 -2
- data/lib/stepper_motor/journey.rb +110 -26
- data/lib/stepper_motor/step.rb +3 -19
- data/lib/stepper_motor/test_helper.rb +28 -3
- data/lib/stepper_motor/version.rb +1 -1
- data/lib/stepper_motor.rb +1 -0
- data/manual/MANUAL.md +182 -13
- data/rbi/stepper_motor.rbi +59 -12
- data/sig/stepper_motor.rbs +49 -7
- data/test/stepper_motor/journey/cancel_if_test.rb +293 -0
- data/test/stepper_motor/journey/if_condition_test.rb +1 -1
- data/test/stepper_motor/journey/step_definition_test.rb +1 -1
- data/test/stepper_motor/journey/step_ordering_test.rb +267 -0
- data/test/stepper_motor/test_helper_test.rb +59 -0
- data/test/stepper_motor/wrap_conditional_test.rb +190 -0
- data/test/test_helper.rb +3 -2
- metadata +10 -3
@@ -0,0 +1,267 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "test_helper"
|
4
|
+
|
5
|
+
class StepOrderingTest < ActiveSupport::TestCase
|
6
|
+
include ActiveJob::TestHelper
|
7
|
+
include SideEffects::TestHelper
|
8
|
+
include StepperMotor::TestHelper
|
9
|
+
|
10
|
+
test "allows inserting step before another step using string" do
|
11
|
+
journey_class = create_journey_subclass do
|
12
|
+
step :first do
|
13
|
+
# noop
|
14
|
+
end
|
15
|
+
step :third do
|
16
|
+
# noop
|
17
|
+
end
|
18
|
+
step :second, before_step: "first" do
|
19
|
+
# noop
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
assert_equal ["second", "first", "third"], journey_class.step_definitions.map(&:name)
|
24
|
+
end
|
25
|
+
|
26
|
+
test "allows inserting step before another step using symbol" do
|
27
|
+
journey_class = create_journey_subclass do
|
28
|
+
step :first do
|
29
|
+
# noop
|
30
|
+
end
|
31
|
+
step :third do
|
32
|
+
# noop
|
33
|
+
end
|
34
|
+
step :second, before_step: :first do
|
35
|
+
# noop
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
assert_equal ["second", "first", "third"], journey_class.step_definitions.map(&:name)
|
40
|
+
end
|
41
|
+
|
42
|
+
test "allows inserting step after another step using string" do
|
43
|
+
journey_class = create_journey_subclass do
|
44
|
+
step :first do
|
45
|
+
# noop
|
46
|
+
end
|
47
|
+
step :third do
|
48
|
+
# noop
|
49
|
+
end
|
50
|
+
step :second, after_step: "first" do
|
51
|
+
# noop
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
assert_equal ["first", "second", "third"], journey_class.step_definitions.map(&:name)
|
56
|
+
end
|
57
|
+
|
58
|
+
test "allows inserting step after another step using symbol" do
|
59
|
+
journey_class = create_journey_subclass do
|
60
|
+
step :first do
|
61
|
+
# noop
|
62
|
+
end
|
63
|
+
step :third do
|
64
|
+
# noop
|
65
|
+
end
|
66
|
+
step :second, after_step: :first do
|
67
|
+
# noop
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
assert_equal ["first", "second", "third"], journey_class.step_definitions.map(&:name)
|
72
|
+
end
|
73
|
+
|
74
|
+
test "allows inserting step at the beginning using before_step" do
|
75
|
+
journey_class = create_journey_subclass do
|
76
|
+
step :second do
|
77
|
+
# noop
|
78
|
+
end
|
79
|
+
step :third do
|
80
|
+
# noop
|
81
|
+
end
|
82
|
+
step :first, before_step: "second" do
|
83
|
+
# noop
|
84
|
+
end
|
85
|
+
end
|
86
|
+
|
87
|
+
assert_equal ["first", "second", "third"], journey_class.step_definitions.map(&:name)
|
88
|
+
end
|
89
|
+
|
90
|
+
test "allows inserting step at the end using after_step" do
|
91
|
+
journey_class = create_journey_subclass do
|
92
|
+
step :first do
|
93
|
+
# noop
|
94
|
+
end
|
95
|
+
step :second do
|
96
|
+
# noop
|
97
|
+
end
|
98
|
+
step :third, after_step: "second" do
|
99
|
+
# noop
|
100
|
+
end
|
101
|
+
end
|
102
|
+
|
103
|
+
assert_equal ["first", "second", "third"], journey_class.step_definitions.map(&:name)
|
104
|
+
end
|
105
|
+
|
106
|
+
test "allows complex step ordering with multiple insertions" do
|
107
|
+
journey_class = create_journey_subclass do
|
108
|
+
step :step_1 do
|
109
|
+
# noop
|
110
|
+
end
|
111
|
+
step :step_4 do
|
112
|
+
# noop
|
113
|
+
end
|
114
|
+
step :step_2, after_step: "step_1" do
|
115
|
+
# noop
|
116
|
+
end
|
117
|
+
step :step_3, before_step: "step_4" do
|
118
|
+
# noop
|
119
|
+
end
|
120
|
+
end
|
121
|
+
|
122
|
+
assert_equal ["step_1", "step_2", "step_3", "step_4"], journey_class.step_definitions.map(&:name)
|
123
|
+
end
|
124
|
+
|
125
|
+
test "raises error when both before_step and after_step are specified" do
|
126
|
+
assert_raises(StepperMotor::StepConfigurationError, "Either before_step: or after_step: can be specified, but not both") do
|
127
|
+
create_journey_subclass do
|
128
|
+
step :first do
|
129
|
+
# noop
|
130
|
+
end
|
131
|
+
step :second, before_step: "first", after_step: "first" do
|
132
|
+
# noop
|
133
|
+
end
|
134
|
+
end
|
135
|
+
end
|
136
|
+
end
|
137
|
+
|
138
|
+
test "raises error when before_step references non-existent step" do
|
139
|
+
assert_raises(StepperMotor::StepConfigurationError, "Step named \"nonexistent\" not found for before_step: parameter") do
|
140
|
+
create_journey_subclass do
|
141
|
+
step :first, before_step: "nonexistent" do
|
142
|
+
# noop
|
143
|
+
end
|
144
|
+
end
|
145
|
+
end
|
146
|
+
end
|
147
|
+
|
148
|
+
test "raises error when after_step references non-existent step" do
|
149
|
+
assert_raises(StepperMotor::StepConfigurationError, "Step named \"nonexistent\" not found for after_step: parameter") do
|
150
|
+
create_journey_subclass do
|
151
|
+
step :first, after_step: "nonexistent" do
|
152
|
+
# noop
|
153
|
+
end
|
154
|
+
end
|
155
|
+
end
|
156
|
+
end
|
157
|
+
|
158
|
+
test "maintains existing after: timing functionality" do
|
159
|
+
journey_class = create_journey_subclass do
|
160
|
+
step :first, after: 5.minutes do
|
161
|
+
# noop
|
162
|
+
end
|
163
|
+
step :second, after: 10.minutes do
|
164
|
+
# noop
|
165
|
+
end
|
166
|
+
end
|
167
|
+
|
168
|
+
assert_equal ["first", "second"], journey_class.step_definitions.map(&:name)
|
169
|
+
assert_equal 5.minutes, journey_class.step_definitions[0].wait
|
170
|
+
assert_equal 5.minutes, journey_class.step_definitions[1].wait
|
171
|
+
end
|
172
|
+
|
173
|
+
test "allows mixing step ordering with timing" do
|
174
|
+
journey_class = create_journey_subclass do
|
175
|
+
step :first, wait: 1.minute do
|
176
|
+
# noop
|
177
|
+
end
|
178
|
+
step :third, after_step: "first" do
|
179
|
+
# noop
|
180
|
+
end
|
181
|
+
step :second, before_step: "third", wait: 2.minutes do
|
182
|
+
# noop
|
183
|
+
end
|
184
|
+
end
|
185
|
+
|
186
|
+
assert_equal ["first", "second", "third"], journey_class.step_definitions.map(&:name)
|
187
|
+
assert_equal 1.minute, journey_class.step_definitions[0].wait
|
188
|
+
assert_equal 2.minutes, journey_class.step_definitions[1].wait
|
189
|
+
assert_equal 0, journey_class.step_definitions[2].wait
|
190
|
+
end
|
191
|
+
|
192
|
+
test "allows inserting step with method name" do
|
193
|
+
journey_class = create_journey_subclass do
|
194
|
+
step :first do
|
195
|
+
# noop
|
196
|
+
end
|
197
|
+
step :third do
|
198
|
+
# noop
|
199
|
+
end
|
200
|
+
step :second, after_step: "first"
|
201
|
+
|
202
|
+
def second
|
203
|
+
# noop
|
204
|
+
end
|
205
|
+
end
|
206
|
+
|
207
|
+
assert_equal ["first", "second", "third"], journey_class.step_definitions.map(&:name)
|
208
|
+
end
|
209
|
+
|
210
|
+
test "allows inserting step with automatic name generation" do
|
211
|
+
journey_class = create_journey_subclass do
|
212
|
+
step :first do
|
213
|
+
# noop
|
214
|
+
end
|
215
|
+
step :third do
|
216
|
+
# noop
|
217
|
+
end
|
218
|
+
step before_step: "third" do
|
219
|
+
# noop
|
220
|
+
end
|
221
|
+
end
|
222
|
+
|
223
|
+
assert_equal ["first", "step_3", "third"], journey_class.step_definitions.map(&:name)
|
224
|
+
end
|
225
|
+
|
226
|
+
test "allows inserting step with additional options" do
|
227
|
+
journey_class = create_journey_subclass do
|
228
|
+
step :first do
|
229
|
+
# noop
|
230
|
+
end
|
231
|
+
step :third do
|
232
|
+
# noop
|
233
|
+
end
|
234
|
+
step :second, after_step: "first", on_exception: :skip! do
|
235
|
+
# noop
|
236
|
+
end
|
237
|
+
end
|
238
|
+
|
239
|
+
assert_equal ["first", "second", "third"], journey_class.step_definitions.map(&:name)
|
240
|
+
assert_equal :skip!, journey_class.step_definitions[1].instance_variable_get(:@on_exception)
|
241
|
+
end
|
242
|
+
|
243
|
+
test "allows inserting steps before or after steps defined in superclass" do
|
244
|
+
parent_class = create_journey_subclass do
|
245
|
+
step :parent_first do
|
246
|
+
# noop
|
247
|
+
end
|
248
|
+
step :parent_last do
|
249
|
+
# noop
|
250
|
+
end
|
251
|
+
end
|
252
|
+
|
253
|
+
child_class = create_journey_subclass(parent_class) do
|
254
|
+
step :child_before, before_step: "parent_first" do
|
255
|
+
# noop
|
256
|
+
end
|
257
|
+
step :child_after, after_step: "parent_last" do
|
258
|
+
# noop
|
259
|
+
end
|
260
|
+
step :child_middle, after_step: "parent_first" do
|
261
|
+
# noop
|
262
|
+
end
|
263
|
+
end
|
264
|
+
|
265
|
+
assert_equal ["child_before", "parent_first", "child_middle", "parent_last", "child_after"], child_class.step_definitions.map(&:name)
|
266
|
+
end
|
267
|
+
end
|
@@ -22,6 +22,16 @@ class TestHelperTest < ActiveSupport::TestCase
|
|
22
22
|
end
|
23
23
|
end
|
24
24
|
|
25
|
+
def infinite_journey_class
|
26
|
+
create_journey_subclass do
|
27
|
+
step :step_1 do
|
28
|
+
SideEffects.touch!("step_1")
|
29
|
+
# This step never finishes, causing infinite loop
|
30
|
+
reattempt!
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
25
35
|
test "speedruns the journey despite waits being configured" do
|
26
36
|
journey = speedy_journey_class.create!
|
27
37
|
assert journey.ready?
|
@@ -33,6 +43,36 @@ class TestHelperTest < ActiveSupport::TestCase
|
|
33
43
|
assert SideEffects.produced?("step_3")
|
34
44
|
end
|
35
45
|
|
46
|
+
test "speedruns the journey with time travel by default" do
|
47
|
+
journey = speedy_journey_class.create!
|
48
|
+
assert journey.ready?
|
49
|
+
|
50
|
+
original_time = Time.current
|
51
|
+
SideEffects.clear!
|
52
|
+
speedrun_journey(journey)
|
53
|
+
assert SideEffects.produced?("step_1")
|
54
|
+
assert SideEffects.produced?("step_2")
|
55
|
+
assert SideEffects.produced?("step_3")
|
56
|
+
|
57
|
+
# Calculate expected time difference: 40 minutes + 2 days + 1 second buffer per step
|
58
|
+
expected_time_difference = 40.minutes + 2.days + 3.seconds
|
59
|
+
|
60
|
+
# Verify that time has traveled forward by approximately the expected amount
|
61
|
+
# (allowing for small execution time differences)
|
62
|
+
assert_in_delta expected_time_difference, Time.current - original_time, 1.second
|
63
|
+
end
|
64
|
+
|
65
|
+
test "speedruns the journey without time travel when specified" do
|
66
|
+
journey = speedy_journey_class.create!
|
67
|
+
assert journey.ready?
|
68
|
+
|
69
|
+
SideEffects.clear!
|
70
|
+
speedrun_journey(journey, time_travel: false)
|
71
|
+
assert SideEffects.produced?("step_1")
|
72
|
+
assert SideEffects.produced?("step_2")
|
73
|
+
assert SideEffects.produced?("step_3")
|
74
|
+
end
|
75
|
+
|
36
76
|
test "is able to perform a single step forcibly" do
|
37
77
|
journey = speedy_journey_class.create!
|
38
78
|
assert journey.ready?
|
@@ -41,4 +81,23 @@ class TestHelperTest < ActiveSupport::TestCase
|
|
41
81
|
immediately_perform_single_step(journey, :step_2)
|
42
82
|
assert SideEffects.produced?("step_2")
|
43
83
|
end
|
84
|
+
|
85
|
+
test "fails when maximum_steps limit is exceeded" do
|
86
|
+
journey = infinite_journey_class.create!
|
87
|
+
assert journey.ready?
|
88
|
+
|
89
|
+
SideEffects.clear!
|
90
|
+
|
91
|
+
# This should raise an exception because the journey will try to perform more than 2 steps
|
92
|
+
# but the infinite loop in step_1 will never finish
|
93
|
+
error = assert_raises(RuntimeError) do
|
94
|
+
speedrun_journey(journey, maximum_steps: 2)
|
95
|
+
end
|
96
|
+
|
97
|
+
# Verify the error message indicates the journey didn't finish after the maximum steps
|
98
|
+
assert_match(/did not finish or cancel after performing 2 steps/, error.message)
|
99
|
+
|
100
|
+
# Verify that the step was executed (at least once)
|
101
|
+
assert SideEffects.produced?("step_1")
|
102
|
+
end
|
44
103
|
end
|
@@ -0,0 +1,190 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "test_helper"
|
4
|
+
|
5
|
+
class WrapConditionalTest < ActiveSupport::TestCase
|
6
|
+
# Validate the skip_if condition
|
7
|
+
# if ![true, false, nil].include?(@skip_if_condition) && !@skip_if_condition.is_a?(Symbol) && !@skip_if_condition.respond_to?(:call)
|
8
|
+
# raise ArgumentError, "skip_if: condition must be a boolean, nil, Symbol or a callable object, but was a #{@skip_if_condition.inspect}"
|
9
|
+
# end
|
10
|
+
|
11
|
+
test "wraps true without negate" do
|
12
|
+
conditional = StepperMotor::Conditional.new(true)
|
13
|
+
assert_equal true, conditional.satisfied_by?(nil)
|
14
|
+
assert_equal true, conditional.satisfied_by?("something")
|
15
|
+
end
|
16
|
+
|
17
|
+
test "wraps true with negate" do
|
18
|
+
conditional = StepperMotor::Conditional.new(true, negate: true)
|
19
|
+
assert_equal false, conditional.satisfied_by?(nil)
|
20
|
+
assert_equal false, conditional.satisfied_by?("something")
|
21
|
+
end
|
22
|
+
|
23
|
+
test "wraps false without negate" do
|
24
|
+
conditional = StepperMotor::Conditional.new(false)
|
25
|
+
assert_equal false, conditional.satisfied_by?(nil)
|
26
|
+
assert_equal false, conditional.satisfied_by?("something")
|
27
|
+
end
|
28
|
+
|
29
|
+
test "wraps false with negate" do
|
30
|
+
conditional = StepperMotor::Conditional.new(false, negate: true)
|
31
|
+
assert_equal true, conditional.satisfied_by?(nil)
|
32
|
+
assert_equal true, conditional.satisfied_by?("something")
|
33
|
+
end
|
34
|
+
|
35
|
+
test "wraps nil without negate" do
|
36
|
+
conditional = StepperMotor::Conditional.new(nil)
|
37
|
+
assert_equal false, conditional.satisfied_by?(nil)
|
38
|
+
assert_equal false, conditional.satisfied_by?("something")
|
39
|
+
end
|
40
|
+
|
41
|
+
test "wraps nil with negate" do
|
42
|
+
conditional = StepperMotor::Conditional.new(nil, negate: true)
|
43
|
+
assert_equal true, conditional.satisfied_by?(nil)
|
44
|
+
assert_equal true, conditional.satisfied_by?("something")
|
45
|
+
end
|
46
|
+
|
47
|
+
test "wraps multiple without negate" do
|
48
|
+
conditional = StepperMotor::Conditional.new([true, true])
|
49
|
+
assert_equal true, conditional.satisfied_by?(nil)
|
50
|
+
|
51
|
+
conditional = StepperMotor::Conditional.new([true, false])
|
52
|
+
assert_equal false, conditional.satisfied_by?(nil)
|
53
|
+
|
54
|
+
conditional = StepperMotor::Conditional.new([false, false])
|
55
|
+
assert_equal false, conditional.satisfied_by?(nil)
|
56
|
+
end
|
57
|
+
|
58
|
+
test "wraps multiple with proc" do
|
59
|
+
conditional = StepperMotor::Conditional.new([true, -> { true }])
|
60
|
+
assert_equal true, conditional.satisfied_by?(nil)
|
61
|
+
|
62
|
+
conditional = StepperMotor::Conditional.new([true, -> { false }])
|
63
|
+
assert_equal false, conditional.satisfied_by?(nil)
|
64
|
+
end
|
65
|
+
|
66
|
+
test "wraps multiple with negate" do
|
67
|
+
conditional = StepperMotor::Conditional.new([true, true], negate: true)
|
68
|
+
assert_equal false, conditional.satisfied_by?(nil)
|
69
|
+
|
70
|
+
conditional = StepperMotor::Conditional.new([true, false], negate: true)
|
71
|
+
assert_equal true, conditional.satisfied_by?(nil)
|
72
|
+
|
73
|
+
conditional = StepperMotor::Conditional.new([false, false], negate: true)
|
74
|
+
assert_equal true, conditional.satisfied_by?(nil)
|
75
|
+
end
|
76
|
+
|
77
|
+
test "wraps callable without negate" do
|
78
|
+
conditional = StepperMotor::Conditional.new(-> { :foo })
|
79
|
+
assert_equal true, conditional.satisfied_by?(nil)
|
80
|
+
|
81
|
+
conditional = StepperMotor::Conditional.new(-> {})
|
82
|
+
assert_equal false, conditional.satisfied_by?(nil)
|
83
|
+
|
84
|
+
conditional = StepperMotor::Conditional.new(-> { false })
|
85
|
+
assert_equal false, conditional.satisfied_by?(nil)
|
86
|
+
|
87
|
+
conditional = StepperMotor::Conditional.new(-> { true })
|
88
|
+
assert_equal true, conditional.satisfied_by?(nil)
|
89
|
+
end
|
90
|
+
|
91
|
+
test "wraps callable with negate" do
|
92
|
+
conditional = StepperMotor::Conditional.new(-> { :foo }, negate: true)
|
93
|
+
assert_equal false, conditional.satisfied_by?(nil)
|
94
|
+
|
95
|
+
conditional = StepperMotor::Conditional.new(-> {}, negate: true)
|
96
|
+
assert_equal true, conditional.satisfied_by?(nil)
|
97
|
+
|
98
|
+
conditional = StepperMotor::Conditional.new(-> { false }, negate: true)
|
99
|
+
assert_equal true, conditional.satisfied_by?(nil)
|
100
|
+
|
101
|
+
conditional = StepperMotor::Conditional.new(-> { true }, negate: true)
|
102
|
+
assert_equal false, conditional.satisfied_by?(nil)
|
103
|
+
end
|
104
|
+
|
105
|
+
class Doer
|
106
|
+
def should_do?
|
107
|
+
true
|
108
|
+
end
|
109
|
+
end
|
110
|
+
|
111
|
+
class NotDoer
|
112
|
+
def should_do?
|
113
|
+
false
|
114
|
+
end
|
115
|
+
end
|
116
|
+
|
117
|
+
test "wraps method without negate" do
|
118
|
+
doer = Doer.new
|
119
|
+
|
120
|
+
conditional = StepperMotor::Conditional.new(:should_do?)
|
121
|
+
assert_equal true, conditional.satisfied_by?(doer)
|
122
|
+
|
123
|
+
not_doer = NotDoer.new
|
124
|
+
assert_equal false, conditional.satisfied_by?(not_doer)
|
125
|
+
end
|
126
|
+
|
127
|
+
test "wraps method with negate" do
|
128
|
+
doer = Doer.new
|
129
|
+
|
130
|
+
conditional = StepperMotor::Conditional.new(:should_do?, negate: true)
|
131
|
+
assert_equal false, conditional.satisfied_by?(doer)
|
132
|
+
|
133
|
+
not_doer = NotDoer.new
|
134
|
+
assert_equal true, conditional.satisfied_by?(not_doer)
|
135
|
+
end
|
136
|
+
|
137
|
+
test "wraps conditional without negate" do
|
138
|
+
inner_conditional = StepperMotor::Conditional.new(true)
|
139
|
+
outer_conditional = StepperMotor::Conditional.new(inner_conditional)
|
140
|
+
|
141
|
+
assert_equal true, outer_conditional.satisfied_by?(nil)
|
142
|
+
assert_equal true, outer_conditional.satisfied_by?("something")
|
143
|
+
end
|
144
|
+
|
145
|
+
test "wraps conditional with negate" do
|
146
|
+
inner_conditional = StepperMotor::Conditional.new(true)
|
147
|
+
outer_conditional = StepperMotor::Conditional.new(inner_conditional, negate: true)
|
148
|
+
|
149
|
+
assert_equal false, outer_conditional.satisfied_by?(nil)
|
150
|
+
assert_equal false, outer_conditional.satisfied_by?("something")
|
151
|
+
end
|
152
|
+
|
153
|
+
test "wraps negated conditional without negate" do
|
154
|
+
inner_conditional = StepperMotor::Conditional.new(true, negate: true)
|
155
|
+
outer_conditional = StepperMotor::Conditional.new(inner_conditional)
|
156
|
+
|
157
|
+
assert_equal false, outer_conditional.satisfied_by?(nil)
|
158
|
+
assert_equal false, outer_conditional.satisfied_by?("something")
|
159
|
+
end
|
160
|
+
|
161
|
+
test "wraps negated conditional with negate" do
|
162
|
+
inner_conditional = StepperMotor::Conditional.new(true, negate: true)
|
163
|
+
outer_conditional = StepperMotor::Conditional.new(inner_conditional, negate: true)
|
164
|
+
|
165
|
+
assert_equal true, outer_conditional.satisfied_by?(nil)
|
166
|
+
assert_equal true, outer_conditional.satisfied_by?("something")
|
167
|
+
end
|
168
|
+
|
169
|
+
test "wraps conditional with method" do
|
170
|
+
doer = Doer.new
|
171
|
+
inner_conditional = StepperMotor::Conditional.new(:should_do?)
|
172
|
+
outer_conditional = StepperMotor::Conditional.new(inner_conditional)
|
173
|
+
|
174
|
+
assert_equal true, outer_conditional.satisfied_by?(doer)
|
175
|
+
|
176
|
+
not_doer = NotDoer.new
|
177
|
+
assert_equal false, outer_conditional.satisfied_by?(not_doer)
|
178
|
+
end
|
179
|
+
|
180
|
+
test "wraps conditional with method and negate" do
|
181
|
+
doer = Doer.new
|
182
|
+
inner_conditional = StepperMotor::Conditional.new(:should_do?)
|
183
|
+
outer_conditional = StepperMotor::Conditional.new(inner_conditional, negate: true)
|
184
|
+
|
185
|
+
assert_equal false, outer_conditional.satisfied_by?(doer)
|
186
|
+
|
187
|
+
not_doer = NotDoer.new
|
188
|
+
assert_equal true, outer_conditional.satisfied_by?(not_doer)
|
189
|
+
end
|
190
|
+
end
|
data/test/test_helper.rb
CHANGED
@@ -32,11 +32,12 @@ module JourneyDefinitionHelper
|
|
32
32
|
super
|
33
33
|
end
|
34
34
|
|
35
|
-
def create_journey_subclass(&blk)
|
35
|
+
def create_journey_subclass(parent_class = nil, &blk)
|
36
36
|
# https://stackoverflow.com/questions/4113479/dynamic-class-definition-with-a-class-name
|
37
37
|
random_component = @class_names_rng.hex(8)
|
38
38
|
random_name = "JourneySubclass_#{random_component}"
|
39
|
-
|
39
|
+
parent_class ||= StepperMotor::Journey
|
40
|
+
klass = Class.new(parent_class, &blk)
|
40
41
|
Object.const_set(random_name, klass)
|
41
42
|
@dynamic_class_names << random_name
|
42
43
|
klass
|
metadata
CHANGED
@@ -1,13 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: stepper_motor
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1.
|
4
|
+
version: 0.1.19
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Julik Tarkhanov
|
8
|
+
autorequire:
|
8
9
|
bindir: exe
|
9
10
|
cert_chain: []
|
10
|
-
date: 2025-06-
|
11
|
+
date: 2025-06-25 00:00:00.000000000 Z
|
11
12
|
dependencies:
|
12
13
|
- !ruby/object:Gem::Dependency
|
13
14
|
name: activerecord
|
@@ -236,6 +237,7 @@ files:
|
|
236
237
|
- lib/generators/stepper_motor_migration_005.rb.erb
|
237
238
|
- lib/stepper_motor.rb
|
238
239
|
- lib/stepper_motor/base_job.rb
|
240
|
+
- lib/stepper_motor/conditional.rb
|
239
241
|
- lib/stepper_motor/cyclic_scheduler.rb
|
240
242
|
- lib/stepper_motor/delete_completed_journeys_job.rb
|
241
243
|
- lib/stepper_motor/forward_scheduler.rb
|
@@ -309,17 +311,20 @@ files:
|
|
309
311
|
- test/stepper_motor/cyclic_scheduler_test.rb
|
310
312
|
- test/stepper_motor/forward_scheduler_test.rb
|
311
313
|
- test/stepper_motor/housekeeping_job_test.rb
|
314
|
+
- test/stepper_motor/journey/cancel_if_test.rb
|
312
315
|
- test/stepper_motor/journey/exception_handling_test.rb
|
313
316
|
- test/stepper_motor/journey/flow_control_test.rb
|
314
317
|
- test/stepper_motor/journey/idempotency_test.rb
|
315
318
|
- test/stepper_motor/journey/if_condition_test.rb
|
316
319
|
- test/stepper_motor/journey/step_definition_test.rb
|
320
|
+
- test/stepper_motor/journey/step_ordering_test.rb
|
317
321
|
- test/stepper_motor/journey/uniqueness_test.rb
|
318
322
|
- test/stepper_motor/journey_test.rb
|
319
323
|
- test/stepper_motor/perform_step_job_test.rb
|
320
324
|
- test/stepper_motor/recover_stuck_journeys_job_test.rb
|
321
325
|
- test/stepper_motor/recovery_test.rb
|
322
326
|
- test/stepper_motor/test_helper_test.rb
|
327
|
+
- test/stepper_motor/wrap_conditional_test.rb
|
323
328
|
- test/stepper_motor_test.rb
|
324
329
|
- test/test_helper.rb
|
325
330
|
homepage: https://steppermotor.dev
|
@@ -330,6 +335,7 @@ metadata:
|
|
330
335
|
homepage_uri: https://steppermotor.dev
|
331
336
|
source_code_uri: https://github.com/stepper-motor/stepper_motor
|
332
337
|
changelog_uri: https://github.com/stepper-motor/stepper_motor/blob/main/CHANGELOG.md
|
338
|
+
post_install_message:
|
333
339
|
rdoc_options: []
|
334
340
|
require_paths:
|
335
341
|
- lib
|
@@ -344,7 +350,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
344
350
|
- !ruby/object:Gem::Version
|
345
351
|
version: '0'
|
346
352
|
requirements: []
|
347
|
-
rubygems_version: 3.
|
353
|
+
rubygems_version: 3.4.10
|
354
|
+
signing_key:
|
348
355
|
specification_version: 4
|
349
356
|
summary: Effortless step workflows that embed nicely inside Rails
|
350
357
|
test_files: []
|