statesman 1.1.0 → 1.2.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (38) hide show
  1. checksums.yaml +4 -4
  2. data/.rubocop.yml +7 -1
  3. data/.travis.yml +19 -4
  4. data/CHANGELOG.md +30 -0
  5. data/README.md +11 -35
  6. data/lib/generators/statesman/add_constraints_to_most_recent_generator.rb +28 -0
  7. data/lib/generators/statesman/add_most_recent_generator.rb +25 -0
  8. data/lib/generators/statesman/generator_helpers.rb +6 -2
  9. data/lib/generators/statesman/templates/add_constraints_to_most_recent_migration.rb.erb +13 -0
  10. data/lib/generators/statesman/templates/add_most_recent_migration.rb.erb +9 -0
  11. data/lib/generators/statesman/templates/create_migration.rb.erb +4 -3
  12. data/lib/generators/statesman/templates/update_migration.rb.erb +5 -4
  13. data/lib/statesman.rb +1 -0
  14. data/lib/statesman/adapters/active_record.rb +23 -8
  15. data/lib/statesman/adapters/active_record_queries.rb +62 -15
  16. data/lib/statesman/railtie.rb +9 -0
  17. data/lib/statesman/version.rb +1 -1
  18. data/lib/tasks/statesman.rake +49 -0
  19. data/spec/fixtures/add_constraints_to_most_recent_for_bacon_transitions.rb +13 -0
  20. data/spec/fixtures/add_most_recent_to_bacon_transitions.rb +9 -0
  21. data/spec/generators/statesman/active_record_transition_generator_spec.rb +0 -2
  22. data/spec/generators/statesman/add_constraints_to_most_recent_generator_spec.rb +38 -0
  23. data/spec/generators/statesman/add_most_recent_generator_spec.rb +35 -0
  24. data/spec/generators/statesman/migration_generator_spec.rb +10 -1
  25. data/spec/generators/statesman/mongoid_transition_generator_spec.rb +0 -2
  26. data/spec/spec_helper.rb +22 -7
  27. data/spec/statesman/adapters/active_record_queries_spec.rb +110 -28
  28. data/spec/statesman/adapters/active_record_spec.rb +61 -31
  29. data/spec/statesman/adapters/mongoid_spec.rb +8 -17
  30. data/spec/statesman/adapters/shared_examples.rb +10 -17
  31. data/spec/statesman/callback_spec.rb +2 -6
  32. data/spec/statesman/config_spec.rb +2 -5
  33. data/spec/statesman/guard_spec.rb +3 -9
  34. data/spec/statesman/machine_spec.rb +91 -129
  35. data/spec/support/active_record.rb +35 -4
  36. data/spec/support/generators_shared_examples.rb +1 -4
  37. data/statesman.gemspec +5 -3
  38. metadata +52 -10
@@ -2,18 +2,14 @@ require "spec_helper"
2
2
  require "statesman/adapters/shared_examples"
3
3
  require "statesman/exceptions"
4
4
 
5
- describe Statesman::Adapters::ActiveRecord do
5
+ describe Statesman::Adapters::ActiveRecord, active_record: true do
6
6
  before do
7
7
  prepare_model_table
8
8
  prepare_transitions_table
9
9
  end
10
10
 
11
11
  before { MyActiveRecordModelTransition.serialize(:metadata, JSON) }
12
- let(:observer) do
13
- result = double(Statesman::Machine)
14
- allow(result).to receive(:execute)
15
- result
16
- end
12
+ let(:observer) { double(Statesman::Machine, execute: nil) }
17
13
  let(:model) { MyActiveRecordModel.create(current_state: :pending) }
18
14
  it_behaves_like "an adapter", described_class, MyActiveRecordModelTransition
19
15
 
@@ -24,11 +20,12 @@ describe Statesman::Adapters::ActiveRecord do
24
20
  allow(metadata_column).to receive_messages(sql_type: '')
25
21
  allow(MyActiveRecordModelTransition).to receive_messages(columns_hash:
26
22
  { 'metadata' => metadata_column })
27
- if ::ActiveRecord.gem_version >= Gem::Version.new('4.2.0.a')
23
+ if ::ActiveRecord.respond_to?(:gem_version) &&
24
+ ::ActiveRecord.gem_version >= Gem::Version.new('4.2.0.a')
28
25
  allow(metadata_column).to receive_messages(cast_type: '')
29
26
  else
30
- allow(MyActiveRecordModelTransition)
31
- .to receive_messages(serialized_attributes: {})
27
+ allow(MyActiveRecordModelTransition).
28
+ to receive_messages(serialized_attributes: {})
32
29
  end
33
30
  end
34
31
 
@@ -46,16 +43,17 @@ describe Statesman::Adapters::ActiveRecord do
46
43
  allow(metadata_column).to receive_messages(sql_type: 'json')
47
44
  allow(MyActiveRecordModelTransition).to receive_messages(columns_hash:
48
45
  { 'metadata' => metadata_column })
49
- if ::ActiveRecord.gem_version >= Gem::Version.new('4.2.0.a')
46
+ if ::ActiveRecord.respond_to?(:gem_version) &&
47
+ ::ActiveRecord.gem_version >= Gem::Version.new('4.2.0.a')
50
48
  serialized_type = ::ActiveRecord::Type::Serialized.new(
51
49
  '', ::ActiveRecord::Coders::JSON
52
50
  )
53
- expect(metadata_column)
54
- .to receive(:cast_type)
55
- .and_return(serialized_type)
51
+ expect(metadata_column).
52
+ to receive(:cast_type).
53
+ and_return(serialized_type)
56
54
  else
57
- expect(MyActiveRecordModelTransition)
58
- .to receive_messages(serialized_attributes: { 'metadata' => '' })
55
+ expect(MyActiveRecordModelTransition).
56
+ to receive_messages(serialized_attributes: { 'metadata' => '' })
59
57
  end
60
58
  end
61
59
 
@@ -83,15 +81,15 @@ describe Statesman::Adapters::ActiveRecord do
83
81
  adapter2.create(:x, :y)
84
82
  adapter.last
85
83
  adapter2.create(:y, :z)
86
- expect { adapter.create(:y, :z) }
87
- .to raise_exception(Statesman::TransitionConflictError)
84
+ expect { adapter.create(:y, :z) }.
85
+ to raise_exception(Statesman::TransitionConflictError)
88
86
  end
89
87
  end
90
88
 
91
89
  context "when other exceptions occur" do
92
90
  before do
93
- allow_any_instance_of(MyActiveRecordModelTransition)
94
- .to receive(:save!).and_raise(error)
91
+ allow_any_instance_of(MyActiveRecordModelTransition).
92
+ to receive(:save!).and_raise(error)
95
93
  end
96
94
 
97
95
  context "ActiveRecord::RecordNotUnique unrelated to this transition" do
@@ -104,6 +102,44 @@ describe Statesman::Adapters::ActiveRecord do
104
102
  it { is_expected.to raise_exception(StandardError) }
105
103
  end
106
104
  end
105
+
106
+ context "when the transition_class has a most_recent column" do
107
+ subject { create }
108
+
109
+ context "with no previous transition" do
110
+ its(:most_recent) { is_expected.to eq(true) }
111
+ end
112
+
113
+ context "with a previous transition" do
114
+ let!(:previous_transition) { adapter.create(from, to) }
115
+ its(:most_recent) { is_expected.to eq(true) }
116
+
117
+ it "updates the previous transition's most_recent flag" do
118
+ expect { create }.
119
+ to change { previous_transition.reload.most_recent }.
120
+ from(true).to(false)
121
+ end
122
+
123
+ context "and the parent model is updated in a callback" do
124
+ before do
125
+ allow(observer).to receive(:execute) do |phase|
126
+ if phase == :before
127
+ model.update_attributes!(current_state: :ready)
128
+ end
129
+ end
130
+ end
131
+
132
+ it "doesn't save the transition too early" do
133
+ expect { create }.to_not raise_exception
134
+ end
135
+ end
136
+ end
137
+ end
138
+
139
+ context "when the transition_class doesn't have a most_recent column" do
140
+ before { drop_most_recent_column }
141
+ it { is_expected.to_not raise_exception }
142
+ end
107
143
  end
108
144
 
109
145
  describe "#last" do
@@ -111,18 +147,14 @@ describe Statesman::Adapters::ActiveRecord do
111
147
  described_class.new(MyActiveRecordModelTransition, model, observer)
112
148
  end
113
149
 
114
- before do
115
- adapter.create(:x, :y)
116
- end
150
+ before { adapter.create(:x, :y) }
117
151
 
118
152
  context "with a previously looked up transition" do
119
- before do
120
- adapter.last
121
- end
153
+ before { adapter.last }
122
154
 
123
155
  it "caches the transition" do
124
- expect_any_instance_of(MyActiveRecordModel)
125
- .to receive(:my_active_record_model_transitions).never
156
+ expect_any_instance_of(MyActiveRecordModel).
157
+ to receive(:my_active_record_model_transitions).never
126
158
  adapter.last
127
159
  end
128
160
 
@@ -135,10 +167,8 @@ describe Statesman::Adapters::ActiveRecord do
135
167
  end
136
168
 
137
169
  context "with a pre-fetched transition history" do
138
- before do
139
- adapter.create(:x, :y)
140
- model.my_active_record_model_transitions.load_target
141
- end
170
+ before { adapter.create(:x, :y) }
171
+ before { model.my_active_record_model_transitions.load_target }
142
172
 
143
173
  it "doesn't query the database" do
144
174
  expect(MyActiveRecordModelTransition).not_to receive(:connection)
@@ -5,23 +5,16 @@ require "support/mongoid"
5
5
  require "mongoid"
6
6
 
7
7
  describe Statesman::Adapters::Mongoid, mongo: true do
8
-
9
- after do
10
- Mongoid.purge!
11
- end
12
- let(:observer) do
13
- result = double(Statesman::Machine)
14
- allow(result).to receive(:execute)
15
- result
16
- end
8
+ after { Mongoid.purge! }
9
+ let(:observer) { double(Statesman::Machine, execute: nil) }
17
10
  let(:model) { MyMongoidModel.create(current_state: :pending) }
18
11
  it_behaves_like "an adapter", described_class, MyMongoidModelTransition
19
12
 
20
13
  describe "#initialize" do
21
14
  context "with unserialized metadata" do
22
15
  before do
23
- allow_any_instance_of(described_class)
24
- .to receive_messages(transition_class_hash_fields: [])
16
+ allow_any_instance_of(described_class).
17
+ to receive_messages(transition_class_hash_fields: [])
25
18
  end
26
19
 
27
20
  it "raises an exception if metadata is not serialized" do
@@ -39,14 +32,12 @@ describe Statesman::Adapters::Mongoid, mongo: true do
39
32
  end
40
33
 
41
34
  context "with a previously looked up transition" do
42
- before do
43
- adapter.create(:x, :y)
44
- adapter.last
45
- end
35
+ before { adapter.create(:x, :y) }
36
+ before { adapter.last }
46
37
 
47
38
  it "caches the transition" do
48
- expect_any_instance_of(MyMongoidModel)
49
- .to receive(:my_mongoid_model_transitions).never
39
+ expect_any_instance_of(MyMongoidModel).
40
+ to receive(:my_mongoid_model_transitions).never
50
41
  adapter.last
51
42
  end
52
43
 
@@ -12,11 +12,7 @@ require "spec_helper"
12
12
  # last: Returns the latest transition history item
13
13
  #
14
14
  shared_examples_for "an adapter" do |adapter_class, transition_class|
15
- let(:observer) do
16
- result = double(Statesman::Machine)
17
- allow(result).to receive(:execute)
18
- result
19
- end
15
+ let(:observer) { double(Statesman::Machine, execute: nil) }
20
16
  let(:adapter) { adapter_class.new(transition_class, model, observer) }
21
17
 
22
18
  describe "#initialize" do
@@ -55,8 +51,8 @@ shared_examples_for "an adapter" do |adapter_class, transition_class|
55
51
 
56
52
  context "with before callbacks" do
57
53
  it "is called before the state transition" do
58
- expect(observer).to receive(:execute)
59
- .with(:before, anything, anything, anything) {
54
+ expect(observer).to receive(:execute).
55
+ with(:before, anything, anything, anything) {
60
56
  expect(adapter.history.length).to eq(0)
61
57
  }.once
62
58
  adapter.create(from, to)
@@ -66,9 +62,8 @@ shared_examples_for "an adapter" do |adapter_class, transition_class|
66
62
 
67
63
  context "with after callbacks" do
68
64
  it "is called after the state transition" do
69
- expect(observer).to receive(:execute)
70
- .with(:after, anything, anything, anything) {
71
- |_phase, _from_state, _to_state, transition|
65
+ expect(observer).to receive(:execute).
66
+ with(:after, anything, anything, anything) { |_, _, _, transition|
72
67
  expect(adapter.last).to eq(transition)
73
68
  }.once
74
69
  adapter.create(from, to)
@@ -77,9 +72,8 @@ shared_examples_for "an adapter" do |adapter_class, transition_class|
77
72
  it "exposes the new transition for subsequent transitions" do
78
73
  adapter.create(from, to)
79
74
 
80
- expect(observer).to receive(:execute)
81
- .with(:after, anything, anything, anything) {
82
- |_phase, _from_state, _to_state, transition|
75
+ expect(observer).to receive(:execute).
76
+ with(:after, anything, anything, anything) { |_, _, _, transition|
83
77
  expect(adapter.last).to eq(transition)
84
78
  }.once
85
79
  adapter.create(to, there)
@@ -104,16 +98,15 @@ shared_examples_for "an adapter" do |adapter_class, transition_class|
104
98
  context "sorting" do
105
99
  let!(:transition2) { adapter.create(:x, :y) }
106
100
  subject { adapter.history }
101
+
107
102
  it { is_expected.to eq(adapter.history.sort_by(&:sort_key)) }
108
103
  end
109
104
  end
110
105
  end
111
106
 
112
107
  describe "#last" do
113
- before do
114
- adapter.create(:x, :y)
115
- adapter.create(:y, :z)
116
- end
108
+ before { adapter.create(:x, :y) }
109
+ before { adapter.create(:y, :z) }
117
110
  subject { adapter.last }
118
111
 
119
112
  it { is_expected.to be_a(transition_class) }
@@ -61,9 +61,7 @@ describe Statesman::Callback do
61
61
  end
62
62
 
63
63
  context "with any to and any from value on the callback" do
64
- let(:callback) do
65
- Statesman::Callback.new(callback: cb_lambda)
66
- end
64
+ let(:callback) { Statesman::Callback.new(callback: cb_lambda) }
67
65
  let(:from) { :x }
68
66
  let(:to) { :y }
69
67
 
@@ -93,9 +91,7 @@ describe Statesman::Callback do
93
91
  end
94
92
 
95
93
  context "with any to value on the callback" do
96
- let(:callback) do
97
- Statesman::Callback.new(from: :x, callback: cb_lambda)
98
- end
94
+ let(:callback) { Statesman::Callback.new(from: :x, callback: cb_lambda) }
99
95
  let(:to) { :y }
100
96
 
101
97
  context "and an allowed to value" do
@@ -2,16 +2,13 @@ require "spec_helper"
2
2
 
3
3
  describe Statesman::Config do
4
4
  let(:instance) { Statesman::Config.new }
5
-
6
- after do
7
- # Don't leak global config changes into other specs
8
- Statesman.configure { storage_adapter(Statesman::Adapters::Memory) }
9
- end
5
+ after { Statesman.configure { storage_adapter(Statesman::Adapters::Memory) } }
10
6
 
11
7
  describe "#storage_adapter" do
12
8
  let(:adapter) { Class.new }
13
9
  before { instance.storage_adapter(adapter) }
14
10
  subject { instance.adapter_class }
11
+
15
12
  it { is_expected.to be(adapter) }
16
13
 
17
14
  it "is DSL configurable" do
@@ -7,22 +7,16 @@ describe Statesman::Guard do
7
7
  specify { expect(guard).to be_a(Statesman::Callback) }
8
8
 
9
9
  describe "#call" do
10
- subject { guard.call }
10
+ subject(:call) { guard.call }
11
11
 
12
12
  context "success" do
13
13
  let(:callback) { -> { true } }
14
-
15
- it "does not raise an error" do
16
- expect { guard.call }.to_not raise_error
17
- end
14
+ specify { expect { call }.to_not raise_error }
18
15
  end
19
16
 
20
17
  context "error" do
21
18
  let(:callback) { -> { false } }
22
-
23
- it "raises an error" do
24
- expect { guard.call }.to raise_error(Statesman::GuardFailedError)
25
- end
19
+ specify { expect { call }.to raise_error(Statesman::GuardFailedError) }
26
20
  end
27
21
  end
28
22
  end
@@ -15,9 +15,8 @@ describe Statesman::Machine do
15
15
 
16
16
  context "when an initial state is already defined" do
17
17
  it "raises an error" do
18
- expect do
19
- machine.state(:y, initial: true)
20
- end.to raise_error(Statesman::InvalidStateError)
18
+ expect { machine.state(:y, initial: true) }.
19
+ to raise_error(Statesman::InvalidStateError)
21
20
  end
22
21
  end
23
22
  end
@@ -51,15 +50,15 @@ describe Statesman::Machine do
51
50
 
52
51
  context "when an irrelevant exception occurs" do
53
52
  it "runs the transition once" do
54
- expect(instance)
55
- .to receive(:transition_to).once
56
- .and_raise(StandardError)
53
+ expect(instance).
54
+ to receive(:transition_to).once.
55
+ and_raise(StandardError)
57
56
  transition_state rescue nil # rubocop:disable RescueModifier
58
57
  end
59
58
 
60
59
  it "re-raises the exception" do
61
- allow(instance).to receive(:transition_to).once
62
- .and_raise(StandardError)
60
+ allow(instance).to receive(:transition_to).once.
61
+ and_raise(StandardError)
63
62
  expect { transition_state }.to raise_error(StandardError)
64
63
  end
65
64
  end
@@ -67,31 +66,31 @@ describe Statesman::Machine do
67
66
  context "when a TransitionConflictError occurs" do
68
67
  context "and is resolved on the second attempt" do
69
68
  it "runs the transition twice" do
70
- expect(instance)
71
- .to receive(:transition_to).once
72
- .and_raise(Statesman::TransitionConflictError)
73
- .ordered
74
- expect(instance)
75
- .to receive(:transition_to).once.ordered.and_call_original
69
+ expect(instance).
70
+ to receive(:transition_to).once.
71
+ and_raise(Statesman::TransitionConflictError).
72
+ ordered
73
+ expect(instance).
74
+ to receive(:transition_to).once.ordered.and_call_original
76
75
  transition_state
77
76
  end
78
77
  end
79
78
 
80
79
  context "and keeps occurring" do
81
80
  it "runs the transition `retry_attempts + 1` times" do
82
- expect(instance)
83
- .to receive(:transition_to)
84
- .exactly(retry_attempts + 1).times
85
- .and_raise(Statesman::TransitionConflictError)
81
+ expect(instance).
82
+ to receive(:transition_to).
83
+ exactly(retry_attempts + 1).times.
84
+ and_raise(Statesman::TransitionConflictError)
86
85
  transition_state rescue nil # rubocop:disable RescueModifier
87
86
  end
88
87
 
89
88
  it "re-raises the conflict" do
90
- allow(instance)
91
- .to receive(:transition_to)
92
- .and_raise(Statesman::TransitionConflictError)
93
- expect { transition_state }
94
- .to raise_error(Statesman::TransitionConflictError)
89
+ allow(instance).
90
+ to receive(:transition_to).
91
+ and_raise(Statesman::TransitionConflictError)
92
+ expect { transition_state }.
93
+ to raise_error(Statesman::TransitionConflictError)
95
94
  end
96
95
  end
97
96
  end
@@ -108,49 +107,43 @@ describe Statesman::Machine do
108
107
 
109
108
  context "given neither a 'from' nor a 'to' state" do
110
109
  it "raises an error" do
111
- expect do
112
- machine.transition
113
- end.to raise_error(Statesman::InvalidStateError)
110
+ expect { machine.transition }.
111
+ to raise_error(Statesman::InvalidStateError)
114
112
  end
115
113
  end
116
114
 
117
115
  context "given no 'from' state and a valid 'to' state" do
118
116
  it "raises an error" do
119
- expect do
120
- machine.transition from: nil, to: :x
121
- end.to raise_error(Statesman::InvalidStateError)
117
+ expect { machine.transition from: nil, to: :x }.
118
+ to raise_error(Statesman::InvalidStateError)
122
119
  end
123
120
  end
124
121
 
125
122
  context "given a valid 'from' state and a no 'to' state" do
126
123
  it "raises an error" do
127
- expect do
128
- machine.transition from: :x, to: nil
129
- end.to raise_error(Statesman::InvalidStateError)
124
+ expect { machine.transition from: :x, to: nil }.
125
+ to raise_error(Statesman::InvalidStateError)
130
126
  end
131
127
  end
132
128
 
133
129
  context "given a valid 'from' state and an empty 'to' state array" do
134
130
  it "raises an error" do
135
- expect do
136
- machine.transition from: :x, to: []
137
- end.to raise_error(Statesman::InvalidStateError)
131
+ expect { machine.transition from: :x, to: [] }.
132
+ to raise_error(Statesman::InvalidStateError)
138
133
  end
139
134
  end
140
135
 
141
136
  context "given an invalid 'from' state" do
142
137
  it "raises an error" do
143
- expect do
144
- machine.transition(from: :a, to: :x)
145
- end.to raise_error(Statesman::InvalidStateError)
138
+ expect { machine.transition(from: :a, to: :x) }.
139
+ to raise_error(Statesman::InvalidStateError)
146
140
  end
147
141
  end
148
142
 
149
143
  context "given an invalid 'to' state" do
150
144
  it "raises an error" do
151
- expect do
152
- machine.transition(from: :x, to: :a)
153
- end.to raise_error(Statesman::InvalidStateError)
145
+ expect { machine.transition(from: :x, to: :a) }.
146
+ to raise_error(Statesman::InvalidStateError)
154
147
  end
155
148
  end
156
149
 
@@ -176,25 +169,22 @@ describe Statesman::Machine do
176
169
 
177
170
  context "with a terminal 'from' state" do
178
171
  it "raises an exception" do
179
- expect do
180
- machine.validate_callback_condition(from: :z, to: :y)
181
- end.to raise_error(Statesman::InvalidTransitionError)
172
+ expect { machine.validate_callback_condition(from: :z, to: :y) }.
173
+ to raise_error(Statesman::InvalidTransitionError)
182
174
  end
183
175
  end
184
176
 
185
177
  context "with an initial 'to' state" do
186
178
  it "raises an exception" do
187
- expect do
188
- machine.validate_callback_condition(from: :y, to: :x)
189
- end.to raise_error(Statesman::InvalidTransitionError)
179
+ expect { machine.validate_callback_condition(from: :y, to: :x) }.
180
+ to raise_error(Statesman::InvalidTransitionError)
190
181
  end
191
182
  end
192
183
 
193
184
  context "with an invalid transition" do
194
185
  it "raises an exception" do
195
- expect do
196
- machine.validate_callback_condition(from: :x, to: :z)
197
- end.to raise_error(Statesman::InvalidTransitionError)
186
+ expect { machine.validate_callback_condition(from: :x, to: :z) }.
187
+ to raise_error(Statesman::InvalidTransitionError)
198
188
  end
199
189
  end
200
190
 
@@ -206,9 +196,8 @@ describe Statesman::Machine do
206
196
 
207
197
  context "with a valid transition" do
208
198
  it "does not raise an exception" do
209
- expect do
210
- machine.validate_callback_condition(from: :x, to: :y)
211
- end.to_not raise_error
199
+ expect { machine.validate_callback_condition(from: :x, to: :y) }.
200
+ to_not raise_error
212
201
  end
213
202
  end
214
203
  end
@@ -227,9 +216,7 @@ describe Statesman::Machine do
227
216
  let(:set_callback) { machine.send(assignment_method, options) {} }
228
217
 
229
218
  shared_examples "fails" do |error_type|
230
- it "raises an exception" do
231
- expect { set_callback }.to raise_error(error_type)
232
- end
219
+ specify { expect { set_callback }.to raise_error(error_type) }
233
220
 
234
221
  it "does not add a callback" do
235
222
  expect do
@@ -243,13 +230,11 @@ describe Statesman::Machine do
243
230
  end
244
231
 
245
232
  shared_examples "adds callback" do
246
- it "does not raise" do
247
- expect { set_callback }.to_not raise_error
248
- end
233
+ specify { expect { set_callback }.to_not raise_error }
249
234
 
250
235
  it "stores callbacks" do
251
- expect { set_callback }.to change(
252
- machine.callbacks[callback_store], :count).by(1)
236
+ expect { set_callback }.
237
+ to change(machine.callbacks[callback_store], :count).by(1)
253
238
  end
254
239
 
255
240
  it "stores callback instances" do
@@ -330,22 +315,22 @@ describe Statesman::Machine do
330
315
 
331
316
  context "transition class" do
332
317
  it "sets a default" do
333
- expect(Statesman.storage_adapter).to receive(:new).once
334
- .with(Statesman::Adapters::MemoryTransition, my_model, anything)
318
+ expect(Statesman.storage_adapter).to receive(:new).once.
319
+ with(Statesman::Adapters::MemoryTransition, my_model, anything)
335
320
  machine.new(my_model)
336
321
  end
337
322
 
338
323
  it "sets the passed class" do
339
324
  my_transition_class = Class.new
340
- expect(Statesman.storage_adapter).to receive(:new).once
341
- .with(my_transition_class, my_model, anything)
325
+ expect(Statesman.storage_adapter).to receive(:new).once.
326
+ with(my_transition_class, my_model, anything)
342
327
  machine.new(my_model, transition_class: my_transition_class)
343
328
  end
344
329
 
345
330
  it "falls back to Memory without transaction_class" do
346
331
  allow(Statesman).to receive(:storage_adapter).and_return(Class.new)
347
- expect(Statesman::Adapters::Memory).to receive(:new).once
348
- .with(Statesman::Adapters::MemoryTransition, my_model, anything)
332
+ expect(Statesman::Adapters::Memory).to receive(:new).once.
333
+ with(Statesman::Adapters::MemoryTransition, my_model, anything)
349
334
  machine.new(my_model)
350
335
  end
351
336
  end
@@ -380,10 +365,8 @@ describe Statesman::Machine do
380
365
  end
381
366
 
382
367
  context "with multiple transitions" do
383
- before do
384
- instance.transition_to!(:y)
385
- instance.transition_to!(:z)
386
- end
368
+ before { instance.transition_to!(:y) }
369
+ before { instance.transition_to!(:z) }
387
370
 
388
371
  it { is_expected.to eq("z") }
389
372
  end
@@ -408,18 +391,12 @@ describe Statesman::Machine do
408
391
  end
409
392
 
410
393
  context "with one possible state" do
411
- before do
412
- instance.transition_to!(:y)
413
- end
414
-
394
+ before { instance.transition_to!(:y) }
415
395
  it { is_expected.to eq(['z']) }
416
396
  end
417
397
 
418
398
  context "with no possible transitions" do
419
- before do
420
- instance.transition_to!(:z)
421
- end
422
-
399
+ before { instance.transition_to!(:z) }
423
400
  it { is_expected.to eq([]) }
424
401
  end
425
402
  end
@@ -429,8 +406,8 @@ describe Statesman::Machine do
429
406
  let(:last_action) { "Whatever" }
430
407
 
431
408
  it "delegates to the storage adapter" do
432
- expect_any_instance_of(Statesman.storage_adapter).to receive(:last).once
433
- .and_return(last_action)
409
+ expect_any_instance_of(Statesman.storage_adapter).to receive(:last).once.
410
+ and_return(last_action)
434
411
  expect(instance.last_transition).to be(last_action)
435
412
  end
436
413
  end
@@ -499,9 +476,8 @@ describe Statesman::Machine do
499
476
 
500
477
  context "when the state cannot be transitioned to" do
501
478
  it "raises an error" do
502
- expect do
503
- instance.transition_to!(:z)
504
- end.to raise_error(Statesman::TransitionFailedError)
479
+ expect { instance.transition_to!(:z) }.
480
+ to raise_error(Statesman::TransitionFailedError)
505
481
  end
506
482
  end
507
483
 
@@ -512,12 +488,11 @@ describe Statesman::Machine do
512
488
  end
513
489
 
514
490
  it "creates a new transition object" do
515
- expect do
516
- instance.transition_to!(:y)
517
- end.to change(instance.history, :count).by(1)
491
+ expect { instance.transition_to!(:y) }.
492
+ to change(instance.history, :count).by(1)
518
493
 
519
- expect(instance.history.first)
520
- .to be_a(Statesman::Adapters::MemoryTransition)
494
+ expect(instance.history.first).
495
+ to be_a(Statesman::Adapters::MemoryTransition)
521
496
  expect(instance.history.first.to_state).to eq("y")
522
497
  end
523
498
 
@@ -532,9 +507,7 @@ describe Statesman::Machine do
532
507
  expect(instance.history.first.metadata).to eq({})
533
508
  end
534
509
 
535
- it "returns true" do
536
- expect(instance.transition_to!(:y)).to be_truthy
537
- end
510
+ specify { expect(instance.transition_to!(:y)).to be_truthy }
538
511
 
539
512
  context "with a guard" do
540
513
  let(:result) { true }
@@ -545,8 +518,8 @@ describe Statesman::Machine do
545
518
  let(:instance) { machine.new(my_model) }
546
519
 
547
520
  it "passes the object to the guard" do
548
- expect(guard_cb).to receive(:call).once
549
- .with(my_model, instance.last_transition, {}).and_return(true)
521
+ expect(guard_cb).to receive(:call).once.
522
+ with(my_model, instance.last_transition, {}).and_return(true)
550
523
  instance.transition_to!(:y)
551
524
  end
552
525
  end
@@ -562,9 +535,8 @@ describe Statesman::Machine do
562
535
  let(:result) { false }
563
536
 
564
537
  it "raises an exception" do
565
- expect do
566
- instance.transition_to!(:y)
567
- end.to raise_error(Statesman::GuardFailedError)
538
+ expect { instance.transition_to!(:y) }.
539
+ to raise_error(Statesman::GuardFailedError)
568
540
  end
569
541
  end
570
542
  end
@@ -578,32 +550,29 @@ describe Statesman::Machine do
578
550
 
579
551
  context "when it is succesful" do
580
552
  before do
581
- expect(instance).to receive(:transition_to!).once
582
- .with(:some_state, metadata).and_return(:some_state)
553
+ expect(instance).to receive(:transition_to!).once.
554
+ with(:some_state, metadata).and_return(:some_state)
583
555
  end
584
556
  it { is_expected.to be(:some_state) }
585
557
  end
586
558
 
587
559
  context "when it is unsuccesful" do
588
560
  before do
589
- allow(instance).to receive(:transition_to!)
590
- .and_raise(Statesman::GuardFailedError)
561
+ allow(instance).to receive(:transition_to!).
562
+ and_raise(Statesman::GuardFailedError)
591
563
  end
592
564
  it { is_expected.to be_falsey }
593
565
  end
594
566
 
595
567
  context "when a non statesman exception is raised" do
596
568
  before do
597
- allow(instance).to receive(:transition_to!)
598
- .and_raise(RuntimeError, 'user defined exception')
569
+ allow(instance).to receive(:transition_to!).
570
+ and_raise(RuntimeError, 'user defined exception')
599
571
  end
600
572
 
601
573
  it "should not rescue the exception" do
602
- expectation = expect do
603
- instance.transition_to(:some_state, metadata)
604
- end
605
-
606
- expectation.to raise_error(RuntimeError, 'user defined exception')
574
+ expect { instance.transition_to(:some_state, metadata) }.
575
+ to raise_error(RuntimeError, 'user defined exception')
607
576
  end
608
577
  end
609
578
  end
@@ -650,13 +619,11 @@ describe Statesman::Machine do
650
619
  end
651
620
 
652
621
  describe "#before_callbacks_for" do
653
- it_behaves_like "a callback filter", :before_transition,
654
- :before
622
+ it_behaves_like "a callback filter", :before_transition, :before
655
623
  end
656
624
 
657
625
  describe "#after_callbacks_for" do
658
- it_behaves_like "a callback filter", :after_transition,
659
- :after
626
+ it_behaves_like "a callback filter", :after_transition, :after
660
627
  end
661
628
 
662
629
  describe "#event" do
@@ -680,9 +647,8 @@ describe Statesman::Machine do
680
647
 
681
648
  context "when the state cannot be transitioned to" do
682
649
  it "raises an error" do
683
- expect do
684
- instance.trigger!(:event_2)
685
- end.to raise_error(Statesman::TransitionFailedError)
650
+ expect { instance.trigger!(:event_2) }.
651
+ to raise_error(Statesman::TransitionFailedError)
686
652
  end
687
653
  end
688
654
 
@@ -693,12 +659,11 @@ describe Statesman::Machine do
693
659
  end
694
660
 
695
661
  it "creates a new transition object" do
696
- expect do
697
- instance.trigger!(:event_1)
698
- end.to change(instance.history, :count).by(1)
662
+ expect { instance.trigger!(:event_1) }.
663
+ to change(instance.history, :count).by(1)
699
664
 
700
- expect(instance.history.first)
701
- .to be_a(Statesman::Adapters::MemoryTransition)
665
+ expect(instance.history.first).
666
+ to be_a(Statesman::Adapters::MemoryTransition)
702
667
  expect(instance.history.first.to_state).to eq("y")
703
668
  end
704
669
 
@@ -728,16 +693,16 @@ describe Statesman::Machine do
728
693
  let(:instance) { machine.new(my_model) }
729
694
 
730
695
  it "passes the object to the guard" do
731
- expect(guard_cb).to receive(:call).once
732
- .with(my_model, instance.last_transition, {}).and_return(true)
696
+ expect(guard_cb).to receive(:call).once.
697
+ with(my_model, instance.last_transition, {}).and_return(true)
733
698
  instance.trigger!(:event_1)
734
699
  end
735
700
  end
736
701
 
737
702
  context "which passes" do
738
703
  it "changes state" do
739
- instance.trigger!(:event_1)
740
- expect(instance.current_state).to eq("y")
704
+ expect { instance.trigger!(:event_1) }.
705
+ to change { instance.current_state }.to("y")
741
706
  end
742
707
  end
743
708
 
@@ -745,14 +710,12 @@ describe Statesman::Machine do
745
710
  let(:result) { false }
746
711
 
747
712
  it "raises an exception" do
748
- expect do
749
- instance.trigger!(:event_1)
750
- end.to raise_error(Statesman::GuardFailedError)
713
+ expect { instance.trigger!(:event_1) }.
714
+ to raise_error(Statesman::GuardFailedError)
751
715
  end
752
716
  end
753
717
  end
754
718
  end
755
-
756
719
  end
757
720
 
758
721
  describe "#available_events" do
@@ -784,5 +747,4 @@ describe Statesman::Machine do
784
747
  expect(instance.available_events).to eq([:event_2, :event_3])
785
748
  end
786
749
  end
787
-
788
750
  end