hanami 2.0.0.alpha8 → 2.0.0.beta1

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 (224) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +442 -241
  3. data/FEATURES.md +30 -9
  4. data/README.md +1 -3
  5. data/hanami.gemspec +21 -11
  6. data/lib/hanami/app.rb +141 -0
  7. data/lib/hanami/assets/application_configuration.rb +10 -4
  8. data/lib/hanami/configuration/actions/content_security_policy.rb +5 -5
  9. data/lib/hanami/configuration/actions/cookies.rb +2 -2
  10. data/lib/hanami/configuration/actions.rb +10 -4
  11. data/lib/hanami/configuration/logger.rb +4 -4
  12. data/lib/hanami/configuration/router.rb +2 -6
  13. data/lib/hanami/configuration/sessions.rb +1 -1
  14. data/lib/hanami/configuration/views.rb +9 -4
  15. data/lib/hanami/configuration.rb +118 -46
  16. data/lib/hanami/constants.rb +24 -2
  17. data/lib/hanami/errors.rb +1 -1
  18. data/lib/hanami/{application → extensions}/action/slice_configured_action.rb +9 -9
  19. data/lib/hanami/extensions/action.rb +79 -0
  20. data/lib/hanami/extensions/view/context.rb +106 -0
  21. data/lib/hanami/{application → extensions}/view/slice_configured_context.rb +10 -10
  22. data/lib/hanami/{application → extensions}/view/slice_configured_view.rb +12 -6
  23. data/lib/hanami/extensions/view.rb +33 -0
  24. data/lib/hanami/extensions.rb +10 -0
  25. data/lib/hanami/providers/inflector.rb +13 -0
  26. data/lib/hanami/providers/logger.rb +13 -0
  27. data/lib/hanami/providers/rack.rb +27 -0
  28. data/lib/hanami/providers/routes.rb +33 -0
  29. data/lib/hanami/providers/settings.rb +23 -0
  30. data/lib/hanami/rake_tasks.rb +61 -0
  31. data/lib/hanami/routes.rb +51 -0
  32. data/lib/hanami/server.rb +1 -1
  33. data/lib/hanami/settings/dotenv_store.rb +58 -0
  34. data/lib/hanami/settings.rb +90 -0
  35. data/lib/hanami/setup.rb +4 -2
  36. data/lib/hanami/{application → slice}/router.rb +18 -13
  37. data/lib/hanami/slice/routes_helper.rb +37 -0
  38. data/lib/hanami/{application → slice}/routing/middleware/stack.rb +43 -5
  39. data/lib/hanami/slice/routing/resolver.rb +97 -0
  40. data/lib/hanami/{application → slice}/view_name_inferrer.rb +3 -3
  41. data/lib/hanami/slice.rb +246 -73
  42. data/lib/hanami/slice_configurable.rb +4 -17
  43. data/lib/hanami/slice_name.rb +6 -6
  44. data/lib/hanami/slice_registrar.rb +119 -0
  45. data/lib/hanami/version.rb +1 -1
  46. data/lib/hanami/web/rack_logger.rb +1 -1
  47. data/lib/hanami.rb +34 -26
  48. data/spec/integration/application_middleware_stack_spec.rb +84 -0
  49. data/spec/integration/assets/cdn_spec.rb +48 -0
  50. data/spec/integration/assets/fingerprint_spec.rb +42 -0
  51. data/spec/integration/assets/helpers_spec.rb +50 -0
  52. data/spec/integration/assets/serve_spec.rb +70 -0
  53. data/spec/integration/assets/subresource_integrity_spec.rb +54 -0
  54. data/spec/integration/body_parsers_spec.rb +50 -0
  55. data/spec/integration/cli/assets/precompile_spec.rb +147 -0
  56. data/spec/integration/cli/assets_spec.rb +14 -0
  57. data/spec/integration/cli/console_spec.rb +105 -0
  58. data/spec/integration/cli/db/apply_spec.rb +74 -0
  59. data/spec/integration/cli/db/console_spec.rb +40 -0
  60. data/spec/integration/cli/db/create_spec.rb +50 -0
  61. data/spec/integration/cli/db/drop_spec.rb +54 -0
  62. data/spec/integration/cli/db/migrate_spec.rb +108 -0
  63. data/spec/integration/cli/db/prepare_spec.rb +36 -0
  64. data/spec/integration/cli/db/rollback_spec.rb +96 -0
  65. data/spec/integration/cli/db/version_spec.rb +38 -0
  66. data/spec/integration/cli/db_spec.rb +21 -0
  67. data/spec/integration/cli/destroy/action_spec.rb +143 -0
  68. data/spec/integration/cli/destroy/app_spec.rb +118 -0
  69. data/spec/integration/cli/destroy/mailer_spec.rb +74 -0
  70. data/spec/integration/cli/destroy/migration_spec.rb +70 -0
  71. data/spec/integration/cli/destroy/model_spec.rb +113 -0
  72. data/spec/integration/cli/destroy_spec.rb +18 -0
  73. data/spec/integration/cli/generate/action_spec.rb +469 -0
  74. data/spec/integration/cli/generate/app_spec.rb +215 -0
  75. data/spec/integration/cli/generate/mailer_spec.rb +189 -0
  76. data/spec/integration/cli/generate/migration_spec.rb +72 -0
  77. data/spec/integration/cli/generate/model_spec.rb +290 -0
  78. data/spec/integration/cli/generate/secret_spec.rb +56 -0
  79. data/spec/integration/cli/generate_spec.rb +19 -0
  80. data/spec/integration/cli/new/database_spec.rb +235 -0
  81. data/spec/integration/cli/new/hanami_head_spec.rb +27 -0
  82. data/spec/integration/cli/new/template_spec.rb +118 -0
  83. data/spec/integration/cli/new/test_spec.rb +274 -0
  84. data/spec/integration/cli/new_spec.rb +970 -0
  85. data/spec/integration/cli/plugins_spec.rb +39 -0
  86. data/spec/integration/cli/routes_spec.rb +49 -0
  87. data/spec/integration/cli/server_spec.rb +626 -0
  88. data/spec/integration/cli/version_spec.rb +85 -0
  89. data/spec/integration/early_hints_spec.rb +35 -0
  90. data/spec/integration/handle_exceptions_spec.rb +244 -0
  91. data/spec/integration/head_spec.rb +89 -0
  92. data/spec/integration/http_headers_spec.rb +29 -0
  93. data/spec/integration/mailer_spec.rb +32 -0
  94. data/spec/integration/middleware_spec.rb +81 -0
  95. data/spec/integration/mount_applications_spec.rb +88 -0
  96. data/spec/integration/project_initializers_spec.rb +40 -0
  97. data/spec/integration/rackup_spec.rb +35 -0
  98. data/spec/integration/rake/with_minitest_spec.rb +67 -0
  99. data/spec/integration/rake/with_rspec_spec.rb +69 -0
  100. data/spec/integration/routing_helpers_spec.rb +61 -0
  101. data/spec/integration/security/content_security_policy_spec.rb +46 -0
  102. data/spec/integration/security/csrf_protection_spec.rb +42 -0
  103. data/spec/integration/security/force_ssl_spec.rb +29 -0
  104. data/spec/integration/security/x_content_type_options_spec.rb +46 -0
  105. data/spec/integration/security/x_frame_options_spec.rb +46 -0
  106. data/spec/integration/security/x_xss_protection_spec.rb +46 -0
  107. data/spec/integration/send_file_spec.rb +51 -0
  108. data/spec/integration/sessions_spec.rb +247 -0
  109. data/spec/integration/static_middleware_spec.rb +21 -0
  110. data/spec/integration/streaming_spec.rb +41 -0
  111. data/spec/integration/unsafe_send_file_spec.rb +52 -0
  112. data/spec/isolation/hanami/application/already_configured_spec.rb +19 -0
  113. data/spec/isolation/hanami/application/inherit_anonymous_class_spec.rb +10 -0
  114. data/spec/isolation/hanami/application/inherit_concrete_class_spec.rb +14 -0
  115. data/spec/isolation/hanami/application/not_configured_spec.rb +9 -0
  116. data/spec/isolation/hanami/application/routes/configured_spec.rb +44 -0
  117. data/spec/isolation/hanami/application/routes/not_configured_spec.rb +16 -0
  118. data/spec/isolation/hanami/boot/success_spec.rb +50 -0
  119. data/spec/new_integration/action/configuration_spec.rb +26 -0
  120. data/spec/new_integration/action/cookies_spec.rb +58 -0
  121. data/spec/new_integration/action/csrf_protection_spec.rb +54 -0
  122. data/spec/new_integration/action/routes_spec.rb +73 -0
  123. data/spec/new_integration/action/sessions_spec.rb +50 -0
  124. data/spec/new_integration/action/view_integration_spec.rb +165 -0
  125. data/spec/new_integration/action/view_rendering/automatic_rendering_spec.rb +247 -0
  126. data/spec/new_integration/action/view_rendering/paired_view_inference_spec.rb +115 -0
  127. data/spec/new_integration/action/view_rendering_spec.rb +107 -0
  128. data/spec/new_integration/code_loading/loading_from_app_spec.rb +152 -0
  129. data/spec/new_integration/code_loading/loading_from_slice_spec.rb +165 -0
  130. data/spec/new_integration/container/application_routes_helper_spec.rb +48 -0
  131. data/spec/new_integration/container/auto_injection_spec.rb +53 -0
  132. data/spec/new_integration/container/auto_registration_spec.rb +86 -0
  133. data/spec/new_integration/container/autoloader_spec.rb +80 -0
  134. data/spec/new_integration/container/imports_spec.rb +253 -0
  135. data/spec/new_integration/container/prepare_container_spec.rb +123 -0
  136. data/spec/new_integration/container/shutdown_spec.rb +91 -0
  137. data/spec/new_integration/container/standard_bootable_components_spec.rb +124 -0
  138. data/spec/new_integration/rack_app/middleware_spec.rb +215 -0
  139. data/spec/new_integration/rack_app/non_booted_rack_app_spec.rb +105 -0
  140. data/spec/new_integration/rack_app/rack_app_spec.rb +524 -0
  141. data/spec/new_integration/settings_spec.rb +115 -0
  142. data/spec/new_integration/slices/external_slice_spec.rb +92 -0
  143. data/spec/new_integration/slices/slice_configuration_spec.rb +40 -0
  144. data/spec/new_integration/slices/slice_routing_spec.rb +226 -0
  145. data/spec/new_integration/slices/slice_settings_spec.rb +141 -0
  146. data/spec/new_integration/slices_spec.rb +101 -0
  147. data/spec/new_integration/view/configuration_spec.rb +49 -0
  148. data/spec/new_integration/view/context/assets_spec.rb +67 -0
  149. data/spec/new_integration/view/context/inflector_spec.rb +48 -0
  150. data/spec/new_integration/view/context/request_spec.rb +61 -0
  151. data/spec/new_integration/view/context/routes_spec.rb +86 -0
  152. data/spec/new_integration/view/context/settings_spec.rb +50 -0
  153. data/spec/new_integration/view/inflector_spec.rb +57 -0
  154. data/spec/new_integration/view/part_namespace_spec.rb +96 -0
  155. data/spec/new_integration/view/path_spec.rb +56 -0
  156. data/spec/new_integration/view/template_spec.rb +68 -0
  157. data/spec/new_integration/view/views_spec.rb +103 -0
  158. data/spec/spec_helper.rb +16 -0
  159. data/spec/support/app_integration.rb +91 -0
  160. data/spec/support/coverage.rb +1 -0
  161. data/spec/support/fixtures/hanami-plugin/Gemfile +8 -0
  162. data/spec/support/fixtures/hanami-plugin/README.md +35 -0
  163. data/spec/support/fixtures/hanami-plugin/Rakefile +4 -0
  164. data/spec/support/fixtures/hanami-plugin/bin/console +15 -0
  165. data/spec/support/fixtures/hanami-plugin/bin/setup +8 -0
  166. data/spec/support/fixtures/hanami-plugin/hanami-plugin.gemspec +28 -0
  167. data/spec/support/fixtures/hanami-plugin/lib/hanami/plugin/cli.rb +19 -0
  168. data/spec/support/fixtures/hanami-plugin/lib/hanami/plugin/version.rb +7 -0
  169. data/spec/support/fixtures/hanami-plugin/lib/hanami/plugin.rb +8 -0
  170. data/spec/support/rspec.rb +27 -0
  171. data/spec/support/shared_examples/cli/generate/app.rb +494 -0
  172. data/spec/support/shared_examples/cli/generate/migration.rb +32 -0
  173. data/spec/support/shared_examples/cli/generate/model.rb +81 -0
  174. data/spec/support/shared_examples/cli/new.rb +97 -0
  175. data/spec/unit/hanami/configuration/actions/content_security_policy_spec.rb +102 -0
  176. data/spec/unit/hanami/configuration/actions/cookies_spec.rb +46 -0
  177. data/spec/unit/hanami/configuration/actions/csrf_protection_spec.rb +57 -0
  178. data/spec/unit/hanami/configuration/actions/default_values_spec.rb +52 -0
  179. data/spec/unit/hanami/configuration/actions/sessions_spec.rb +50 -0
  180. data/spec/unit/hanami/configuration/actions_spec.rb +78 -0
  181. data/spec/unit/hanami/configuration/base_url_spec.rb +25 -0
  182. data/spec/unit/hanami/configuration/inflector_spec.rb +35 -0
  183. data/spec/unit/hanami/configuration/logger_spec.rb +203 -0
  184. data/spec/unit/hanami/configuration/views_spec.rb +120 -0
  185. data/spec/unit/hanami/configuration_spec.rb +43 -0
  186. data/spec/unit/hanami/env_spec.rb +54 -0
  187. data/spec/unit/hanami/routes_spec.rb +25 -0
  188. data/spec/unit/hanami/settings/dotenv_store_spec.rb +119 -0
  189. data/spec/unit/hanami/settings_spec.rb +56 -0
  190. data/spec/unit/hanami/slice_configurable_spec.rb +104 -0
  191. data/spec/unit/hanami/slice_name_spec.rb +47 -0
  192. data/spec/unit/hanami/slice_spec.rb +17 -0
  193. data/spec/unit/hanami/version_spec.rb +7 -0
  194. data/spec/unit/hanami/web/rack_logger_spec.rb +78 -0
  195. metadata +353 -57
  196. data/lib/hanami/application/action.rb +0 -72
  197. data/lib/hanami/application/container/providers/inflector.rb +0 -7
  198. data/lib/hanami/application/container/providers/logger.rb +0 -7
  199. data/lib/hanami/application/container/providers/rack_logger.rb +0 -15
  200. data/lib/hanami/application/container/providers/rack_monitor.rb +0 -12
  201. data/lib/hanami/application/container/providers/routes_helper.rb +0 -9
  202. data/lib/hanami/application/container/providers/settings.rb +0 -7
  203. data/lib/hanami/application/routes.rb +0 -55
  204. data/lib/hanami/application/routes_helper.rb +0 -34
  205. data/lib/hanami/application/routing/resolver/node.rb +0 -50
  206. data/lib/hanami/application/routing/resolver/trie.rb +0 -59
  207. data/lib/hanami/application/routing/resolver.rb +0 -87
  208. data/lib/hanami/application/routing/router.rb +0 -36
  209. data/lib/hanami/application/settings/dotenv_store.rb +0 -60
  210. data/lib/hanami/application/settings.rb +0 -93
  211. data/lib/hanami/application/slice_registrar.rb +0 -106
  212. data/lib/hanami/application/view/context.rb +0 -95
  213. data/lib/hanami/application/view.rb +0 -24
  214. data/lib/hanami/application.rb +0 -273
  215. data/lib/hanami/cli/application/cli.rb +0 -40
  216. data/lib/hanami/cli/application/command.rb +0 -47
  217. data/lib/hanami/cli/application/commands/console.rb +0 -81
  218. data/lib/hanami/cli/application/commands.rb +0 -16
  219. data/lib/hanami/cli/base_command.rb +0 -48
  220. data/lib/hanami/cli/commands/command.rb +0 -171
  221. data/lib/hanami/cli/commands/server.rb +0 -88
  222. data/lib/hanami/cli/commands.rb +0 -65
  223. data/lib/hanami/configuration/middleware.rb +0 -20
  224. data/lib/hanami/configuration/source_dirs.rb +0 -42
@@ -0,0 +1,102 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "hanami/configuration/actions"
4
+
5
+ RSpec.describe Hanami::Configuration::Actions, "#content_security_policy" do
6
+ let(:configuration) { described_class.new }
7
+ subject(:content_security_policy) { configuration.content_security_policy }
8
+
9
+ 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
+ %(plugin-types application/pdf;),
28
+ %(script-src 'self';),
29
+ %(style-src 'self' 'unsafe-inline' https:)
30
+ ].join("\n")
31
+
32
+ expect(content_security_policy.to_str).to eq(expected)
33
+ end
34
+ end
35
+
36
+ context "with assets_server_url" do
37
+ let(:configuration) { described_class.new(assets_server_url: assets_server_url) }
38
+ let(:assets_server_url) { "http://localhost:8080" }
39
+
40
+ it "includes server url" do
41
+ expect(content_security_policy[:script_src]).to eq("'self' #{assets_server_url}")
42
+ expect(content_security_policy[:style_src]).to eq("'self' 'unsafe-inline' https: #{assets_server_url}")
43
+ end
44
+ end
45
+ end
46
+
47
+ context "CSP settings specified" do
48
+ let(:cdn_url) { "https://assets.hanamirb.test" }
49
+
50
+ it "appends to default values" do
51
+ content_security_policy[:script_src] += " #{cdn_url}"
52
+
53
+ expect(content_security_policy[:script_src]).to eq("'self' #{cdn_url}")
54
+ expect(content_security_policy.to_str).to match("'self' #{cdn_url}")
55
+ end
56
+
57
+ it "overrides default values" do
58
+ content_security_policy[:style_src] = cdn_url
59
+
60
+ expect(content_security_policy[:style_src]).to eq(cdn_url)
61
+ expect(content_security_policy.to_str).to match(cdn_url)
62
+ end
63
+
64
+ it "nullifies value" do
65
+ content_security_policy[:plugin_types] = nil
66
+
67
+ expect(content_security_policy[:plugin_types]).to be(nil)
68
+ expect(content_security_policy.to_str).to match("plugin-types ;")
69
+ end
70
+
71
+ it "deletes key" do
72
+ content_security_policy.delete(:object_src)
73
+
74
+ expect(content_security_policy[:object_src]).to be(nil)
75
+ expect(content_security_policy.to_str).to_not match("object-src")
76
+ end
77
+
78
+ it "adds a custom key" do
79
+ content_security_policy[:a_custom_key] = "foo"
80
+
81
+ expect(content_security_policy[:a_custom_key]).to eq("foo")
82
+ expect(content_security_policy.to_str).to match("a-custom-key foo")
83
+ end
84
+ end
85
+
86
+ context "with CSP enabled" do
87
+ it "sets default header" do
88
+ configuration.finalize!
89
+
90
+ expect(configuration.default_headers.fetch("Content-Security-Policy")).to eq(content_security_policy.to_str)
91
+ end
92
+ end
93
+
94
+ context "with CSP disabled" do
95
+ it "doesn't set default header" do
96
+ configuration.content_security_policy = false
97
+ configuration.finalize!
98
+
99
+ expect(configuration.default_headers.key?("Content-Security-Policy")).to be(false)
100
+ end
101
+ end
102
+ end
@@ -0,0 +1,46 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "hanami/configuration/actions"
4
+
5
+ RSpec.describe Hanami::Configuration::Actions, "#cookies" do
6
+ let(:configuration) { described_class.new }
7
+ subject(:cookies) { configuration.cookies }
8
+
9
+ context "default config" do
10
+ it "is enabled" do
11
+ expect(cookies).to be_enabled
12
+ end
13
+
14
+ it "is an empty hash" do
15
+ expect(cookies.to_h).to eq({})
16
+ end
17
+ end
18
+
19
+ context "options given" do
20
+ before do
21
+ configuration.cookies = {max_age: 300}
22
+ end
23
+
24
+ it "is enabled" do
25
+ expect(cookies).to be_enabled
26
+ end
27
+
28
+ it "returns the given options" do
29
+ expect(cookies.to_h).to eq(max_age: 300)
30
+ end
31
+ end
32
+
33
+ context "nil value given" do
34
+ before do
35
+ configuration.cookies = nil
36
+ end
37
+
38
+ it "is not enabled" do
39
+ expect(cookies).not_to be_enabled
40
+ end
41
+
42
+ it "returns an empty hash" do
43
+ expect(cookies.to_h).to eq({})
44
+ end
45
+ end
46
+ end
@@ -0,0 +1,57 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "hanami/configuration/actions"
4
+
5
+ RSpec.describe Hanami::Configuration::Actions, "#csrf_protection" do
6
+ let(:configuration) { described_class.new }
7
+ subject(:value) { configuration.csrf_protection }
8
+
9
+ context "non-finalized configuration" do
10
+ it "returns a default of nil" do
11
+ is_expected.to be_nil
12
+ end
13
+
14
+ it "can be explicitly enabled" do
15
+ configuration.csrf_protection = true
16
+ is_expected.to be true
17
+ end
18
+
19
+ it "can be explicitly disabled" do
20
+ configuration.csrf_protection = false
21
+ is_expected.to be false
22
+ end
23
+ end
24
+
25
+ context "finalized configuration" do
26
+ context "sessions enabled" do
27
+ before do
28
+ configuration.sessions = :cookie, {secret: "abc"}
29
+ configuration.finalize!
30
+ end
31
+
32
+ it "is true" do
33
+ is_expected.to be true
34
+ end
35
+
36
+ context "explicitly disabled" do
37
+ before do
38
+ configuration.csrf_protection = false
39
+ end
40
+
41
+ it "is false" do
42
+ is_expected.to be false
43
+ end
44
+ end
45
+ end
46
+
47
+ context "sessions not enabled" do
48
+ before do
49
+ configuration.finalize!
50
+ end
51
+
52
+ it "is true" do
53
+ is_expected.to be false
54
+ end
55
+ end
56
+ end
57
+ end
@@ -0,0 +1,52 @@
1
+ require "hanami/configuration/actions"
2
+
3
+ RSpec.describe Hanami::Configuration::Actions, "default values" do
4
+ subject(:configuration) { described_class.new }
5
+
6
+ describe "sessions" do
7
+ specify { expect(configuration.sessions).not_to be_enabled }
8
+ end
9
+
10
+ describe "name_inference_base" do
11
+ specify { expect(configuration.name_inference_base).to eq "actions" }
12
+ end
13
+
14
+ describe "view_context_identifier" do
15
+ specify { expect(configuration.view_context_identifier).to eq "views.context" }
16
+ end
17
+
18
+ describe "view_name_inferrer" do
19
+ specify { expect(configuration.view_name_inferrer).to eq Hanami::Slice::ViewNameInferrer }
20
+ end
21
+
22
+ describe "view_name_inference_base" do
23
+ specify { expect(configuration.view_name_inference_base).to eq "views" }
24
+ end
25
+
26
+ describe "new default values applied to base action settings" do
27
+ describe "default_request_format" do
28
+ specify { expect(configuration.default_request_format).to eq :html }
29
+ end
30
+
31
+ describe "default_response_format" do
32
+ specify { expect(configuration.default_response_format).to eq :html }
33
+ end
34
+
35
+ describe "content_security_policy" do
36
+ specify { expect(configuration.content_security_policy).to be_kind_of(Hanami::Configuration::Actions::ContentSecurityPolicy) }
37
+ end
38
+
39
+ describe "default_headers" do
40
+ specify {
41
+ configuration.finalize!
42
+
43
+ expect(configuration.default_headers).to eq(
44
+ "X-Frame-Options" => "DENY",
45
+ "X-Content-Type-Options" => "nosniff",
46
+ "X-XSS-Protection" => "1; mode=block",
47
+ "Content-Security-Policy" => configuration.content_security_policy.to_str
48
+ )
49
+ }
50
+ end
51
+ end
52
+ end
@@ -0,0 +1,50 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "hanami/configuration/actions"
4
+
5
+ RSpec.describe Hanami::Configuration::Actions, "#sessions" do
6
+ let(:configuration) { described_class.new }
7
+ subject(:sessions) { configuration.sessions }
8
+
9
+ context "no session config specified" do
10
+ it "is not enabled" do
11
+ expect(sessions).not_to be_enabled
12
+ end
13
+
14
+ it "returns nil storage" do
15
+ expect(sessions.storage).to be_nil
16
+ end
17
+
18
+ it "returns empty options" do
19
+ expect(sessions.options).to eq []
20
+ end
21
+
22
+ it "returns no session middleware" do
23
+ expect(sessions.middleware).to eq []
24
+ end
25
+ end
26
+
27
+ context "valid session config provided" do
28
+ before do
29
+ configuration.sessions = :cookie, {secret: "abc"}
30
+ end
31
+
32
+ it "is enabled" do
33
+ expect(sessions).to be_enabled
34
+ end
35
+
36
+ it "returns the given storage" do
37
+ expect(sessions.storage).to eq :cookie
38
+ end
39
+
40
+ it "returns the given options" do
41
+ expect(sessions.options).to eq [secret: "abc"]
42
+ end
43
+
44
+ it "returns an array of middleware classes and options" do
45
+ expect(sessions.middleware).to eq [
46
+ [Rack::Session::Cookie, [secret: "abc"]]
47
+ ]
48
+ end
49
+ end
50
+ end
@@ -0,0 +1,78 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "hanami/configuration"
4
+ require "hanami/configuration/actions"
5
+ require "hanami/action/configuration"
6
+
7
+ RSpec.describe Hanami::Configuration, "#actions" do
8
+ let(:configuration) { described_class.new(app_name: app_name, env: :development) }
9
+ let(:app_name) { "MyApp::app" }
10
+
11
+ subject(:actions) { configuration.actions }
12
+
13
+ context "Hanami::Action available" do
14
+ it "is a full actions configuration" do
15
+ is_expected.to be_an_instance_of(Hanami::Configuration::Actions)
16
+
17
+ is_expected.to respond_to(:default_response_format)
18
+ is_expected.to respond_to(:default_response_format=)
19
+ end
20
+
21
+ it "configures base action settings" do
22
+ expect { actions.default_request_format = :json }
23
+ .to change { actions.default_request_format }
24
+ .to :json
25
+ end
26
+
27
+ it "configures base actions settings using custom methods" do
28
+ actions.formats = {}
29
+
30
+ expect { actions.format json: "app/json" }
31
+ .to change { actions.formats }
32
+ .to("app/json" => :json)
33
+ end
34
+
35
+ it "can be finalized" do
36
+ is_expected.to respond_to(:finalize!)
37
+ end
38
+
39
+ describe "#settings" do
40
+ it "returns a set of available settings" do
41
+ expect(actions.settings).to be_a(Set)
42
+ expect(actions.settings).to include(:view_context_identifier, :handled_exceptions)
43
+ end
44
+
45
+ it "includes all base action settings" do
46
+ expect(actions.settings).to include(Hanami::Action::Configuration.settings)
47
+ end
48
+ end
49
+ end
50
+
51
+ context "Hanami::Action not available" do
52
+ before do
53
+ load_error = LoadError.new.tap do |error|
54
+ error.instance_variable_set :@path, "hanami/action"
55
+ end
56
+
57
+ allow_any_instance_of(described_class)
58
+ .to receive(:require)
59
+ .with(anything)
60
+ .and_call_original
61
+
62
+ allow_any_instance_of(described_class)
63
+ .to receive(:require)
64
+ .with("hanami/action")
65
+ .and_raise load_error
66
+ end
67
+
68
+ it "does not expose any settings" do
69
+ is_expected.not_to be_an_instance_of(Hanami::Configuration::Actions)
70
+ is_expected.not_to respond_to(:default_response_format)
71
+ is_expected.not_to respond_to(:default_response_format=)
72
+ end
73
+
74
+ it "can be finalized" do
75
+ is_expected.to respond_to(:finalize!)
76
+ end
77
+ end
78
+ end
@@ -0,0 +1,25 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "hanami/configuration"
4
+ require "uri"
5
+
6
+ RSpec.describe Hanami::Configuration, "base_url" do
7
+ subject(:config) { described_class.new(app_name: app_name, env: :development) }
8
+ let(:app_name) { "MyApp::app" }
9
+
10
+ it "defaults to a URI of 'http://0.0.0.0:2300'" do
11
+ expect(config.base_url).to eq URI("http://0.0.0.0:2300")
12
+ end
13
+
14
+ it "can be changed to another URI via a string" do
15
+ expect { config.base_url = "http://example.com" }
16
+ .to change { config.base_url }
17
+ .to(URI("http://example.com"))
18
+ end
19
+
20
+ it "can be changed to another URI object" do
21
+ expect { config.base_url = URI("http://example.com") }
22
+ .to change { config.base_url }
23
+ .to(URI("http://example.com"))
24
+ end
25
+ end
@@ -0,0 +1,35 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "hanami/configuration"
4
+
5
+ RSpec.describe Hanami::Configuration do
6
+ subject(:config) { described_class.new(app_name: app_name, env: :development) }
7
+ let(:app_name) { "MyApp::app" }
8
+
9
+ describe "inflector" do
10
+ it "defaults to a Dry::Inflector instance" do
11
+ expect(config.inflector).to be_kind_of(Dry::Inflector)
12
+ end
13
+
14
+ it "can be replaced with another inflector" do
15
+ new_inflector = double(:inflector)
16
+
17
+ expect { config.inflector = new_inflector }
18
+ .to change { config.inflector }
19
+ .to new_inflector
20
+ end
21
+ end
22
+
23
+ describe "inflections" do
24
+ it "configures a new inflector with the given inflections" do
25
+ expect(config.inflector.pluralize("hanami")).to eq("hanamis")
26
+
27
+ config.inflections do |i|
28
+ i.uncountable("hanami")
29
+ end
30
+
31
+ expect(config.inflector).to be_kind_of(Dry::Inflector)
32
+ expect(config.inflector.pluralize("hanami")).to eq("hanami")
33
+ end
34
+ end
35
+ end
@@ -0,0 +1,203 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "hanami/configuration/logger"
4
+ require "hanami/slice_name"
5
+ require "dry/inflector"
6
+ require "logger"
7
+
8
+ RSpec.describe Hanami::Configuration::Logger do
9
+ subject { described_class.new(app_name: app_name, env: env) }
10
+ let(:app_name) { Hanami::SliceName.new(double(name: "MyApp::app"), inflector: -> { Dry::Inflector.new }) }
11
+ let(:env) { :development }
12
+
13
+ describe "#logger_class" do
14
+ it "defaults to Hanami::Logger" do
15
+ expect(subject.logger_class).to eql Hanami::Logger
16
+ end
17
+
18
+ it "can be changed to another class" do
19
+ another_class = Class.new
20
+
21
+ expect { subject.logger_class = another_class }
22
+ .to change { subject.logger_class }
23
+ .to(another_class)
24
+ end
25
+ end
26
+
27
+ describe "#level" do
28
+ it "defaults to :debug" do
29
+ expect(subject.level).to eq(:debug)
30
+ end
31
+
32
+ context "when :production environment" do
33
+ let(:env) { :production }
34
+
35
+ it "returns :info" do
36
+ expect(subject.level).to eq(:info)
37
+ end
38
+ end
39
+ end
40
+
41
+ describe "#level=" do
42
+ it "a value" do
43
+ expect { subject.level = :warn }
44
+ .to change { subject.level }
45
+ .to(:warn)
46
+ end
47
+ end
48
+
49
+ describe "#stream" do
50
+ it "defaults to $stdout" do
51
+ expect(subject.stream).to eq($stdout)
52
+ end
53
+
54
+ context "when :test environment" do
55
+ let(:env) { :test }
56
+
57
+ it "returns a file" do
58
+ expected = File.join("log", "test.log")
59
+
60
+ expect(subject.stream).to eq(expected)
61
+ end
62
+ end
63
+ end
64
+
65
+ describe "#stream=" do
66
+ it "accepts a IO object or a path to a file" do
67
+ expect { subject.stream = "/dev/null" }
68
+ .to change { subject.stream }
69
+ .to("/dev/null")
70
+ end
71
+ end
72
+
73
+ describe "#formatter" do
74
+ it "defaults to nil" do
75
+ expect(subject.formatter).to eq(nil)
76
+ end
77
+
78
+ context "when :production environment" do
79
+ let(:env) { :production }
80
+
81
+ it "returns :json" do
82
+ expect(subject.formatter).to eq(:json)
83
+ end
84
+ end
85
+ end
86
+
87
+ describe "#formatter=" do
88
+ it "accepts a formatter" do
89
+ expect { subject.formatter = :json }
90
+ .to change { subject.formatter }
91
+ .to(:json)
92
+ end
93
+ end
94
+
95
+ describe "#colors" do
96
+ it "defaults to nil" do
97
+ expect(subject.colors).to eq(nil)
98
+ end
99
+
100
+ context "when :test environment" do
101
+ let(:env) { :test }
102
+
103
+ it "returns false" do
104
+ expect(subject.colors).to eq(false)
105
+ end
106
+ end
107
+
108
+ context "when :production environment" do
109
+ let(:env) { :production }
110
+
111
+ it "returns false" do
112
+ expect(subject.colors).to eq(false)
113
+ end
114
+ end
115
+ end
116
+
117
+ describe "#colors=" do
118
+ it "accepts a value" do
119
+ expect { subject.colors = false }
120
+ .to change { subject.colors }
121
+ .to(false)
122
+ end
123
+ end
124
+
125
+ describe "#filters" do
126
+ it "defaults to a standard array of sensitive param names" do
127
+ expect(subject.filters).to include(*%w[_csrf password password_confirmation])
128
+ end
129
+
130
+ it "can have other params names added" do
131
+ expect { subject.filters << "secret" }
132
+ .to change { subject.filters }
133
+ .to array_including("secret")
134
+
135
+ expect { subject.filters += ["yet", "another"] }
136
+ .to change { subject.filters }
137
+ .to array_including(["yet", "another"])
138
+ end
139
+
140
+ it "can be changed to another array" do
141
+ expect { subject.filters = ["secret"] }
142
+ .to change { subject.filters }
143
+ .to ["secret"]
144
+ end
145
+ end
146
+
147
+ describe "#options" do
148
+ it "defaults to empty array" do
149
+ expect(subject.options).to eq([])
150
+ end
151
+ end
152
+
153
+ describe "#options=" do
154
+ it "accepts value" do
155
+ subject.options = expected = "daily"
156
+
157
+ expect(subject.options).to eq([expected])
158
+ end
159
+
160
+ it "accepts values" do
161
+ subject.options = expected = [0, 1048576]
162
+
163
+ expect(subject.options).to eq(expected)
164
+ end
165
+ end
166
+ end
167
+
168
+ RSpec.describe Hanami::Configuration do
169
+ subject(:config) { described_class.new(app_name: app_name, env: env) }
170
+ let(:app_name) { Hanami::SliceName.new(double(name: "SOS::app"), inflector: -> { Dry::Inflector.new }) }
171
+ let(:env) { :development }
172
+
173
+ describe "#logger" do
174
+ before do
175
+ config.inflections do |inflections|
176
+ inflections.acronym "SOS"
177
+ end
178
+
179
+ config.logger.finalize!
180
+ end
181
+
182
+ describe "#app_name" do
183
+ it "defaults to Hanami::Configuration#app_name" do
184
+ expect(config.logger.app_name).to eq(config.app_name)
185
+ end
186
+ end
187
+ end
188
+
189
+ describe "#logger_instance" do
190
+ it "defaults to an Hanami::Logger instance, based on the default logger settings" do
191
+ expect(config.logger_instance).to be_an_instance_of config.logger.logger_class
192
+ expect(config.logger_instance.level).to eq Logger::DEBUG
193
+ end
194
+
195
+ it "can be changed to a pre-initialized instance via #logger=" do
196
+ logger_instance = Object.new
197
+
198
+ expect { config.logger = logger_instance }
199
+ .to change { config.logger_instance }
200
+ .to logger_instance
201
+ end
202
+ end
203
+ end