hanami 2.0.0.beta1.1 → 2.0.0.beta3

Sign up to get free protection for your applications and to get access to all the features.
Files changed (156) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +82 -0
  3. data/hanami.gemspec +1 -2
  4. data/lib/hanami/app.rb +76 -16
  5. data/lib/hanami/assets/{application_configuration.rb → app_configuration.rb} +1 -1
  6. data/lib/hanami/configuration/null_configuration.rb +2 -2
  7. data/lib/hanami/configuration.rb +36 -36
  8. data/lib/hanami/extensions/action/slice_configured_action.rb +44 -1
  9. data/lib/hanami/extensions/view/slice_configured_view.rb +47 -7
  10. data/lib/hanami/providers/rack.rb +2 -0
  11. data/lib/hanami/providers/settings.rb +81 -6
  12. data/lib/hanami/routes.rb +48 -21
  13. data/lib/hanami/settings/env_store.rb +32 -0
  14. data/lib/hanami/settings.rb +8 -12
  15. data/lib/hanami/setup.rb +1 -6
  16. data/lib/hanami/slice/routing/middleware/stack.rb +26 -5
  17. data/lib/hanami/slice.rb +38 -45
  18. data/lib/hanami/slice_configurable.rb +14 -1
  19. data/lib/hanami/slice_registrar.rb +65 -5
  20. data/lib/hanami/version.rb +1 -1
  21. data/lib/hanami.rb +53 -2
  22. data/spec/{new_integration → integration}/action/cookies_spec.rb +0 -0
  23. data/spec/{new_integration → integration}/action/csrf_protection_spec.rb +0 -0
  24. data/spec/{new_integration → integration}/action/routes_spec.rb +3 -5
  25. data/spec/{new_integration → integration}/action/sessions_spec.rb +0 -0
  26. data/spec/integration/action/slice_configuration_spec.rb +287 -0
  27. data/spec/{new_integration → integration}/action/view_integration_spec.rb +0 -0
  28. data/spec/{new_integration → integration}/action/view_rendering/automatic_rendering_spec.rb +0 -0
  29. data/spec/{new_integration → integration}/action/view_rendering/paired_view_inference_spec.rb +0 -0
  30. data/spec/{new_integration → integration}/action/view_rendering_spec.rb +0 -0
  31. data/spec/{new_integration → integration}/code_loading/loading_from_app_spec.rb +0 -0
  32. data/spec/integration/code_loading/loading_from_lib_spec.rb +208 -0
  33. data/spec/{new_integration → integration}/code_loading/loading_from_slice_spec.rb +0 -0
  34. data/spec/{new_integration → integration}/container/application_routes_helper_spec.rb +1 -3
  35. data/spec/{new_integration → integration}/container/auto_injection_spec.rb +0 -0
  36. data/spec/{new_integration → integration}/container/auto_registration_spec.rb +0 -0
  37. data/spec/{new_integration → integration}/container/autoloader_spec.rb +0 -0
  38. data/spec/{new_integration → integration}/container/imports_spec.rb +0 -0
  39. data/spec/{new_integration → integration}/container/prepare_container_spec.rb +0 -0
  40. data/spec/{new_integration → integration}/container/shutdown_spec.rb +0 -0
  41. data/spec/{new_integration → integration}/container/standard_bootable_components_spec.rb +0 -0
  42. data/spec/integration/dotenv_loading_spec.rb +137 -0
  43. data/spec/{new_integration → integration}/rack_app/middleware_spec.rb +9 -15
  44. data/spec/{new_integration → integration}/rack_app/non_booted_rack_app_spec.rb +3 -5
  45. data/spec/{new_integration → integration}/rack_app/rack_app_spec.rb +28 -48
  46. data/spec/integration/settings/access_to_constants_spec.rb +169 -0
  47. data/spec/integration/settings/loading_from_env_spec.rb +187 -0
  48. data/spec/integration/settings/settings_component_loading_spec.rb +113 -0
  49. data/spec/integration/settings/using_types_spec.rb +87 -0
  50. data/spec/integration/setup_spec.rb +165 -0
  51. data/spec/{new_integration → integration}/slices/external_slice_spec.rb +2 -4
  52. data/spec/{new_integration → integration}/slices/slice_configuration_spec.rb +0 -0
  53. data/spec/integration/slices/slice_loading_spec.rb +171 -0
  54. data/spec/{new_integration → integration}/slices/slice_routing_spec.rb +5 -13
  55. data/spec/{new_integration → integration}/slices/slice_settings_spec.rb +0 -0
  56. data/spec/{new_integration → integration}/slices_spec.rb +0 -0
  57. data/spec/{new_integration → integration}/view/context/assets_spec.rb +0 -0
  58. data/spec/{new_integration → integration}/view/context/inflector_spec.rb +0 -0
  59. data/spec/{new_integration → integration}/view/context/request_spec.rb +0 -0
  60. data/spec/{new_integration → integration}/view/context/routes_spec.rb +1 -3
  61. data/spec/{new_integration → integration}/view/context/settings_spec.rb +5 -1
  62. data/spec/{new_integration → integration}/view/inflector_spec.rb +0 -0
  63. data/spec/{new_integration → integration}/view/part_namespace_spec.rb +0 -0
  64. data/spec/{new_integration → integration}/view/path_spec.rb +0 -0
  65. data/spec/integration/view/slice_configuration_spec.rb +289 -0
  66. data/spec/{new_integration → integration}/view/template_spec.rb +0 -0
  67. data/spec/{new_integration → integration}/view/views_spec.rb +0 -0
  68. data/spec/support/app_integration.rb +4 -5
  69. data/spec/unit/hanami/configuration/actions_spec.rb +4 -15
  70. data/spec/unit/hanami/configuration/router_spec.rb +45 -0
  71. data/spec/unit/hanami/configuration/slices_spec.rb +34 -0
  72. data/spec/unit/hanami/configuration/views_spec.rb +4 -15
  73. data/spec/unit/hanami/settings/env_store_spec.rb +52 -0
  74. data/spec/unit/hanami/slice_configurable_spec.rb +2 -2
  75. data/spec/unit/hanami/version_spec.rb +1 -1
  76. metadata +105 -250
  77. data/lib/hanami/server.rb +0 -29
  78. data/lib/hanami/settings/dotenv_store.rb +0 -58
  79. data/spec/integration/application_middleware_stack_spec.rb +0 -84
  80. data/spec/integration/assets/cdn_spec.rb +0 -48
  81. data/spec/integration/assets/fingerprint_spec.rb +0 -42
  82. data/spec/integration/assets/helpers_spec.rb +0 -50
  83. data/spec/integration/assets/serve_spec.rb +0 -70
  84. data/spec/integration/assets/subresource_integrity_spec.rb +0 -54
  85. data/spec/integration/body_parsers_spec.rb +0 -50
  86. data/spec/integration/cli/assets/precompile_spec.rb +0 -147
  87. data/spec/integration/cli/assets_spec.rb +0 -14
  88. data/spec/integration/cli/console_spec.rb +0 -105
  89. data/spec/integration/cli/db/apply_spec.rb +0 -74
  90. data/spec/integration/cli/db/console_spec.rb +0 -40
  91. data/spec/integration/cli/db/create_spec.rb +0 -50
  92. data/spec/integration/cli/db/drop_spec.rb +0 -54
  93. data/spec/integration/cli/db/migrate_spec.rb +0 -108
  94. data/spec/integration/cli/db/prepare_spec.rb +0 -36
  95. data/spec/integration/cli/db/rollback_spec.rb +0 -96
  96. data/spec/integration/cli/db/version_spec.rb +0 -38
  97. data/spec/integration/cli/db_spec.rb +0 -21
  98. data/spec/integration/cli/destroy/action_spec.rb +0 -143
  99. data/spec/integration/cli/destroy/app_spec.rb +0 -118
  100. data/spec/integration/cli/destroy/mailer_spec.rb +0 -74
  101. data/spec/integration/cli/destroy/migration_spec.rb +0 -70
  102. data/spec/integration/cli/destroy/model_spec.rb +0 -113
  103. data/spec/integration/cli/destroy_spec.rb +0 -18
  104. data/spec/integration/cli/generate/action_spec.rb +0 -469
  105. data/spec/integration/cli/generate/app_spec.rb +0 -215
  106. data/spec/integration/cli/generate/mailer_spec.rb +0 -189
  107. data/spec/integration/cli/generate/migration_spec.rb +0 -72
  108. data/spec/integration/cli/generate/model_spec.rb +0 -290
  109. data/spec/integration/cli/generate/secret_spec.rb +0 -56
  110. data/spec/integration/cli/generate_spec.rb +0 -19
  111. data/spec/integration/cli/new/database_spec.rb +0 -235
  112. data/spec/integration/cli/new/hanami_head_spec.rb +0 -27
  113. data/spec/integration/cli/new/template_spec.rb +0 -118
  114. data/spec/integration/cli/new/test_spec.rb +0 -274
  115. data/spec/integration/cli/new_spec.rb +0 -970
  116. data/spec/integration/cli/plugins_spec.rb +0 -39
  117. data/spec/integration/cli/routes_spec.rb +0 -49
  118. data/spec/integration/cli/server_spec.rb +0 -626
  119. data/spec/integration/cli/version_spec.rb +0 -85
  120. data/spec/integration/early_hints_spec.rb +0 -35
  121. data/spec/integration/handle_exceptions_spec.rb +0 -244
  122. data/spec/integration/head_spec.rb +0 -89
  123. data/spec/integration/http_headers_spec.rb +0 -29
  124. data/spec/integration/mailer_spec.rb +0 -32
  125. data/spec/integration/middleware_spec.rb +0 -81
  126. data/spec/integration/mount_applications_spec.rb +0 -88
  127. data/spec/integration/project_initializers_spec.rb +0 -40
  128. data/spec/integration/rackup_spec.rb +0 -35
  129. data/spec/integration/rake/with_minitest_spec.rb +0 -67
  130. data/spec/integration/rake/with_rspec_spec.rb +0 -69
  131. data/spec/integration/routing_helpers_spec.rb +0 -61
  132. data/spec/integration/security/content_security_policy_spec.rb +0 -46
  133. data/spec/integration/security/csrf_protection_spec.rb +0 -42
  134. data/spec/integration/security/force_ssl_spec.rb +0 -29
  135. data/spec/integration/security/x_content_type_options_spec.rb +0 -46
  136. data/spec/integration/security/x_frame_options_spec.rb +0 -46
  137. data/spec/integration/security/x_xss_protection_spec.rb +0 -46
  138. data/spec/integration/send_file_spec.rb +0 -51
  139. data/spec/integration/sessions_spec.rb +0 -247
  140. data/spec/integration/static_middleware_spec.rb +0 -21
  141. data/spec/integration/streaming_spec.rb +0 -41
  142. data/spec/integration/unsafe_send_file_spec.rb +0 -52
  143. data/spec/new_integration/action/configuration_spec.rb +0 -26
  144. data/spec/new_integration/settings_spec.rb +0 -115
  145. data/spec/new_integration/view/configuration_spec.rb +0 -49
  146. data/spec/support/fixtures/hanami-plugin/Gemfile +0 -8
  147. data/spec/support/fixtures/hanami-plugin/README.md +0 -35
  148. data/spec/support/fixtures/hanami-plugin/Rakefile +0 -4
  149. data/spec/support/fixtures/hanami-plugin/bin/console +0 -15
  150. data/spec/support/fixtures/hanami-plugin/bin/setup +0 -8
  151. data/spec/support/fixtures/hanami-plugin/hanami-plugin.gemspec +0 -28
  152. data/spec/support/fixtures/hanami-plugin/lib/hanami/plugin/cli.rb +0 -19
  153. data/spec/support/fixtures/hanami-plugin/lib/hanami/plugin/version.rb +0 -7
  154. data/spec/support/fixtures/hanami-plugin/lib/hanami/plugin.rb +0 -8
  155. data/spec/unit/hanami/routes_spec.rb +0 -25
  156. data/spec/unit/hanami/settings/dotenv_store_spec.rb +0 -119
@@ -0,0 +1,287 @@
1
+ # frozen_string_literal: true
2
+
3
+ RSpec.describe "App action / Slice configuration", :app_integration do
4
+ before do
5
+ with_directory(@dir = make_tmp_directory) do
6
+ write "config/app.rb", <<~'RUBY'
7
+ require "hanami"
8
+
9
+ module TestApp
10
+ class App < Hanami::App
11
+ end
12
+ end
13
+ RUBY
14
+
15
+ write "app/action.rb", <<~'RUBY'
16
+ require "hanami/action"
17
+
18
+ module TestApp
19
+ class Action < Hanami::Action
20
+ end
21
+ end
22
+ RUBY
23
+
24
+ require "hanami/setup"
25
+ end
26
+ end
27
+
28
+ def prepare_app
29
+ with_directory(@dir) { require "hanami/prepare" }
30
+ end
31
+
32
+ describe "inheriting from app-level base class" do
33
+ describe "app-level base class" do
34
+ it "applies default actions config from the app", :aggregate_failures do
35
+ prepare_app
36
+
37
+ expect(TestApp::Action.config.default_request_format).to eq :html
38
+ expect(TestApp::Action.config.default_response_format).to eq :html
39
+ end
40
+
41
+ it "applies actions config from the app" do
42
+ Hanami.app.config.actions.default_response_format = :json
43
+
44
+ prepare_app
45
+
46
+ expect(TestApp::Action.config.default_response_format).to eq :json
47
+ end
48
+
49
+ it "does not override config in the base class" do
50
+ Hanami.app.config.actions.default_response_format = :csv
51
+
52
+ prepare_app
53
+
54
+ TestApp::Action.config.default_response_format = :json
55
+ end
56
+ end
57
+
58
+ describe "subclass in app" do
59
+ before do
60
+ with_directory(@dir) do
61
+ write "app/actions/articles/index.rb", <<~'RUBY'
62
+ module TestApp
63
+ module Actions
64
+ module Articles
65
+ class Index < TestApp::Action
66
+ end
67
+ end
68
+ end
69
+ end
70
+ RUBY
71
+ end
72
+ end
73
+
74
+ it "applies default actions config from the app", :aggregate_failures do
75
+ prepare_app
76
+
77
+ expect(TestApp::Actions::Articles::Index.config.default_request_format).to eq :html
78
+ expect(TestApp::Actions::Articles::Index.config.default_response_format).to eq :html
79
+ end
80
+
81
+ it "applies actions config from the app" do
82
+ Hanami.app.config.actions.default_response_format = :json
83
+
84
+ prepare_app
85
+
86
+ expect(TestApp::Actions::Articles::Index.config.default_response_format).to eq :json
87
+ end
88
+
89
+ it "applies config from the base class" do
90
+ prepare_app
91
+
92
+ TestApp::Action.config.default_response_format = :json
93
+
94
+ expect(TestApp::Actions::Articles::Index.config.default_response_format).to eq :json
95
+ end
96
+ end
97
+
98
+ describe "subclass in slice" do
99
+ before do
100
+ with_directory(@dir) do
101
+ write "slices/admin/actions/articles/index.rb", <<~'RUBY'
102
+ module Admin
103
+ module Actions
104
+ module Articles
105
+ class Index < TestApp::Action
106
+ end
107
+ end
108
+ end
109
+ end
110
+ RUBY
111
+ end
112
+ end
113
+
114
+ it "applies default actions config from the app", :aggregate_failures do
115
+ prepare_app
116
+
117
+ expect(Admin::Actions::Articles::Index.config.default_request_format).to eq :html
118
+ expect(Admin::Actions::Articles::Index.config.default_response_format).to eq :html
119
+ end
120
+
121
+ it "applies actions config from the app" do
122
+ Hanami.app.config.actions.default_response_format = :json
123
+
124
+ prepare_app
125
+
126
+ expect(Admin::Actions::Articles::Index.config.default_response_format).to eq :json
127
+ end
128
+
129
+ it "applies config from the base class" do
130
+ prepare_app
131
+
132
+ TestApp::Action.config.default_response_format = :json
133
+
134
+ expect(Admin::Actions::Articles::Index.config.default_response_format).to eq :json
135
+ end
136
+ end
137
+ end
138
+
139
+ describe "inheriting from a slice-level base class, in turn inheriting from an app-level base class" do
140
+ before do
141
+ with_directory(@dir) do
142
+ write "slices/admin/action.rb", <<~'RUBY'
143
+ module Admin
144
+ class Action < TestApp::Action
145
+ end
146
+ end
147
+ RUBY
148
+ end
149
+ end
150
+
151
+ describe "slice-level base class" do
152
+ it "applies default actions config from the app", :aggregate_failures do
153
+ prepare_app
154
+
155
+ expect(Admin::Action.config.default_request_format).to eq :html
156
+ expect(Admin::Action.config.default_response_format).to eq :html
157
+ end
158
+
159
+ it "applies actions config from the app" do
160
+ Hanami.app.config.actions.default_response_format = :json
161
+
162
+ prepare_app
163
+
164
+ expect(Admin::Action.config.default_response_format).to eq :json
165
+ end
166
+
167
+ it "applies config from the app base class" do
168
+ prepare_app
169
+
170
+ TestApp::Action.config.default_response_format = :json
171
+
172
+ expect(Admin::Action.config.default_response_format).to eq :json
173
+ end
174
+
175
+ context "slice actions config present" do
176
+ before do
177
+ with_directory(@dir) do
178
+ write "config/slices/admin.rb", <<~'RUBY'
179
+ module Admin
180
+ class Slice < Hanami::Slice
181
+ config.actions.default_response_format = :csv
182
+ end
183
+ end
184
+ RUBY
185
+ end
186
+ end
187
+
188
+ it "applies actions config from the slice" do
189
+ prepare_app
190
+
191
+ expect(Admin::Action.config.default_response_format).to eq :csv
192
+ end
193
+
194
+ it "prefers actions config from the slice over config from the app-level base class" do
195
+ prepare_app
196
+
197
+ TestApp::Action.config.default_response_format = :json
198
+
199
+ expect(Admin::Action.config.default_response_format).to eq :csv
200
+ end
201
+
202
+ it "prefers config from the base class over actions config from the slice" do
203
+ prepare_app
204
+
205
+ TestApp::Action.config.default_response_format = :csv
206
+ Admin::Action.config.default_response_format = :json
207
+
208
+ expect(Admin::Action.config.default_response_format).to eq :json
209
+ end
210
+ end
211
+ end
212
+
213
+ describe "subclass in slice" do
214
+ before do
215
+ with_directory(@dir) do
216
+ write "slices/admin/actions/articles/index.rb", <<~'RUBY'
217
+ module Admin
218
+ module Actions
219
+ module Articles
220
+ class Index < Admin::Action
221
+ end
222
+ end
223
+ end
224
+ end
225
+ RUBY
226
+ end
227
+ end
228
+
229
+ it "applies default actions config from the app", :aggregate_failures do
230
+ prepare_app
231
+
232
+ expect(Admin::Actions::Articles::Index.config.default_request_format).to eq :html
233
+ expect(Admin::Actions::Articles::Index.config.default_response_format).to eq :html
234
+ end
235
+
236
+ it "applies actions config from the app" do
237
+ Hanami.app.config.actions.default_response_format = :json
238
+
239
+ prepare_app
240
+
241
+ expect(Admin::Actions::Articles::Index.config.default_response_format).to eq :json
242
+ end
243
+
244
+ it "applies actions config from the slice" do
245
+ with_directory(@dir) do
246
+ write "config/slices/admin.rb", <<~'RUBY'
247
+ module Admin
248
+ class Slice < Hanami::Slice
249
+ config.actions.default_response_format = :json
250
+ end
251
+ end
252
+ RUBY
253
+ end
254
+
255
+ prepare_app
256
+
257
+ expect(Admin::Actions::Articles::Index.config.default_response_format).to eq :json
258
+ end
259
+
260
+ it "applies config from the slice base class" do
261
+ prepare_app
262
+
263
+ Admin::Action.config.default_response_format = :json
264
+
265
+ expect(Admin::Actions::Articles::Index.config.default_response_format).to eq :json
266
+ end
267
+
268
+ it "prefers config from the slice base class over actions config from the slice" do
269
+ with_directory(@dir) do
270
+ write "config/slices/admin.rb", <<~'RUBY'
271
+ module Admin
272
+ class Slice < Hanami::Slice
273
+ config.actions.default_response_format = :csv
274
+ end
275
+ end
276
+ RUBY
277
+ end
278
+
279
+ prepare_app
280
+
281
+ Admin::Action.config.default_response_format = :json
282
+
283
+ expect(Admin::Actions::Articles::Index.config.default_response_format).to eq :json
284
+ end
285
+ end
286
+ end
287
+ end
@@ -0,0 +1,208 @@
1
+ # frozen_string_literal: true
2
+
3
+ RSpec.describe "Code loading / Loading from lib directory", :app_integration do
4
+ describe "default root" do
5
+ before :context do
6
+ with_directory(@dir = make_tmp_directory.realpath) do
7
+ write "config/app.rb", <<~'RUBY'
8
+ require "hanami"
9
+
10
+ module TestApp
11
+ class App < Hanami::App
12
+ end
13
+ end
14
+ RUBY
15
+
16
+ write "lib/external_class.rb", <<~'RUBY'
17
+ class ExternalClass
18
+ end
19
+ RUBY
20
+
21
+ write "lib/test_app/test_class.rb", <<~'RUBY'
22
+ module TestApp
23
+ class TestClass
24
+ end
25
+ end
26
+ RUBY
27
+ end
28
+ end
29
+
30
+ context "setup app" do
31
+ before do
32
+ with_directory(@dir) { require "hanami/setup" }
33
+ end
34
+
35
+ it "adds the lib directory to the load path" do
36
+ expect($LOAD_PATH).to include(@dir.join("lib").to_s)
37
+ end
38
+
39
+ specify "classes in lib/ can be required directly" do
40
+ expect(require("external_class")).to be true
41
+ expect(ExternalClass).to be
42
+ end
43
+
44
+ specify "classes in lib/[app_namespace]/ cannot yet be autoloaded" do
45
+ expect { TestApp::TestClass }.to raise_error(NameError)
46
+ end
47
+ end
48
+
49
+ context "prepared app" do
50
+ before do
51
+ with_directory(@dir) { require "hanami/prepare" }
52
+ end
53
+
54
+ it "leaves the lib directory already in the load path" do
55
+ expect($LOAD_PATH).to include(@dir.join("lib").to_s).exactly(1).times
56
+ end
57
+
58
+ specify "classes in lib/[app_namespace]/ can be autoloaded" do
59
+ expect(TestApp::TestClass).to be
60
+ end
61
+ end
62
+
63
+ context "lib dir missing" do
64
+ before do
65
+ with_directory(@dir = make_tmp_directory.realpath) do
66
+ write "config/app.rb", <<~'RUBY'
67
+ require "hanami"
68
+
69
+ module TestApp
70
+ class App < Hanami::App
71
+ end
72
+ end
73
+ RUBY
74
+
75
+ require "hanami/setup"
76
+ end
77
+ end
78
+
79
+ it "does not add the lib directory to the load path" do
80
+ expect($LOAD_PATH).not_to include(@dir.join("lib").to_s)
81
+ end
82
+ end
83
+ end
84
+
85
+ context "app root reconfigured" do
86
+ before :context do
87
+ with_directory(@dir = make_tmp_directory.realpath) do
88
+ write "config/app.rb", <<~'RUBY'
89
+ require "hanami"
90
+
91
+ module TestApp
92
+ class App < Hanami::App
93
+ config.root = Pathname(__dir__).join("..", "src").realpath
94
+ end
95
+ end
96
+ RUBY
97
+
98
+ write "src/lib/external_class.rb", <<~'RUBY'
99
+ class ExternalClass
100
+ end
101
+ RUBY
102
+
103
+ write "src/lib/test_app/test_class.rb", <<~'RUBY'
104
+ module TestApp
105
+ class TestClass
106
+ end
107
+ end
108
+ RUBY
109
+ end
110
+ end
111
+
112
+ context "setup app" do
113
+ before do
114
+ with_directory(@dir) { require "hanami/setup" }
115
+ end
116
+
117
+ it "does not add the lib directory to the load path (already done at time of subclassing)" do
118
+ expect($LOAD_PATH).not_to include(@dir.join("src", "lib").to_s)
119
+ end
120
+
121
+ it "adds the lib directory under the new root with `prepare_load_path`" do
122
+ expect { Hanami.app.prepare_load_path }
123
+ .to change { $LOAD_PATH }
124
+ .to include(@dir.join("src", "lib").to_s)
125
+ end
126
+ end
127
+
128
+ context "prepared app" do
129
+ before do
130
+ with_directory(@dir) { require "hanami/prepare" }
131
+ end
132
+
133
+ it "adds the lib directory to the load path" do
134
+ expect($LOAD_PATH).to include(@dir.join("src", "lib").to_s)
135
+ end
136
+
137
+ specify "classes in lib/ can be required directly" do
138
+ expect(require("external_class")).to be true
139
+ expect(ExternalClass).to be
140
+ end
141
+
142
+ specify "classes in lib/[app_namespace]/ can be autoloaded" do
143
+ expect(TestApp::TestClass).to be
144
+ end
145
+ end
146
+ end
147
+
148
+ context "app root reconfigured and load path immediately prepared" do
149
+ before :context do
150
+ with_directory(@dir = make_tmp_directory.realpath) do
151
+ write "config/app.rb", <<~'RUBY'
152
+ require "hanami"
153
+
154
+ module TestApp
155
+ class App < Hanami::App
156
+ config.root = Pathname(__dir__).join("..", "src").realpath and prepare_load_path
157
+ end
158
+ end
159
+ RUBY
160
+
161
+ write "src/lib/external_class.rb", <<~'RUBY'
162
+ class ExternalClass
163
+ end
164
+ RUBY
165
+
166
+ write "src/lib/test_app/test_class.rb", <<~'RUBY'
167
+ module TestApp
168
+ class TestClass
169
+ end
170
+ end
171
+ RUBY
172
+ end
173
+ end
174
+
175
+ context "setup app" do
176
+ before do
177
+ with_directory(@dir) { require "hanami/setup" }
178
+ end
179
+
180
+ it "adds the lib directory to the load path" do
181
+ expect($LOAD_PATH).to include(@dir.join("src", "lib").to_s)
182
+ end
183
+
184
+ specify "classes in lib/ can be required directly" do
185
+ expect(require("external_class")).to be true
186
+ expect(ExternalClass).to be
187
+ end
188
+
189
+ specify "classes in lib/[app_namespace]/ cannot yet be autoloaded" do
190
+ expect { TestApp::TestClass }.to raise_error(NameError)
191
+ end
192
+ end
193
+
194
+ context "prepared app" do
195
+ before do
196
+ with_directory(@dir) { require "hanami/prepare" }
197
+ end
198
+
199
+ it "leaves the lib directory to the load path" do
200
+ expect($LOAD_PATH).to include(@dir.join("src", "lib").to_s).exactly(1).times
201
+ end
202
+
203
+ specify "classes in lib/[app_namespace]/ can be autoloaded" do
204
+ expect(TestApp::TestClass).to be
205
+ end
206
+ end
207
+ end
208
+ end
@@ -16,9 +16,7 @@ RSpec.describe "App routes helper", :app_integration do
16
16
  write "config/routes.rb", <<~RUBY
17
17
  module TestApp
18
18
  class Routes < Hanami::Routes
19
- define do
20
- root to: "home.index"
21
- end
19
+ root to: "home.index"
22
20
  end
23
21
  end
24
22
  RUBY
@@ -0,0 +1,137 @@
1
+ # frozen_string_literal: true
2
+
3
+ # rubocop:disable Style/FetchEnvVar
4
+
5
+ RSpec.describe "Dotenv loading", :app_integration do
6
+ before do
7
+ @orig_env = ENV.to_h
8
+ end
9
+
10
+ after do
11
+ ENV.replace(@orig_env)
12
+ end
13
+
14
+ context "dotenv gem is available" do
15
+ before do
16
+ require "dotenv"
17
+ end
18
+
19
+ context "hanami env is development" do
20
+ it "loads .env.development.local, .env.local, .env.development and .env (in this order) into ENV", :aggregate_failures do
21
+ with_tmp_directory(Dir.mktmpdir) do
22
+ write "config/app.rb", <<~'RUBY'
23
+ require "hanami"
24
+
25
+ module TestApp
26
+ class App < Hanami::App
27
+ end
28
+ end
29
+ RUBY
30
+
31
+ write ".env.development.local", <<~'TEXT'
32
+ FROM_SPECIFIC_ENV_LOCAL="from .env.development.local"
33
+ TEXT
34
+
35
+ write ".env.local", <<~'TEXT'
36
+ FROM_BASE_LOCAL="from .env.local"
37
+ FROM_SPECIFIC_ENV_LOCAL=nope
38
+ TEXT
39
+
40
+ write ".env.development", <<~'TEXT'
41
+ FROM_SPECIFIC_ENV="from .env.development"
42
+ FROM_SPECIFIC_ENV_LOCAL=nope
43
+ FROM_BASE_LOCAL=nope
44
+ TEXT
45
+
46
+ write ".env", <<~'TEXT'
47
+ FROM_BASE="from .env"
48
+ FROM_SPECIFIC_ENV_LOCAL=nope
49
+ FROM_BASE_LOCAL=nope
50
+ FROM_SPECIFIC_ENV=nope
51
+ TEXT
52
+
53
+ ENV["HANAMI_ENV"] = "development"
54
+
55
+ require "hanami/setup"
56
+
57
+ expect(ENV["FROM_SPECIFIC_ENV_LOCAL"]).to eq "from .env.development.local"
58
+ expect(ENV["FROM_BASE_LOCAL"]).to eq "from .env.local"
59
+ expect(ENV["FROM_SPECIFIC_ENV"]).to eq "from .env.development"
60
+ expect(ENV["FROM_BASE"]).to eq "from .env"
61
+ end
62
+ end
63
+ end
64
+
65
+ context "hanami env is test" do
66
+ it "loads .env.development.local, .env.development and .env (in this order) into ENV", :aggregate_failures do
67
+ with_tmp_directory(Dir.mktmpdir) do
68
+ write "config/app.rb", <<~'RUBY'
69
+ require "hanami"
70
+
71
+ module TestApp
72
+ class App < Hanami::App
73
+ end
74
+ end
75
+ RUBY
76
+
77
+ write ".env.test.local", <<~'TEXT'
78
+ FROM_SPECIFIC_ENV_LOCAL="from .env.test.local"
79
+ TEXT
80
+
81
+ write ".env.local", <<~'TEXT'
82
+ FROM_BASE_LOCAL="from .env.local"
83
+ TEXT
84
+
85
+ write ".env.test", <<~'TEXT'
86
+ FROM_SPECIFIC_ENV="from .env.test"
87
+ FROM_SPECIFIC_ENV_LOCAL=nope
88
+ TEXT
89
+
90
+ write ".env", <<~'TEXT'
91
+ FROM_BASE="from .env"
92
+ FROM_SPECIFIC_ENV_LOCAL=nope
93
+ FROM_SPECIFIC_ENV=nope
94
+ TEXT
95
+
96
+ ENV["HANAMI_ENV"] = "test"
97
+
98
+ require "hanami/prepare"
99
+
100
+ expect(ENV["FROM_SPECIFIC_ENV_LOCAL"]).to eq "from .env.test.local"
101
+ expect(ENV["FROM_BASE_LOCAL"]).to be nil
102
+ expect(ENV["FROM_SPECIFIC_ENV"]).to eq "from .env.test"
103
+ expect(ENV["FROM_BASE"]).to eq "from .env"
104
+ end
105
+ end
106
+ end
107
+ end
108
+
109
+ context "dotenv gem is unavailable" do
110
+ before do
111
+ allow_any_instance_of(Object).to receive(:gem).and_call_original
112
+ allow_any_instance_of(Object).to receive(:gem).with("dotenv").and_raise(Gem::LoadError)
113
+ end
114
+
115
+ it "does not load from .env files" do
116
+ with_tmp_directory(Dir.mktmpdir) do
117
+ write "config/app.rb", <<~'RUBY'
118
+ require "hanami"
119
+
120
+ module TestApp
121
+ class App < Hanami::App
122
+ end
123
+ end
124
+ RUBY
125
+
126
+ write ".env", <<~'TEXT'
127
+ FOO=bar
128
+ TEXT
129
+
130
+ expect { require "hanami/prepare" }.not_to(change { ENV.to_h })
131
+ expect(ENV.key?("FOO")).to be false
132
+ end
133
+ end
134
+ end
135
+ end
136
+
137
+ # rubocop:enable Style/FetchEnvVar