hanami 2.3.2 → 3.0.0.rc1

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 (184) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +55 -19
  3. data/LICENSE +20 -0
  4. data/README.md +18 -35
  5. data/hanami.gemspec +36 -37
  6. data/lib/hanami/config/db.rb +2 -0
  7. data/lib/hanami/config/i18n.rb +138 -0
  8. data/lib/hanami/config/logger.rb +15 -7
  9. data/lib/hanami/config/null_config.rb +1 -1
  10. data/lib/hanami/config/views.rb +17 -0
  11. data/lib/hanami/config.rb +66 -22
  12. data/lib/hanami/errors.rb +6 -0
  13. data/lib/hanami/extensions/action/slice_configured_action.rb +1 -1
  14. data/lib/hanami/extensions/action.rb +2 -2
  15. data/lib/hanami/extensions/mailer/slice_configured_mailer.rb +120 -0
  16. data/lib/hanami/extensions/mailer.rb +28 -0
  17. data/lib/hanami/extensions/operation/slice_configured_db_operation.rb +2 -0
  18. data/lib/hanami/extensions/view/context.rb +26 -4
  19. data/lib/hanami/extensions/view/part.rb +2 -0
  20. data/lib/hanami/extensions/view/slice_configured_context.rb +7 -0
  21. data/lib/hanami/extensions/view/slice_configured_part.rb +2 -0
  22. data/lib/hanami/extensions/view/slice_configured_view.rb +8 -8
  23. data/lib/hanami/extensions/view/standard_helpers.rb +4 -0
  24. data/lib/hanami/extensions.rb +6 -1
  25. data/lib/hanami/helpers/assets_helper.rb +0 -4
  26. data/lib/hanami/helpers/form_helper.rb +1 -1
  27. data/lib/hanami/helpers/i18n_helper.rb +176 -0
  28. data/lib/hanami/logger/rack_formatter.rb +73 -0
  29. data/lib/hanami/logger/sql_formatter.rb +80 -0
  30. data/lib/hanami/logger/sql_logger.rb +48 -0
  31. data/lib/hanami/middleware/render_errors.rb +2 -2
  32. data/lib/hanami/providers/db.rb +7 -2
  33. data/lib/hanami/providers/db_logging.rb +4 -7
  34. data/lib/hanami/providers/i18n/backend.rb +369 -0
  35. data/lib/hanami/providers/i18n/locale/en.yml +57 -0
  36. data/lib/hanami/providers/i18n.rb +114 -0
  37. data/lib/hanami/providers/mailers.rb +101 -0
  38. data/lib/hanami/routes.rb +1 -0
  39. data/lib/hanami/settings/composite_store.rb +53 -0
  40. data/lib/hanami/settings.rb +4 -4
  41. data/lib/hanami/slice/router.rb +15 -10
  42. data/lib/hanami/slice.rb +71 -11
  43. data/lib/hanami/slice_registrar.rb +2 -2
  44. data/lib/hanami/universal_logger.rb +250 -0
  45. data/lib/hanami/version.rb +1 -1
  46. data/lib/hanami/web/rack_logger.rb +2 -80
  47. data/lib/hanami/web/welcome.html.erb +443 -58
  48. data/lib/hanami.rb +4 -2
  49. metadata +28 -276
  50. data/CODE_OF_CONDUCT.md +0 -74
  51. data/FEATURES.md +0 -269
  52. data/LICENSE.md +0 -22
  53. data/spec/integration/action/cookies_spec.rb +0 -58
  54. data/spec/integration/action/csrf_protection_spec.rb +0 -54
  55. data/spec/integration/action/format_config_spec.rb +0 -129
  56. data/spec/integration/action/routes_spec.rb +0 -71
  57. data/spec/integration/action/sessions_spec.rb +0 -50
  58. data/spec/integration/action/slice_configuration_spec.rb +0 -284
  59. data/spec/integration/action/view_rendering/automatic_rendering_spec.rb +0 -247
  60. data/spec/integration/action/view_rendering/paired_view_inference_spec.rb +0 -115
  61. data/spec/integration/action/view_rendering/view_context_spec.rb +0 -221
  62. data/spec/integration/action/view_rendering_spec.rb +0 -89
  63. data/spec/integration/assets/assets_spec.rb +0 -155
  64. data/spec/integration/assets/cross_slice_assets_helpers_spec.rb +0 -129
  65. data/spec/integration/assets/serve_static_assets_spec.rb +0 -152
  66. data/spec/integration/code_loading/loading_from_app_spec.rb +0 -152
  67. data/spec/integration/code_loading/loading_from_lib_spec.rb +0 -242
  68. data/spec/integration/code_loading/loading_from_slice_spec.rb +0 -165
  69. data/spec/integration/container/application_routes_helper_spec.rb +0 -48
  70. data/spec/integration/container/auto_injection_spec.rb +0 -53
  71. data/spec/integration/container/auto_registration_spec.rb +0 -86
  72. data/spec/integration/container/autoloader_spec.rb +0 -82
  73. data/spec/integration/container/imports_spec.rb +0 -253
  74. data/spec/integration/container/prepare_container_spec.rb +0 -125
  75. data/spec/integration/container/provider_environment_spec.rb +0 -52
  76. data/spec/integration/container/provider_lifecycle_spec.rb +0 -61
  77. data/spec/integration/container/shutdown_spec.rb +0 -91
  78. data/spec/integration/container/standard_providers/rack_provider_spec.rb +0 -44
  79. data/spec/integration/container/standard_providers_spec.rb +0 -124
  80. data/spec/integration/db/auto_registration_spec.rb +0 -39
  81. data/spec/integration/db/commands_spec.rb +0 -80
  82. data/spec/integration/db/db_inflector_spec.rb +0 -57
  83. data/spec/integration/db/db_slices_spec.rb +0 -398
  84. data/spec/integration/db/db_spec.rb +0 -245
  85. data/spec/integration/db/gateways_spec.rb +0 -361
  86. data/spec/integration/db/logging_spec.rb +0 -301
  87. data/spec/integration/db/mappers_spec.rb +0 -84
  88. data/spec/integration/db/provider_config_spec.rb +0 -88
  89. data/spec/integration/db/provider_spec.rb +0 -35
  90. data/spec/integration/db/relations_spec.rb +0 -60
  91. data/spec/integration/db/repo_spec.rb +0 -300
  92. data/spec/integration/db/slices_importing_from_parent.rb +0 -130
  93. data/spec/integration/dotenv_loading_spec.rb +0 -138
  94. data/spec/integration/logging/exception_logging_spec.rb +0 -120
  95. data/spec/integration/logging/notifications_spec.rb +0 -68
  96. data/spec/integration/logging/request_logging_spec.rb +0 -202
  97. data/spec/integration/operations/extension_spec.rb +0 -122
  98. data/spec/integration/rack_app/body_parser_spec.rb +0 -108
  99. data/spec/integration/rack_app/method_override_spec.rb +0 -97
  100. data/spec/integration/rack_app/middleware_spec.rb +0 -720
  101. data/spec/integration/rack_app/non_booted_rack_app_spec.rb +0 -104
  102. data/spec/integration/rack_app/rack_app_spec.rb +0 -442
  103. data/spec/integration/rake_tasks_spec.rb +0 -107
  104. data/spec/integration/router/resource_routes_spec.rb +0 -281
  105. data/spec/integration/settings/access_in_slice_class_body_spec.rb +0 -83
  106. data/spec/integration/settings/access_to_constants_spec.rb +0 -46
  107. data/spec/integration/settings/loading_from_env_spec.rb +0 -188
  108. data/spec/integration/settings/settings_component_loading_spec.rb +0 -113
  109. data/spec/integration/settings/slice_registration_spec.rb +0 -145
  110. data/spec/integration/settings/using_types_spec.rb +0 -80
  111. data/spec/integration/setup_spec.rb +0 -165
  112. data/spec/integration/slices/external_slice_spec.rb +0 -91
  113. data/spec/integration/slices/slice_configuration_spec.rb +0 -42
  114. data/spec/integration/slices/slice_loading_spec.rb +0 -171
  115. data/spec/integration/slices/slice_registrations_spec.rb +0 -80
  116. data/spec/integration/slices/slice_routing_spec.rb +0 -219
  117. data/spec/integration/slices_spec.rb +0 -471
  118. data/spec/integration/view/config/default_context_spec.rb +0 -149
  119. data/spec/integration/view/config/inflector_spec.rb +0 -57
  120. data/spec/integration/view/config/part_class_spec.rb +0 -147
  121. data/spec/integration/view/config/part_namespace_spec.rb +0 -103
  122. data/spec/integration/view/config/paths_spec.rb +0 -119
  123. data/spec/integration/view/config/scope_class_spec.rb +0 -147
  124. data/spec/integration/view/config/scope_namespace_spec.rb +0 -103
  125. data/spec/integration/view/config/template_spec.rb +0 -38
  126. data/spec/integration/view/context/assets_spec.rb +0 -79
  127. data/spec/integration/view/context/inflector_spec.rb +0 -40
  128. data/spec/integration/view/context/request_spec.rb +0 -57
  129. data/spec/integration/view/context/routes_spec.rb +0 -84
  130. data/spec/integration/view/helpers/form_helper_spec.rb +0 -174
  131. data/spec/integration/view/helpers/part_helpers_spec.rb +0 -124
  132. data/spec/integration/view/helpers/scope_helpers_spec.rb +0 -84
  133. data/spec/integration/view/helpers/user_defined_helpers/part_helpers_spec.rb +0 -162
  134. data/spec/integration/view/helpers/user_defined_helpers/scope_helpers_spec.rb +0 -119
  135. data/spec/integration/view/parts/default_rendering_spec.rb +0 -138
  136. data/spec/integration/view/slice_configuration_spec.rb +0 -289
  137. data/spec/integration/view/views_spec.rb +0 -103
  138. data/spec/integration/web/content_security_policy_nonce_spec.rb +0 -251
  139. data/spec/integration/web/render_detailed_errors_spec.rb +0 -107
  140. data/spec/integration/web/render_errors_spec.rb +0 -242
  141. data/spec/integration/web/welcome_view_spec.rb +0 -84
  142. data/spec/spec_helper.rb +0 -28
  143. data/spec/support/app_integration.rb +0 -157
  144. data/spec/support/coverage.rb +0 -1
  145. data/spec/support/matchers.rb +0 -32
  146. data/spec/support/rspec.rb +0 -27
  147. data/spec/unit/hanami/config/actions/content_security_policy_spec.rb +0 -96
  148. data/spec/unit/hanami/config/actions/cookies_spec.rb +0 -46
  149. data/spec/unit/hanami/config/actions/csrf_protection_spec.rb +0 -58
  150. data/spec/unit/hanami/config/actions/default_values_spec.rb +0 -43
  151. data/spec/unit/hanami/config/actions/sessions_spec.rb +0 -48
  152. data/spec/unit/hanami/config/actions_spec.rb +0 -52
  153. data/spec/unit/hanami/config/base_url_spec.rb +0 -25
  154. data/spec/unit/hanami/config/console_spec.rb +0 -22
  155. data/spec/unit/hanami/config/db_spec.rb +0 -38
  156. data/spec/unit/hanami/config/inflector_spec.rb +0 -35
  157. data/spec/unit/hanami/config/logger_spec.rb +0 -195
  158. data/spec/unit/hanami/config/render_detailed_errors_spec.rb +0 -25
  159. data/spec/unit/hanami/config/render_errors_spec.rb +0 -25
  160. data/spec/unit/hanami/config/router_spec.rb +0 -44
  161. data/spec/unit/hanami/config/slices_spec.rb +0 -34
  162. data/spec/unit/hanami/config/views_spec.rb +0 -80
  163. data/spec/unit/hanami/env_spec.rb +0 -37
  164. data/spec/unit/hanami/extensions/view/context_spec.rb +0 -59
  165. data/spec/unit/hanami/helpers/assets_helper/asset_url_spec.rb +0 -120
  166. data/spec/unit/hanami/helpers/assets_helper/audio_tag_spec.rb +0 -132
  167. data/spec/unit/hanami/helpers/assets_helper/favicon_tag_spec.rb +0 -87
  168. data/spec/unit/hanami/helpers/assets_helper/image_tag_spec.rb +0 -92
  169. data/spec/unit/hanami/helpers/assets_helper/javascript_tag_spec.rb +0 -143
  170. data/spec/unit/hanami/helpers/assets_helper/stylesheet_tag_spec.rb +0 -126
  171. data/spec/unit/hanami/helpers/assets_helper/video_tag_spec.rb +0 -136
  172. data/spec/unit/hanami/helpers/form_helper_spec.rb +0 -2857
  173. data/spec/unit/hanami/port_spec.rb +0 -117
  174. data/spec/unit/hanami/providers/db/config/default_config_spec.rb +0 -100
  175. data/spec/unit/hanami/providers/db/config/gateway_spec.rb +0 -73
  176. data/spec/unit/hanami/providers/db/config_spec.rb +0 -143
  177. data/spec/unit/hanami/router/errors/not_allowed_error_spec.rb +0 -27
  178. data/spec/unit/hanami/router/errors/not_found_error_spec.rb +0 -22
  179. data/spec/unit/hanami/settings/env_store_spec.rb +0 -52
  180. data/spec/unit/hanami/settings_spec.rb +0 -111
  181. data/spec/unit/hanami/slice_configurable_spec.rb +0 -141
  182. data/spec/unit/hanami/slice_name_spec.rb +0 -47
  183. data/spec/unit/hanami/slice_spec.rb +0 -99
  184. data/spec/unit/hanami/web/rack_logger_spec.rb +0 -99
@@ -1,242 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require "json"
4
- require "rack/test"
5
-
6
- RSpec.describe "Web / Rendering errors", :app_integration do
7
- include Rack::Test::Methods
8
-
9
- let(:app) { Hanami.app }
10
-
11
- before do
12
- with_directory(@dir = make_tmp_directory) do
13
- write "config/app.rb", <<~RUBY
14
- require "hanami"
15
-
16
- module TestApp
17
- class App < Hanami::App
18
- config.logger.stream = File.new("/dev/null", "w")
19
- config.render_errors = true
20
- config.render_detailed_errors = false
21
- end
22
- end
23
- RUBY
24
-
25
- write "config/routes.rb", <<~RUBY
26
- module TestApp
27
- class Routes < Hanami::Routes
28
- get "index", to: "index"
29
- get "error", to: "error"
30
- end
31
- end
32
- RUBY
33
-
34
- write "app/actions/index.rb", <<~RUBY
35
- module TestApp
36
- module Actions
37
- class Index < Hanami::Action
38
- def handle(*, response)
39
- response.body = "Hello"
40
- end
41
- end
42
- end
43
- end
44
- RUBY
45
-
46
- write "app/actions/error.rb", <<~RUBY
47
- module TestApp
48
- module Actions
49
- class Error < Hanami::Action
50
- def handle(*)
51
- raise "oops"
52
- end
53
- end
54
- end
55
- end
56
- RUBY
57
-
58
- before_prepare if respond_to?(:before_prepare)
59
- require "hanami/prepare"
60
- end
61
- end
62
-
63
- describe "HTML request" do
64
- context "error pages present" do
65
- def before_prepare
66
- write "public/404.html", <<~HTML
67
- <h1>Not found</h1>
68
- HTML
69
-
70
- write "public/500.html", <<~HTML
71
- <h1>Error</h1>
72
- HTML
73
- end
74
-
75
- it "responds with the HTML for a 404 from a not found error" do
76
- get "/__not_found__"
77
-
78
- expect(last_response.status).to eq 404
79
- expect(last_response.body.strip).to eq "<h1>Not found</h1>"
80
- expect(last_response.get_header("Content-Type")).to eq "text/html; charset=utf-8"
81
- expect(last_response.get_header("Content-Length")).to eq "19"
82
- end
83
-
84
- it "responds with the HTML for a 404 from a method not allowed error" do
85
- post "/index"
86
-
87
- expect(last_response.status).to eq 404
88
- expect(last_response.body.strip).to eq "<h1>Not found</h1>"
89
- expect(last_response.get_header("Content-Type")).to eq "text/html; charset=utf-8"
90
- expect(last_response.get_header("Content-Length")).to eq "19"
91
- end
92
-
93
- it "responds with the HTML for a 500" do
94
- get "/error"
95
-
96
- expect(last_response.status).to eq 500
97
- expect(last_response.body.strip).to eq "<h1>Error</h1>"
98
- expect(last_response.get_header("Content-Type")).to eq "text/html; charset=utf-8"
99
- expect(last_response.get_header("Content-Length")).to eq "15"
100
- end
101
- end
102
-
103
- context "error pages missing" do
104
- it "responds with default text for a 404 from a not found error" do
105
- get "/__not_found__"
106
-
107
- expect(last_response.status).to eq 404
108
- expect(last_response.body.strip).to eq "Not Found"
109
- expect(last_response.get_header("Content-Type")).to eq "text/html; charset=utf-8"
110
- expect(last_response.get_header("Content-Length")).to eq "9"
111
- end
112
-
113
- it "responds with default text for a 404 from a metohd not allowed error" do
114
- post "/index"
115
-
116
- expect(last_response.status).to eq 404
117
- expect(last_response.body.strip).to eq "Not Found"
118
- expect(last_response.get_header("Content-Type")).to eq "text/html; charset=utf-8"
119
- expect(last_response.get_header("Content-Length")).to eq "9"
120
- end
121
-
122
- it "responds with default text for a 500" do
123
- get "/error"
124
-
125
- expect(last_response.status).to eq 500
126
- expect(last_response.body.strip).to eq "Internal Server Error"
127
- expect(last_response.get_header("Content-Type")).to eq "text/html; charset=utf-8"
128
- expect(last_response.get_header("Content-Length")).to eq "21"
129
- end
130
- end
131
- end
132
-
133
- describe "JSON request" do
134
- it "renders a JSON response for a 404 from a not found error" do
135
- get "/__not_found__", {}, "HTTP_ACCEPT" => "application/json"
136
-
137
- expect(last_response.status).to eq 404
138
- expect(last_response.body.strip).to eq %({"status":404,"error":"Not Found"})
139
- expect(last_response.get_header("Content-Type")).to eq "application/json; charset=utf-8"
140
- expect(last_response.get_header("Content-Length")).to eq "34"
141
- end
142
-
143
- it "renders a JSON response for a 404 from a metnod not allowed error" do
144
- post "/index", {}, "HTTP_ACCEPT" => "application/json"
145
-
146
- expect(last_response.status).to eq 404
147
- expect(last_response.body.strip).to eq %({"status":404,"error":"Not Found"})
148
- expect(last_response.get_header("Content-Type")).to eq "application/json; charset=utf-8"
149
- expect(last_response.get_header("Content-Length")).to eq "34"
150
- end
151
-
152
- it "renders a JSON response for a 500" do
153
- get "/error", {}, "HTTP_ACCEPT" => "application/json"
154
-
155
- expect(last_response.status).to eq 500
156
- expect(last_response.body.strip).to eq %({"status":500,"error":"Internal Server Error"})
157
- expect(last_response.get_header("Content-Type")).to eq "application/json; charset=utf-8"
158
- expect(last_response.get_header("Content-Length")).to eq "46"
159
- end
160
- end
161
-
162
- describe "configuring error responses" do
163
- def before_prepare
164
- write "config/app.rb", <<~RUBY
165
- require "hanami"
166
-
167
- module TestApp
168
- CustomNotFoundError = Class.new(StandardError)
169
-
170
- class App < Hanami::App
171
- config.logger.stream = File.new("/dev/null", "w")
172
- config.render_errors = true
173
- config.render_error_responses["TestApp::CustomNotFoundError"] = :not_found
174
- config.render_detailed_errors = false
175
- end
176
- end
177
- RUBY
178
-
179
- write "app/actions/error.rb", <<~RUBY
180
- module TestApp
181
- module Actions
182
- class Error < Hanami::Action
183
- def handle(*)
184
- raise CustomNotFoundError
185
- end
186
- end
187
- end
188
- end
189
- RUBY
190
-
191
- write "public/404.html", <<~HTML
192
- <h1>Not found</h1>
193
- HTML
194
- end
195
-
196
- it "uses the configured errors to determine the response" do
197
- get "/error"
198
-
199
- expect(last_response.status).to eq 404
200
- expect(last_response.body.strip).to eq "<h1>Not found</h1>"
201
- end
202
- end
203
-
204
- describe "render_errors config disabled" do
205
- def before_prepare
206
- write "config/app.rb", <<~RUBY
207
- require "hanami"
208
-
209
- module TestApp
210
- class App < Hanami::App
211
- config.logger.stream = File.new("/dev/null", "w")
212
- config.render_errors = false
213
- config.render_detailed_errors = false
214
- end
215
- end
216
- RUBY
217
-
218
- # Include error pages here to prove they are _not_ used
219
- write "public/404.html", <<~HTML
220
- <h1>Not found</h1>
221
- HTML
222
-
223
- write "public/500.html", <<~HTML
224
- <h1>Error</h1>
225
- HTML
226
- end
227
-
228
- it "renders the hanami-router default 404 response for a not found error" do
229
- get "/__not_found__"
230
- expect(last_response.status).to eq 404
231
- end
232
-
233
- it "renders the hanami-router default 405 response for a not allowed error" do
234
- post "/index"
235
- expect(last_response.status).to eq 405
236
- end
237
-
238
- it "raises the original error for a 500" do
239
- expect { get "/error" }.to raise_error(RuntimeError, "oops")
240
- end
241
- end
242
- end
@@ -1,84 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require "json"
4
- require "rack/test"
5
-
6
- RSpec.describe "Web / Welcome view", :app_integration do
7
- include Rack::Test::Methods
8
-
9
- let(:app) { Hanami.app }
10
-
11
- before do
12
- with_directory(@dir = make_tmp_directory) do
13
- write "config/app.rb", <<~RUBY
14
- require "hanami"
15
-
16
- module TestApp
17
- class App < Hanami::App
18
- config.logger.stream = File::NULL
19
- end
20
- end
21
- RUBY
22
-
23
- write "config/routes.rb", <<~RUBY
24
- module TestApp
25
- class Routes < Hanami::Routes
26
- end
27
- end
28
- RUBY
29
-
30
- before_prepare if respond_to?(:before_prepare)
31
- require "hanami/prepare"
32
- end
33
- end
34
-
35
- context "no routes defined" do
36
- it "renders the welcome page" do
37
- get "/"
38
-
39
- body = last_response.body.strip
40
- expect(body).to include "<h1>Welcome to Hanami</h1>"
41
- expect(body).to include "Hanami version: #{Hanami::VERSION}"
42
- expect(body).to include "Ruby version: #{RUBY_DESCRIPTION}"
43
-
44
- expect(last_response.status).to eq 200
45
- end
46
- end
47
-
48
- context "routes defined" do
49
- def before_prepare
50
- write "config/routes.rb", <<~RUBY
51
- module TestApp
52
- class Routes < Hanami::Routes
53
- root to: -> * { [200, {}, "Hello from a route"] }
54
- end
55
- end
56
- RUBY
57
- end
58
-
59
- it "does not render the welcome page" do
60
- get "/"
61
-
62
- expect(last_response.body).to eq "Hello from a route"
63
- expect(last_response.status).to eq 200
64
- end
65
- end
66
-
67
- context "non-development env" do
68
- def before_prepare
69
- @hanami_env = ENV["HANAMI_ENV"]
70
- ENV["HANAMI_ENV"] = "production"
71
- end
72
-
73
- after do
74
- ENV["HANAMI_ENV"] = @hanami_env
75
- end
76
-
77
- it "does not render the welcome page" do
78
- get "/"
79
-
80
- expect(last_response.body).to eq "Not Found"
81
- expect(last_response.status).to eq 404
82
- end
83
- end
84
- end
data/spec/spec_helper.rb DELETED
@@ -1,28 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require "pathname"
4
-
5
- SPEC_ROOT = File.expand_path(__dir__).freeze
6
- LOG_DIR = Pathname(SPEC_ROOT).join("..").join("log")
7
-
8
- require_relative "support/coverage" if ENV["COVERAGE"].eql?("true")
9
-
10
- require "hanami"
11
- begin; require "byebug"; rescue LoadError; end
12
- require "hanami/utils/file_list"
13
- require "hanami/devtools/unit"
14
-
15
- Hanami::Utils::FileList["./spec/support/**/*.rb"].each do |file|
16
- next if file.include?("hanami-plugin")
17
-
18
- require file
19
- end
20
-
21
- RSpec.configure do |config|
22
- config.after(:suite) do
23
- # TODO: Find out what causes logger to create this dir when running specs.
24
- # There's probably a test app class being created somewhere with root
25
- # not pointing to a tmp dir.
26
- FileUtils.rm_rf(LOG_DIR) if LOG_DIR.exist?
27
- end
28
- end
@@ -1,157 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require "hanami/devtools/integration/files"
4
- require "hanami/devtools/integration/with_tmp_directory"
5
- require "json"
6
- require "tmpdir"
7
- require "zeitwerk"
8
-
9
- module RSpec
10
- module Support
11
- module WithTmpDirectory
12
- private
13
-
14
- def make_tmp_directory
15
- Pathname(Dir.mktmpdir).tap do |dir|
16
- (@made_tmp_dirs ||= []) << dir
17
- end
18
- end
19
- end
20
-
21
- module App
22
- def self.included(base)
23
- super
24
-
25
- base.class_eval do
26
- let!(:node_modules_path) { File.join(Dir.pwd, "node_modules") }
27
- end
28
- end
29
-
30
- private
31
-
32
- # TODO: make slice-aware
33
- def stub_assets(*assets)
34
- manifest_hash = assets.each_with_object({}) { |source_path, hsh|
35
- hsh[source_path] = {url: File.join("/assets", source_path)}
36
- }
37
-
38
- write "public/assets/assets.json", JSON.generate(manifest_hash)
39
-
40
- # An assets dir is required to load the assets provider
41
- write "app/assets/.keep", ""
42
- end
43
-
44
- def compile_assets!
45
- link_node_modules
46
- generate_assets_config
47
-
48
- require "hanami/cli/command"
49
- require "hanami/cli/commands/app/command"
50
- require "hanami/cli/commands/app/assets/compile"
51
- assets_compile = Hanami::CLI::Commands::App::Assets::Compile.new(
52
- config: Hanami.app.config.assets,
53
- out: File.new(File::NULL, "w"),
54
- err: File.new(File::NULL, "w"),
55
- )
56
-
57
- with_directory(Hanami.app.root) { assets_compile.call }
58
- end
59
-
60
- def link_node_modules
61
- root = Hanami.app.root
62
-
63
- return if File.exist?(File.join(root, "node_modules", "hanami-assets", "dist", "hanami-assets.js"))
64
-
65
- FileUtils.ln_s(node_modules_path, root)
66
- rescue Errno::EEXIST # rubocop:disable Lint/SuppressedException
67
- end
68
-
69
- def generate_assets_config
70
- root = Hanami.app.root
71
-
72
- with_directory(root) do
73
- write("config/assets.js", <<~JS) unless root.join("config", "assets.js").exist?
74
- import * as assets from "hanami-assets";
75
- await assets.run();
76
- JS
77
-
78
- write("package.json", <<~JSON) unless root.join("package.json").exist?
79
- {
80
- "type": "module"
81
- }
82
- JSON
83
- end
84
- end
85
- end
86
- end
87
- end
88
-
89
- RSpec.shared_context "App integration" do
90
- let(:app_modules) { %i[TestApp Admin Main Search] }
91
- end
92
-
93
- def autoloaders_teardown!
94
- ObjectSpace.each_object(Zeitwerk::Loader) do |loader|
95
- loader.unregister if loader.dirs.any? { |dir|
96
- dir.include?("/spec/") || dir.include?(Dir.tmpdir) ||
97
- dir.include?("/slices/") || dir.include?("/app")
98
- }
99
- end
100
- end
101
-
102
- RSpec.configure do |config|
103
- config.include RSpec::Support::Files, :app_integration
104
- config.include RSpec::Support::WithTmpDirectory, :app_integration
105
- config.include RSpec::Support::App, :app_integration
106
- config.include_context "App integration", :app_integration
107
-
108
- config.before :each, :app_integration do
109
- # Conditionally assign these in case they have been assigned earlier for specific
110
- # example groups (e.g. container/prepare_container_spec.rb)
111
- @load_paths ||= $LOAD_PATH.dup
112
- @loaded_features ||= $LOADED_FEATURES.dup
113
- end
114
-
115
- config.after :each, :app_integration do
116
- autoloaders_teardown!
117
-
118
- Hanami.instance_variable_set(:@_bundled, {})
119
- Hanami.remove_instance_variable(:@_app) if Hanami.instance_variable_defined?(:@_app)
120
-
121
- # Disconnect and clear cached DB gateways across slices
122
- Hanami::Providers::DB.cache.values.map(&:disconnect)
123
- Hanami::Providers::DB.cache.clear
124
-
125
- $LOAD_PATH.replace(@load_paths)
126
-
127
- # Remove example-specific LOADED_FEATURES added when running each example
128
- new_features_to_keep = ($LOADED_FEATURES - @loaded_features).tap { |feats|
129
- feats.delete_if do |path|
130
- path =~ %r{hanami/(setup|prepare|boot|application/container/providers)} ||
131
- path.include?(SPEC_ROOT.to_s) ||
132
- path.include?(Dir.tmpdir)
133
- end
134
- }
135
- $LOADED_FEATURES.replace(@loaded_features + new_features_to_keep)
136
-
137
- app_modules.each do |app_module_name|
138
- next unless Object.const_defined?(app_module_name)
139
-
140
- Object.const_get(app_module_name).tap do |mod|
141
- mod.constants.each do |name|
142
- mod.send(:remove_const, name)
143
- end
144
- end
145
-
146
- Object.send(:remove_const, app_module_name)
147
- end
148
- end
149
-
150
- config.after :all do
151
- if instance_variable_defined?(:@made_tmp_dirs)
152
- Array(@made_tmp_dirs).each do |dir|
153
- FileUtils.remove_entry dir
154
- end
155
- end
156
- end
157
- end
@@ -1 +0,0 @@
1
- require "hanami/devtools/unit/support/coverage"
@@ -1,32 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module RSpec
4
- module Support
5
- module Matchers
6
- module HTML
7
- def squish_html(str)
8
- str
9
- .gsub(/^[[:space:]]+/, "")
10
- .gsub(/>[[:space:]]+</m, "><")
11
- .strip
12
- end
13
- end
14
- end
15
- end
16
- end
17
-
18
- RSpec::Matchers.define :eq_html do |expected_html|
19
- include RSpec::Support::Matchers::HTML
20
-
21
- match do |actual_html|
22
- squish_html(actual_html) == squish_html(expected_html)
23
- end
24
- end
25
-
26
- RSpec::Matchers.define :include_html do |expected_html|
27
- include RSpec::Support::Matchers::HTML
28
-
29
- match do |actual_html|
30
- squish_html(actual_html).include?(squish_html(expected_html))
31
- end
32
- end
@@ -1,27 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- RSpec.configure do |config|
4
- config.expect_with :rspec do |expectations|
5
- expectations.include_chain_clauses_in_custom_matcher_descriptions = true
6
- end
7
-
8
- config.mock_with :rspec do |mocks|
9
- mocks.verify_partial_doubles = true
10
- end
11
-
12
- config.before :suite do
13
- require "hanami/devtools/integration"
14
- Pathname.new(Dir.pwd).join("tmp").mkpath
15
- end
16
-
17
- config.shared_context_metadata_behavior = :apply_to_host_groups
18
-
19
- config.filter_run_when_matching :focus
20
- config.disable_monkey_patching!
21
- config.warnings = false
22
-
23
- config.default_formatter = "doc" if config.files_to_run.one?
24
-
25
- config.order = :random
26
- Kernel.srand config.seed
27
- end
@@ -1,96 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require "hanami/config/actions"
4
-
5
- RSpec.describe Hanami::Config::Actions, "#content_security_policy" do
6
- let(:app_config) { Hanami::Config.new(app_name: "MyApp::App", env: :development) }
7
- let(:config) { app_config.actions }
8
- subject(:content_security_policy) { config.content_security_policy }
9
-
10
- context "no CSP config specified" do
11
- it "has defaults" do
12
- expect(content_security_policy[:base_uri]).to eq("'self'")
13
-
14
- expected = [
15
- %(base-uri 'self'),
16
- %(child-src 'self'),
17
- %(connect-src 'self'),
18
- %(default-src 'none'),
19
- %(font-src 'self'),
20
- %(form-action 'self'),
21
- %(frame-ancestors 'self'),
22
- %(frame-src 'self'),
23
- %(img-src 'self' https: data:),
24
- %(media-src 'self'),
25
- %(object-src 'none'),
26
- %(script-src 'self'),
27
- %(style-src 'self' 'unsafe-inline' https:)
28
- ].join(";")
29
-
30
- expect(content_security_policy.to_s).to eq(expected)
31
- expect(content_security_policy.nonce?).to be(false)
32
- end
33
- end
34
-
35
- context "CSP settings specified" do
36
- let(:cdn_url) { "https://assets.hanamirb.test" }
37
-
38
- it "appends to default values" do
39
- content_security_policy[:script_src] += " #{cdn_url}"
40
-
41
- expect(content_security_policy[:script_src]).to eq("'self' #{cdn_url}")
42
- expect(content_security_policy.to_s).to match("'self' #{cdn_url}")
43
- end
44
-
45
- it "overrides default values" do
46
- content_security_policy[:style_src] = cdn_url
47
-
48
- expect(content_security_policy[:style_src]).to eq(cdn_url)
49
- expect(content_security_policy.to_s).to match(cdn_url)
50
- end
51
-
52
- it "nullifies value" do
53
- content_security_policy[:object_src] = nil
54
-
55
- expect(content_security_policy[:object_src]).to be(nil)
56
- expect(content_security_policy.to_s).to match("object-src ;")
57
- end
58
-
59
- it "deletes key" do
60
- content_security_policy.delete(:object_src)
61
-
62
- expect(content_security_policy[:object_src]).to be(nil)
63
- expect(content_security_policy.to_s).to_not match("object-src")
64
- end
65
-
66
- it "adds a custom key" do
67
- content_security_policy[:a_custom_key] = "foo"
68
-
69
- expect(content_security_policy[:a_custom_key]).to eq("foo")
70
- expect(content_security_policy.to_s).to match("a-custom-key foo")
71
- end
72
-
73
- it "uses 'nonce' in value" do
74
- content_security_policy[:javascript_src] = "'self' 'nonce'"
75
-
76
- expect(content_security_policy.nonce?).to be(true)
77
- end
78
- end
79
-
80
- context "with CSP enabled" do
81
- it "sets default header" do
82
- app_config.finalize!
83
-
84
- expect(config.default_headers.fetch("Content-Security-Policy")).to eq(content_security_policy.to_s)
85
- end
86
- end
87
-
88
- context "with CSP disabled" do
89
- it "doesn't set default header" do
90
- config.content_security_policy = false
91
- app_config.finalize!
92
-
93
- expect(config.default_headers.key?("Content-Security-Policy")).to be(false)
94
- end
95
- end
96
- end