hanami 2.0.3 → 2.1.0.beta2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (103) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +37 -2
  3. data/LICENSE.md +1 -1
  4. data/README.md +26 -10
  5. data/hanami.gemspec +2 -2
  6. data/lib/hanami/app.rb +5 -0
  7. data/lib/hanami/config/actions.rb +4 -11
  8. data/lib/hanami/config/assets.rb +84 -0
  9. data/lib/hanami/config/null_config.rb +3 -0
  10. data/lib/hanami/config/views.rb +0 -4
  11. data/lib/hanami/config.rb +71 -5
  12. data/lib/hanami/extensions/action/slice_configured_action.rb +15 -7
  13. data/lib/hanami/extensions/action.rb +8 -6
  14. data/lib/hanami/extensions/router/errors.rb +58 -0
  15. data/lib/hanami/extensions/view/context.rb +129 -60
  16. data/lib/hanami/extensions/view/part.rb +26 -0
  17. data/lib/hanami/extensions/view/scope.rb +26 -0
  18. data/lib/hanami/extensions/view/slice_configured_context.rb +0 -2
  19. data/lib/hanami/extensions/view/slice_configured_helpers.rb +44 -0
  20. data/lib/hanami/extensions/view/slice_configured_view.rb +106 -21
  21. data/lib/hanami/extensions/view/standard_helpers.rb +18 -0
  22. data/lib/hanami/extensions.rb +10 -3
  23. data/lib/hanami/helpers/assets_helper.rb +752 -0
  24. data/lib/hanami/helpers/form_helper/form_builder.rb +1391 -0
  25. data/lib/hanami/helpers/form_helper/values.rb +75 -0
  26. data/lib/hanami/helpers/form_helper.rb +213 -0
  27. data/lib/hanami/middleware/assets.rb +21 -0
  28. data/lib/hanami/middleware/public_errors_app.rb +75 -0
  29. data/lib/hanami/middleware/render_errors.rb +90 -0
  30. data/lib/hanami/providers/assets.rb +44 -0
  31. data/lib/hanami/rake_tasks.rb +19 -18
  32. data/lib/hanami/settings.rb +1 -1
  33. data/lib/hanami/slice.rb +48 -2
  34. data/lib/hanami/slice_configurable.rb +3 -2
  35. data/lib/hanami/version.rb +1 -1
  36. data/lib/hanami/web/rack_logger.rb +1 -1
  37. data/lib/hanami.rb +3 -3
  38. data/spec/integration/action/view_rendering/view_context_spec.rb +221 -0
  39. data/spec/integration/action/view_rendering_spec.rb +0 -18
  40. data/spec/integration/assets/assets_spec.rb +101 -0
  41. data/spec/integration/assets/serve_static_assets_spec.rb +152 -0
  42. data/spec/integration/logging/exception_logging_spec.rb +115 -0
  43. data/spec/integration/logging/notifications_spec.rb +68 -0
  44. data/spec/integration/logging/request_logging_spec.rb +128 -0
  45. data/spec/integration/rack_app/middleware_spec.rb +22 -22
  46. data/spec/integration/rack_app/rack_app_spec.rb +3 -220
  47. data/spec/integration/rake_tasks_spec.rb +107 -0
  48. data/spec/integration/view/config/default_context_spec.rb +149 -0
  49. data/spec/integration/view/{inflector_spec.rb → config/inflector_spec.rb} +1 -1
  50. data/spec/integration/view/config/part_class_spec.rb +147 -0
  51. data/spec/integration/view/config/part_namespace_spec.rb +103 -0
  52. data/spec/integration/view/config/paths_spec.rb +119 -0
  53. data/spec/integration/view/config/scope_class_spec.rb +147 -0
  54. data/spec/integration/view/config/scope_namespace_spec.rb +103 -0
  55. data/spec/integration/view/config/template_spec.rb +38 -0
  56. data/spec/integration/view/context/assets_spec.rb +3 -9
  57. data/spec/integration/view/context/request_spec.rb +3 -7
  58. data/spec/integration/view/helpers/form_helper_spec.rb +174 -0
  59. data/spec/integration/view/helpers/part_helpers_spec.rb +124 -0
  60. data/spec/integration/view/helpers/scope_helpers_spec.rb +84 -0
  61. data/spec/integration/view/helpers/user_defined_helpers/part_helpers_spec.rb +162 -0
  62. data/spec/integration/view/helpers/user_defined_helpers/scope_helpers_spec.rb +119 -0
  63. data/spec/integration/view/slice_configuration_spec.rb +9 -9
  64. data/spec/integration/web/render_detailed_errors_spec.rb +107 -0
  65. data/spec/integration/web/render_errors_spec.rb +242 -0
  66. data/spec/spec_helper.rb +1 -1
  67. data/spec/support/app_integration.rb +46 -2
  68. data/spec/support/matchers.rb +32 -0
  69. data/spec/unit/hanami/config/actions/content_security_policy_spec.rb +24 -36
  70. data/spec/unit/hanami/config/actions/csrf_protection_spec.rb +4 -3
  71. data/spec/unit/hanami/config/actions/default_values_spec.rb +3 -6
  72. data/spec/unit/hanami/config/render_detailed_errors_spec.rb +25 -0
  73. data/spec/unit/hanami/config/render_errors_spec.rb +25 -0
  74. data/spec/unit/hanami/config/views_spec.rb +0 -18
  75. data/spec/unit/hanami/env_spec.rb +11 -25
  76. data/spec/unit/hanami/extensions/view/context_spec.rb +59 -0
  77. data/spec/unit/hanami/helpers/assets_helper/asset_url_spec.rb +109 -0
  78. data/spec/unit/hanami/helpers/assets_helper/audio_tag_spec.rb +132 -0
  79. data/spec/unit/hanami/helpers/assets_helper/favicon_link_tag_spec.rb +91 -0
  80. data/spec/unit/hanami/helpers/assets_helper/image_tag_spec.rb +92 -0
  81. data/spec/unit/hanami/helpers/assets_helper/javascript_tag_spec.rb +143 -0
  82. data/spec/unit/hanami/helpers/assets_helper/stylesheet_link_tag_spec.rb +126 -0
  83. data/spec/unit/hanami/helpers/assets_helper/video_tag_spec.rb +132 -0
  84. data/spec/unit/hanami/helpers/form_helper_spec.rb +2826 -0
  85. data/spec/unit/hanami/router/errors/not_allowed_error_spec.rb +27 -0
  86. data/spec/unit/hanami/router/errors/not_found_error_spec.rb +22 -0
  87. data/spec/unit/hanami/slice_configurable_spec.rb +18 -0
  88. data/spec/unit/hanami/version_spec.rb +1 -1
  89. data/spec/unit/hanami/web/rack_logger_spec.rb +1 -1
  90. metadata +95 -35
  91. data/lib/hanami/assets/app_config.rb +0 -61
  92. data/lib/hanami/assets/config.rb +0 -53
  93. data/spec/integration/action/view_integration_spec.rb +0 -165
  94. data/spec/integration/view/part_namespace_spec.rb +0 -96
  95. data/spec/integration/view/path_spec.rb +0 -56
  96. data/spec/integration/view/template_spec.rb +0 -68
  97. data/spec/isolation/hanami/application/already_configured_spec.rb +0 -19
  98. data/spec/isolation/hanami/application/inherit_anonymous_class_spec.rb +0 -10
  99. data/spec/isolation/hanami/application/inherit_concrete_class_spec.rb +0 -14
  100. data/spec/isolation/hanami/application/not_configured_spec.rb +0 -9
  101. data/spec/isolation/hanami/application/routes/configured_spec.rb +0 -44
  102. data/spec/isolation/hanami/application/routes/not_configured_spec.rb +0 -16
  103. data/spec/isolation/hanami/boot/success_spec.rb +0 -50
@@ -0,0 +1,242 @@
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
data/spec/spec_helper.rb CHANGED
@@ -23,6 +23,6 @@ RSpec.configure do |config|
23
23
  # TODO: Find out what causes logger to create this dir when running specs.
24
24
  # There's probably a test app class being created somewhere with root
25
25
  # not pointing to a tmp dir.
26
- FileUtils.rm_r(LOG_DIR) if LOG_DIR.exist?
26
+ FileUtils.rm_rf(LOG_DIR) if LOG_DIR.exist?
27
27
  end
28
28
  end
@@ -2,6 +2,7 @@
2
2
 
3
3
  require "hanami/devtools/integration/files"
4
4
  require "hanami/devtools/integration/with_tmp_directory"
5
+ require "json"
5
6
  require "tmpdir"
6
7
  require "zeitwerk"
7
8
 
@@ -16,10 +17,52 @@ module RSpec
16
17
  end
17
18
  end
18
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
+ def stub_assets(*assets)
33
+ manifest_hash = assets.each_with_object({}) { |source_path, hsh|
34
+ hsh[source_path] = {url: File.join("/assets", source_path)}
35
+ }
36
+
37
+ write "public/assets.json", JSON.generate(manifest_hash)
38
+ end
39
+
40
+ def compile_assets!
41
+ link_node_modules
42
+
43
+ require "hanami/cli/command"
44
+ require "hanami/cli/commands/app/command"
45
+ require "hanami/cli/commands/app/assets/compile"
46
+ compiler = Hanami::CLI::Commands::App::Assets::Compile.new(config: Hanami.app.config.assets)
47
+
48
+ with_directory(Hanami.app.root) do
49
+ compiler.call
50
+ end
51
+ end
52
+
53
+ def link_node_modules
54
+ root = Hanami.app.root
55
+
56
+ return if File.exist?(File.join(root, "node_modules", "hanami-assets", "dist", "hanami-assets.js"))
57
+
58
+ FileUtils.ln_s(node_modules_path, root)
59
+ rescue Errno::EEXIST # rubocop:disable Lint/SuppressedException
60
+ end
61
+ end
19
62
  end
20
63
  end
21
64
 
22
- RSpec.shared_context "Application integration" do
65
+ RSpec.shared_context "App integration" do
23
66
  let(:app_modules) { %i[TestApp Admin Main Search] }
24
67
  end
25
68
 
@@ -35,7 +78,8 @@ end
35
78
  RSpec.configure do |config|
36
79
  config.include RSpec::Support::Files, :app_integration
37
80
  config.include RSpec::Support::WithTmpDirectory, :app_integration
38
- config.include_context "Application integration", :app_integration
81
+ config.include RSpec::Support::App, :app_integration
82
+ config.include_context "App integration", :app_integration
39
83
 
40
84
  config.before :each, :app_integration do
41
85
  # Conditionally assign these in case they have been assigned earlier for specific
@@ -0,0 +1,32 @@
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
@@ -3,43 +3,31 @@
3
3
  require "hanami/config/actions"
4
4
 
5
5
  RSpec.describe Hanami::Config::Actions, "#content_security_policy" do
6
- let(:config) { described_class.new }
6
+ let(:app_config) { Hanami::Config.new(app_name: "MyApp::App", env: :development) }
7
+ let(:config) { app_config.actions }
7
8
  subject(:content_security_policy) { config.content_security_policy }
8
9
 
9
10
  context "no CSP config specified" do
10
- context "without assets_server_url" do
11
-
12
- it "has defaults" do
13
- expect(content_security_policy[:base_uri]).to eq("'self'")
14
-
15
- expected = [
16
- %(base-uri 'self'),
17
- %(child-src 'self'),
18
- %(connect-src 'self'),
19
- %(default-src 'none'),
20
- %(font-src 'self'),
21
- %(form-action 'self'),
22
- %(frame-ancestors 'self'),
23
- %(frame-src 'self'),
24
- %(img-src 'self' https: data:),
25
- %(media-src 'self'),
26
- %(object-src 'none'),
27
- %(script-src 'self'),
28
- %(style-src 'self' 'unsafe-inline' https:)
29
- ].join(";")
30
-
31
- expect(content_security_policy.to_s).to eq(expected)
32
- end
33
- end
34
-
35
- context "with assets_server_url" do
36
- let(:config) { described_class.new(assets_server_url: assets_server_url) }
37
- let(:assets_server_url) { "http://localhost:8080" }
38
-
39
- it "includes server url" do
40
- expect(content_security_policy[:script_src]).to eq("'self' #{assets_server_url}")
41
- expect(content_security_policy[:style_src]).to eq("'self' 'unsafe-inline' https: #{assets_server_url}")
42
- end
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)
43
31
  end
44
32
  end
45
33
 
@@ -84,7 +72,7 @@ RSpec.describe Hanami::Config::Actions, "#content_security_policy" do
84
72
 
85
73
  context "with CSP enabled" do
86
74
  it "sets default header" do
87
- config.finalize!
75
+ app_config.finalize!
88
76
 
89
77
  expect(config.default_headers.fetch("Content-Security-Policy")).to eq(content_security_policy.to_s)
90
78
  end
@@ -93,7 +81,7 @@ RSpec.describe Hanami::Config::Actions, "#content_security_policy" do
93
81
  context "with CSP disabled" do
94
82
  it "doesn't set default header" do
95
83
  config.content_security_policy = false
96
- config.finalize!
84
+ app_config.finalize!
97
85
 
98
86
  expect(config.default_headers.key?("Content-Security-Policy")).to be(false)
99
87
  end
@@ -3,7 +3,8 @@
3
3
  require "hanami/config/actions"
4
4
 
5
5
  RSpec.describe Hanami::Config::Actions, "#csrf_protection" do
6
- let(:config) { described_class.new }
6
+ let(:app_config) { Hanami::Config.new(app_name: "MyApp::App", env: :development) }
7
+ let(:config) { app_config.actions }
7
8
  subject(:value) { config.csrf_protection }
8
9
 
9
10
  context "non-finalized config" do
@@ -26,7 +27,7 @@ RSpec.describe Hanami::Config::Actions, "#csrf_protection" do
26
27
  context "sessions enabled" do
27
28
  before do
28
29
  config.sessions = :cookie, {secret: "abc"}
29
- config.finalize!
30
+ app_config.finalize!
30
31
  end
31
32
 
32
33
  it "is true" do
@@ -46,7 +47,7 @@ RSpec.describe Hanami::Config::Actions, "#csrf_protection" do
46
47
 
47
48
  context "sessions not enabled" do
48
49
  before do
49
- config.finalize!
50
+ app_config.finalize!
50
51
  end
51
52
 
52
53
  it "is true" do
@@ -3,7 +3,8 @@
3
3
  require "hanami/config/actions"
4
4
 
5
5
  RSpec.describe Hanami::Config::Actions, "default values" do
6
- subject(:config) { described_class.new }
6
+ let(:app_config) { Hanami::Config.new(app_name: "MyApp::App", env: :development) }
7
+ subject(:config) { app_config.actions }
7
8
 
8
9
  describe "sessions" do
9
10
  specify { expect(config.sessions).not_to be_enabled }
@@ -13,10 +14,6 @@ RSpec.describe Hanami::Config::Actions, "default values" do
13
14
  specify { expect(config.name_inference_base).to eq "actions" }
14
15
  end
15
16
 
16
- describe "view_context_identifier" do
17
- specify { expect(config.view_context_identifier).to eq "views.context" }
18
- end
19
-
20
17
  describe "view_name_inferrer" do
21
18
  specify { expect(config.view_name_inferrer).to eq Hanami::Slice::ViewNameInferrer }
22
19
  end
@@ -32,7 +29,7 @@ RSpec.describe Hanami::Config::Actions, "default values" do
32
29
 
33
30
  describe "default_headers" do
34
31
  specify {
35
- config.finalize!
32
+ app_config.finalize!
36
33
 
37
34
  expect(config.default_headers).to eq(
38
35
  "X-Frame-Options" => "DENY",
@@ -0,0 +1,25 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "dry/inflector"
4
+
5
+ RSpec.describe Hanami::Config, "#render_detailed_errors" do
6
+ let(:config) { described_class.new(app_name: app_name, env: env) }
7
+ let(:app_name) { Hanami::SliceName.new(double(name: "MyApp::App"), inflector: Dry::Inflector.new) }
8
+
9
+ subject(:render_detailed_errors) { config.render_detailed_errors }
10
+
11
+ context "development mode" do
12
+ let(:env) { :development }
13
+ it { is_expected.to be true }
14
+ end
15
+
16
+ context "test mode" do
17
+ let(:env) { :test }
18
+ it { is_expected.to be true }
19
+ end
20
+
21
+ context "production mode" do
22
+ let(:env) { :production }
23
+ it { is_expected.to be false }
24
+ end
25
+ end
@@ -0,0 +1,25 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "dry/inflector"
4
+
5
+ RSpec.describe Hanami::Config, "#render_errors" do
6
+ let(:config) { described_class.new(app_name: app_name, env: env) }
7
+ let(:app_name) { Hanami::SliceName.new(double(name: "MyApp::App"), inflector: Dry::Inflector.new) }
8
+
9
+ subject(:render_errors) { config.render_errors }
10
+
11
+ context "development mode" do
12
+ let(:env) { :development }
13
+ it { is_expected.to be false }
14
+ end
15
+
16
+ context "test mode" do
17
+ let(:env) { :test }
18
+ it { is_expected.to be false }
19
+ end
20
+
21
+ context "production mode" do
22
+ let(:env) { :production }
23
+ it { is_expected.to be true }
24
+ end
25
+ end
@@ -39,20 +39,6 @@ RSpec.describe Hanami::Config, "#views" do
39
39
  end
40
40
 
41
41
  describe "specialised default values" do
42
- describe "paths" do
43
- it 'is ["templates"]' do
44
- expect(views.paths).to match [
45
- an_object_satisfying { |path| path.dir.to_s == "templates" }
46
- ]
47
- end
48
- end
49
-
50
- describe "template_inference_base" do
51
- it 'is "views"' do
52
- expect(views.template_inference_base).to eq "views"
53
- end
54
- end
55
-
56
42
  describe "layout" do
57
43
  it 'is "app"' do
58
44
  expect(views.layout).to eq "app"
@@ -69,10 +55,6 @@ RSpec.describe Hanami::Config, "#views" do
69
55
  expect(views).to be_frozen
70
56
  end
71
57
 
72
- it "does not allow changes to locally defined settings" do
73
- expect { views.parts_path = "parts" }.to raise_error(Dry::Configurable::FrozenConfigError)
74
- end
75
-
76
58
  it "does not allow changes to base view settings" do
77
59
  expect { views.paths = [] }.to raise_error(Dry::Configurable::FrozenConfigError)
78
60
  end
@@ -1,54 +1,40 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  RSpec.describe Hanami, ".env" do
4
- subject(:env) { described_class.env }
5
-
6
- before do
7
- @orig_env = ENV.to_h
8
- end
9
-
10
- after do
11
- ENV.replace(@orig_env)
12
- end
4
+ subject { described_class.env(e: env) }
13
5
 
14
6
  context "HANAMI_ENV in ENV" do
15
- before do
16
- ENV["HANAMI_ENV"] = "test"
17
- end
7
+ let(:env) { {"HANAMI_ENV" => "test"} }
18
8
 
19
9
  it "is the value of HANAMI_ENV" do
20
- is_expected.to eq :test
10
+ is_expected.to eq(:test)
21
11
  end
22
12
  end
23
13
 
24
14
  context "RACK_ENV in ENV" do
25
- before do
26
- ENV["RACK_ENV"] = "test"
27
- end
15
+ let(:env) { {"HANAMI_ENV" => "test"} }
28
16
 
29
17
  it "is the value of RACK_ENV" do
30
- is_expected.to eq :test
18
+ is_expected.to eq(:test)
31
19
  end
32
20
  end
33
21
 
34
22
  context "both HANAMI_ENV and RACK_ENV in ENV" do
35
- before do
36
- ENV["HANAMI_ENV"] = "test"
37
- ENV["RACK_ENV"] = "production"
23
+ let(:env) do
24
+ {"HANAMI_ENV" => "test",
25
+ "RACK_ENV" => "production"}
38
26
  end
39
27
 
40
28
  it "is the value of HANAMI_ENV" do
41
- is_expected.to eq :test
29
+ is_expected.to eq(:test)
42
30
  end
43
31
  end
44
32
 
45
33
  context "no ENV vars set" do
46
- before do
47
- ENV.delete("HANAMI_ENV")
48
- end
34
+ let(:env) { {} }
49
35
 
50
36
  it "defaults to \"development\"" do
51
- is_expected.to eq :development
37
+ is_expected.to eq(:development)
52
38
  end
53
39
  end
54
40
  end