flow_machine 0.2.2 → 0.2.3
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/README.md +8 -2
- data/Rakefile +13 -17
- data/lib/flow_machine.rb +1 -2
- data/lib/flow_machine/callback.rb +36 -33
- data/lib/flow_machine/change_callback.rb +10 -8
- data/lib/flow_machine/state_callback.rb +5 -3
- data/lib/flow_machine/version.rb +1 -1
- data/lib/flow_machine/workflow.rb +6 -6
- data/lib/flow_machine/workflow/factory_methods.rb +2 -1
- data/lib/flow_machine/workflow_state.rb +132 -122
- data/spec/flow_machine/factory_methods_spec.rb +23 -15
- data/spec/flow_machine/multiple_workflow_spec.rb +14 -8
- data/spec/flow_machine/workflow/model_extension_spec.rb +15 -15
- data/spec/flow_machine/workflow_callback_spec.rb +38 -34
- data/spec/flow_machine/workflow_change_callback_spec.rb +13 -10
- data/spec/flow_machine/workflow_spec.rb +55 -45
- data/spec/flow_machine/workflow_state/transition_callbacks_spec.rb +66 -0
- data/spec/flow_machine/workflow_state_spec.rb +100 -58
- data/spec/spec_helper.rb +7 -7
- metadata +22 -6
@@ -5,44 +5,52 @@ RSpec.describe FlowMachine::Workflow do
|
|
5
5
|
include FlowMachine::Workflow
|
6
6
|
end
|
7
7
|
|
8
|
-
describe
|
8
|
+
describe ".class_for" do
|
9
9
|
subject(:workflow_class) { described_class.class_for(target) }
|
10
10
|
|
11
|
-
describe
|
11
|
+
describe "with a class" do
|
12
12
|
let(:target) { TestClass }
|
13
|
-
|
13
|
+
|
14
|
+
it { is_expected.to eq(TestClassWorkflow) }
|
14
15
|
end
|
15
16
|
|
16
|
-
describe
|
17
|
+
describe "with an object" do
|
17
18
|
let(:target) { TestClass.new }
|
18
|
-
|
19
|
+
|
20
|
+
it { is_expected.to eq(TestClassWorkflow) }
|
19
21
|
end
|
20
22
|
end
|
21
23
|
|
22
|
-
describe
|
24
|
+
describe ".for" do
|
23
25
|
subject(:workflow) { described_class.for(target) }
|
26
|
+
|
24
27
|
class SomeNewClass; end
|
25
28
|
|
26
|
-
describe
|
29
|
+
describe "not found" do
|
27
30
|
let(:target) { SomeNewClass.new }
|
28
|
-
|
31
|
+
|
32
|
+
it { is_expected.to be_nil }
|
29
33
|
end
|
30
34
|
|
31
|
-
describe
|
35
|
+
describe "with an object" do
|
32
36
|
let(:target) { TestClass.new }
|
33
|
-
|
34
|
-
|
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
|
42
|
+
describe "with an array of objects" do
|
38
43
|
let(:target) { [TestClass.new, TestClass.new] }
|
39
|
-
|
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
|
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
|
-
|
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
|
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
|
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
|
30
|
+
context "class1" do
|
27
31
|
subject { workflow_class1.new(double) }
|
28
|
-
|
29
|
-
it {
|
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
|
37
|
+
context "class2" do
|
33
38
|
subject { workflow_class2.new(double) }
|
34
|
-
|
35
|
-
it {
|
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
|
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
|
17
|
-
|
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
|
-
|
25
|
+
UnPersistedModel = Struct.new(:state) do
|
26
26
|
TestWorkflow.create_scopes_on(self)
|
27
27
|
end
|
28
28
|
|
29
|
-
it
|
30
|
-
expect(PersistedModel.new(
|
31
|
-
expect(PersistedModel.new(
|
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
|
35
|
-
expect(PersistedModel.new(
|
36
|
-
expect(PersistedModel.new(
|
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
|
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(
|
42
|
+
expect(PersistedModel.test1.first).to eq(PersistedModel.new("test1"))
|
43
43
|
end
|
44
44
|
|
45
|
-
it
|
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(
|
48
|
+
expect(PersistedModel.test2.first).to eq(PersistedModel.new("test2"))
|
49
49
|
end
|
50
50
|
|
51
|
-
it
|
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
|
4
|
+
describe "callback with method" do
|
5
5
|
let(:callback) { described_class.new(:some_method) }
|
6
6
|
|
7
|
-
it
|
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
|
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
|
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
|
26
|
-
context
|
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
|
28
|
+
context "if method returns true" do
|
30
29
|
before { allow(object).to receive(:if_method?).and_return true }
|
31
|
-
|
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
|
37
|
+
context "if method returns false" do
|
38
38
|
before { allow(object).to receive(:if_method?).and_return false }
|
39
|
-
|
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
|
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
|
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
|
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
|
65
|
-
let(:callback) { described_class.new(:some_method, if: [
|
66
|
-
|
67
|
-
|
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
|
-
|
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
|
78
|
-
before
|
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
|
84
|
-
expect(object).
|
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
|
92
|
-
context
|
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
|
98
|
+
context "unless method returns false" do
|
96
99
|
before { allow(object).to receive(:unless_method?).and_return false }
|
97
100
|
|
98
|
-
it
|
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
|
105
|
-
|
106
|
-
|
107
|
-
|
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
|
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
|
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
|
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(
|
10
|
+
specify { expect(callback.options).to eq(if: :condition?) }
|
7
11
|
|
8
|
-
|
9
|
-
|
12
|
+
context "the field changes" do
|
13
|
+
let(:changes) { { "field" => %i[old new] } }
|
10
14
|
|
11
|
-
|
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
|
20
|
-
let(:changes) { {
|
21
|
-
|
22
|
-
|
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
|
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
|
26
|
-
it
|
27
|
-
expect(TestWorkflow.state_names).to eq([
|
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
|
31
|
-
expect(TestWorkflow.states).to eq(
|
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
|
38
|
+
describe "reading initial state" do
|
36
39
|
subject(:workflow) { TestWorkflow.new(object) }
|
37
|
-
|
40
|
+
|
41
|
+
context "default state field" do
|
38
42
|
let(:object) { double(state: :test1) }
|
39
|
-
|
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
|
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
|
-
|
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
|
63
|
+
describe "#transition" do
|
57
64
|
subject(:workflow) { TestWorkflow.new(object) }
|
65
|
+
|
58
66
|
let(:object) { double(state: :test1) }
|
59
67
|
|
60
|
-
it
|
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
|
65
|
-
expect(object).to receive(:state=).with(
|
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
|
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
|
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
|
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
|
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
|
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
|
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
|
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
|
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
|
117
|
-
it
|
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
|
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
|
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
|
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
|
139
|
-
it
|
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
|
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(
|
151
|
-
expect(workflow.current_state).to receive(:fire_callbacks).with(:before_change,
|
152
|
-
expect(workflow.current_state).to receive(:fire_callbacks).with(:after_change,
|
153
|
-
expect(workflow.current_state).to receive(:fire_callbacks).with(:after_enter,
|
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
|
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
|
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
|
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
|
183
|
+
it "does not save the object" do
|
174
184
|
expect(workflow.persist).to be false
|
175
185
|
end
|
176
186
|
|
177
|
-
it
|
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
|
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
|
188
|
-
expect(workflow).
|
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
|
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
|