flow_machine 0.2.2 → 0.2.3

Sign up to get free protection for your applications and to get access to all the features.
@@ -5,44 +5,52 @@ RSpec.describe FlowMachine::Workflow do
5
5
  include FlowMachine::Workflow
6
6
  end
7
7
 
8
- describe '.class_for' do
8
+ describe ".class_for" do
9
9
  subject(:workflow_class) { described_class.class_for(target) }
10
10
 
11
- describe 'with a class' do
11
+ describe "with a class" do
12
12
  let(:target) { TestClass }
13
- it { should eq(TestClassWorkflow) }
13
+
14
+ it { is_expected.to eq(TestClassWorkflow) }
14
15
  end
15
16
 
16
- describe 'with an object' do
17
+ describe "with an object" do
17
18
  let(:target) { TestClass.new }
18
- it { should eq(TestClassWorkflow) }
19
+
20
+ it { is_expected.to eq(TestClassWorkflow) }
19
21
  end
20
22
  end
21
23
 
22
- describe '.for' do
24
+ describe ".for" do
23
25
  subject(:workflow) { described_class.for(target) }
26
+
24
27
  class SomeNewClass; end
25
28
 
26
- describe 'not found' do
29
+ describe "not found" do
27
30
  let(:target) { SomeNewClass.new }
28
- it { should be_nil }
31
+
32
+ it { is_expected.to be_nil }
29
33
  end
30
34
 
31
- describe 'with an object' do
35
+ describe "with an object" do
32
36
  let(:target) { TestClass.new }
33
- it { should be_an_instance_of(TestClassWorkflow) }
34
- its(:object) { should eq(target) }
37
+
38
+ it { is_expected.to be_an_instance_of(TestClassWorkflow) }
39
+ its(:object) { is_expected.to eq(target) }
35
40
  end
36
41
 
37
- describe 'with an array of objects' do
42
+ describe "with an array of objects" do
38
43
  let(:target) { [TestClass.new, TestClass.new] }
39
- it { should match [an_instance_of(TestClassWorkflow), an_instance_of(TestClassWorkflow)] }
44
+
45
+ it { is_expected.to match [an_instance_of(TestClassWorkflow), an_instance_of(TestClassWorkflow)] }
40
46
  end
41
47
  end
42
48
 
43
- describe '.workflow_for_collection' do
49
+ describe ".workflow_for_collection" do
44
50
  subject(:result) { described_class.for_collection(target) }
51
+
45
52
  let(:target) { [TestClass.new, TestClass.new] }
46
- it { should match [an_instance_of(TestClassWorkflow), an_instance_of(TestClassWorkflow)] }
53
+
54
+ it { is_expected.to match [an_instance_of(TestClassWorkflow), an_instance_of(TestClassWorkflow)] }
47
55
  end
48
56
  end
@@ -1,14 +1,18 @@
1
1
  RSpec.describe FlowMachine::Workflow do
2
2
  let(:state_class1) do
3
3
  Class.new(FlowMachine::WorkflowState) do
4
- def self.state_name; :state1; end
4
+ def self.state_name
5
+ :state1
6
+ end
5
7
  event :event1
6
8
  end
7
9
  end
8
10
 
9
11
  let(:state_class2) do
10
12
  Class.new(FlowMachine::WorkflowState) do
11
- def self.state_name; :state2; end
13
+ def self.state_name
14
+ :state2
15
+ end
12
16
  event :event2
13
17
  end
14
18
  end
@@ -23,15 +27,17 @@ RSpec.describe FlowMachine::Workflow do
23
27
  workflow_class2.state state_class2
24
28
  end
25
29
 
26
- context 'class1' do
30
+ context "class1" do
27
31
  subject { workflow_class1.new(double) }
28
- it { should respond_to 'event1' }
29
- it { should_not respond_to 'event2' }
32
+
33
+ it { is_expected.to respond_to "event1" }
34
+ it { is_expected.not_to respond_to "event2" }
30
35
  end
31
36
 
32
- context 'class2' do
37
+ context "class2" do
33
38
  subject { workflow_class2.new(double) }
34
- it { should_not respond_to 'event1' }
35
- it { should respond_to 'event2' }
39
+
40
+ it { is_expected.not_to respond_to "event1" }
41
+ it { is_expected.to respond_to "event2" }
36
42
  end
37
43
  end
@@ -1,4 +1,4 @@
1
- require 'ostruct'
1
+ require "ostruct"
2
2
 
3
3
  RSpec.describe FlowMachine::Workflow::ModelExtension do
4
4
  class Test1State < FlowMachine::WorkflowState
@@ -13,8 +13,8 @@ RSpec.describe FlowMachine::Workflow::ModelExtension do
13
13
  state Test2State
14
14
  end
15
15
 
16
- describe '.create_scopes_on' do
17
- class PersistedModel < Struct.new(:state)
16
+ describe ".create_scopes_on" do
17
+ PersistedModel = Struct.new(:state) do
18
18
  def self.where(opts)
19
19
  [new(opts[:state])]
20
20
  end
@@ -22,33 +22,33 @@ RSpec.describe FlowMachine::Workflow::ModelExtension do
22
22
  TestWorkflow.create_scopes_on(self)
23
23
  end
24
24
 
25
- class UnPersistedModel < Struct.new(:state)
25
+ UnPersistedModel = Struct.new(:state) do
26
26
  TestWorkflow.create_scopes_on(self)
27
27
  end
28
28
 
29
- it 'adds the predicate model for state 1' do
30
- expect(PersistedModel.new('test1')).to be_test1
31
- expect(PersistedModel.new('test2')).not_to be_test1
29
+ it "adds the predicate model for state 1" do
30
+ expect(PersistedModel.new("test1")).to be_test1
31
+ expect(PersistedModel.new("test2")).not_to be_test1
32
32
  end
33
33
 
34
- it 'adds the predicate model for state 2' do
35
- expect(PersistedModel.new('test1')).not_to be_test2
36
- expect(PersistedModel.new('test2')).to be_test2
34
+ it "adds the predicate model for state 2" do
35
+ expect(PersistedModel.new("test1")).not_to be_test2
36
+ expect(PersistedModel.new("test2")).to be_test2
37
37
  end
38
38
 
39
- it 'adds a scope for test1' do
39
+ it "adds a scope for test1" do
40
40
  expect(PersistedModel.test1).to be_an(Array)
41
41
  expect(PersistedModel.test1).to be_one
42
- expect(PersistedModel.test1.first).to eq(PersistedModel.new('test1'))
42
+ expect(PersistedModel.test1.first).to eq(PersistedModel.new("test1"))
43
43
  end
44
44
 
45
- it 'adds a scope for test2' do
45
+ it "adds a scope for test2" do
46
46
  expect(PersistedModel.test2).to be_an(Array)
47
47
  expect(PersistedModel.test2).to be_one
48
- expect(PersistedModel.test2.first).to eq(PersistedModel.new('test2'))
48
+ expect(PersistedModel.test2.first).to eq(PersistedModel.new("test2"))
49
49
  end
50
50
 
51
- it 'does not add scopes if where is not defined' do
51
+ it "does not add scopes if where is not defined" do
52
52
  expect(UnPersistedModel).not_to respond_to(:test1)
53
53
  end
54
54
  end
@@ -1,127 +1,131 @@
1
1
  RSpec.describe FlowMachine::Callback do
2
2
  let(:object) { double }
3
3
 
4
- describe 'callback with method' do
4
+ describe "callback with method" do
5
5
  let(:callback) { described_class.new(:some_method) }
6
6
 
7
- it 'calls the method' do
7
+ it "calls the method" do
8
8
  expect(object).to receive(:some_method)
9
9
  callback.call(object)
10
10
  end
11
11
  end
12
12
 
13
- describe 'callback with block' do
13
+ describe "callback with block" do
14
14
  let(:callback) do
15
15
  described_class.new { some_method }
16
16
  end
17
17
 
18
- it 'calls the method' do
18
+ it "calls the method" do
19
19
  expect(object).to receive(:some_method)
20
20
  callback.call(object)
21
21
  end
22
-
23
22
  end
24
23
 
25
- describe 'callback with if' do
26
- context 'a single if' do
24
+ describe "callback with if" do
25
+ context "a single if" do
27
26
  let(:callback) { described_class.new(:some_method, if: :if_method?) }
28
27
 
29
- context 'if method returns true' do
28
+ context "if method returns true" do
30
29
  before { allow(object).to receive(:if_method?).and_return true }
31
- it 'calls the method' do
30
+
31
+ it "calls the method" do
32
32
  expect(object).to receive(:some_method)
33
33
  callback.call(object)
34
34
  end
35
35
  end
36
36
 
37
- context 'if method returns false' do
37
+ context "if method returns false" do
38
38
  before { allow(object).to receive(:if_method?).and_return false }
39
- it 'does not call the method' do
39
+
40
+ it "does not call the method" do
40
41
  expect(object).not_to receive(:some_method)
41
42
  callback.call(object)
42
43
  end
43
44
  end
44
45
  end
45
46
 
46
- context 'a lambda for if' do
47
+ context "a lambda for if" do
47
48
  let(:callback) do
48
49
  described_class.new(:some_method, if: -> { if_method? })
49
50
  end
50
51
 
51
- it 'calls the method when true' do
52
+ it "calls the method when true" do
52
53
  allow(object).to receive(:if_method?).and_return true
53
54
  expect(object).to receive(:some_method)
54
55
  callback.call(object)
55
56
  end
56
57
 
57
- it 'does not call the method when false' do
58
+ it "does not call the method when false" do
58
59
  allow(object).to receive(:if_method?).and_return false
59
60
  expect(object).not_to receive(:some_method)
60
61
  callback.call(object)
61
62
  end
62
63
  end
63
64
 
64
- context 'an array of ifs' do
65
- let(:callback) { described_class.new(:some_method, if: [:if_method?, :if2?]) }
66
- context 'both return true' do
67
- before :each do
65
+ context "an array of ifs" do
66
+ let(:callback) { described_class.new(:some_method, if: %i[if_method? if2?]) }
67
+
68
+ context "both return true" do
69
+ before do
68
70
  allow(object).to receive(:if_method?).and_return true
69
71
  allow(object).to receive(:if2?).and_return true
70
72
  end
71
- it 'calls the method' do
73
+
74
+ it "calls the method" do
72
75
  expect(object).to receive(:some_method)
73
76
  callback.call(object)
74
77
  end
75
78
  end
76
79
 
77
- context 'one returns false' do
78
- before :each do
80
+ context "one returns false" do
81
+ before do
79
82
  allow(object).to receive(:if_method?).and_return true
80
83
  allow(object).to receive(:if2?).and_return false
81
84
  end
82
85
 
83
- it 'does not call the method' do
84
- expect(object).to receive(:some_method).never
86
+ it "does not call the method" do
87
+ expect(object).not_to receive(:some_method)
85
88
  callback.call(object)
86
89
  end
87
90
  end
88
91
  end
89
92
  end
90
93
 
91
- describe 'callback with unless' do
92
- context 'a single if' do
94
+ describe "callback with unless" do
95
+ context "a single if" do
93
96
  let(:callback) { described_class.new(:some_method, unless: :unless_method?) }
94
97
 
95
- context 'unless method returns false' do
98
+ context "unless method returns false" do
96
99
  before { allow(object).to receive(:unless_method?).and_return false }
97
100
 
98
- it 'calls the method' do
101
+ it "calls the method" do
99
102
  expect(object).to receive(:some_method)
100
103
  callback.call(object)
101
104
  end
102
105
  end
103
106
 
104
- context 'unless method returns true' do
105
- before { allow(object).to receive(:unless_method?).and_return true }
106
- it 'does not call the method' do
107
- expect(object).to receive(:some_method).never
107
+ context "unless method returns true" do
108
+ before { allow(object).to receive(:unless_method?).and_return true }
109
+
110
+ it "does not call the method" do
111
+ expect(object).not_to receive(:some_method)
108
112
  callback.call(object)
109
113
  end
110
114
  end
111
115
  end
112
116
 
113
- context 'a lambda for unless' do
117
+ context "a lambda for unless" do
114
118
  let(:callback) do
115
119
  described_class.new(:some_method, unless: -> { unless_method? })
116
120
  end
117
121
 
118
- it 'calls the method when false' do
122
+ it "calls the method when false" do
119
123
  allow(object).to receive(:unless_method?).and_return false
120
124
  expect(object).to receive(:some_method)
121
125
  callback.call(object)
122
126
  end
123
127
 
124
- it 'does not call the method when true' do
128
+ it "does not call the method when true" do
125
129
  allow(object).to receive(:unless_method?).and_return true
126
130
  expect(object).not_to receive(:some_method)
127
131
  callback.call(object)
@@ -1,25 +1,28 @@
1
1
  RSpec.describe FlowMachine::ChangeCallback do
2
2
  subject(:callback) { described_class.new(:field, :method, if: :condition?) }
3
3
 
4
+ before { allow(object).to receive(:run_workflow_method) { |m| object.send(m) } }
5
+
6
+ let(:object) { double(condition?: true) }
7
+
4
8
  specify { expect(callback.field).to eq(:field) }
5
9
  specify { expect(callback.method).to eq(:method) }
6
- specify { expect(callback.options).to eq({ if: :condition? }) }
10
+ specify { expect(callback.options).to eq(if: :condition?) }
7
11
 
8
- let(:object) { double(condition?: true) }
9
- before { allow(object).to receive(:run_workflow_method) { |m| object.send(m) } }
12
+ context "the field changes" do
13
+ let(:changes) { { "field" => %i[old new] } }
10
14
 
11
- context 'the field changes' do
12
- let(:changes) { { 'field' => [:old, :new] } }
13
- it 'calls the method' do
15
+ it "calls the method" do
14
16
  expect(object).to receive(:method)
15
17
  callback.call(object, changes)
16
18
  end
17
19
  end
18
20
 
19
- context 'the field does not change' do
20
- let(:changes) { { 'other_field' => [:old, :new] } }
21
- it 'does not call the method' do
22
- expect(object).to receive(:method).never
21
+ context "the field does not change" do
22
+ let(:changes) { { "other_field" => %i[old new] } }
23
+
24
+ it "does not call the method" do
25
+ expect(object).not_to receive(:method)
23
26
  callback.call(object, changes)
24
27
  end
25
28
  end
@@ -1,4 +1,4 @@
1
- require 'ostruct'
1
+ require "ostruct"
2
2
 
3
3
  RSpec.describe FlowMachine::Workflow do
4
4
  class Test1State < FlowMachine::WorkflowState
@@ -17,179 +17,189 @@ RSpec.describe FlowMachine::Workflow do
17
17
  after_save :after_save_callback
18
18
  after_transition :after_transition_callback
19
19
  def workflow_method; end
20
+
20
21
  def before_save_callback; end
22
+
21
23
  def after_save_callback; end
24
+
22
25
  def after_transition_callback; end
23
26
  end
24
27
 
25
- describe 'state_names' do
26
- it 'has the state names' do
27
- expect(TestWorkflow.state_names).to eq(['test1', 'test2'])
28
+ describe "state_names" do
29
+ it "has the state names" do
30
+ expect(TestWorkflow.state_names).to eq(%w[test1 test2])
28
31
  end
29
32
 
30
- it 'has the states in a hash keyed by names' do
31
- expect(TestWorkflow.states).to eq({ test1: Test1State, test2: Test2State })
33
+ it "has the states in a hash keyed by names" do
34
+ expect(TestWorkflow.states).to eq(test1: Test1State, test2: Test2State)
32
35
  end
33
36
  end
34
37
 
35
- describe 'reading initial state' do
38
+ describe "reading initial state" do
36
39
  subject(:workflow) { TestWorkflow.new(object) }
37
- context 'default state field' do
40
+
41
+ context "default state field" do
38
42
  let(:object) { double(state: :test1) }
39
- it 'has the state' do
43
+
44
+ it "has the state" do
40
45
  expect(workflow.current_state_name).to eq(:test1)
41
46
  end
42
47
  end
43
48
 
44
- context 'with a different state field on the object' do
49
+ context "with a different state field on the object" do
45
50
  before { TestWorkflow.send(:state_attribute, :status) }
46
51
  # return to default
52
+
47
53
  after { TestWorkflow.send(:state_attribute, :state) }
48
54
 
49
55
  let(:object) { double(status: :test2) }
50
- it 'has the state' do
56
+
57
+ it "has the state" do
51
58
  expect(workflow.current_state_name).to eq(:test2)
52
59
  end
53
60
  end
54
61
  end
55
62
 
56
- describe '#transition' do
63
+ describe "#transition" do
57
64
  subject(:workflow) { TestWorkflow.new(object) }
65
+
58
66
  let(:object) { double(state: :test1) }
59
67
 
60
- it 'errors on an invalid state' do
68
+ it "errors on an invalid state" do
61
69
  expect { workflow.transition to: :invalid }.to raise_error(ArgumentError)
62
70
  end
63
71
 
64
- it 'changes the state of the object' do
65
- expect(object).to receive(:state=).with('test2')
72
+ it "changes the state of the object" do
73
+ expect(object).to receive(:state=).with("test2")
66
74
  workflow.transition to: :test2
67
75
  end
68
76
 
69
- it 'leaves the state if transitions to itself' do
77
+ it "leaves the state if transitions to itself" do
70
78
  workflow.transition
71
79
  expect(workflow.current_state_name).to eq(:test1)
72
80
  expect(object.state).to eq(:test1)
73
81
  end
74
82
  end
75
83
 
76
- describe 'transition :after hooks' do
84
+ describe "transition :after hooks" do
77
85
  subject(:workflow) { TestWorkflow.new(object) }
86
+
78
87
  let(:object) { OpenStruct.new(state: :test1, changes: {}, save: true, object_method: true) }
79
88
 
80
- it 'does not call the :after hook before saving' do
89
+ it "does not call the :after hook before saving" do
81
90
  expect(workflow).not_to receive(:workflow_method)
82
91
  workflow.transition to: :test2, after: :workflow_method
83
92
  end
84
93
 
85
- it 'does not calls the :after hook on failure' do
94
+ it "does not calls the :after hook on failure" do
86
95
  expect(workflow).not_to receive(:workflow_method)
87
96
  workflow.transition to: :test1
88
97
  workflow.save
89
98
  end
90
99
 
91
- it 'calls the :after hook on a state method' do
100
+ it "calls the :after hook on a state method" do
92
101
  expect_any_instance_of(Test1State).to receive(:state_method)
93
102
  expect_any_instance_of(Test2State).not_to receive(:state_method)
94
103
  workflow.transition to: :test2, after: :state_method
95
104
  workflow.save
96
105
  end
97
106
 
98
- it 'calls the :after hook on a workflow method' do
107
+ it "calls the :after hook on a workflow method" do
99
108
  expect(workflow).to receive(:workflow_method)
100
109
  workflow.transition to: :test2, after: :workflow_method
101
110
  workflow.save
102
111
  end
103
112
 
104
- it 'calls the :after hook on an object method' do
113
+ it "calls the :after hook on an object method" do
105
114
  expect(object).to receive(:object_method)
106
115
  workflow.transition to: :test2, after: :object_method
107
116
  workflow.save
108
117
  end
109
118
 
110
- it 'allows a lambda' do
119
+ it "allows a lambda" do
111
120
  expect_any_instance_of(Test1State).to receive(:state_method)
112
- workflow.transition to: :test2, after: ->{ state_method }
121
+ workflow.transition to: :test2, after: -> { state_method }
113
122
  workflow.save
114
123
  end
115
124
 
116
- describe 'after_transition hook' do
117
- it 'calls the hook on transition' do
125
+ describe "after_transition hook" do
126
+ it "calls the hook on transition" do
118
127
  expect(workflow).to receive(:after_transition_callback)
119
128
  workflow.transition to: :test2
120
129
  end
121
130
 
122
- it 'does not call for invalid states' do
131
+ it "does not call for invalid states" do
123
132
  expect(workflow).not_to receive(:after_transition_callback)
124
133
  expect { workflow.transition to: :invalid_state }.to raise_error(ArgumentError)
125
134
  end
126
135
 
127
- it 'does not call for ending in the same state' do
136
+ it "does not call for ending in the same state" do
128
137
  expect(workflow).not_to receive(:after_transition_callback)
129
138
  workflow.transition to: :test1
130
139
  end
131
140
  end
132
141
  end
133
142
 
134
- describe '#persist' do
143
+ describe "#persist" do
135
144
  subject(:workflow) { TestWorkflow.new(object) }
145
+
136
146
  let(:object) { OpenStruct.new(state: :test1, changes: {}, save: true) }
137
147
 
138
- context 'success' do
139
- it 'saves the object' do
148
+ context "success" do
149
+ it "saves the object" do
140
150
  expect(workflow.persist).to be true
141
151
  end
142
152
 
143
- it 'runs before and after_change hooks' do
153
+ it "runs before and after_change hooks" do
144
154
  expect(workflow.current_state).to receive(:fire_callbacks).with(:before_change, {})
145
155
  expect(workflow.current_state).to receive(:fire_callbacks).with(:after_change, {})
146
156
  expect(workflow.persist).to be true
147
157
  end
148
158
 
149
159
  it "runs after_enter hooks if it's in a new state" do
150
- allow(object).to receive(:changes).and_return({'state' => ['test1', 'test2']})
151
- expect(workflow.current_state).to receive(:fire_callbacks).with(:before_change, { 'state' => ['test1', 'test2'] })
152
- expect(workflow.current_state).to receive(:fire_callbacks).with(:after_change, { 'state' => ['test1', 'test2'] })
153
- expect(workflow.current_state).to receive(:fire_callbacks).with(:after_enter, { 'state' => ['test1', 'test2'] })
160
+ allow(object).to receive(:changes).and_return("state" => %w[test1 test2])
161
+ expect(workflow.current_state).to receive(:fire_callbacks).with(:before_change, "state" => %w[test1 test2])
162
+ expect(workflow.current_state).to receive(:fire_callbacks).with(:after_change, "state" => %w[test1 test2])
163
+ expect(workflow.current_state).to receive(:fire_callbacks).with(:after_enter, "state" => %w[test1 test2])
154
164
  expect(workflow.persist).to be true
155
165
  end
156
166
 
157
- it 'runs the before_save callback' do
167
+ it "runs the before_save callback" do
158
168
  expect(workflow).to receive(:before_save_callback)
159
169
  workflow.persist
160
170
  end
161
171
 
162
- it 'runs the after_save callback' do
172
+ it "runs the after_save callback" do
163
173
  expect(workflow).to receive(:after_save_callback)
164
174
  workflow.persist
165
175
  end
166
176
  end
167
177
 
168
- context 'failure' do
178
+ context "failure" do
169
179
  before do
170
180
  expect(object).to receive(:save).and_return false
171
181
  end
172
182
 
173
- it 'does not save the object' do
183
+ it "does not save the object" do
174
184
  expect(workflow.persist).to be false
175
185
  end
176
186
 
177
- it 'runs the before_change callback' do
187
+ it "runs the before_change callback" do
178
188
  expect(workflow.current_state).to receive(:fire_callbacks).with(:before_change, {})
179
189
  expect(workflow.persist).to be false
180
190
  end
181
191
 
182
- it 'runs the before_save callback' do
192
+ it "runs the before_save callback" do
183
193
  expect(workflow).to receive(:before_save_callback)
184
194
  workflow.persist
185
195
  end
186
196
 
187
- it 'does not run the after_save callback' do
188
- expect(workflow).to_not receive(:after_save_callback)
197
+ it "does not run the after_save callback" do
198
+ expect(workflow).not_to receive(:after_save_callback)
189
199
  workflow.persist
190
200
  end
191
201
 
192
- it 'reverts to the old state' do
202
+ it "reverts to the old state" do
193
203
  expect(workflow).to be_test1
194
204
  workflow.transition to: :test2
195
205
  expect(workflow).to be_test2