action_logic 0.0.3 → 0.0.4

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,234 @@
1
+ require 'spec_helper'
2
+ require 'action_logic'
3
+ require 'fixtures/tasks'
4
+
5
+ module ActionLogic
6
+ describe ActionTask do
7
+
8
+ it "returns an instance of ActionContext" do
9
+ result = SimpleTestTask.execute()
10
+
11
+ expect(result).to be_a(ActionLogic::ActionContext)
12
+ end
13
+
14
+ it "sets an attribute and value on the context" do
15
+ result = SimpleTestTask.execute()
16
+
17
+ expect(result.new_attribute).to be_truthy
18
+ end
19
+
20
+ describe "around validations" do
21
+ describe "required attributes and type validation" do
22
+ it "does not raise error if context has required keys and values are of the correct type" do
23
+ expect { ValidateAroundTestTask.execute(Constants::VALID_ATTRIBUTES) }.to_not raise_error
24
+ end
25
+
26
+ it "raises error if context is missing required keys" do
27
+ expect { ValidateAroundTestTask.execute() }.to\
28
+ raise_error(ActionLogic::MissingAttributeError)
29
+ end
30
+
31
+ it "raises error if context has required keys but values are not of correct type" do
32
+ expect { ValidateAroundTestTask.execute(Constants::INVALID_ATTRIBUTES) }.to\
33
+ raise_error(ActionLogic::AttributeTypeError)
34
+ end
35
+ end
36
+
37
+ describe "custom types" do
38
+ it "allows validation against custom defined types" do
39
+ expect { ValidateAroundCustomTypeTestTask.execute(:custom_type => CustomType1.new) }.to_not raise_error
40
+ end
41
+
42
+ it "raises error if context has custom type attribute but value is not correct custom type" do
43
+ expect { ValidateAroundCustomTypeTestTask.execute(:custom_type => CustomType2.new) }.to\
44
+ raise_error(ActionLogic::AttributeTypeError)
45
+ end
46
+ end
47
+
48
+ describe "presence" do
49
+ it "validates presence if presence is specified" do
50
+ expect { ValidateAroundPresenceTestTask.execute(:integer_test => 1) }.to_not raise_error
51
+ end
52
+
53
+ it "raises error if context has required key but value is not defined when validation requires presence" do
54
+ expect { ValidateAroundPresenceTestTask.execute(:integer_test => nil) }.to\
55
+ raise_error(ActionLogic::PresenceError)
56
+ end
57
+ end
58
+
59
+ describe "custom presence" do
60
+ it "allows custom presence validation if custom presence is defined" do
61
+ expect { ValidateAroundCustomPresenceTestTask.execute(:array_test => [1]) }.to_not raise_error
62
+ end
63
+
64
+ it "raises error if custom presence validation is not satisfied" do
65
+ expect { ValidateAroundCustomPresenceTestTask.execute(:array_test => []) }.to\
66
+ raise_error(ActionLogic::PresenceError)
67
+ end
68
+
69
+ it "raises error if custom presence validation is not supported" do
70
+ expect { ValidateAroundUnrecognizablePresenceTestTask.execute(:integer_test => 1) }.to\
71
+ raise_error(ActionLogic::UnrecognizablePresenceValidatorError)
72
+ end
73
+ end
74
+ end
75
+
76
+ describe "before validations" do
77
+ describe "required attributes and type validation" do
78
+ it "does not raise error if context has required keys and values are of the correct type" do
79
+ expect { ValidateBeforeTestTask.execute(Constants::VALID_ATTRIBUTES) }.to_not raise_error
80
+ end
81
+
82
+ it "raises error if context is missing required keys" do
83
+ expect { ValidateBeforeTestTask.execute() }.to\
84
+ raise_error(ActionLogic::MissingAttributeError)
85
+ end
86
+
87
+ it "raises error if context has required keys but values are not of correct type" do
88
+ expect { ValidateBeforeTestTask.execute(Constants::INVALID_ATTRIBUTES) }.to\
89
+ raise_error(ActionLogic::AttributeTypeError)
90
+ end
91
+ end
92
+
93
+ describe "custom types" do
94
+ it "allows validation against custom defined types" do
95
+ expect { ValidateBeforeCustomTypeTestTask.execute(:custom_type => CustomType1.new) }.to_not raise_error
96
+ end
97
+
98
+ it "raises error if context has custom type attribute but value is not correct custom type" do
99
+ expect { ValidateBeforeCustomTypeTestTask.execute(:custom_type => CustomType2.new) }.to\
100
+ raise_error(ActionLogic::AttributeTypeError)
101
+ end
102
+ end
103
+
104
+ describe "presence" do
105
+ it "validates presence if presence is specified" do
106
+ expect { ValidateBeforePresenceTestTask.execute(:integer_test => 1) }.to_not raise_error
107
+ end
108
+
109
+ it "raises error if context has required key but value is not defined when validation requires presence" do
110
+ expect { ValidateBeforePresenceTestTask.execute(:integer_test => nil) }.to\
111
+ raise_error(ActionLogic::PresenceError)
112
+ end
113
+ end
114
+
115
+ describe "custom presence" do
116
+ it "allows custom presence validation if custom presence is defined" do
117
+ expect { ValidateBeforeCustomPresenceTestTask.execute(:array_test => [1]) }.to_not raise_error
118
+ end
119
+
120
+ it "raises error if custom presence validation is not satisfied" do
121
+ expect { ValidateBeforeCustomPresenceTestTask.execute(:array_test => []) }.to\
122
+ raise_error(ActionLogic::PresenceError)
123
+ end
124
+
125
+ it "raises error if custom presence validation is not supported" do
126
+ expect { ValidateBeforeUnrecognizablePresenceTestTask.execute(:integer_test => 1) }.to\
127
+ raise_error(ActionLogic::UnrecognizablePresenceValidatorError)
128
+ end
129
+ end
130
+ end
131
+
132
+ describe "after validations" do
133
+ describe "required attributes and type validation" do
134
+ it "does not raise error if the task sets all required keys and values are of the correct type" do
135
+ expect { ValidateAfterTestTask.execute() }.to_not raise_error
136
+ end
137
+
138
+ it "raises error if task does not provide the necessary keys" do
139
+ expect { ValidateAfterMissingAttributesTestTask.execute() }.to\
140
+ raise_error(ActionLogic::MissingAttributeError)
141
+ end
142
+
143
+ it "raises error if task has required key but is not of correct type" do
144
+ expect { ValidateAfterInvalidTypeTestTask.execute() }.to\
145
+ raise_error(ActionLogic::AttributeTypeError)
146
+ end
147
+ end
148
+
149
+ describe "custom types" do
150
+ it "allows validation against custom defined types" do
151
+ expect { ValidateAfterCustomTypeTestTask.execute() }.to_not raise_error
152
+ end
153
+
154
+ it "raises error if context has custom type attribute but value is not correct custom type" do
155
+ expect { ValidateAfterInvalidCustomTypeTestTask.execute() }.to\
156
+ raise_error(ActionLogic::AttributeTypeError)
157
+ end
158
+ end
159
+
160
+ describe "presence" do
161
+ it "validates presence if presence is specified" do
162
+ expect { ValidateAfterPresenceTestTask.execute() }.to_not raise_error
163
+ end
164
+
165
+ it "raises error if context has required key but value is not defined when validation requires presence" do
166
+ expect { ValidateAfterInvalidPresenceTestTask.execute() }.to\
167
+ raise_error(ActionLogic::PresenceError)
168
+ end
169
+ end
170
+
171
+ describe "custom presence" do
172
+ it "allows custom presence validation if custom presence is defined" do
173
+ expect { ValidateAfterCustomPresenceTestTask.execute() }.to_not raise_error
174
+ end
175
+
176
+ it "raises error if custom presence validation is not satisfied" do
177
+ expect { ValidateAfterInvalidCustomPresenceTestTask.execute() }.to\
178
+ raise_error(ActionLogic::PresenceError)
179
+ end
180
+
181
+ it "raises error if custom presence validation is not supported" do
182
+ expect { ValidateAfterUnrecognizablePresenceTestTask.execute() }.to\
183
+ raise_error(ActionLogic::UnrecognizablePresenceValidatorError)
184
+ end
185
+ end
186
+ end
187
+
188
+ describe "error handler" do
189
+ context "with error handler defined" do
190
+ it "does not catch exceptions due to before validation errors" do
191
+ expect { ErrorHandlerInvalidAttributesBeforeTestTask.execute() }.to\
192
+ raise_error(ActionLogic::MissingAttributeError)
193
+ end
194
+
195
+ it "does not catch exceptions due to after validation errors" do
196
+ expect { ErrorHandlerInvalidAttributesAfterTestTask.execute() }.to\
197
+ raise_error(ActionLogic::MissingAttributeError)
198
+ end
199
+
200
+ it "the error and context are passed to the error handler" do
201
+ result = ErrorHandlerTestTask.execute()
202
+
203
+ expect(result.e).to be_a(RuntimeError)
204
+ expect(result).to be_a(ActionLogic::ActionContext)
205
+ end
206
+ end
207
+
208
+ context "without error handler defined" do
209
+ it "raises original exception if error handler is not defined" do
210
+ expect { MissingErrorHandlerTestTask.execute() }.to\
211
+ raise_error(RuntimeError)
212
+ end
213
+ end
214
+ end
215
+
216
+ describe "fail!" do
217
+ it "returns the context with the correct status and failure message" do
218
+ result = FailureTestTask.execute()
219
+
220
+ expect(result.status).to eq(:failure)
221
+ expect(result.message).to eq(Constants::FAILURE_MESSAGE)
222
+ end
223
+ end
224
+
225
+ describe "halt!" do
226
+ it "returns the context with the correct status and halt message" do
227
+ result = HaltTestTask.execute()
228
+
229
+ expect(result.status).to eq(:halted)
230
+ expect(result.message).to eq(Constants::HALT_MESSAGE)
231
+ end
232
+ end
233
+ end
234
+ end
@@ -0,0 +1,199 @@
1
+ require 'spec_helper'
2
+ require 'action_logic'
3
+ require 'fixtures/use_cases'
4
+ require 'fixtures/custom_types'
5
+
6
+ module ActionLogic
7
+ describe ActionUseCase do
8
+
9
+ it "returns an instance of ActionContext" do
10
+ result = SimpleTestUseCase.execute()
11
+
12
+ expect(result).to be_a(ActionLogic::ActionContext)
13
+ end
14
+
15
+ it "evalutes a task defined by the use case" do
16
+ result = SimpleTestUseCase.execute()
17
+
18
+ expect(result.new_attribute).to be_truthy
19
+ end
20
+
21
+ it "evalutes multiple tasks defined by the use case" do
22
+ result = SimpleTestUseCase2.execute()
23
+
24
+ expect(result.first).to eq("first")
25
+ expect(result.second).to eq("second")
26
+ end
27
+
28
+ it "calls the use case before evaluating the tasks" do
29
+ result = SimpleTestUseCase3.execute()
30
+
31
+ expect(result.first).to eq("first")
32
+ expect(result.second).to eq("defined in use case")
33
+ end
34
+
35
+ describe "before validations" do
36
+ describe "required attributes and type validation" do
37
+ it "does not raise error if context has required keys and values are of the correct type" do
38
+ expect { ValidateBeforeTestUseCase.execute(Constants::VALID_ATTRIBUTES) }.to_not raise_error
39
+ end
40
+
41
+ it "raises error if context is missing required keys" do
42
+ expect { ValidateBeforeTestUseCase.execute() }.to\
43
+ raise_error(ActionLogic::MissingAttributeError)
44
+ end
45
+
46
+ it "raises error if context has required key but is not of correct type" do
47
+ expect { ValidateBeforeTestUseCase.execute(Constants::INVALID_ATTRIBUTES) }.to\
48
+ raise_error(ActionLogic::AttributeTypeError)
49
+ end
50
+ end
51
+
52
+ describe "custom types" do
53
+ it "allows validation against custom defined types" do
54
+ expect { ValidateBeforeCustomTypeTestUseCase.execute(Constants::CUSTOM_TYPE_ATTRIBUTES1) }.to_not raise_error
55
+ end
56
+
57
+ it "raises error if context has custom type attribute but value is not correct custom type" do
58
+ expect { ValidateBeforeCustomTypeTestUseCase.execute(Constants::CUSTOM_TYPE_ATTRIBUTES2) }.to\
59
+ raise_error(ActionLogic::AttributeTypeError)
60
+ end
61
+ end
62
+
63
+ describe "presence" do
64
+ it "validates presence if presence is specified" do
65
+ expect { ValidateBeforePresenceTestUseCase.execute(:integer_test => 1) }.to_not raise_error
66
+ end
67
+
68
+ it "raises error if context has required key but value is not defined when validation requires presence" do
69
+ expect { ValidateBeforePresenceTestUseCase.execute(:integer_test => nil) }.to\
70
+ raise_error(ActionLogic::PresenceError)
71
+ end
72
+ end
73
+
74
+ describe "custom presence" do
75
+ it "allows custom presence validation if custom presence is defined" do
76
+ expect { ValidateBeforeCustomPresenceTestUseCase.execute(:array_test => [1]) }.to_not raise_error
77
+ end
78
+
79
+ it "raises error if custom presence validation is not satisfied" do
80
+ expect { ValidateBeforeCustomPresenceTestUseCase.execute(:array_test => []) }.to\
81
+ raise_error(ActionLogic::PresenceError)
82
+ end
83
+
84
+ it "raises error if custom presence validation is not supported" do
85
+ expect { ValidateBeforeUnrecognizablePresenceTestUseCase.execute(:integer_test => 1) }.to\
86
+ raise_error(ActionLogic::UnrecognizablePresenceValidatorError)
87
+ end
88
+ end
89
+ end
90
+
91
+ describe "after validations" do
92
+ describe "required attributes and type validation" do
93
+ it "does not raise error if the task sets all required keys and values are of the correct type" do
94
+ expect { ValidateAfterTestUseCase.execute() }.to_not raise_error
95
+ end
96
+
97
+ it "raises error if task does not provide the necessary keys" do
98
+ expect { ValidateAfterMissingAttributesTestUseCase.execute() }.to\
99
+ raise_error(ActionLogic::MissingAttributeError)
100
+ end
101
+
102
+ it "raises error if task has required key but is not of correct type" do
103
+ expect { ValidateAfterInvalidTypeTestUseCase.execute() }.to\
104
+ raise_error(ActionLogic::AttributeTypeError)
105
+ end
106
+ end
107
+
108
+ describe "custom types" do
109
+ it "allows validation against custom defined types" do
110
+ expect { ValidateAfterCustomTypeTestUseCase.execute() }.to_not raise_error
111
+ end
112
+
113
+ it "raises error if context has custom type attribute but value is not correct custom type" do
114
+ expect { ValidateAfterInvalidCustomTypeTestUseCase.execute() }.to\
115
+ raise_error(ActionLogic::AttributeTypeError)
116
+ end
117
+ end
118
+
119
+ describe "presence" do
120
+ it "validates presence if presence is specified" do
121
+ expect { ValidateAfterPresenceTestUseCase.execute() }.to_not raise_error
122
+ end
123
+
124
+ it "raises error if context has required key but value is not defined when validation requires presence" do
125
+ expect { ValidateAfterInvalidPresenceTestUseCase.execute() }.to\
126
+ raise_error(ActionLogic::PresenceError)
127
+ end
128
+ end
129
+
130
+ describe "custom presence" do
131
+ it "allows custom presence validation if custom presence is defined" do
132
+ expect { ValidateAfterCustomPresenceTestUseCase.execute() }.to_not raise_error
133
+ end
134
+
135
+ it "raises error if custom presence validation is not satisfied" do
136
+ expect { ValidateAfterInvalidCustomPresenceTestUseCase.execute() }.to\
137
+ raise_error(ActionLogic::PresenceError)
138
+ end
139
+
140
+ it "raises error if custom presence validation is not supported" do
141
+ expect { ValidateAfterUnrecognizablePresenceTestUseCase.execute() }.to\
142
+ raise_error(ActionLogic::UnrecognizablePresenceValidatorError)
143
+ end
144
+ end
145
+ end
146
+
147
+ describe "fail!" do
148
+ it "returns the context with the correct status and failure message" do
149
+ result = FailureTestUseCase.execute()
150
+
151
+ expect(result.status).to eq(:failure)
152
+ expect(result.message).to eq(Constants::FAILURE_MESSAGE)
153
+ end
154
+
155
+ it "stops execution of tasks after a task fails the context" do
156
+ result = FailureTestUseCase.execute()
157
+
158
+ expect(result.first).to eq("first")
159
+ expect(result.second).to eq("second")
160
+ expect(result.third).to be_nil
161
+ end
162
+ end
163
+
164
+ describe "halt!" do
165
+ it "returns the context with the correct status and halt message" do
166
+ result = HaltTestUseCase.execute()
167
+
168
+ expect(result.status).to eq(:halted)
169
+ expect(result.message).to eq(Constants::HALT_MESSAGE)
170
+ end
171
+
172
+ it "stops execution of tasks after a task halts the context" do
173
+ result = HaltTestUseCase.execute()
174
+
175
+ expect(result.first).to eq("first")
176
+ expect(result.second).to eq("second")
177
+ expect(result.third).to be_nil
178
+ end
179
+ end
180
+
181
+ describe "multiple use cases" do
182
+ it "does not persist attributes set on contexts from different use cases" do
183
+ result = HaltTestUseCase.execute()
184
+
185
+ expect(result.first).to eq("first")
186
+ expect(result.second).to eq("second")
187
+ expect(result.third).to be_nil
188
+ expect(result.status).to eq(:halted)
189
+
190
+ result2 = ValidateAfterPresenceTestUseCase.execute()
191
+
192
+ expect(result2.first).to be_nil
193
+ expect(result2.second).to be_nil
194
+ expect(result2.integer_test).to eq(1)
195
+ expect(result2.success?).to be_truthy
196
+ end
197
+ end
198
+ end
199
+ end
@@ -0,0 +1,46 @@
1
+ require 'fixtures/custom_types'
2
+
3
+ class Constants
4
+ ALL_VALIDATIONS = { :integer_test => { :type => :integer, :presence => true },
5
+ :float_test => { :type => :float, :presence => true },
6
+ :string_test => { :type => :string, :presence => true },
7
+ :bool_test => { :type => :boolean, :presence => true },
8
+ :hash_test => { :type => :hash, :presence => true },
9
+ :array_test => { :type => :array, :presence => true },
10
+ :symbol_test => { :type => :symbol, :presence => true },
11
+ :nil_test => { :type => :nil } }
12
+
13
+ INVALID_ATTRIBUTES = { :integer_test => nil,
14
+ :float_test => nil,
15
+ :string_test => nil,
16
+ :bool_test => nil,
17
+ :hash_test => nil,
18
+ :array_test => nil,
19
+ :symbol_test => nil,
20
+ :nil_test => 1 }
21
+
22
+ VALID_ATTRIBUTES = { :integer_test => 1,
23
+ :float_test => 1.0,
24
+ :string_test => "string",
25
+ :bool_test => true,
26
+ :hash_test => {},
27
+ :array_test => [],
28
+ :symbol_test => :symbol,
29
+ :nil_test => nil }
30
+
31
+ CUSTOM_TYPE_VALIDATION1 = { :custom_type => { :type => :customtype1, :presence => true } }
32
+
33
+ CUSTOM_TYPE_ATTRIBUTES1 = { :custom_type => CustomType1.new }
34
+
35
+ CUSTOM_TYPE_VALIDATION2 = { :custom_type => { :type => :customtype2, :presence => true } }
36
+
37
+ CUSTOM_TYPE_ATTRIBUTES2 = { :custom_type => CustomType2.new }
38
+
39
+ PRESENCE_VALIDATION = { :integer_test => { :presence => true } }
40
+
41
+ CUSTOM_PRESENCE_VALIDATION = { :array_test => { :presence => ->(array_test) { array_test.any? } } }
42
+
43
+ FAILURE_MESSAGE = "error"
44
+
45
+ HALT_MESSAGE = "halt"
46
+ end