action_logic 0.0.3 → 0.0.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,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