hexx 0.0.1

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.
Files changed (75) hide show
  1. checksums.yaml +7 -0
  2. data/.rubocop.yml +45 -0
  3. data/CHANGELOG.rdoc +1 -0
  4. data/LICENSE.rdoc +21 -0
  5. data/README.rdoc +235 -0
  6. data/Rakefile +31 -0
  7. data/bin/hexx +54 -0
  8. data/lib/generators/base.rb +59 -0
  9. data/lib/generators/controller/controller.rb +87 -0
  10. data/lib/generators/controller/templates/controller.erb +18 -0
  11. data/lib/generators/controller/templates/controller_action.erb +8 -0
  12. data/lib/generators/controller/templates/controller_action_spec.erb +28 -0
  13. data/lib/generators/controller/templates/controller_spec.erb +52 -0
  14. data/lib/generators/controller/templates/routing_action_spec.erb +10 -0
  15. data/lib/generators/controller/templates/routing_spec.erb +10 -0
  16. data/lib/generators/dependency/dependency.rb +34 -0
  17. data/lib/generators/dependency/templates/dependency_setting.erb +4 -0
  18. data/lib/generators/dependency/templates/dependency_setting_spec.erb +34 -0
  19. data/lib/generators/dependency/templates/module_spec.erb +22 -0
  20. data/lib/generators/domain/domain.rb +24 -0
  21. data/lib/generators/domain/templates/spec.erb +84 -0
  22. data/lib/generators/install/install.rb +115 -0
  23. data/lib/generators/install/templates/CHANGELOG.erb +1 -0
  24. data/lib/generators/install/templates/Gemfile.erb +5 -0
  25. data/lib/generators/install/templates/LICENSE.erb +21 -0
  26. data/lib/generators/install/templates/README.erb +55 -0
  27. data/lib/generators/install/templates/Rakefile.erb +34 -0
  28. data/lib/generators/install/templates/bin/rails.erb +11 -0
  29. data/lib/generators/install/templates/config/routes.erb +6 -0
  30. data/lib/generators/install/templates/gemspec.erb +29 -0
  31. data/lib/generators/install/templates/lib/engine.erb +12 -0
  32. data/lib/generators/install/templates/lib/lib.erb +10 -0
  33. data/lib/generators/install/templates/lib/version.erb +4 -0
  34. data/lib/generators/install/templates/spec/coveralls.erb +4 -0
  35. data/lib/generators/install/templates/spec/database_cleaner.erb +27 -0
  36. data/lib/generators/install/templates/spec/factory_girl.erb +6 -0
  37. data/lib/generators/install/templates/spec/factory_girl_rails.erb +1 -0
  38. data/lib/generators/install/templates/spec/focus.erb +5 -0
  39. data/lib/generators/install/templates/spec/garbage_collection.erb +11 -0
  40. data/lib/generators/install/templates/spec/i18n.erb +1 -0
  41. data/lib/generators/install/templates/spec/migrations.erb +3 -0
  42. data/lib/generators/install/templates/spec/rails.erb +6 -0
  43. data/lib/generators/install/templates/spec/random_order.erb +4 -0
  44. data/lib/generators/install/templates/spec/rspec.erb +5 -0
  45. data/lib/generators/install/templates/spec/spec_helper.erb +12 -0
  46. data/lib/generators/install/templates/spec/timecop.erb +1 -0
  47. data/lib/generators/request/request.rb +52 -0
  48. data/lib/generators/request/templates/request_spec.erb +73 -0
  49. data/lib/generators/use_case/templates/use_case.erb +29 -0
  50. data/lib/generators/use_case/templates/use_case_spec.erb +77 -0
  51. data/lib/generators/use_case/use_case.rb +31 -0
  52. data/lib/hexx.rb +2 -0
  53. data/lib/hexx/exceptions/not_found_error.rb +12 -0
  54. data/lib/hexx/exceptions/record_invalid.rb +12 -0
  55. data/lib/hexx/exceptions/runtime_error.rb +24 -0
  56. data/lib/hexx/exceptions/use_case_invalid.rb +12 -0
  57. data/lib/hexx/models.rb +82 -0
  58. data/lib/hexx/settings.rb +47 -0
  59. data/lib/hexx/use_case.rb +228 -0
  60. data/lib/hexx/version.rb +4 -0
  61. data/spec/hexx/exceptions/not_found_error_spec.rb +27 -0
  62. data/spec/hexx/exceptions/record_invalid_spec.rb +27 -0
  63. data/spec/hexx/exceptions/runtime_error_spec.rb +61 -0
  64. data/spec/hexx/exceptions/use_case_invalid_spec.rb +27 -0
  65. data/spec/hexx/models_spec.rb +64 -0
  66. data/spec/hexx/settings_spec.rb +51 -0
  67. data/spec/hexx/use_case_spec.rb +262 -0
  68. data/spec/spec_helper.rb +3 -0
  69. data/spec/support/initializers/coveralls.rb +3 -0
  70. data/spec/support/initializers/focus.rb +5 -0
  71. data/spec/support/initializers/garbage_collection.rb +11 -0
  72. data/spec/support/initializers/i18n.rb +1 -0
  73. data/spec/support/initializers/random_order.rb +4 -0
  74. data/spec/support/initializers/rspec.rb +5 -0
  75. metadata +236 -0
@@ -0,0 +1,4 @@
1
+ # Core classes to follow hexagonal domain architecture.
2
+ module Hexx
3
+ VERSION = "0.0.1"
4
+ end
@@ -0,0 +1,27 @@
1
+ require "spec_helper"
2
+
3
+ module Hexx
4
+ describe NotFoundError do
5
+
6
+ let!(:subject) { NotFoundError }
7
+
8
+ it "inherits RuntimeError" do
9
+ expect(subject.ancestors).to be_include Hexx::RuntimeError
10
+ end
11
+
12
+ describe "#message" do
13
+
14
+ let!(:object) { double "object" }
15
+ let!(:errors) { double "errors" }
16
+ before { allow(object).to receive(:errors) { errors } }
17
+
18
+ it "customized" do
19
+ begin
20
+ fail subject.new(object)
21
+ rescue => error
22
+ expect(error.message).to eq "Not found: #{ errors.inspect }"
23
+ end
24
+ end
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,27 @@
1
+ require "spec_helper"
2
+
3
+ module Hexx
4
+ describe RecordInvalid do
5
+
6
+ let!(:subject) { RecordInvalid }
7
+
8
+ it "inherits RuntimeError" do
9
+ expect(subject.ancestors).to be_include Hexx::RuntimeError
10
+ end
11
+
12
+ describe "#message" do
13
+
14
+ let!(:object) { double "object" }
15
+ let!(:errors) { double "errors" }
16
+ before { allow(object).to receive(:errors) { errors } }
17
+
18
+ it "customized" do
19
+ begin
20
+ fail subject.new(object)
21
+ rescue => error
22
+ expect(error.message).to eq "Invalid use case: #{ errors.inspect }"
23
+ end
24
+ end
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,61 @@
1
+ require "spec_helper"
2
+
3
+ module Hexx
4
+ describe RuntimeError do
5
+
6
+ let!(:subject) { RuntimeError }
7
+ let!(:object) { double "object" }
8
+ let!(:errors) { double "errors" }
9
+ before { allow(object).to receive(:errors) { errors } }
10
+
11
+ let!(:error) { subject.new object }
12
+
13
+ it "inherits core RuntimeError" do
14
+ expect(subject.ancestors).to be_include ::RuntimeError
15
+ end
16
+
17
+ describe ".new" do
18
+
19
+ it "initializes the object attribute" do
20
+ expect(subject).to respond_to(:new).with(1).argument
21
+ end
22
+ end
23
+
24
+ describe "#object" do
25
+
26
+ it "is public" do
27
+ expect(error).to respond_to :object
28
+ end
29
+
30
+ it "initializes the #object attribute" do
31
+ expect(error.object).to eq object
32
+ end
33
+ end
34
+
35
+ describe "#errors" do
36
+
37
+ it "is public" do
38
+ expect(error).to respond_to :errors
39
+ end
40
+
41
+ it "delegated to object" do
42
+ expect(error.errors).to eq errors
43
+ end
44
+
45
+ it "set to nil unless object is set" do
46
+ expect(subject.new(nil).errors).to be_nil
47
+ end
48
+ end
49
+
50
+ describe "#message" do
51
+
52
+ it "customized" do
53
+ begin
54
+ fail error
55
+ rescue => e
56
+ expect(e.message).to eq "Runtime error: #{ errors.inspect }"
57
+ end
58
+ end
59
+ end
60
+ end
61
+ end
@@ -0,0 +1,27 @@
1
+ require "spec_helper"
2
+
3
+ module Hexx
4
+ describe UseCaseInvalid do
5
+
6
+ let!(:subject) { UseCaseInvalid }
7
+
8
+ it "inherits RuntimeError" do
9
+ expect(subject.ancestors).to be_include Hexx::RuntimeError
10
+ end
11
+
12
+ describe "#message" do
13
+
14
+ let!(:object) { double "object" }
15
+ let!(:errors) { double "errors" }
16
+ before { allow(object).to receive(:errors) { errors } }
17
+
18
+ it "customized" do
19
+ begin
20
+ fail subject.new(object)
21
+ rescue => error
22
+ expect(error.message).to eq "Invalid use case: #{ errors.inspect }"
23
+ end
24
+ end
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,64 @@
1
+ module Hexx
2
+ describe Models do
3
+
4
+ # ==========================================================================
5
+ # Prepare environment
6
+ # ==========================================================================
7
+
8
+ around do |example|
9
+ class TestModel; include Models; end
10
+ class TestAttribute; end
11
+ example.run
12
+ Hexx.send :remove_const, :TestAttribute
13
+ Hexx.send :remove_const, :TestModel
14
+ end
15
+
16
+ let!(:coerced_attribute) { double "coerced attribute" }
17
+ before do
18
+ allow(TestAttribute).to receive(:new) { |val| coerced_attribute if val }
19
+ end
20
+
21
+ # ==========================================================================
22
+ # Prepare variables
23
+ # ==========================================================================
24
+
25
+ let!(:subject) { TestModel }
26
+
27
+ # ==========================================================================
28
+ # Run tests
29
+ # ==========================================================================
30
+
31
+ describe "#validate!" do
32
+
33
+ let!(:object) { subject.new }
34
+
35
+ it "is public" do
36
+ expect(object).to respond_to(:validate!).with(0).arguments
37
+ end
38
+
39
+ it "returns true for valid instance" do
40
+ allow(object).to receive(:valid?) { true }
41
+ expect(object.validate!).to be_truthy
42
+ end
43
+
44
+ it "fails with Hexx::RecordInvalid for invalid instance" do
45
+ allow(object).to receive(:valid?) { false }
46
+ expect { object.validate! }.to raise_error do |error|
47
+ expect(error).to be_kind_of Hexx::RecordInvalid
48
+ expect(error.object).to eq object
49
+ end
50
+ end
51
+ end
52
+
53
+ describe ".attr_coerced" do
54
+
55
+ it "coerces an attribute with given type" do
56
+ subject.send :attr_coerced, :name, type: TestAttribute
57
+ object = subject.new
58
+ expect { object.name = "some name" }
59
+ .to change { object.name }
60
+ .from(nil).to coerced_attribute
61
+ end
62
+ end
63
+ end
64
+ end
@@ -0,0 +1,51 @@
1
+ require "spec_helper"
2
+
3
+ module Hexx
4
+ describe Settings do
5
+
6
+ around do |example|
7
+ module TestModule; include Settings; end
8
+ class TestClass; end
9
+ example.run
10
+ Hexx.send :remove_const, :TestClass
11
+ Hexx.send :remove_const, :TestModule
12
+ end
13
+
14
+ let!(:subject) { TestModule }
15
+
16
+ describe ".configure" do
17
+
18
+ it "is public" do
19
+ expect(subject).to respond_to(:configure).with(0).arguments
20
+ end
21
+
22
+ it "sends itself to a block" do
23
+ subject.configure do |c|
24
+ expect(c).to eq subject
25
+ end
26
+ end
27
+ end
28
+
29
+ describe ".depends_on" do
30
+
31
+ it "is public" do
32
+ expect(subject).to respond_to(:depends_on).with(1).argument
33
+ end
34
+
35
+ it "defines name settings accessor" do
36
+ subject.depends_on :test_class
37
+ expect(subject).to respond_to(:test_class_name).with(0).arguments
38
+ expect(subject).to respond_to(:test_class_name=).with(1).argument
39
+ expect { subject.test_class_name = "TestClass" }
40
+ .to change { subject.test_class_name }.from(nil).to "TestClass"
41
+ end
42
+
43
+ it "defines corresponding constant reader" do
44
+ subject.depends_on :test_class
45
+ expect(subject).to respond_to(:test_class).with(0).arguments
46
+ expect { subject.test_class_name = "Hexx::TestClass" }
47
+ .to change { subject.test_class }.from(nil).to TestClass
48
+ end
49
+ end
50
+ end
51
+ end
@@ -0,0 +1,262 @@
1
+ require "spec_helper"
2
+
3
+ module Hexx
4
+ describe UseCase do
5
+
6
+ around :each do |example|
7
+ class TestCase < UseCase; end
8
+ example.run
9
+ Hexx.send :remove_const, :TestCase
10
+ end
11
+
12
+ let!(:subject) { TestCase }
13
+
14
+ # ==========================================================================
15
+ # Tests
16
+ # ==========================================================================
17
+
18
+ it "includes ActiveModel validations" do
19
+ expect(subject.ancestors).to be_include ActiveModel::Validations
20
+ end
21
+
22
+ describe ".new" do
23
+
24
+ it "accepts 0 to 1 arguments" do
25
+ expect(subject).to respond_to(:new).with(0).arguments
26
+ expect(subject).to respond_to(:new).with(1).arguments
27
+ end
28
+
29
+ it "without arguments sets #params to {}" do
30
+ use_case = subject.new
31
+ expect(use_case.send(:params)).to eq({})
32
+ end
33
+
34
+ it "with unknown key sets #params to {}" do
35
+ use_case = subject.new id: 1
36
+ expect(use_case.send(:params)).to eq({})
37
+ end
38
+
39
+ it "with non-hash argument sets #params to {}" do
40
+ use_case = subject.new 1
41
+ expect(use_case.send(:params)).to eq({})
42
+ end
43
+ end
44
+
45
+ describe ".allow_params" do
46
+
47
+ it "allows #params to accept value from arguments" do
48
+ subject.send :allow_params, :id, :name
49
+ use_case = subject.new id: 1, name: "text", wrong: :wrong
50
+ expect(use_case.send(:params)).to eq("id" => 1, "name" => "text")
51
+ end
52
+
53
+ it "stringifies keys" do
54
+ subject.send :allow_params, :"1"
55
+ use_case = subject.new 1 => 1, "1" => 2, :"1" => 3
56
+ expect(use_case.send(:params)).to eq("1" => 3)
57
+ end
58
+ end
59
+
60
+ describe "#params" do
61
+
62
+ it "is private" do
63
+ expect(subject.new).not_to respond_to :params
64
+ end
65
+ end
66
+
67
+ describe "#valid?" do
68
+
69
+ it "is private" do
70
+ expect(subject.new).not_to respond_to :valid?
71
+ end
72
+ end
73
+
74
+ describe "#invalid?" do
75
+
76
+ it "is private" do
77
+ expect(subject.new).not_to respond_to :valid?
78
+ end
79
+ end
80
+
81
+ describe "#validate!" do
82
+
83
+ let!(:use_case) { subject.new }
84
+
85
+ it "is private" do
86
+ expect(use_case).not_to respond_to :validate!
87
+ end
88
+
89
+ context "invalid use_case" do
90
+
91
+ before { allow(use_case).to receive(:valid?) { false } }
92
+
93
+ it "calls the #valid? method" do
94
+ expect(use_case).to receive :valid?
95
+ begin; use_case.send :validate!; rescue Exception; end
96
+ end
97
+
98
+ it "fails" do
99
+ expect { use_case.send :validate! }.to raise_error do |error|
100
+ expect(error).to be_kind_of UseCaseInvalid
101
+ end
102
+ end
103
+ end
104
+
105
+ context "valid use_case" do
106
+
107
+ it "passes" do
108
+ expect { use_case.send :validate! }.not_to raise_error
109
+ end
110
+
111
+ it "not changes it" do
112
+ expect { use_case.send :validate! }.not_to change { use_case }
113
+ end
114
+ end
115
+ end
116
+
117
+ describe "#run!" do
118
+
119
+ let!(:use_case) { subject.new }
120
+
121
+ it "is public" do
122
+ expect(use_case).to respond_to(:run!).with(0).arguments
123
+ end
124
+
125
+ it "raises NotImplementedError" do
126
+ expect { use_case.run! }.to raise_error do |error|
127
+ expect(error).to be_kind_of NotImplementedError
128
+ end
129
+ end
130
+ end
131
+
132
+ describe "#run" do
133
+
134
+ let!(:use_case) { subject.new }
135
+ let!(:object) { double "entity" }
136
+ let!(:errors) { { base: :invalid } }
137
+ let!(:listener) { double "listener" }
138
+
139
+ before { allow(object).to receive(:errors) { errors } }
140
+ before { use_case.subscribe listener }
141
+
142
+ it "calls the #run!" do
143
+ expect(use_case).to receive(:run!)
144
+ begin; use_case.run; rescue Exception; end
145
+ end
146
+
147
+ context "if the #run! passes" do
148
+
149
+ let!(:result) { double "result" }
150
+ before { allow(use_case).to receive(:run!) { result } }
151
+
152
+ it "returns its output" do
153
+ expect(use_case.run).to eq result
154
+ end
155
+ end
156
+
157
+ context "if the #run! raises NotFoundError" do
158
+
159
+ before do
160
+ allow(use_case).to receive(:run!) { fail NotFoundError.new object }
161
+ end
162
+
163
+ it "doesn't raise" do
164
+ expect { use_case.run }.not_to raise_error
165
+ end
166
+
167
+ it "publishes the :not_found notification" do
168
+ expect(listener).to receive(:not_found) do |messages|
169
+ expect(messages).to eq errors.values
170
+ end
171
+ use_case.run
172
+ end
173
+
174
+ it "returns nil" do
175
+ expect(use_case.run).to be_nil
176
+ end
177
+ end
178
+
179
+ context "if the #run! raises another Hexx::Runtime error" do
180
+
181
+ before do
182
+ allow(use_case).to receive(:run!) { fail RuntimeError.new object }
183
+ end
184
+
185
+ it "doesn't raise" do
186
+ expect { use_case.run }.not_to raise_error
187
+ end
188
+
189
+ it "publishes the :error notification" do
190
+ expect(listener).to receive(:error) do |messages|
191
+ expect(messages).to eq errors.values
192
+ end
193
+ use_case.run
194
+ end
195
+
196
+ it "returns nil" do
197
+ expect(use_case.run).to be_nil
198
+ end
199
+ end
200
+
201
+ context "if the #run! raises core StandardError" do
202
+
203
+ before do
204
+ allow(use_case).to receive(:run!) { fail ::StandardError }
205
+ end
206
+
207
+ it "doesn't raise" do
208
+ expect { use_case.run }.not_to raise_error
209
+ end
210
+
211
+ it "publishes the :error notification" do
212
+ expect(listener).to receive(:error) do |arg|
213
+ expect(arg).to eq ["StandardError"]
214
+ end
215
+ use_case.run
216
+ end
217
+
218
+ it "returns nil" do
219
+ expect(use_case.run).to be_nil
220
+ end
221
+ end
222
+
223
+ context "if the #run! raises non-runtime error" do
224
+
225
+ before do
226
+ allow(use_case).to receive(:run!) { fail Exception }
227
+ end
228
+
229
+ it "re-raises the error" do
230
+ expect { use_case.run }.to raise_error do |error|
231
+ expect(error.inspect).to eq Exception.new.inspect
232
+ end
233
+ end
234
+ end
235
+ end
236
+
237
+ describe "#subscribe" do
238
+
239
+ let!(:use_case) { subject.new }
240
+ let!(:listener) { double "listener" }
241
+ let!(:messages) { double "messages" }
242
+
243
+ before do
244
+ allow(use_case)
245
+ .to receive(:run!) { use_case.send :publish, :ok, messages }
246
+ end
247
+
248
+ it "is public" do
249
+ expect(use_case).to respond_to(:subscribe).with(1).argument
250
+ expect(use_case).to respond_to(:subscribe).with(2).arguments
251
+ end
252
+
253
+ it "subscribes a listener to use_case notifications" do
254
+ use_case.subscribe listener
255
+ expect(listener).to receive(:ok) do |messages|
256
+ expect(messages).to eq messages
257
+ end
258
+ use_case.run!
259
+ end
260
+ end
261
+ end
262
+ end