hanami 2.0.0.alpha7.1 → 2.0.0.beta1.1

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 (223) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +457 -237
  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 +118 -0
  9. data/lib/hanami/configuration/actions/cookies.rb +29 -0
  10. data/lib/hanami/configuration/actions/sessions.rb +46 -0
  11. data/lib/hanami/configuration/actions.rb +23 -12
  12. data/lib/hanami/configuration/logger.rb +13 -10
  13. data/lib/hanami/configuration/router.rb +2 -6
  14. data/lib/hanami/configuration/sessions.rb +1 -1
  15. data/lib/hanami/configuration/views.rb +86 -0
  16. data/lib/hanami/configuration.rb +139 -82
  17. data/lib/hanami/constants.rb +30 -2
  18. data/lib/hanami/errors.rb +4 -1
  19. data/lib/hanami/extensions/action/slice_configured_action.rb +103 -0
  20. data/lib/hanami/extensions/action.rb +79 -0
  21. data/lib/hanami/extensions/view/context.rb +106 -0
  22. data/lib/hanami/extensions/view/slice_configured_context.rb +71 -0
  23. data/lib/hanami/extensions/view/slice_configured_view.rb +107 -0
  24. data/lib/hanami/extensions/view.rb +33 -0
  25. data/lib/hanami/extensions.rb +10 -0
  26. data/lib/hanami/providers/inflector.rb +13 -0
  27. data/lib/hanami/providers/logger.rb +13 -0
  28. data/lib/hanami/providers/rack.rb +27 -0
  29. data/lib/hanami/providers/routes.rb +33 -0
  30. data/lib/hanami/providers/settings.rb +23 -0
  31. data/lib/hanami/rake_tasks.rb +61 -0
  32. data/lib/hanami/routes.rb +51 -0
  33. data/lib/hanami/server.rb +1 -1
  34. data/lib/hanami/settings/dotenv_store.rb +58 -0
  35. data/lib/hanami/settings.rb +90 -0
  36. data/lib/hanami/setup.rb +4 -2
  37. data/lib/hanami/{application → slice}/router.rb +18 -13
  38. data/lib/hanami/slice/routes_helper.rb +37 -0
  39. data/lib/hanami/{application → slice}/routing/middleware/stack.rb +43 -5
  40. data/lib/hanami/slice/routing/resolver.rb +97 -0
  41. data/lib/hanami/slice/view_name_inferrer.rb +63 -0
  42. data/lib/hanami/slice.rb +252 -82
  43. data/lib/hanami/slice_configurable.rb +62 -0
  44. data/lib/hanami/slice_name.rb +111 -0
  45. data/lib/hanami/slice_registrar.rb +119 -0
  46. data/lib/hanami/version.rb +1 -1
  47. data/lib/hanami/web/rack_logger.rb +1 -1
  48. data/lib/hanami.rb +34 -26
  49. data/spec/integration/application_middleware_stack_spec.rb +84 -0
  50. data/spec/integration/assets/cdn_spec.rb +48 -0
  51. data/spec/integration/assets/fingerprint_spec.rb +42 -0
  52. data/spec/integration/assets/helpers_spec.rb +50 -0
  53. data/spec/integration/assets/serve_spec.rb +70 -0
  54. data/spec/integration/assets/subresource_integrity_spec.rb +54 -0
  55. data/spec/integration/body_parsers_spec.rb +50 -0
  56. data/spec/integration/cli/assets/precompile_spec.rb +147 -0
  57. data/spec/integration/cli/assets_spec.rb +14 -0
  58. data/spec/integration/cli/console_spec.rb +105 -0
  59. data/spec/integration/cli/db/apply_spec.rb +74 -0
  60. data/spec/integration/cli/db/console_spec.rb +40 -0
  61. data/spec/integration/cli/db/create_spec.rb +50 -0
  62. data/spec/integration/cli/db/drop_spec.rb +54 -0
  63. data/spec/integration/cli/db/migrate_spec.rb +108 -0
  64. data/spec/integration/cli/db/prepare_spec.rb +36 -0
  65. data/spec/integration/cli/db/rollback_spec.rb +96 -0
  66. data/spec/integration/cli/db/version_spec.rb +38 -0
  67. data/spec/integration/cli/db_spec.rb +21 -0
  68. data/spec/integration/cli/destroy/action_spec.rb +143 -0
  69. data/spec/integration/cli/destroy/app_spec.rb +118 -0
  70. data/spec/integration/cli/destroy/mailer_spec.rb +74 -0
  71. data/spec/integration/cli/destroy/migration_spec.rb +70 -0
  72. data/spec/integration/cli/destroy/model_spec.rb +113 -0
  73. data/spec/integration/cli/destroy_spec.rb +18 -0
  74. data/spec/integration/cli/generate/action_spec.rb +469 -0
  75. data/spec/integration/cli/generate/app_spec.rb +215 -0
  76. data/spec/integration/cli/generate/mailer_spec.rb +189 -0
  77. data/spec/integration/cli/generate/migration_spec.rb +72 -0
  78. data/spec/integration/cli/generate/model_spec.rb +290 -0
  79. data/spec/integration/cli/generate/secret_spec.rb +56 -0
  80. data/spec/integration/cli/generate_spec.rb +19 -0
  81. data/spec/integration/cli/new/database_spec.rb +235 -0
  82. data/spec/integration/cli/new/hanami_head_spec.rb +27 -0
  83. data/spec/integration/cli/new/template_spec.rb +118 -0
  84. data/spec/integration/cli/new/test_spec.rb +274 -0
  85. data/spec/integration/cli/new_spec.rb +970 -0
  86. data/spec/integration/cli/plugins_spec.rb +39 -0
  87. data/spec/integration/cli/routes_spec.rb +49 -0
  88. data/spec/integration/cli/server_spec.rb +626 -0
  89. data/spec/integration/cli/version_spec.rb +85 -0
  90. data/spec/integration/early_hints_spec.rb +35 -0
  91. data/spec/integration/handle_exceptions_spec.rb +244 -0
  92. data/spec/integration/head_spec.rb +89 -0
  93. data/spec/integration/http_headers_spec.rb +29 -0
  94. data/spec/integration/mailer_spec.rb +32 -0
  95. data/spec/integration/middleware_spec.rb +81 -0
  96. data/spec/integration/mount_applications_spec.rb +88 -0
  97. data/spec/integration/project_initializers_spec.rb +40 -0
  98. data/spec/integration/rackup_spec.rb +35 -0
  99. data/spec/integration/rake/with_minitest_spec.rb +67 -0
  100. data/spec/integration/rake/with_rspec_spec.rb +69 -0
  101. data/spec/integration/routing_helpers_spec.rb +61 -0
  102. data/spec/integration/security/content_security_policy_spec.rb +46 -0
  103. data/spec/integration/security/csrf_protection_spec.rb +42 -0
  104. data/spec/integration/security/force_ssl_spec.rb +29 -0
  105. data/spec/integration/security/x_content_type_options_spec.rb +46 -0
  106. data/spec/integration/security/x_frame_options_spec.rb +46 -0
  107. data/spec/integration/security/x_xss_protection_spec.rb +46 -0
  108. data/spec/integration/send_file_spec.rb +51 -0
  109. data/spec/integration/sessions_spec.rb +247 -0
  110. data/spec/integration/static_middleware_spec.rb +21 -0
  111. data/spec/integration/streaming_spec.rb +41 -0
  112. data/spec/integration/unsafe_send_file_spec.rb +52 -0
  113. data/spec/isolation/hanami/application/already_configured_spec.rb +19 -0
  114. data/spec/isolation/hanami/application/inherit_anonymous_class_spec.rb +10 -0
  115. data/spec/isolation/hanami/application/inherit_concrete_class_spec.rb +14 -0
  116. data/spec/isolation/hanami/application/not_configured_spec.rb +9 -0
  117. data/spec/isolation/hanami/application/routes/configured_spec.rb +44 -0
  118. data/spec/isolation/hanami/application/routes/not_configured_spec.rb +16 -0
  119. data/spec/isolation/hanami/boot/success_spec.rb +50 -0
  120. data/spec/new_integration/action/configuration_spec.rb +26 -0
  121. data/spec/new_integration/action/cookies_spec.rb +58 -0
  122. data/spec/new_integration/action/csrf_protection_spec.rb +54 -0
  123. data/spec/new_integration/action/routes_spec.rb +73 -0
  124. data/spec/new_integration/action/sessions_spec.rb +50 -0
  125. data/spec/new_integration/action/view_integration_spec.rb +165 -0
  126. data/spec/new_integration/action/view_rendering/automatic_rendering_spec.rb +247 -0
  127. data/spec/new_integration/action/view_rendering/paired_view_inference_spec.rb +115 -0
  128. data/spec/new_integration/action/view_rendering_spec.rb +107 -0
  129. data/spec/new_integration/code_loading/loading_from_app_spec.rb +152 -0
  130. data/spec/new_integration/code_loading/loading_from_slice_spec.rb +165 -0
  131. data/spec/new_integration/container/application_routes_helper_spec.rb +48 -0
  132. data/spec/new_integration/container/auto_injection_spec.rb +53 -0
  133. data/spec/new_integration/container/auto_registration_spec.rb +86 -0
  134. data/spec/new_integration/container/autoloader_spec.rb +80 -0
  135. data/spec/new_integration/container/imports_spec.rb +253 -0
  136. data/spec/new_integration/container/prepare_container_spec.rb +123 -0
  137. data/spec/new_integration/container/shutdown_spec.rb +91 -0
  138. data/spec/new_integration/container/standard_bootable_components_spec.rb +124 -0
  139. data/spec/new_integration/rack_app/middleware_spec.rb +215 -0
  140. data/spec/new_integration/rack_app/non_booted_rack_app_spec.rb +105 -0
  141. data/spec/new_integration/rack_app/rack_app_spec.rb +524 -0
  142. data/spec/new_integration/settings_spec.rb +115 -0
  143. data/spec/new_integration/slices/external_slice_spec.rb +92 -0
  144. data/spec/new_integration/slices/slice_configuration_spec.rb +40 -0
  145. data/spec/new_integration/slices/slice_routing_spec.rb +226 -0
  146. data/spec/new_integration/slices/slice_settings_spec.rb +141 -0
  147. data/spec/new_integration/slices_spec.rb +101 -0
  148. data/spec/new_integration/view/configuration_spec.rb +49 -0
  149. data/spec/new_integration/view/context/assets_spec.rb +67 -0
  150. data/spec/new_integration/view/context/inflector_spec.rb +48 -0
  151. data/spec/new_integration/view/context/request_spec.rb +61 -0
  152. data/spec/new_integration/view/context/routes_spec.rb +86 -0
  153. data/spec/new_integration/view/context/settings_spec.rb +50 -0
  154. data/spec/new_integration/view/inflector_spec.rb +57 -0
  155. data/spec/new_integration/view/part_namespace_spec.rb +96 -0
  156. data/spec/new_integration/view/path_spec.rb +56 -0
  157. data/spec/new_integration/view/template_spec.rb +68 -0
  158. data/spec/new_integration/view/views_spec.rb +103 -0
  159. data/spec/spec_helper.rb +16 -0
  160. data/spec/support/app_integration.rb +91 -0
  161. data/spec/support/coverage.rb +1 -0
  162. data/spec/support/fixtures/hanami-plugin/Gemfile +8 -0
  163. data/spec/support/fixtures/hanami-plugin/README.md +35 -0
  164. data/spec/support/fixtures/hanami-plugin/Rakefile +4 -0
  165. data/spec/support/fixtures/hanami-plugin/bin/console +15 -0
  166. data/spec/support/fixtures/hanami-plugin/bin/setup +8 -0
  167. data/spec/support/fixtures/hanami-plugin/hanami-plugin.gemspec +28 -0
  168. data/spec/support/fixtures/hanami-plugin/lib/hanami/plugin/cli.rb +19 -0
  169. data/spec/support/fixtures/hanami-plugin/lib/hanami/plugin/version.rb +7 -0
  170. data/spec/support/fixtures/hanami-plugin/lib/hanami/plugin.rb +8 -0
  171. data/spec/support/rspec.rb +27 -0
  172. data/spec/support/shared_examples/cli/generate/app.rb +494 -0
  173. data/spec/support/shared_examples/cli/generate/migration.rb +32 -0
  174. data/spec/support/shared_examples/cli/generate/model.rb +81 -0
  175. data/spec/support/shared_examples/cli/new.rb +97 -0
  176. data/spec/unit/hanami/configuration/actions/content_security_policy_spec.rb +102 -0
  177. data/spec/unit/hanami/configuration/actions/cookies_spec.rb +46 -0
  178. data/spec/unit/hanami/configuration/actions/csrf_protection_spec.rb +57 -0
  179. data/spec/unit/hanami/configuration/actions/default_values_spec.rb +52 -0
  180. data/spec/unit/hanami/configuration/actions/sessions_spec.rb +50 -0
  181. data/spec/unit/hanami/configuration/actions_spec.rb +78 -0
  182. data/spec/unit/hanami/configuration/base_url_spec.rb +25 -0
  183. data/spec/unit/hanami/configuration/inflector_spec.rb +35 -0
  184. data/spec/unit/hanami/configuration/logger_spec.rb +203 -0
  185. data/spec/unit/hanami/configuration/views_spec.rb +120 -0
  186. data/spec/unit/hanami/configuration_spec.rb +43 -0
  187. data/spec/unit/hanami/env_spec.rb +54 -0
  188. data/spec/unit/hanami/routes_spec.rb +25 -0
  189. data/spec/unit/hanami/settings/dotenv_store_spec.rb +119 -0
  190. data/spec/unit/hanami/settings_spec.rb +56 -0
  191. data/spec/unit/hanami/slice_configurable_spec.rb +104 -0
  192. data/spec/unit/hanami/slice_name_spec.rb +47 -0
  193. data/spec/unit/hanami/slice_spec.rb +17 -0
  194. data/spec/unit/hanami/version_spec.rb +7 -0
  195. data/spec/unit/hanami/web/rack_logger_spec.rb +78 -0
  196. metadata +363 -55
  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.rb +0 -299
  213. data/lib/hanami/boot/source_dirs.rb +0 -44
  214. data/lib/hanami/cli/application/cli.rb +0 -40
  215. data/lib/hanami/cli/application/command.rb +0 -47
  216. data/lib/hanami/cli/application/commands/console.rb +0 -81
  217. data/lib/hanami/cli/application/commands.rb +0 -16
  218. data/lib/hanami/cli/base_command.rb +0 -48
  219. data/lib/hanami/cli/commands/command.rb +0 -171
  220. data/lib/hanami/cli/commands/server.rb +0 -88
  221. data/lib/hanami/cli/commands.rb +0 -65
  222. data/lib/hanami/configuration/middleware.rb +0 -20
  223. data/lib/hanami/configuration/source_dirs.rb +0 -42
@@ -0,0 +1,147 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "json"
4
+
5
+ RSpec.describe "hanami assets", type: :integration do
6
+ describe "precompile" do
7
+ it "precompiles assets" do
8
+ gems = %w[sassc coffee-script]
9
+
10
+ Platform.match do
11
+ os(:linux).engine(:ruby) { gems.push("therubyracer") }
12
+ os(:linux).engine(:jruby) { gems.push("therubyrhino") }
13
+ end
14
+
15
+ with_project("bookshelf_assets_precompile", gems: gems) do
16
+ #
17
+ # Web assets
18
+ #
19
+ write "apps/web/assets/javascripts/app.js.coffee", <<~EOF
20
+ class App
21
+ constructor: () ->
22
+ @init = true
23
+ EOF
24
+ write "apps/web/assets/stylesheets/_colors.scss", <<~EOF
25
+ $background-color: #f5f5f5;
26
+ EOF
27
+
28
+ write "apps/web/assets/stylesheets/app.css.scss", <<~EOF
29
+ @import 'colors';
30
+
31
+ body {
32
+ background-color: $background-color;
33
+ }
34
+ EOF
35
+ #
36
+ # Admin assets
37
+ #
38
+ generate "app admin"
39
+ write "apps/admin/assets/javascripts/dashboard.js.coffee", <<~EOF
40
+ class Dashboard
41
+ constructor: (@data) ->
42
+ EOF
43
+
44
+ #
45
+ # Precompile
46
+ #
47
+ RSpec::Support::Env["HANAMI_ENV"] = "production"
48
+ hanami "assets precompile"
49
+
50
+ # rubocop:disable Lint/ImplicitStringConcatenation
51
+
52
+ #
53
+ # Verify manifest
54
+ #
55
+ manifest = retry_exec(Errno::ENOENT) do
56
+ File.read("public/assets.json")
57
+ end
58
+
59
+ expect(JSON.parse(manifest)).to be_kind_of(Hash) # assert it's a well-formed JSON
60
+
61
+ expect(manifest).to include(%("/assets/admin/dashboard.js":{"target":"/assets/admin/dashboard-39744f9626a70683b6c2d46305798883.js","sri":["sha256-1myPVWoqrq+uAVP2DSkmAown+5dm0x61+E3AjlGOKEc="]}))
62
+ expect(manifest).to include(%("/assets/admin/favicon.ico":{"target":"/assets/admin/favicon-b0979f93c7f7246ac70949a80f7cbdfd.ico","sri":["sha256-PLEDhpDsTBpxl1KtXjzBjg+PUG67zpf05B1z2db4iJU="]}))
63
+ expect(manifest).to include(%("/assets/app.css":{"target":"/assets/app-adb4104884aadde9abfef0bd98ac461e.css","sri":["sha256-S6V565W2In9pWE0uzMASpp58xCg32TN3at3Fv4g9aRA="]}))
64
+ expect(manifest).to include(%("/assets/app.js":{"target":"/assets/app-bb8f10498d83d401db238549409dc4c5.js","sri":["sha256-9m4OTbWigbDPp4oCe1LZz9isqidvW1c3jNL6mXMj2xs="]}))
65
+ expect(manifest).to include(%("/assets/favicon.ico":{"target":"/assets/favicon-b0979f93c7f7246ac70949a80f7cbdfd.ico","sri":["sha256-PLEDhpDsTBpxl1KtXjzBjg+PUG67zpf05B1z2db4iJU="]}))
66
+
67
+ #
68
+ # Verify web assets (w/ checksum)
69
+ #
70
+ expect("public/assets/app-adb4104884aadde9abfef0bd98ac461e.css").to have_file_content <<~EOF
71
+ body {background-color: #f5f5f5}
72
+ EOF
73
+
74
+ expect("public/assets/app-bb8f10498d83d401db238549409dc4c5.js").to have_file_content \
75
+ """
76
+ (function(){var App;App=(function(){function App(){this.init=true;}
77
+ return App;})();}).call(this);
78
+ """
79
+
80
+ expect("public/assets/favicon-b0979f93c7f7246ac70949a80f7cbdfd.ico").to be_an_existing_file
81
+
82
+ #
83
+ # Verify web assets (w/o checksum)
84
+ #
85
+ expect("public/assets/app.css").to have_file_content <<~EOF
86
+ body {background-color: #f5f5f5}
87
+ EOF
88
+
89
+ expect("public/assets/app.js").to have_file_content \
90
+ """
91
+ (function(){var App;App=(function(){function App(){this.init=true;}
92
+ return App;})();}).call(this);
93
+ """
94
+
95
+ expect("public/assets/favicon.ico").to be_an_existing_file
96
+
97
+ #
98
+ # Verify admin assets (w/ checksum)
99
+ #
100
+ expect("public/assets/admin/dashboard-39744f9626a70683b6c2d46305798883.js").to have_file_content \
101
+ """
102
+ (function(){var Dashboard;Dashboard=(function(){function Dashboard(data){this.data=data;}
103
+ return Dashboard;})();}).call(this);
104
+ """
105
+
106
+ expect("public/assets/admin/favicon-b0979f93c7f7246ac70949a80f7cbdfd.ico").to be_an_existing_file
107
+
108
+ #
109
+ # Verify admin assets (w/o checksum)
110
+ #
111
+ expect("public/assets/admin/dashboard.js").to have_file_content \
112
+ """
113
+ (function(){var Dashboard;Dashboard=(function(){function Dashboard(data){this.data=data;}
114
+ return Dashboard;})();}).call(this);
115
+ """
116
+
117
+ expect("public/assets/admin/favicon.ico").to be_an_existing_file
118
+
119
+ # rubocop:enable Lint/ImplicitStringConcatenation
120
+ end
121
+ end
122
+
123
+ it "prints help message" do
124
+ with_project do
125
+ output = <<~OUT
126
+ Command:
127
+ hanami assets precompile
128
+
129
+ Usage:
130
+ hanami assets precompile
131
+
132
+ Description:
133
+ Precompile assets for deployment
134
+
135
+ Options:
136
+ --help, -h # Print this help
137
+
138
+ Examples:
139
+ hanami assets precompile # Basic usage
140
+ hanami assets precompile HANAMI_ENV=production # Precompile assets for production environment
141
+ OUT
142
+
143
+ run_cmd "hanami assets precompile --help", output
144
+ end
145
+ end
146
+ end
147
+ end
@@ -0,0 +1,14 @@
1
+ # frozen_string_literal: true
2
+
3
+ RSpec.describe "hanami assets", type: :integration do
4
+ it "prints subcommands" do
5
+ with_project do
6
+ output = <<~OUT
7
+ Commands:
8
+ hanami assets precompile # Precompile assets for deployment
9
+ OUT
10
+
11
+ run_cmd "hanami assets", output, exit_status: 1
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,105 @@
1
+ # frozen_string_literal: true
2
+
3
+ RSpec.describe "hanami console", type: :integration do
4
+ context "irb" do
5
+ it "starts console" do
6
+ project_name = "bookshelf_console_irb"
7
+ with_project(project_name, console: :irb) do
8
+ setup_model
9
+
10
+ console do |input, _, _|
11
+ input.puts("Hanami::VERSION")
12
+ input.puts("Web::App")
13
+ input.puts("Web.routes")
14
+ input.puts("BookRepository.new.all.to_a")
15
+ input.puts("exit")
16
+ end
17
+
18
+ expect(out).to include(Hanami::VERSION)
19
+ expect(out).to include("Web::App")
20
+ expect(out).to include("#<Hanami::Routes")
21
+ expect(out).to include("[]")
22
+ expect(out).to include("[#{project_name}] [INFO]")
23
+ expect(out).to include("SELECT `id`, `title` FROM `books` ORDER BY `books`.`id`")
24
+ end
25
+ end
26
+
27
+ it "starts console with --engine option" do
28
+ with_project("bookshelf_console_irb", console: :irb) do
29
+ console(" --engine=irb") do |input, _, _|
30
+ input.puts("Hanami::VERSION")
31
+ input.puts("exit")
32
+ end
33
+
34
+ expect(out).to include(Hanami::VERSION)
35
+ end
36
+ end
37
+
38
+ it "starts console without hanami-model" do
39
+ project_without_hanami_model("bookshelf", gems: ["dry-struct"], console: :irb) do
40
+ write "lib/entities/access_token.rb", <<~EOF
41
+ require 'dry-struct'
42
+ require 'securerandom'
43
+
44
+ module Types
45
+ include Dry::Types.module
46
+ end
47
+
48
+ class AccessToken < Dry::Struct
49
+ attribute :id, Types::String.default { SecureRandom.uuid }
50
+ attribute :secret, Types::String
51
+ attribute :digest, Types::String
52
+ end
53
+ EOF
54
+ console do |input, _, _|
55
+ input.puts("AccessToken.new(id: '1', secret: 'shh', digest: 'def')")
56
+ input.puts("exit")
57
+ end
58
+
59
+ expect(out).to include('#<AccessToken id="1" secret="shh" digest="def">')
60
+ end
61
+ end
62
+ end # irb
63
+
64
+ xit "returns error when known engine isn't bundled" do
65
+ with_project("bookshelf_console_irb", console: :irb) do
66
+ output = "Missing gem for `pry' console engine. Please make sure to add it to `Gemfile'."
67
+ run_cmd "hanami console --engine=pry", output, exit_status: 1
68
+ end
69
+ end
70
+
71
+ it "returns error when unknown engine is requested" do
72
+ with_project("bookshelf_console_irb", console: :irb) do
73
+ output = "Unknown console engine: `foo'."
74
+ run_cmd "hanami console --engine=foo", output, exit_status: 1
75
+ end
76
+ end
77
+
78
+ it "prints help message" do
79
+ with_project do
80
+ output = <<~OUT
81
+ Command:
82
+ hanami console
83
+
84
+ Usage:
85
+ hanami console
86
+
87
+ Description:
88
+ Starts Hanami console
89
+
90
+ Options:
91
+ --engine=VALUE # Force a specific console engine: (pry/ripl/irb)
92
+ --help, -h # Print this help
93
+
94
+ Examples:
95
+ hanami console # Uses the bundled engine
96
+ hanami console --engine=pry # Force to use Pry
97
+ OUT
98
+
99
+ run_cmd "hanami console --help", output
100
+ end
101
+ end
102
+
103
+ # TODO: test with pry
104
+ # TODO: test with ripl
105
+ end
@@ -0,0 +1,74 @@
1
+ # frozen_string_literal: true
2
+
3
+ RSpec.describe "hanami db", type: :integration do
4
+ describe "apply" do
5
+ it "migrates, dumps structure, deletes migrations", if: RUBY_VERSION < '2.4' do
6
+ with_project do
7
+ versions = generate_migrations
8
+
9
+ hanami "db apply"
10
+
11
+ hanami "db version"
12
+ expect(out).to include(versions.last.to_s)
13
+
14
+ db = Pathname.new("db")
15
+ schema = db.join("schema.sql").to_s
16
+ migrations = db.join("migrations")
17
+
18
+ expect(schema).to have_file_content <<~SQL
19
+ CREATE TABLE `schema_migrations` (`filename` varchar(255) NOT NULL PRIMARY KEY);
20
+ CREATE TABLE `users` (`id` integer NOT NULL PRIMARY KEY AUTOINCREMENT, `name` varchar(255), `age` integer);
21
+ INSERT INTO "schema_migrations" VALUES('#{versions.first}_create_users.rb');
22
+ INSERT INTO "schema_migrations" VALUES('#{versions.last}_add_age_to_users.rb');
23
+ SQL
24
+
25
+ expect(migrations.children).to be_empty
26
+ end
27
+ end
28
+
29
+ it "migrates, dumps structure, deletes migrations", if: RUBY_VERSION >= '2.4' do
30
+ with_project do
31
+ versions = generate_migrations
32
+
33
+ hanami "db apply"
34
+
35
+ hanami "db version"
36
+ expect(out).to include(versions.last.to_s)
37
+
38
+ db = Pathname.new('db')
39
+ schema = db.join('schema.sql').to_s
40
+ migrations = db.join('migrations')
41
+
42
+ expect(schema).to have_file_content <<-SQL
43
+ CREATE TABLE `schema_migrations` (`filename` varchar(255) NOT NULL PRIMARY KEY);
44
+ CREATE TABLE `users` (`id` integer NOT NULL PRIMARY KEY AUTOINCREMENT, `name` varchar(255), `age` integer);
45
+ CREATE TABLE sqlite_sequence(name,seq);
46
+ INSERT INTO schema_migrations VALUES('#{versions.first}_create_users.rb');
47
+ INSERT INTO schema_migrations VALUES('#{versions.last}_add_age_to_users.rb');
48
+ SQL
49
+
50
+ expect(migrations.children).to be_empty
51
+ end
52
+ end
53
+
54
+ it "prints help message" do
55
+ with_project do
56
+ output = <<~OUT
57
+ Command:
58
+ hanami db apply
59
+
60
+ Usage:
61
+ hanami db apply
62
+
63
+ Description:
64
+ Migrate, dump the SQL schema, and delete the migrations (experimental)
65
+
66
+ Options:
67
+ --help, -h # Print this help
68
+ OUT
69
+
70
+ run_cmd "hanami db apply --help", output
71
+ end
72
+ end
73
+ end
74
+ end
@@ -0,0 +1,40 @@
1
+ # frozen_string_literal: true
2
+
3
+ RSpec.describe "hanami db", type: :integration do
4
+ describe "console" do
5
+ it "starts database console" do
6
+ with_project do
7
+ generate_migrations
8
+ hanami "db prepare"
9
+
10
+ db_console do |input, _, _|
11
+ input.puts('INSERT INTO users (id, name, age) VALUES(1, "Luca", 34);')
12
+ input.puts("SELECT * FROM users;")
13
+ input.puts(".quit")
14
+ end
15
+
16
+ expect(out).to include("1|Luca|34")
17
+ end
18
+ end
19
+
20
+ it "prints help message" do
21
+ with_project do
22
+ output = <<~OUT
23
+ Command:
24
+ hanami db console
25
+
26
+ Usage:
27
+ hanami db console
28
+
29
+ Description:
30
+ Starts a database console
31
+
32
+ Options:
33
+ --help, -h # Print this help
34
+ OUT
35
+
36
+ run_cmd "hanami db console --help", output
37
+ end
38
+ end
39
+ end
40
+ end
@@ -0,0 +1,50 @@
1
+ # frozen_string_literal: true
2
+
3
+ RSpec.describe "hanami db", type: :integration do
4
+ describe "create" do
5
+ it "creates database" do
6
+ project = "bookshelf_db_create"
7
+
8
+ with_project(project) do
9
+ hanami "db create"
10
+
11
+ db = Pathname.new("db").join("#{project}_development.sqlite").to_s
12
+ expect(db).to be_an_existing_file
13
+ end
14
+ end
15
+
16
+ it "doesn't create in production" do
17
+ project = "bookshelf_db_create_production"
18
+
19
+ with_project(project) do
20
+ RSpec::Support::Env["HANAMI_ENV"] = "production"
21
+ hanami "db create"
22
+
23
+ expect(exitstatus).to eq(1)
24
+
25
+ db = Pathname.new("db").join("#{project}.sqlite").to_s
26
+ expect(db).to_not be_an_existing_file
27
+ end
28
+ end
29
+
30
+ it "prints help message" do
31
+ with_project do
32
+ output = <<~OUT
33
+ Command:
34
+ hanami db create
35
+
36
+ Usage:
37
+ hanami db create
38
+
39
+ Description:
40
+ Create the database (only for development/test)
41
+
42
+ Options:
43
+ --help, -h # Print this help
44
+ OUT
45
+
46
+ run_cmd 'hanami db create --help', output
47
+ end
48
+ end
49
+ end
50
+ end
@@ -0,0 +1,54 @@
1
+ # frozen_string_literal: true
2
+
3
+ RSpec.describe "hanami db", type: :integration do
4
+ describe "drop" do
5
+ it "drops database" do
6
+ project = "bookshelf_db_drop"
7
+
8
+ with_project(project) do
9
+ db = Pathname.new("db").join("#{project}_development.sqlite").to_s
10
+
11
+ hanami "db create"
12
+ expect(db).to be_an_existing_file
13
+
14
+ hanami "db drop"
15
+ expect(db).to_not be_an_existing_file
16
+ end
17
+ end
18
+
19
+ it "doesn't drop in production" do
20
+ project = "bookshelf_db_drop_production"
21
+
22
+ with_project(project) do
23
+ RSpec::Support::Env["HANAMI_ENV"] = "production"
24
+ db = Pathname.new("db").join("#{project}.sqlite").to_s
25
+ FileUtils.touch(db) # simulate existing database
26
+
27
+ hanami "db drop"
28
+
29
+ expect(exitstatus).to eq(1)
30
+ expect(db).to be_an_existing_file
31
+ end
32
+ end
33
+
34
+ it "prints help message" do
35
+ with_project do
36
+ output = <<~OUT
37
+ Command:
38
+ hanami db drop
39
+
40
+ Usage:
41
+ hanami db drop
42
+
43
+ Description:
44
+ Drop the database (only for development/test)
45
+
46
+ Options:
47
+ --help, -h # Print this help
48
+ OUT
49
+
50
+ run_cmd 'hanami db drop --help', output
51
+ end
52
+ end
53
+ end
54
+ end
@@ -0,0 +1,108 @@
1
+ # frozen_string_literal: true
2
+
3
+ RSpec.describe "hanami db", type: :integration do
4
+ describe "migrate" do
5
+ it "migrates database" do
6
+ project = "bookshelf_db_migrate"
7
+
8
+ with_project(project) do
9
+ generate_migrations
10
+
11
+ hanami "db create"
12
+ hanami "db migrate"
13
+
14
+ db = Pathname.new("db").join("#{project}_development.sqlite")
15
+
16
+ users = `sqlite3 #{db} ".schema users"`
17
+ expect(users).to include("CREATE TABLE `users` (`id` integer NOT NULL PRIMARY KEY AUTOINCREMENT, `name` varchar(255), `age` integer);")
18
+
19
+ version = `sqlite3 #{db} "SELECT filename FROM schema_migrations ORDER BY filename DESC LIMIT 1"`
20
+ expect(version).to include("add_age_to_users")
21
+ end
22
+ end
23
+
24
+ it "migrates database up to a version" do
25
+ project = "bookshelf_db_migrate_up_to_version"
26
+
27
+ with_project(project) do
28
+ versions = generate_migrations
29
+
30
+ hanami "db create"
31
+ hanami "db migrate #{versions.first}"
32
+
33
+ db = Pathname.new("db").join("#{project}_development.sqlite")
34
+
35
+ users = `sqlite3 #{db} ".schema users"`
36
+ expect(users).to include("CREATE TABLE `users` (`id` integer NOT NULL PRIMARY KEY AUTOINCREMENT, `name` varchar(255));")
37
+
38
+ version = `sqlite3 #{db} "SELECT filename FROM schema_migrations ORDER BY filename DESC LIMIT 1"`
39
+ expect(version).to include("create_users")
40
+ end
41
+ end
42
+
43
+ it "migrates database down to a version" do
44
+ project = "bookshelf_db_migrate_down_to_version"
45
+
46
+ with_project(project) do
47
+ versions = generate_migrations
48
+
49
+ hanami "db create"
50
+ hanami "db migrate" # up to latest version
51
+ hanami "db migrate #{versions.first}"
52
+
53
+ db = Pathname.new("db").join("#{project}_development.sqlite")
54
+
55
+ users = `sqlite3 #{db} ".schema users"`
56
+ expect(users).to include("CREATE TABLE `users`(`id` integer DEFAULT (NULL) NOT NULL PRIMARY KEY AUTOINCREMENT, `name` varchar(255) DEFAULT (NULL) NULL);")
57
+
58
+ version = `sqlite3 #{db} "SELECT filename FROM schema_migrations ORDER BY filename DESC LIMIT 1"`
59
+ expect(version).to include("create_users")
60
+ end
61
+ end
62
+
63
+ it "migrates database down to 0" do
64
+ project = "bookshelf_db_migrate_down_to_zero"
65
+
66
+ with_project(project) do
67
+ generate_migrations
68
+
69
+ hanami "db create"
70
+ hanami "db migrate" # up to latest version
71
+ hanami "db migrate 0"
72
+
73
+ db = Pathname.new("db").join("#{project}_development.sqlite")
74
+
75
+ users = `sqlite3 #{db} ".schema users"`
76
+ expect(users).to eq("")
77
+
78
+ version = `sqlite3 #{db} "SELECT filename FROM schema_migrations ORDER BY filename DESC LIMIT 1"`
79
+ expect(version).to eq("")
80
+ end
81
+ end
82
+
83
+ it "prints help message" do
84
+ with_project do
85
+ banner = <<~OUT
86
+ Command:
87
+ hanami db drop
88
+
89
+ Usage:
90
+ hanami db drop
91
+
92
+ Description:
93
+ Drop the database (only for development/test)
94
+
95
+ Options:
96
+ --help, -h # Print this help
97
+ OUT
98
+
99
+ output = [
100
+ banner,
101
+ # %r{ hanami db migrate [\d]{14} # Migrate to a specific version}
102
+ ]
103
+
104
+ run_cmd 'hanami db drop --help', output
105
+ end
106
+ end
107
+ end
108
+ end
@@ -0,0 +1,36 @@
1
+ # frozen_string_literal: true
2
+
3
+ RSpec.describe "hanami db", type: :integration do
4
+ describe "prepare" do
5
+ it "prepares database" do
6
+ with_project do
7
+ versions = generate_migrations
8
+
9
+ hanami "db prepare"
10
+ hanami "db version"
11
+
12
+ expect(out).to include(versions.last.to_s)
13
+ end
14
+ end
15
+
16
+ it "prints help message" do
17
+ with_project do
18
+ output = <<~OUT
19
+ Command:
20
+ hanami db prepare
21
+
22
+ Usage:
23
+ hanami db prepare
24
+
25
+ Description:
26
+ Drop, create, and migrate the database (only for development/test)
27
+
28
+ Options:
29
+ --help, -h # Print this help
30
+ OUT
31
+
32
+ run_cmd 'hanami db prepare --help', output
33
+ end
34
+ end
35
+ end
36
+ end