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,92 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "rack/test"
4
+
5
+ RSpec.describe "Slices / External slices", :app_integration do
6
+ include Rack::Test::Methods
7
+
8
+ let(:app) { TestApp::App.app }
9
+
10
+ specify "External slices can be registered and used" do
11
+ with_tmp_directory(Dir.mktmpdir) do
12
+ write "config/app.rb", <<~'RUBY'
13
+ require "hanami"
14
+
15
+ module TestApp
16
+ class App < Hanami::App
17
+ config.logger.stream = File.new("/dev/null", "w")
18
+
19
+ require "external/slice"
20
+ register_slice(:external, External::Slice)
21
+ end
22
+ end
23
+ RUBY
24
+
25
+ write "config/routes.rb", <<~'RUBY'
26
+ require "hanami/routes"
27
+
28
+ module TestApp
29
+ class Routes < Hanami::Routes
30
+ define do
31
+ slice :external, at: "/" do
32
+ root to: "test_action"
33
+ end
34
+ end
35
+ end
36
+ end
37
+ RUBY
38
+
39
+ # Put a slice and its components in `lib/external/`, as if it were an external gem
40
+
41
+ write "lib/external/slice.rb", <<~'RUBY'
42
+ # auto_register: false
43
+
44
+ require "hanami/slice"
45
+
46
+ module External
47
+ class Slice < Hanami::Slice
48
+ config.root = __dir__
49
+ end
50
+ end
51
+ RUBY
52
+
53
+ # FIXME: Remove redundant `lib/` dir once hanami/hanami#1174 is merged
54
+ write "lib/external/lib/test_repo.rb", <<~'RUBY'
55
+ require "hanami/slice"
56
+
57
+ module External
58
+ class TestRepo
59
+ def things
60
+ %w[foo bar baz]
61
+ end
62
+ end
63
+ end
64
+ RUBY
65
+
66
+ write "lib/external/actions/test_action.rb", <<~'RUBY'
67
+ require "hanami/action"
68
+
69
+ module External
70
+ module Actions
71
+ class TestAction < Hanami::Action
72
+ include Deps["test_repo"]
73
+
74
+ def handle(req, res)
75
+ res.body = test_repo.things.join(", ")
76
+ end
77
+ end
78
+ end
79
+ end
80
+ RUBY
81
+
82
+ require "hanami/prepare"
83
+
84
+ expect(Hanami.app.slices[:external]).to be External::Slice
85
+
86
+ get "/"
87
+
88
+ expect(last_response.status).to eq 200
89
+ expect(last_response.body).to eq "foo, bar, baz"
90
+ end
91
+ end
92
+ end
@@ -0,0 +1,40 @@
1
+ # frozen_string_literal: true
2
+
3
+ RSpec.describe "Slices / Slice configuration", :app_integration do
4
+ specify "Slices receive a copy of the app configuration, and can make distinct modifications" do
5
+ with_tmp_directory(Dir.mktmpdir) do
6
+ write "config/app.rb", <<~RUBY
7
+ require "hanami"
8
+
9
+ module TestApp
10
+ class App < Hanami::App
11
+ config.logger.stream = File.new("/dev/null", "w")
12
+
13
+ config.no_auto_register_paths << "structs"
14
+ end
15
+ end
16
+ RUBY
17
+
18
+ write "config/slices/main.rb", <<~'RUBY'
19
+ module Main
20
+ class Slice < Hanami::Slice
21
+ config.no_auto_register_paths << "schemas"
22
+ end
23
+ end
24
+ RUBY
25
+
26
+ write "config/slices/search.rb", <<~'RUBY'
27
+ module Search
28
+ class Slice < Hanami::Slice
29
+ end
30
+ end
31
+ RUBY
32
+
33
+ require "hanami/prepare"
34
+
35
+ expect(TestApp::App.config.no_auto_register_paths).to eq %w[entities structs]
36
+ expect(Main::Slice.config.no_auto_register_paths).to eq %w[entities structs schemas]
37
+ expect(Search::Slice.config.no_auto_register_paths).to eq %w[entities structs]
38
+ end
39
+ end
40
+ end
@@ -0,0 +1,226 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "rack/test"
4
+
5
+ RSpec.describe "Slices / Slice routing", :app_integration do
6
+ include Rack::Test::Methods
7
+
8
+ let(:app) { Main::Slice.rack_app }
9
+
10
+ specify "Slices have a nil router when no routes are defined" do
11
+ with_tmp_directory(Dir.mktmpdir) do
12
+ write "config/app.rb", <<~'RUBY'
13
+ require "hanami"
14
+
15
+ module TestApp
16
+ class App < Hanami::App
17
+ end
18
+ end
19
+ RUBY
20
+
21
+ write "slices/main/.keep", ""
22
+
23
+ require "hanami/prepare"
24
+
25
+ expect(Main::Slice.routes).to be nil
26
+ expect(Main::Slice.router).to be nil
27
+ end
28
+ end
29
+
30
+ specify "Slices have the app 'routes' component registered when app routes are defined but not their own" do
31
+ with_tmp_directory(Dir.mktmpdir) do
32
+ write "config/app.rb", <<~'RUBY'
33
+ require "hanami"
34
+
35
+ module TestApp
36
+ class App < Hanami::App
37
+ config.logger.stream = File.new("/dev/null", "w")
38
+ end
39
+ end
40
+ RUBY
41
+
42
+ write "config/routes.rb", <<~'RUBY'
43
+ require "hanami/routes"
44
+
45
+ module TestApp
46
+ class Routes < Hanami::Routes
47
+ define do
48
+ get "home", to: "home.show", as: :home
49
+ end
50
+ end
51
+ end
52
+ RUBY
53
+
54
+ write "slices/main/.keep", ""
55
+
56
+ require "hanami/prepare"
57
+
58
+ expect(Main::Slice["routes"].path(:home)).to eq "/home"
59
+
60
+ expect(Main::Slice.router).to be nil
61
+ expect(TestApp::App.router).not_to be nil
62
+ end
63
+ end
64
+
65
+ specify "Slices use their own router and registered 'routes' component when their own routes are defined" do
66
+ with_tmp_directory(Dir.mktmpdir) do
67
+ write "config/app.rb", <<~'RUBY'
68
+ require "hanami"
69
+
70
+ module TestApp
71
+ class App < Hanami::App
72
+ config.logger.stream = File.new("/dev/null", "w")
73
+ end
74
+ end
75
+ RUBY
76
+
77
+ write "slices/main/config/routes.rb", <<~'RUBY'
78
+ require "hanami/routes"
79
+
80
+ module Main
81
+ class Routes < Hanami::Routes
82
+ define do
83
+ get "home", to: "home.show", as: :home
84
+ end
85
+ end
86
+ end
87
+ RUBY
88
+
89
+ write "slices/main/actions/home/show.rb", <<~'RUBY'
90
+ require "hanami/action"
91
+
92
+ module Main
93
+ module Actions
94
+ module Home
95
+ class Show < Hanami::Action
96
+ def handle(*, res)
97
+ res.body = "Hello world"
98
+ end
99
+ end
100
+ end
101
+ end
102
+ end
103
+ RUBY
104
+
105
+ require "hanami/prepare"
106
+ Main::Slice.boot
107
+
108
+ expect(Main::Slice["routes"].path(:home)).to eq "/home"
109
+
110
+ get "/home"
111
+
112
+ expect(last_response.status).to eq 200
113
+ expect(last_response.body).to eq "Hello world"
114
+ end
115
+ end
116
+
117
+ describe "Mounting slice routes" do
118
+ before :context do
119
+ with_directory(@dir = make_tmp_directory) do
120
+ write "config/app.rb", <<~'RUBY'
121
+ require "hanami"
122
+
123
+ module TestApp
124
+ class App < Hanami::App
125
+ config.logger.stream = File.new("/dev/null", "w")
126
+ end
127
+ end
128
+ RUBY
129
+
130
+ write "config/routes.rb", <<~'RUBY'
131
+ module TestApp
132
+ class Routes < Hanami::Routes
133
+ define do
134
+ root to: "home.show"
135
+
136
+ slice :main, at: "/main"
137
+ end
138
+ end
139
+ end
140
+ RUBY
141
+
142
+ write "app/actions/home/show.rb", <<~'RUBY'
143
+ require "hanami/action"
144
+
145
+ module TestApp
146
+ module Actions
147
+ module Home
148
+ class Show < Hanami::Action
149
+ def handle(*, res)
150
+ res.body = "Hello from app"
151
+ end
152
+ end
153
+ end
154
+ end
155
+ end
156
+ RUBY
157
+
158
+ write "slices/main/config/routes.rb", <<~'RUBY'
159
+ module Main
160
+ class Routes < Hanami::Routes
161
+ define do
162
+ root to: "home.show"
163
+ end
164
+ end
165
+ end
166
+ RUBY
167
+
168
+ write "slices/main/actions/home/show.rb", <<~'RUBY'
169
+ require "hanami/action"
170
+
171
+ module Main
172
+ module Actions
173
+ module Home
174
+ class Show < Hanami::Action
175
+ def handle(*, res)
176
+ res.body = "Hello from slice"
177
+ end
178
+ end
179
+ end
180
+ end
181
+ end
182
+ RUBY
183
+ end
184
+ end
185
+
186
+ let(:app) { TestApp::App.app }
187
+
188
+ describe "A slice with its own router can be mounted in its parent's routes" do
189
+ context "prepared" do
190
+ before do
191
+ with_directory(@dir) { require "hanami/prepare" }
192
+ end
193
+
194
+ specify do
195
+ get "/"
196
+
197
+ expect(last_response.status).to eq 200
198
+ expect(last_response.body).to eq "Hello from app"
199
+
200
+ get "/main"
201
+
202
+ expect(last_response.status).to eq 200
203
+ expect(last_response.body).to eq "Hello from slice"
204
+ end
205
+ end
206
+
207
+ context "booted" do
208
+ before do
209
+ with_directory(@dir) { require "hanami/boot" }
210
+ end
211
+
212
+ specify do
213
+ get "/"
214
+
215
+ expect(last_response.status).to eq 200
216
+ expect(last_response.body).to eq "Hello from app"
217
+
218
+ get "/main"
219
+
220
+ expect(last_response.status).to eq 200
221
+ expect(last_response.body).to eq "Hello from slice"
222
+ end
223
+ end
224
+ end
225
+ end
226
+ end
@@ -0,0 +1,141 @@
1
+ RSpec.describe "Slices / Slice settings", :app_integration do
2
+ specify "Settings are registered for each slice with a settings file" do
3
+ with_tmp_directory(Dir.mktmpdir) do
4
+ write "config/app.rb", <<~RUBY
5
+ require "hanami"
6
+
7
+ module TestApp
8
+ class App < Hanami::App
9
+ end
10
+ end
11
+ RUBY
12
+
13
+ # The main slice has settings
14
+ write "slices/main/config/settings.rb", <<~RUBY
15
+ # frozen_string_literal: true
16
+
17
+ require "hanami/settings"
18
+
19
+ module Main
20
+ class Settings < Hanami::Settings
21
+ setting :main_session_secret
22
+ end
23
+ end
24
+ RUBY
25
+
26
+ # The admin slice has none
27
+ write "slices/admin/.keep", ""
28
+
29
+ require "hanami/prepare"
30
+
31
+ expect(Main::Slice.key?("settings")).to be true
32
+ expect(Main::Slice["settings"]).to respond_to :main_session_secret
33
+
34
+ expect(Admin::Slice.key?("settings")).to be false
35
+ end
36
+ end
37
+
38
+ describe "App settings are shared with slices if no local settings are defined" do
39
+ context "prepared" do
40
+ specify do
41
+ with_tmp_directory(Dir.mktmpdir) do
42
+ write "config/app.rb", <<~RUBY
43
+ require "hanami"
44
+
45
+ module TestApp
46
+ class App < Hanami::App
47
+ end
48
+ end
49
+ RUBY
50
+
51
+ write "config/settings.rb", <<~'RUBY'
52
+ # frozen_string_literal: true
53
+
54
+ require "hanami/settings"
55
+
56
+ module TestApp
57
+ class Settings < Hanami::Settings
58
+ setting :app_session_secret
59
+ end
60
+ end
61
+ RUBY
62
+
63
+ write "slices/main/config/settings.rb", <<~RUBY
64
+ # frozen_string_literal: true
65
+
66
+ require "hanami/settings"
67
+
68
+ module Main
69
+ class Settings < Hanami::Settings
70
+ setting :main_session_secret
71
+ end
72
+ end
73
+ RUBY
74
+
75
+ write "slices/admin/.keep", ""
76
+
77
+ require "hanami/prepare"
78
+
79
+ expect(TestApp::App.key?("settings")).to be true
80
+ expect(Main::Slice.key?("settings")).to be true
81
+ expect(Admin::Slice.key?("settings")).to be true
82
+
83
+ expect(TestApp::App["settings"]).to respond_to :app_session_secret
84
+ expect(Main::Slice["settings"]).to respond_to :main_session_secret
85
+ expect(Admin::Slice["settings"]).to respond_to :app_session_secret
86
+ end
87
+ end
88
+ end
89
+
90
+ context "booted" do
91
+ specify do
92
+ with_tmp_directory(Dir.mktmpdir) do
93
+ write "config/app.rb", <<~RUBY
94
+ require "hanami"
95
+
96
+ module TestApp
97
+ class App < Hanami::App
98
+ end
99
+ end
100
+ RUBY
101
+
102
+ write "config/settings.rb", <<~'RUBY'
103
+ # frozen_string_literal: true
104
+
105
+ require "hanami/settings"
106
+
107
+ module TestApp
108
+ class Settings < Hanami::Settings
109
+ setting :app_session_secret
110
+ end
111
+ end
112
+ RUBY
113
+
114
+ write "slices/main/config/settings.rb", <<~RUBY
115
+ # frozen_string_literal: true
116
+
117
+ require "hanami/settings"
118
+
119
+ module Main
120
+ class Settings < Hanami::Settings
121
+ setting :main_session_secret
122
+ end
123
+ end
124
+ RUBY
125
+
126
+ write "slices/admin/.keep", ""
127
+
128
+ require "hanami/boot"
129
+
130
+ expect(TestApp::App.key?("settings")).to be true
131
+ expect(Main::Slice.key?("settings")).to be true
132
+ expect(Admin::Slice.key?("settings")).to be true
133
+
134
+ expect(TestApp::App["settings"]).to respond_to :app_session_secret
135
+ expect(Main::Slice["settings"]).to respond_to :main_session_secret
136
+ expect(Admin::Slice["settings"]).to respond_to :app_session_secret
137
+ end
138
+ end
139
+ end
140
+ end
141
+ end
@@ -0,0 +1,101 @@
1
+ # frozen_string_literal: true
2
+
3
+ RSpec.describe "Slices", :app_integration do
4
+ it "Loading a slice uses a defined slice class" do
5
+ with_tmp_directory(Dir.mktmpdir) 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 "config/slices/main.rb", <<~RUBY
16
+ module Main
17
+ class Slice < Hanami::Slice
18
+ end
19
+ end
20
+ RUBY
21
+
22
+ write "slices/main/lib/foo.rb", <<~RUBY
23
+ module Main
24
+ class Foo; end
25
+ end
26
+ RUBY
27
+
28
+ require "hanami/prepare"
29
+
30
+ expect(Hanami.app.slices[:main]).to be Main::Slice
31
+ end
32
+ end
33
+
34
+ it "Loading a slice with a defined slice class but no slice dir" do
35
+ with_tmp_directory(Dir.mktmpdir) do
36
+ write "config/app.rb", <<~RUBY
37
+ require "hanami"
38
+
39
+ module TestApp
40
+ class App < Hanami::App
41
+ end
42
+ end
43
+ RUBY
44
+
45
+ write "config/slices/main.rb", <<~RUBY
46
+ module Main
47
+ class Slice < Hanami::Slice
48
+ end
49
+ end
50
+ RUBY
51
+
52
+ require "hanami/prepare"
53
+
54
+ expect(Hanami.app.slices[:main]).to be Main::Slice
55
+ end
56
+ end
57
+
58
+ it "Loading a slice generates a slice class if none is defined" do
59
+ with_tmp_directory(Dir.mktmpdir) do
60
+ write "config/app.rb", <<~RUBY
61
+ require "hanami"
62
+
63
+ module TestApp
64
+ class App < Hanami::App
65
+ end
66
+ end
67
+ RUBY
68
+
69
+ write "slices/main/lib/foo.rb", <<~RUBY
70
+ module Main
71
+ class Foo; end
72
+ end
73
+ RUBY
74
+
75
+ require "hanami/prepare"
76
+
77
+ expect(Hanami.app.slices[:main]).to be Main::Slice
78
+ end
79
+ end
80
+
81
+ it "Registering a slice with a block creates a slice class and evals the block" do
82
+ with_tmp_directory(Dir.mktmpdir) do
83
+ write "config/app.rb", <<~RUBY
84
+ require "hanami"
85
+
86
+ module TestApp
87
+ class App < Hanami::App
88
+ register_slice :main do
89
+ register "greeting", "hello world"
90
+ end
91
+ end
92
+ end
93
+ RUBY
94
+
95
+ require "hanami/prepare"
96
+
97
+ expect(Hanami.app.slices[:main]).to be Main::Slice
98
+ expect(Main::Slice["greeting"]).to eq "hello world"
99
+ end
100
+ end
101
+ end
@@ -0,0 +1,49 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "hanami"
4
+
5
+ RSpec.describe "App view / Configuration", :app_integration do
6
+ before do
7
+ module TestApp
8
+ class App < Hanami::App
9
+ config.root = "/test_app"
10
+ end
11
+ end
12
+
13
+ Hanami.app.instance_eval(&app_hook) if respond_to?(:app_hook)
14
+ Hanami.app.register_slice :main
15
+ Hanami.app.prepare
16
+
17
+ module TestApp
18
+ class View < Hanami::View
19
+ end
20
+ end
21
+ end
22
+
23
+ let(:view_class) { TestApp::View }
24
+
25
+ subject(:config) { view_class.config }
26
+
27
+ it "applies default view configuration from the app" do
28
+ aggregate_failures do
29
+ expect(config.layouts_dir).to eq "layouts"
30
+ expect(config.layout).to eq "app"
31
+ end
32
+ end
33
+
34
+ context "custom views configuration on app" do
35
+ let(:app_hook) {
36
+ proc do
37
+ config.views.layouts_dir = "custom_layouts"
38
+ config.views.layout = "my_layout"
39
+ end
40
+ }
41
+
42
+ it "applies the custom configuration" do
43
+ aggregate_failures do
44
+ expect(config.layouts_dir).to eq "custom_layouts"
45
+ expect(config.layout).to eq "my_layout"
46
+ end
47
+ end
48
+ end
49
+ end