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,67 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "hanami"
4
+
5
+ RSpec.describe "App view / Context / Assets", :app_integration do
6
+ before do
7
+ module TestApp
8
+ class App < Hanami::App
9
+ end
10
+ end
11
+
12
+ Hanami.prepare
13
+
14
+ module TestApp
15
+ module Views
16
+ class Context < Hanami::View::Context
17
+ end
18
+ end
19
+ end
20
+ end
21
+
22
+ let(:context_class) { TestApp::Views::Context }
23
+ subject(:context) { context_class.new }
24
+
25
+ describe "#assets" do
26
+ context "without assets provider" do
27
+ it "raises error" do
28
+ expect { context.assets }
29
+ .to raise_error(Hanami::ComponentLoadError, /hanami-assets/)
30
+ end
31
+ end
32
+
33
+ context "with assets provider" do
34
+ before do
35
+ Hanami.app.register_provider(:assets) do
36
+ start do
37
+ register "assets", Object.new
38
+ end
39
+ end
40
+ end
41
+
42
+ it "is the app assets by default" do
43
+ expect(context.assets).to be TestApp::App[:assets]
44
+ end
45
+
46
+ context "injected assets" do
47
+ subject(:context) {
48
+ context_class.new(assets: assets)
49
+ }
50
+
51
+ let(:assets) { double(:assets) }
52
+
53
+ it "is the injected assets" do
54
+ expect(context.assets).to be assets
55
+ end
56
+
57
+ context "rebuilt context" do
58
+ subject(:new_context) { context.with }
59
+
60
+ it "retains the injected assets" do
61
+ expect(new_context.assets).to be assets
62
+ end
63
+ end
64
+ end
65
+ end
66
+ end
67
+ end
@@ -0,0 +1,48 @@
1
+ require "hanami"
2
+
3
+ RSpec.describe "App view / Context / Inflector", :app_integration do
4
+ before do
5
+ module TestApp
6
+ class App < Hanami::App
7
+ end
8
+ end
9
+
10
+ Hanami.prepare
11
+
12
+ module TestApp
13
+ module Views
14
+ class Context < Hanami::View::Context
15
+ end
16
+ end
17
+ end
18
+ end
19
+
20
+ let(:context_class) { TestApp::Views::Context }
21
+ subject(:context) { context_class.new }
22
+
23
+ describe "#inflector" do
24
+ it "is the app inflector by default" do
25
+ expect(context.inflector).to be TestApp::App.inflector
26
+ end
27
+
28
+ context "injected inflector" do
29
+ subject(:context) {
30
+ context_class.new(inflector: inflector)
31
+ }
32
+
33
+ let(:inflector) { double(:inflector) }
34
+
35
+ it "is the injected inflector" do
36
+ expect(context.inflector).to be inflector
37
+ end
38
+
39
+ context "rebuilt context" do
40
+ subject(:new_context) { context.with }
41
+
42
+ it "retains the injected inflector" do
43
+ expect(new_context.inflector).to be inflector
44
+ end
45
+ end
46
+ end
47
+ end
48
+ end
@@ -0,0 +1,61 @@
1
+ require "hanami"
2
+
3
+ RSpec.describe "App view / Context / Request", :app_integration do
4
+ before do
5
+ module TestApp
6
+ class App < Hanami::App
7
+ end
8
+ end
9
+
10
+ Hanami.prepare
11
+
12
+ module TestApp
13
+ module Views
14
+ class Context < Hanami::View::Context
15
+ end
16
+ end
17
+ end
18
+ end
19
+
20
+ let(:context_class) { TestApp::Views::Context }
21
+
22
+ subject(:context) {
23
+ context_class.new(
24
+ request: request,
25
+ response: response,
26
+ )
27
+ }
28
+
29
+ let(:request) { double(:request) }
30
+ let(:response) { double(:response) }
31
+
32
+ describe "#request" do
33
+ it "is the provided request" do
34
+ expect(context.request).to be request
35
+ end
36
+ end
37
+
38
+ describe "#sesion" do
39
+ let(:session) { double(:session) }
40
+
41
+ before do
42
+ allow(request).to receive(:session) { session }
43
+ end
44
+
45
+ it "is the request's session" do
46
+ expect(context.session).to be session
47
+ end
48
+ end
49
+
50
+ describe "#flash" do
51
+ let(:flash) { double(:flash) }
52
+
53
+ before do
54
+ allow(response).to receive(:flash) { flash }
55
+ end
56
+
57
+ it "is the response's flash" do
58
+ expect(context.flash).to be flash
59
+ end
60
+ end
61
+ end
@@ -0,0 +1,86 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "hanami"
4
+
5
+ RSpec.describe "App view / Context / Routes", :app_integration do
6
+ it "accesses app routes" do
7
+ with_tmp_directory(Dir.mktmpdir) do
8
+ write "config/app.rb", <<~RUBY
9
+ require "hanami"
10
+
11
+ module TestApp
12
+ class App < Hanami::App
13
+ end
14
+ end
15
+ RUBY
16
+
17
+ write "config/routes.rb", <<~RUBY
18
+ module TestApp
19
+ class Routes < Hanami::Routes
20
+ define do
21
+ root to: "home.index"
22
+ end
23
+ end
24
+ end
25
+ RUBY
26
+
27
+ write "app/action.rb", <<~RUBY
28
+ require "hanami/action"
29
+
30
+ module TestApp
31
+ class Action < Hanami::Action
32
+ end
33
+ end
34
+ RUBY
35
+
36
+ write "app/actions/home/index.rb", <<~RUBY
37
+ module TestApp
38
+ module Actions
39
+ module Home
40
+ class Index < Hanami::Action
41
+ end
42
+ end
43
+ end
44
+ end
45
+ RUBY
46
+
47
+ write "app/views/context.rb", <<~RUBY
48
+ require "hanami/view/context"
49
+
50
+ module TestApp
51
+ module Views
52
+ class Context < Hanami::View::Context
53
+ end
54
+ end
55
+ end
56
+ RUBY
57
+
58
+ require "hanami/prepare"
59
+
60
+ context = TestApp::Views::Context.new
61
+ expect(context.routes.path(:root)).to eq "/"
62
+ end
63
+ end
64
+
65
+ it "can inject routes" do
66
+ module TestApp
67
+ class App < Hanami::App
68
+ end
69
+ end
70
+
71
+ Hanami.prepare
72
+
73
+ module TestApp
74
+ module Views
75
+ class Context < Hanami::View::Context
76
+ end
77
+ end
78
+ end
79
+
80
+ routes = double(:routes)
81
+
82
+ context = TestApp::Views::Context.new(routes: routes)
83
+
84
+ expect(context.routes).to be(routes)
85
+ end
86
+ end
@@ -0,0 +1,50 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "hanami"
4
+
5
+ RSpec.describe "App view / Context / Settings", :app_integration do
6
+ before do
7
+ module TestApp
8
+ class App < Hanami::App
9
+ end
10
+ end
11
+
12
+ Hanami.prepare
13
+
14
+ module TestApp
15
+ module Views
16
+ class Context < Hanami::View::Context
17
+ end
18
+ end
19
+ end
20
+ end
21
+
22
+ let(:context_class) { TestApp::Views::Context }
23
+ subject(:context) { context_class.new }
24
+
25
+ describe "#settings" do
26
+ it "is the app settings by default" do
27
+ expect(context.settings).to be TestApp::App.settings
28
+ end
29
+
30
+ context "injected settings" do
31
+ subject(:context) {
32
+ context_class.new(settings: settings)
33
+ }
34
+
35
+ let(:settings) { double(:settings) }
36
+
37
+ it "is the injected settings" do
38
+ expect(context.settings).to be settings
39
+ end
40
+
41
+ context "rebuilt context" do
42
+ subject(:new_context) { context.with }
43
+
44
+ it "retains the injected settings" do
45
+ expect(new_context.settings).to be settings
46
+ end
47
+ end
48
+ end
49
+ end
50
+ end
@@ -0,0 +1,57 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "hanami"
4
+
5
+ RSpec.describe "App view / Inflector", :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
+ subject(:view_class) { TestApp::View }
24
+
25
+ context "default app inflector" do
26
+ it "configures the view with the default app inflector" do
27
+ expect(view_class.config.inflector).to be TestApp::App.config.inflector
28
+ end
29
+ end
30
+
31
+ context "custom inflections configured" do
32
+ let(:app_hook) {
33
+ proc do
34
+ config.inflections do |inflections|
35
+ inflections.acronym "NBA"
36
+ end
37
+ end
38
+ }
39
+
40
+ it "configures the view with the customized app inflector" do
41
+ expect(view_class.config.inflector).to be TestApp::App.config.inflector
42
+ expect(view_class.config.inflector.camelize("nba_jam")).to eq "NBAJam"
43
+ end
44
+ end
45
+
46
+ context "custom inflector configured on view class" do
47
+ let(:custom_inflector) { Object.new }
48
+
49
+ before do
50
+ view_class.config.inflector = custom_inflector
51
+ end
52
+
53
+ it "overrides the default app inflector" do
54
+ expect(view_class.config.inflector).to be custom_inflector
55
+ end
56
+ end
57
+ end
@@ -0,0 +1,96 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "hanami"
4
+
5
+ RSpec.describe "App view / Part namespace", :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
+ # The parts module (or any related setup) must exist _before_ we subclass
18
+ # Hanami::View, because the parts_namespace is configured at the time of
19
+ # subclassing (which happens right below)
20
+ parts_module! if respond_to?(:parts_module!)
21
+
22
+ module TestApp
23
+ class View < Hanami::View
24
+ end
25
+ end
26
+
27
+ module TestApp
28
+ module Views
29
+ module Article
30
+ class Index < TestApp::View
31
+ end
32
+ end
33
+ end
34
+ end
35
+ end
36
+
37
+ subject(:part_namespace) { view_class.config.part_namespace }
38
+
39
+ let(:view_class) { TestApp::Views::Article::Index }
40
+
41
+ context "default parts_path" do
42
+ let(:parts_module!) do
43
+ module TestApp
44
+ module Views
45
+ module Parts
46
+ end
47
+ end
48
+ end
49
+ end
50
+
51
+ it "is View::Parts" do
52
+ is_expected.to eq TestApp::Views::Parts
53
+ end
54
+ end
55
+
56
+ context "custom parts_path configured" do
57
+ let(:app_hook) {
58
+ proc do
59
+ config.views.parts_path = "views/custom_parts"
60
+ end
61
+ }
62
+
63
+ context "parts module exists" do
64
+ let(:parts_module!) do
65
+ module TestApp
66
+ module Views
67
+ module CustomParts
68
+ end
69
+ end
70
+ end
71
+ end
72
+
73
+ it "is the matching module within the slice" do
74
+ is_expected.to eq TestApp::Views::CustomParts
75
+ end
76
+ end
77
+
78
+ context "namespace does not exist" do
79
+ it "is nil" do
80
+ is_expected.to be_nil
81
+ end
82
+ end
83
+ end
84
+
85
+ context "nil parts_path configured" do
86
+ let(:app_hook) {
87
+ proc do
88
+ config.views.parts_path = nil
89
+ end
90
+ }
91
+
92
+ it "is nil" do
93
+ is_expected.to be_nil
94
+ end
95
+ end
96
+ end
@@ -0,0 +1,56 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "hanami"
4
+
5
+ RSpec.describe "App view / Path", :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(:paths) { view_class.config.paths }
26
+
27
+ context "default path" do
28
+ it "is 'templates' appended to the slice's root path" do
29
+ expect(paths.map { |path| path.dir.to_s }).to eq ["/test_app/app/templates"]
30
+ end
31
+ end
32
+
33
+ context "relative path provided in app config" do
34
+ let(:app_hook) {
35
+ proc do
36
+ config.views.paths = ["my_templates"]
37
+ end
38
+ }
39
+
40
+ it "configures the path as the relative path appended to the slice's root path" do
41
+ expect(paths.map { |path| path.dir.to_s }).to eq ["/test_app/app/my_templates"]
42
+ end
43
+ end
44
+
45
+ context "absolute path provided in app config" do
46
+ let(:app_hook) {
47
+ proc do
48
+ config.views.paths = ["/absolute/path"]
49
+ end
50
+ }
51
+
52
+ it "leaves the absolute path in place" do
53
+ expect(paths.map { |path| path.dir.to_s }).to eq ["/absolute/path"]
54
+ end
55
+ end
56
+ end
@@ -0,0 +1,68 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "hanami"
4
+
5
+ RSpec.describe "App view / Template", :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
+ subject(:template) { view_class.config.template }
24
+
25
+ context "Ordinary app view" do
26
+ before do
27
+ module TestApp
28
+ module Views
29
+ module Article
30
+ class Index < TestApp::View
31
+ end
32
+ end
33
+ end
34
+ end
35
+ end
36
+
37
+ let(:view_class) { TestApp::Views::Article::Index }
38
+
39
+ it "configures the tempalte to match the class name" do
40
+ expect(template).to eq "article/index"
41
+ end
42
+ end
43
+
44
+ context "Slice view with namespace matching template inference base" do
45
+ before do
46
+ module TestApp
47
+ module MyViews
48
+ module Users
49
+ class Show < TestApp::View
50
+ end
51
+ end
52
+ end
53
+ end
54
+ end
55
+
56
+ let(:app_hook) {
57
+ proc do
58
+ config.views.template_inference_base = "my_views"
59
+ end
60
+ }
61
+
62
+ let(:view_class) { TestApp::MyViews::Users::Show }
63
+
64
+ it "configures the tempalte to match the class name" do
65
+ expect(template).to eq "users/show"
66
+ end
67
+ end
68
+ end
@@ -0,0 +1,103 @@
1
+ # frozen_string_literal: true
2
+
3
+ RSpec.describe "Hanami view integration", :app_integration do
4
+ specify "Views take their configuration from their slice in which they are defined" 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 "app/view.rb", <<~RUBY
16
+ # auto_register: false
17
+ require "hanami/view"
18
+
19
+ module TestApp
20
+ class View < Hanami::View
21
+ end
22
+ end
23
+ RUBY
24
+
25
+ write "app/views/users/show.rb", <<~RUBY
26
+ module TestApp
27
+ module Views
28
+ module Users
29
+ class Show < TestApp::View
30
+ expose :name
31
+ end
32
+ end
33
+ end
34
+ end
35
+ RUBY
36
+
37
+ write "app/templates/layouts/app.html.slim", <<~SLIM
38
+ html
39
+ body
40
+ == yield
41
+ SLIM
42
+
43
+ write "app/templates/users/show.html.slim", <<~'SLIM'
44
+ h1 Hello, #{name}
45
+ SLIM
46
+
47
+ require "hanami/prepare"
48
+
49
+ rendered = TestApp::App["views.users.show"].(name: "Jennifer")
50
+ expect(rendered.to_s).to eq "<html><body><h1>Hello, Jennifer</h1></body></html>"
51
+ end
52
+ end
53
+
54
+ specify "Views can also take configuration from the app when defined in the top-level app module" do
55
+ with_tmp_directory(Dir.mktmpdir) do
56
+ write "config/app.rb", <<~RUBY
57
+ require "hanami"
58
+
59
+ module TestApp
60
+ class App < Hanami::App
61
+ end
62
+ end
63
+ RUBY
64
+
65
+ write "app/view.rb", <<~RUBY
66
+ # auto_register: false
67
+ require "hanami/view"
68
+
69
+ module TestApp
70
+ class View < Hanami::View
71
+ end
72
+ end
73
+ RUBY
74
+
75
+ write "app/views/users/show.rb", <<~RUBY
76
+ module TestApp
77
+ module Views
78
+ module Users
79
+ class Show < TestApp::View
80
+ expose :name
81
+ end
82
+ end
83
+ end
84
+ end
85
+ RUBY
86
+
87
+ write "app/templates/layouts/app.html.slim", <<~SLIM
88
+ html
89
+ body
90
+ == yield
91
+ SLIM
92
+
93
+ write "app/templates/users/show.html.slim", <<~'SLIM'
94
+ h1 Hello, #{name}
95
+ SLIM
96
+
97
+ require "hanami/prepare"
98
+
99
+ rendered = TestApp::App["views.users.show"].(name: "Jennifer")
100
+ expect(rendered.to_s).to eq "<html><body><h1>Hello, Jennifer</h1></body></html>"
101
+ end
102
+ end
103
+ end
@@ -0,0 +1,16 @@
1
+ # frozen_string_literal: true
2
+
3
+ SPEC_ROOT = File.expand_path(__dir__).freeze
4
+
5
+ require_relative "support/coverage" if ENV["COVERAGE"].eql?("true")
6
+
7
+ require "hanami"
8
+ begin; require "byebug"; rescue LoadError; end
9
+ require "hanami/utils/file_list"
10
+ require "hanami/devtools/unit"
11
+
12
+ Hanami::Utils::FileList["./spec/support/**/*.rb"].each do |file|
13
+ next if file.include?("hanami-plugin")
14
+
15
+ require file
16
+ end