stepper_motor 0.1.12 → 0.1.16

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.
@@ -0,0 +1,355 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "test_helper"
4
+ require "minitest/mock"
5
+
6
+ class IfConditionTest < ActiveSupport::TestCase
7
+ include ActiveJob::TestHelper
8
+ include SideEffects::TestHelper
9
+ include StepperMotor::TestHelper
10
+
11
+ test "supports skip_if: with symbol condition that returns false (performs step)" do
12
+ journey_class = create_journey_subclass do
13
+ step :one, skip_if: :should_skip do
14
+ SideEffects.touch!("step executed")
15
+ end
16
+
17
+ def should_skip
18
+ false
19
+ end
20
+ end
21
+
22
+ journey = journey_class.create!
23
+ assert_produced_side_effects("step executed") do
24
+ journey.perform_next_step!
25
+ end
26
+ assert journey.finished?
27
+ end
28
+
29
+ test "supports skip_if: with symbol condition that returns true (skips step)" do
30
+ journey_class = create_journey_subclass do
31
+ step :one, skip_if: :should_skip do
32
+ SideEffects.touch!("step executed")
33
+ end
34
+
35
+ step :two do
36
+ SideEffects.touch!("second step executed")
37
+ end
38
+
39
+ def should_skip
40
+ true
41
+ end
42
+ end
43
+
44
+ journey = journey_class.create!
45
+ speedrun_journey(journey)
46
+ assert SideEffects.produced?("second step executed")
47
+ refute SideEffects.produced?("step executed")
48
+ end
49
+
50
+ test "supports skip_if: with block condition that returns false (performs step)" do
51
+ journey_class = create_journey_subclass do
52
+ step :one, skip_if: -> { hero.nil? } do
53
+ SideEffects.touch!("step executed")
54
+ end
55
+ end
56
+
57
+ journey = journey_class.create!(hero: create_journey_subclass.create!)
58
+ assert_produced_side_effects("step executed") do
59
+ journey.perform_next_step!
60
+ end
61
+ assert journey.finished?
62
+ end
63
+
64
+ test "supports skip_if: with block condition that returns true (skips step)" do
65
+ journey_class = create_journey_subclass do
66
+ step :one, skip_if: -> { hero.present? } do
67
+ SideEffects.touch!("step executed")
68
+ end
69
+
70
+ step :two do
71
+ SideEffects.touch!("second step executed")
72
+ end
73
+ end
74
+
75
+ journey = journey_class.create!(hero: create_journey_subclass.create!)
76
+ speedrun_journey(journey)
77
+ assert SideEffects.produced?("second step executed")
78
+ refute SideEffects.produced?("step executed")
79
+ end
80
+
81
+ test "supports skip_if: with block condition that accesses journey instance variables" do
82
+ journey_class = create_journey_subclass do
83
+ step :one, skip_if: -> { @condition_met } do
84
+ SideEffects.touch!("step executed")
85
+ end
86
+
87
+ step :two do
88
+ SideEffects.touch!("second step executed")
89
+ end
90
+
91
+ def initialize(*args)
92
+ super
93
+ @condition_met = true
94
+ end
95
+ end
96
+
97
+ journey = journey_class.create!
98
+ speedrun_journey(journey)
99
+ assert SideEffects.produced?("second step executed")
100
+ refute SideEffects.produced?("step executed")
101
+ end
102
+
103
+ test "supports skip_if: with block condition that can be changed during journey execution" do
104
+ journey_class = create_journey_subclass do
105
+ step :one, skip_if: -> { @condition_met } do
106
+ SideEffects.touch!("first step executed")
107
+ end
108
+
109
+ step :two do
110
+ SideEffects.touch!("second step executed")
111
+ @condition_met = false
112
+ end
113
+
114
+ step :three, skip_if: -> { @condition_met } do
115
+ SideEffects.touch!("third step executed")
116
+ end
117
+
118
+ def initialize(*args)
119
+ super
120
+ @condition_met = true
121
+ end
122
+ end
123
+
124
+ journey = journey_class.create!
125
+ speedrun_journey(journey)
126
+ assert SideEffects.produced?("second step executed")
127
+ assert SideEffects.produced?("third step executed")
128
+ refute SideEffects.produced?("first step executed")
129
+ end
130
+
131
+ test "skips step when skip_if: condition is true and continues to next step" do
132
+ journey_class = create_journey_subclass do
133
+ step :one, skip_if: :true_condition do
134
+ SideEffects.touch!("first step executed")
135
+ end
136
+
137
+ step :two do
138
+ SideEffects.touch!("second step executed")
139
+ end
140
+
141
+ step :three do
142
+ SideEffects.touch!("third step executed")
143
+ end
144
+
145
+ def true_condition
146
+ true
147
+ end
148
+ end
149
+
150
+ journey = journey_class.create!
151
+ speedrun_journey(journey)
152
+ assert SideEffects.produced?("second step executed")
153
+ assert SideEffects.produced?("third step executed")
154
+ refute SideEffects.produced?("first step executed")
155
+ end
156
+
157
+ test "skips step when skip_if: condition is true and finishes journey if no more steps" do
158
+ journey_class = create_journey_subclass do
159
+ step :one, skip_if: :true_condition do
160
+ SideEffects.touch!("step executed")
161
+ end
162
+
163
+ def true_condition
164
+ true
165
+ end
166
+ end
167
+
168
+ journey = journey_class.create!
169
+ speedrun_journey(journey)
170
+ refute SideEffects.produced?("step executed")
171
+ end
172
+
173
+ test "supports skip_if: with literal false (performs step)" do
174
+ journey_class = create_journey_subclass do
175
+ step :one, skip_if: false do
176
+ SideEffects.touch!("step executed")
177
+ end
178
+ end
179
+
180
+ journey = journey_class.create!
181
+ assert_produced_side_effects("step executed") do
182
+ journey.perform_next_step!
183
+ end
184
+ assert journey.finished?
185
+ end
186
+
187
+ test "supports skip_if: with literal true (skips step)" do
188
+ journey_class = create_journey_subclass do
189
+ step :one, skip_if: true do
190
+ SideEffects.touch!("step executed")
191
+ end
192
+
193
+ step :two do
194
+ SideEffects.touch!("second step executed")
195
+ end
196
+ end
197
+
198
+ journey = journey_class.create!
199
+ speedrun_journey(journey)
200
+ assert SideEffects.produced?("second step executed")
201
+ refute SideEffects.produced?("step executed")
202
+ end
203
+
204
+ test "supports skip_if: with literal true and finishes journey if no more steps" do
205
+ journey_class = create_journey_subclass do
206
+ step :one, skip_if: true do
207
+ SideEffects.touch!("step executed")
208
+ end
209
+ end
210
+
211
+ journey = journey_class.create!
212
+ speedrun_journey(journey)
213
+ refute SideEffects.produced?("step executed")
214
+ end
215
+
216
+ test "defaults to false when skip_if: is not specified" do
217
+ journey_class = create_journey_subclass do
218
+ step :one do
219
+ SideEffects.touch!("step executed")
220
+ end
221
+ end
222
+
223
+ journey = journey_class.create!
224
+ assert_produced_side_effects("step executed") do
225
+ journey.perform_next_step!
226
+ end
227
+ assert journey.finished?
228
+ end
229
+
230
+ test "treats nil as false in skip_if condition (performs step)" do
231
+ journey_class = create_journey_subclass do
232
+ step :one, skip_if: nil do
233
+ SideEffects.touch!("step executed")
234
+ end
235
+
236
+ step :two do
237
+ SideEffects.touch!("second step executed")
238
+ end
239
+ end
240
+
241
+ journey = journey_class.create!
242
+ speedrun_journey(journey)
243
+ assert SideEffects.produced?("step executed")
244
+ assert SideEffects.produced?("second step executed")
245
+ end
246
+
247
+ test "raises ArgumentError when skip_if: condition is neither symbol nor callable" do
248
+ assert_raises(ArgumentError) do
249
+ create_journey_subclass do
250
+ step :one, skip_if: "not a symbol or callable" do
251
+ # noop
252
+ end
253
+ end
254
+ end
255
+ end
256
+
257
+ test "passes skip_if: parameter to step definition" do
258
+ step_def = StepperMotor::Step.new(name: "a_step", seq: 1, on_exception: :reattempt!)
259
+ assert_skip_if_parameter = ->(**options) {
260
+ assert options.key?(:skip_if)
261
+ assert_equal :test_condition, options[:skip_if]
262
+ # Return the original definition
263
+ step_def
264
+ }
265
+
266
+ StepperMotor::Step.stub :new, assert_skip_if_parameter do
267
+ create_journey_subclass do
268
+ step :test_step, skip_if: :test_condition do
269
+ # noop
270
+ end
271
+ end
272
+ end
273
+ end
274
+
275
+ # Backward compatibility tests for if: parameter
276
+ test "supports if: with symbol condition that returns true (performs step, backward compatibility)" do
277
+ journey_class = create_journey_subclass do
278
+ step :one, if: :should_run do
279
+ SideEffects.touch!("step executed")
280
+ end
281
+
282
+ def should_run
283
+ true
284
+ end
285
+ end
286
+
287
+ journey = journey_class.create!
288
+ assert_produced_side_effects("step executed") do
289
+ journey.perform_next_step!
290
+ end
291
+ assert journey.finished?
292
+ end
293
+
294
+ test "supports if: with symbol condition that returns false (skips step, backward compatibility)" do
295
+ journey_class = create_journey_subclass do
296
+ step :one, if: :should_run do
297
+ SideEffects.touch!("step executed")
298
+ end
299
+
300
+ step :two do
301
+ SideEffects.touch!("second step executed")
302
+ end
303
+
304
+ def should_run
305
+ false
306
+ end
307
+ end
308
+
309
+ journey = journey_class.create!
310
+ speedrun_journey(journey)
311
+ assert SideEffects.produced?("second step executed")
312
+ refute SideEffects.produced?("step executed")
313
+ end
314
+
315
+ test "supports if: with literal true (performs step, backward compatibility)" do
316
+ journey_class = create_journey_subclass do
317
+ step :one, if: true do
318
+ SideEffects.touch!("step executed")
319
+ end
320
+ end
321
+
322
+ journey = journey_class.create!
323
+ assert_produced_side_effects("step executed") do
324
+ journey.perform_next_step!
325
+ end
326
+ assert journey.finished?
327
+ end
328
+
329
+ test "supports if: with literal false (skips step, backward compatibility)" do
330
+ journey_class = create_journey_subclass do
331
+ step :one, if: false do
332
+ SideEffects.touch!("step executed")
333
+ end
334
+
335
+ step :two do
336
+ SideEffects.touch!("second step executed")
337
+ end
338
+ end
339
+
340
+ journey = journey_class.create!
341
+ speedrun_journey(journey)
342
+ assert SideEffects.produced?("second step executed")
343
+ refute SideEffects.produced?("step executed")
344
+ end
345
+
346
+ test "raises error when both skip_if: and if: are specified" do
347
+ assert_raises(StepperMotor::StepConfigurationError) do
348
+ create_journey_subclass do
349
+ step :one, skip_if: :condition1, if: :condition2 do
350
+ # noop
351
+ end
352
+ end
353
+ end
354
+ end
355
+ end
@@ -6,6 +6,7 @@ require "minitest/mock"
6
6
  class StepDefinitionTest < ActiveSupport::TestCase
7
7
  include ActiveJob::TestHelper
8
8
  include SideEffects::TestHelper
9
+ include StepperMotor::TestHelper
9
10
 
10
11
  test "requires either a block or a name" do
11
12
  assert_raises(StepperMotor::StepConfigurationError) do
metadata CHANGED
@@ -1,14 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: stepper_motor
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.12
4
+ version: 0.1.16
5
5
  platform: ruby
6
6
  authors:
7
7
  - Julik Tarkhanov
8
- autorequire:
9
8
  bindir: exe
10
9
  cert_chain: []
11
- date: 2025-06-08 00:00:00.000000000 Z
10
+ date: 2025-06-20 00:00:00.000000000 Z
12
11
  dependencies:
13
12
  - !ruby/object:Gem::Dependency
14
13
  name: activerecord
@@ -94,6 +93,34 @@ dependencies:
94
93
  - - ">="
95
94
  - !ruby/object:Gem::Version
96
95
  version: '0'
96
+ - !ruby/object:Gem::Dependency
97
+ name: mysql2
98
+ requirement: !ruby/object:Gem::Requirement
99
+ requirements:
100
+ - - ">="
101
+ - !ruby/object:Gem::Version
102
+ version: '0'
103
+ type: :development
104
+ prerelease: false
105
+ version_requirements: !ruby/object:Gem::Requirement
106
+ requirements:
107
+ - - ">="
108
+ - !ruby/object:Gem::Version
109
+ version: '0'
110
+ - !ruby/object:Gem::Dependency
111
+ name: pg
112
+ requirement: !ruby/object:Gem::Requirement
113
+ requirements:
114
+ - - ">="
115
+ - !ruby/object:Gem::Version
116
+ version: '0'
117
+ type: :development
118
+ prerelease: false
119
+ version_requirements: !ruby/object:Gem::Requirement
120
+ requirements:
121
+ - - ">="
122
+ - !ruby/object:Gem::Version
123
+ version: '0'
97
124
  - !ruby/object:Gem::Dependency
98
125
  name: rake
99
126
  requirement: !ruby/object:Gem::Requirement
@@ -206,6 +233,7 @@ files:
206
233
  - lib/generators/stepper_motor_migration_002.rb.erb
207
234
  - lib/generators/stepper_motor_migration_003.rb.erb
208
235
  - lib/generators/stepper_motor_migration_004.rb.erb
236
+ - lib/generators/stepper_motor_migration_005.rb.erb
209
237
  - lib/stepper_motor.rb
210
238
  - lib/stepper_motor/base_job.rb
211
239
  - lib/stepper_motor/cyclic_scheduler.rb
@@ -246,6 +274,9 @@ files:
246
274
  - test/dummy/config/application.rb
247
275
  - test/dummy/config/boot.rb
248
276
  - test/dummy/config/cable.yml
277
+ - test/dummy/config/database.mysql2.yml
278
+ - test/dummy/config/database.postgres.yml
279
+ - test/dummy/config/database.sqlite3.yml
249
280
  - test/dummy/config/database.yml
250
281
  - test/dummy/config/environment.rb
251
282
  - test/dummy/config/environments/development.rb
@@ -263,6 +294,7 @@ files:
263
294
  - test/dummy/db/migrate/20250525132524_stepper_motor_migration_002.rb
264
295
  - test/dummy/db/migrate/20250525132525_stepper_motor_migration_003.rb
265
296
  - test/dummy/db/migrate/20250528141038_stepper_motor_migration_004.rb
297
+ - test/dummy/db/migrate/20250609221201_stepper_motor_migration_005.rb
266
298
  - test/dummy/db/schema.rb
267
299
  - test/dummy/public/400.html
268
300
  - test/dummy/public/404.html
@@ -280,6 +312,7 @@ files:
280
312
  - test/stepper_motor/journey/exception_handling_test.rb
281
313
  - test/stepper_motor/journey/flow_control_test.rb
282
314
  - test/stepper_motor/journey/idempotency_test.rb
315
+ - test/stepper_motor/journey/if_condition_test.rb
283
316
  - test/stepper_motor/journey/step_definition_test.rb
284
317
  - test/stepper_motor/journey/uniqueness_test.rb
285
318
  - test/stepper_motor/journey_test.rb
@@ -297,7 +330,6 @@ metadata:
297
330
  homepage_uri: https://steppermotor.dev
298
331
  source_code_uri: https://github.com/stepper-motor/stepper_motor
299
332
  changelog_uri: https://github.com/stepper-motor/stepper_motor/blob/main/CHANGELOG.md
300
- post_install_message:
301
333
  rdoc_options: []
302
334
  require_paths:
303
335
  - lib
@@ -312,8 +344,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
312
344
  - !ruby/object:Gem::Version
313
345
  version: '0'
314
346
  requirements: []
315
- rubygems_version: 3.4.10
316
- signing_key:
347
+ rubygems_version: 3.6.6
317
348
  specification_version: 4
318
349
  summary: Effortless step workflows that embed nicely inside Rails
319
350
  test_files: []