hanami 2.0.0.beta2 → 2.0.0.beta4

Sign up to get free protection for your applications and to get access to all the features.
Files changed (176) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +30 -1
  3. data/hanami.gemspec +5 -5
  4. data/lib/hanami/app.rb +4 -4
  5. data/lib/hanami/assets/{app_configuration.rb → app_config.rb} +10 -10
  6. data/lib/hanami/assets/{configuration.rb → config.rb} +4 -4
  7. data/lib/hanami/{configuration → config}/actions/content_security_policy.rb +2 -2
  8. data/lib/hanami/{configuration → config}/actions/cookies.rb +6 -5
  9. data/lib/hanami/{configuration → config}/actions/sessions.rb +2 -2
  10. data/lib/hanami/{configuration → config}/actions.rb +11 -12
  11. data/lib/hanami/{configuration → config}/logger.rb +2 -2
  12. data/lib/hanami/config/null_config.rb +14 -0
  13. data/lib/hanami/{configuration → config}/router.rb +8 -8
  14. data/lib/hanami/{configuration → config}/sessions.rb +2 -2
  15. data/lib/hanami/{configuration → config}/views.rb +10 -10
  16. data/lib/hanami/{configuration.rb → config.rb} +30 -30
  17. data/lib/hanami/errors.rb +3 -0
  18. data/lib/hanami/extensions/action/slice_configured_action.rb +1 -1
  19. data/lib/hanami/providers/inflector.rb +0 -2
  20. data/lib/hanami/providers/logger.rb +1 -3
  21. data/lib/hanami/providers/rack.rb +0 -2
  22. data/lib/hanami/providers/routes.rb +0 -2
  23. data/lib/hanami/routes.rb +48 -21
  24. data/lib/hanami/settings/env_store.rb +3 -3
  25. data/lib/hanami/settings.rb +87 -5
  26. data/lib/hanami/slice/routing/middleware/stack.rb +45 -1
  27. data/lib/hanami/slice.rb +52 -37
  28. data/lib/hanami/slice_configurable.rb +1 -1
  29. data/lib/hanami/slice_registrar.rb +6 -0
  30. data/lib/hanami/version.rb +1 -1
  31. data/lib/hanami.rb +0 -1
  32. data/spec/{new_integration → integration}/action/cookies_spec.rb +0 -0
  33. data/spec/{new_integration → integration}/action/csrf_protection_spec.rb +0 -0
  34. data/spec/{new_integration → integration}/action/routes_spec.rb +3 -5
  35. data/spec/{new_integration → integration}/action/sessions_spec.rb +0 -0
  36. data/spec/{new_integration → integration}/action/slice_configuration_spec.rb +0 -0
  37. data/spec/{new_integration → integration}/action/view_integration_spec.rb +0 -0
  38. data/spec/{new_integration → integration}/action/view_rendering/automatic_rendering_spec.rb +0 -0
  39. data/spec/{new_integration → integration}/action/view_rendering/paired_view_inference_spec.rb +0 -0
  40. data/spec/{new_integration → integration}/action/view_rendering_spec.rb +0 -0
  41. data/spec/{new_integration → integration}/code_loading/loading_from_app_spec.rb +0 -0
  42. data/spec/{new_integration → integration}/code_loading/loading_from_lib_spec.rb +0 -0
  43. data/spec/{new_integration → integration}/code_loading/loading_from_slice_spec.rb +0 -0
  44. data/spec/{new_integration → integration}/container/application_routes_helper_spec.rb +1 -3
  45. data/spec/{new_integration → integration}/container/auto_injection_spec.rb +0 -0
  46. data/spec/{new_integration → integration}/container/auto_registration_spec.rb +0 -0
  47. data/spec/{new_integration → integration}/container/autoloader_spec.rb +0 -0
  48. data/spec/{new_integration → integration}/container/imports_spec.rb +0 -0
  49. data/spec/{new_integration → integration}/container/prepare_container_spec.rb +2 -0
  50. data/spec/{new_integration → integration}/container/shutdown_spec.rb +0 -0
  51. data/spec/{new_integration → integration}/container/standard_bootable_components_spec.rb +0 -0
  52. data/spec/{new_integration → integration}/dotenv_loading_spec.rb +0 -0
  53. data/spec/integration/rack_app/body_parser_spec.rb +108 -0
  54. data/spec/{new_integration → integration}/rack_app/middleware_spec.rb +37 -15
  55. data/spec/{new_integration → integration}/rack_app/non_booted_rack_app_spec.rb +3 -5
  56. data/spec/{new_integration → integration}/rack_app/rack_app_spec.rb +28 -48
  57. data/spec/integration/settings/access_in_slice_class_body_spec.rb +82 -0
  58. data/spec/integration/settings/access_to_constants_spec.rb +46 -0
  59. data/spec/{new_integration → integration}/settings/loading_from_env_spec.rb +0 -0
  60. data/spec/{new_integration → integration}/settings/settings_component_loading_spec.rb +0 -0
  61. data/spec/{new_integration/slices/slice_settings_spec.rb → integration/settings/slice_registration_spec.rb} +5 -1
  62. data/spec/{new_integration → integration}/settings/using_types_spec.rb +4 -11
  63. data/spec/{new_integration → integration}/setup_spec.rb +20 -0
  64. data/spec/{new_integration → integration}/slices/external_slice_spec.rb +2 -4
  65. data/spec/{new_integration → integration}/slices/slice_configuration_spec.rb +0 -0
  66. data/spec/{new_integration → integration}/slices/slice_loading_spec.rb +0 -0
  67. data/spec/{new_integration → integration}/slices/slice_routing_spec.rb +5 -13
  68. data/spec/{new_integration → integration}/slices_spec.rb +0 -0
  69. data/spec/{new_integration → integration}/view/context/assets_spec.rb +0 -0
  70. data/spec/{new_integration → integration}/view/context/inflector_spec.rb +0 -0
  71. data/spec/{new_integration → integration}/view/context/request_spec.rb +0 -0
  72. data/spec/{new_integration → integration}/view/context/routes_spec.rb +1 -3
  73. data/spec/{new_integration → integration}/view/context/settings_spec.rb +0 -0
  74. data/spec/{new_integration → integration}/view/inflector_spec.rb +0 -0
  75. data/spec/{new_integration → integration}/view/part_namespace_spec.rb +0 -0
  76. data/spec/{new_integration → integration}/view/path_spec.rb +0 -0
  77. data/spec/{new_integration → integration}/view/slice_configuration_spec.rb +0 -0
  78. data/spec/{new_integration → integration}/view/template_spec.rb +0 -0
  79. data/spec/{new_integration → integration}/view/views_spec.rb +0 -0
  80. data/spec/support/app_integration.rb +18 -15
  81. data/spec/unit/hanami/{configuration → config}/actions/content_security_policy_spec.rb +10 -10
  82. data/spec/unit/hanami/{configuration → config}/actions/cookies_spec.rb +6 -6
  83. data/spec/unit/hanami/{configuration → config}/actions/csrf_protection_spec.rb +12 -12
  84. data/spec/unit/hanami/config/actions/default_values_spec.rb +54 -0
  85. data/spec/unit/hanami/{configuration → config}/actions/sessions_spec.rb +5 -5
  86. data/spec/unit/hanami/{configuration → config}/actions_spec.rb +13 -25
  87. data/spec/unit/hanami/{configuration → config}/base_url_spec.rb +2 -2
  88. data/spec/unit/hanami/{configuration → config}/inflector_spec.rb +2 -2
  89. data/spec/unit/hanami/{configuration → config}/logger_spec.rb +4 -4
  90. data/spec/unit/hanami/config/router_spec.rb +44 -0
  91. data/spec/unit/hanami/{configuration → config}/slices_spec.rb +2 -2
  92. data/spec/unit/hanami/{configuration → config}/views_spec.rb +15 -27
  93. data/spec/unit/hanami/{configuration_spec.rb → config_spec.rb} +3 -3
  94. data/spec/unit/hanami/settings_spec.rb +65 -10
  95. data/spec/unit/hanami/slice_configurable_spec.rb +21 -2
  96. data/spec/unit/hanami/version_spec.rb +1 -1
  97. metadata +162 -294
  98. data/lib/hanami/configuration/null_configuration.rb +0 -14
  99. data/lib/hanami/providers/settings.rb +0 -98
  100. data/lib/hanami/server.rb +0 -29
  101. data/spec/integration/application_middleware_stack_spec.rb +0 -84
  102. data/spec/integration/assets/cdn_spec.rb +0 -48
  103. data/spec/integration/assets/fingerprint_spec.rb +0 -42
  104. data/spec/integration/assets/helpers_spec.rb +0 -50
  105. data/spec/integration/assets/serve_spec.rb +0 -70
  106. data/spec/integration/assets/subresource_integrity_spec.rb +0 -54
  107. data/spec/integration/body_parsers_spec.rb +0 -50
  108. data/spec/integration/cli/assets/precompile_spec.rb +0 -147
  109. data/spec/integration/cli/assets_spec.rb +0 -14
  110. data/spec/integration/cli/console_spec.rb +0 -105
  111. data/spec/integration/cli/db/apply_spec.rb +0 -74
  112. data/spec/integration/cli/db/console_spec.rb +0 -40
  113. data/spec/integration/cli/db/create_spec.rb +0 -50
  114. data/spec/integration/cli/db/drop_spec.rb +0 -54
  115. data/spec/integration/cli/db/migrate_spec.rb +0 -108
  116. data/spec/integration/cli/db/prepare_spec.rb +0 -36
  117. data/spec/integration/cli/db/rollback_spec.rb +0 -96
  118. data/spec/integration/cli/db/version_spec.rb +0 -38
  119. data/spec/integration/cli/db_spec.rb +0 -21
  120. data/spec/integration/cli/destroy/action_spec.rb +0 -143
  121. data/spec/integration/cli/destroy/app_spec.rb +0 -118
  122. data/spec/integration/cli/destroy/mailer_spec.rb +0 -74
  123. data/spec/integration/cli/destroy/migration_spec.rb +0 -70
  124. data/spec/integration/cli/destroy/model_spec.rb +0 -113
  125. data/spec/integration/cli/destroy_spec.rb +0 -18
  126. data/spec/integration/cli/generate/action_spec.rb +0 -469
  127. data/spec/integration/cli/generate/app_spec.rb +0 -215
  128. data/spec/integration/cli/generate/mailer_spec.rb +0 -189
  129. data/spec/integration/cli/generate/migration_spec.rb +0 -72
  130. data/spec/integration/cli/generate/model_spec.rb +0 -290
  131. data/spec/integration/cli/generate/secret_spec.rb +0 -56
  132. data/spec/integration/cli/generate_spec.rb +0 -19
  133. data/spec/integration/cli/new/database_spec.rb +0 -235
  134. data/spec/integration/cli/new/hanami_head_spec.rb +0 -27
  135. data/spec/integration/cli/new/template_spec.rb +0 -118
  136. data/spec/integration/cli/new/test_spec.rb +0 -274
  137. data/spec/integration/cli/new_spec.rb +0 -970
  138. data/spec/integration/cli/plugins_spec.rb +0 -39
  139. data/spec/integration/cli/routes_spec.rb +0 -49
  140. data/spec/integration/cli/server_spec.rb +0 -626
  141. data/spec/integration/cli/version_spec.rb +0 -85
  142. data/spec/integration/early_hints_spec.rb +0 -35
  143. data/spec/integration/handle_exceptions_spec.rb +0 -244
  144. data/spec/integration/head_spec.rb +0 -89
  145. data/spec/integration/http_headers_spec.rb +0 -29
  146. data/spec/integration/mailer_spec.rb +0 -32
  147. data/spec/integration/middleware_spec.rb +0 -81
  148. data/spec/integration/mount_applications_spec.rb +0 -88
  149. data/spec/integration/project_initializers_spec.rb +0 -40
  150. data/spec/integration/rackup_spec.rb +0 -35
  151. data/spec/integration/rake/with_minitest_spec.rb +0 -67
  152. data/spec/integration/rake/with_rspec_spec.rb +0 -69
  153. data/spec/integration/routing_helpers_spec.rb +0 -61
  154. data/spec/integration/security/content_security_policy_spec.rb +0 -46
  155. data/spec/integration/security/csrf_protection_spec.rb +0 -42
  156. data/spec/integration/security/force_ssl_spec.rb +0 -29
  157. data/spec/integration/security/x_content_type_options_spec.rb +0 -46
  158. data/spec/integration/security/x_frame_options_spec.rb +0 -46
  159. data/spec/integration/security/x_xss_protection_spec.rb +0 -46
  160. data/spec/integration/send_file_spec.rb +0 -51
  161. data/spec/integration/sessions_spec.rb +0 -247
  162. data/spec/integration/static_middleware_spec.rb +0 -21
  163. data/spec/integration/streaming_spec.rb +0 -41
  164. data/spec/integration/unsafe_send_file_spec.rb +0 -52
  165. data/spec/new_integration/settings/access_to_constants_spec.rb +0 -169
  166. data/spec/support/fixtures/hanami-plugin/Gemfile +0 -8
  167. data/spec/support/fixtures/hanami-plugin/README.md +0 -35
  168. data/spec/support/fixtures/hanami-plugin/Rakefile +0 -4
  169. data/spec/support/fixtures/hanami-plugin/bin/console +0 -15
  170. data/spec/support/fixtures/hanami-plugin/bin/setup +0 -8
  171. data/spec/support/fixtures/hanami-plugin/hanami-plugin.gemspec +0 -28
  172. data/spec/support/fixtures/hanami-plugin/lib/hanami/plugin/cli.rb +0 -19
  173. data/spec/support/fixtures/hanami-plugin/lib/hanami/plugin/version.rb +0 -7
  174. data/spec/support/fixtures/hanami-plugin/lib/hanami/plugin.rb +0 -8
  175. data/spec/unit/hanami/configuration/actions/default_values_spec.rb +0 -52
  176. data/spec/unit/hanami/routes_spec.rb +0 -25
@@ -1,98 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require "dry/system/provider/source"
4
- require_relative "../constants"
5
- require_relative "../errors"
6
-
7
- module Hanami
8
- module Providers
9
- # The settings provider loads and registers the "settings" component in app and slice
10
- # containers.
11
- #
12
- # To register this provider with a slice container, you should use
13
- # {.register_with_slice}, which will register the provider only if settings are
14
- # defined for the slice.
15
- #
16
- # @see Slice::ClassMethods.prepare_container_providers
17
- #
18
- # @api private
19
- # @since 2.0.0
20
- class Settings < Dry::System::Provider::Source
21
- class << self
22
- # Registers the provider with the slice's container, but only if settings are
23
- # defined for the slice.
24
- def register_with_slice(slice)
25
- return unless settings_defined?(slice)
26
-
27
- slice.register_provider(:settings, source: with_slice(slice))
28
- end
29
-
30
- # Creates a new subclass of the provider for the given slice.
31
- #
32
- # You must do this before registering the provider with a container. The provider
33
- # uses the slice to locate the settings definition based on the slice's config.
34
- def with_slice(slice)
35
- Class.new(self) do |klass|
36
- klass.instance_variable_set(:@slice, slice)
37
- end
38
- end
39
-
40
- # Returns the slice for the provider
41
- def slice
42
- unless @slice
43
- raise SliceLoadError, "a slice must be given to #{self} via `.with_slice(slice)`"
44
- end
45
-
46
- @slice
47
- end
48
-
49
- private
50
-
51
- # Returns true if settings are defined for the slice.
52
- #
53
- # Settings are considered defined if a `Settings` class is already defined in the
54
- # slice namespace, or a `config/settings.rb` exists under the slice root.
55
- def settings_defined?(slice)
56
- slice.namespace.const_defined?(SETTINGS_CLASS_NAME) ||
57
- slice.root.join("#{SETTINGS_PATH}#{RB_EXT}").file?
58
- end
59
- end
60
-
61
- def prepare
62
- require_slice_settings unless slice_settings_class?
63
- end
64
-
65
- def start
66
- settings = slice_settings_class.new(slice.config.settings_store)
67
-
68
- register :settings, settings
69
- end
70
-
71
- private
72
-
73
- def slice
74
- self.class.slice
75
- end
76
-
77
- def slice_settings_class?
78
- slice.namespace.const_defined?(SETTINGS_CLASS_NAME)
79
- end
80
-
81
- def slice_settings_class
82
- slice.namespace.const_get(SETTINGS_CLASS_NAME)
83
- end
84
-
85
- def require_slice_settings
86
- require "hanami/settings"
87
-
88
- slice_settings_require_path = File.join(slice.root, SETTINGS_PATH)
89
-
90
- begin
91
- require slice_settings_require_path
92
- rescue LoadError => e
93
- raise e unless e.path == slice_settings_require_path
94
- end
95
- end
96
- end
97
- end
98
- end
data/lib/hanami/server.rb DELETED
@@ -1,29 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require "hanami"
4
- require "rack"
5
-
6
- module Hanami
7
- # Rack compatible server.
8
- #
9
- # It is run with:
10
- #
11
- # `bundle exec hanami server`
12
- #
13
- # It runs the app, by using the server specified in your `Gemfile`
14
- # (eg. Puma or Unicorn).
15
- #
16
- # @since 0.8.0
17
- # @api private
18
- class Server < ::Rack::Server
19
- # Primarily this removes the ::Rack::Chunked middleware
20
- # which is the cause of Safari content-length bugs.
21
- #
22
- # @since 0.8.0
23
- def middleware
24
- mw = ::Hash.new { |e, m| e[m] = [] }
25
- mw["development"].concat([::Rack::ShowExceptions, ::Rack::Lint])
26
- mw
27
- end
28
- end
29
- end
@@ -1,84 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- RSpec.describe "App middleware stack", type: :integration do
4
- it "mounts Rack middleware" do
5
- with_project do
6
- generate "action web home#index --url=/"
7
- generate_middleware
8
-
9
- # Add apps/web/middleware to the load paths
10
- replace "apps/web/app.rb", "load_paths << [", "load_paths << ['middleware',"
11
-
12
- # Require Rack::ETag
13
- unshift "apps/web/app.rb", "require 'rack/etag'"
14
-
15
- # Mount middleware
16
- replace "apps/web/app.rb", "# middleware.use", "middleware.use 'Web::Middleware::Runtime'\nmiddleware.use 'Web::Middleware::Custom', 'OK'\nmiddleware.use Rack::ETag"
17
-
18
- rewrite "apps/web/controllers/home/index.rb", <<~EOF
19
- module Web::Controllers::Home
20
- class Index
21
- include Web::Action
22
-
23
- def call(params)
24
- self.body = "OK"
25
- end
26
- end
27
- end
28
- EOF
29
-
30
- server do
31
- get "/"
32
-
33
- expect(last_response.status).to eq(200)
34
-
35
- expect(last_response.headers["X-Runtime"]).to eq("1ms")
36
- expect(last_response.headers["X-Custom"]).to eq("OK")
37
- expect(last_response.headers["ETag"]).to_not be_nil
38
- end
39
- end
40
- end
41
-
42
- private
43
-
44
- def generate_middleware # rubocop:disable Metrics/MethodLength
45
- write "apps/web/middleware/runtime.rb", <<~EOF
46
- module Web
47
- module Middleware
48
- class Runtime
49
- def initialize(app)
50
- @app = app
51
- end
52
-
53
- def call(env)
54
- status, headers, body = @app.call(env)
55
- headers["X-Runtime"] = "1ms"
56
-
57
- [status, headers, body]
58
- end
59
- end
60
- end
61
- end
62
- EOF
63
-
64
- write "apps/web/middleware/custom.rb", <<~EOF
65
- module Web
66
- module Middleware
67
- class Custom
68
- def initialize(app, value)
69
- @app = app
70
- @value = value
71
- end
72
-
73
- def call(env)
74
- status, headers, body = @app.call(env)
75
- headers["X-Custom"] = @value
76
-
77
- [status, headers, body]
78
- end
79
- end
80
- end
81
- end
82
- EOF
83
- end
84
- end
@@ -1,48 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- RSpec.describe "assets", type: :integration do
4
- describe "CDN mode" do
5
- it "servers assets with CDN url" do
6
- with_project do
7
- generate "action web home#index --url=/"
8
-
9
- write "apps/web/assets/javascripts/app.css", <<~EOF
10
- body { color: #333 };
11
- EOF
12
- rewrite "apps/web/templates/app.html.erb", <<~EOF
13
- <!DOCTYPE html>
14
- <html>
15
- <head>
16
- <title>Web</title>
17
- <%= favicon %>
18
- <%= stylesheet 'app' %>
19
- </head>
20
- <body>
21
- <%= yield %>
22
- </body>
23
- </html>
24
- EOF
25
-
26
- replace_last "apps/web/app.rb", "# scheme 'https'", "scheme 'https'"
27
- replace "apps/web/app.rb", "# host 'cdn.example.org'", "host 'cdn.example.org'"
28
- replace_last "apps/web/app.rb", "# port 443", "port 443"
29
-
30
- #
31
- # Precompile
32
- #
33
- RSpec::Support::Env["HANAMI_ENV"] = "production"
34
- RSpec::Support::Env["DATABASE_URL"] = "sqlite://#{Pathname.new('db').join('bookshelf.sqlite')}"
35
- RSpec::Support::Env["SMTP_HOST"] = "localhost"
36
- RSpec::Support::Env["SMTP_PORT"] = "25"
37
-
38
- hanami "assets precompile"
39
-
40
- server do
41
- visit "/"
42
-
43
- expect(page.body).to include(%(<link href="https://cdn.example.org/assets/app-5df86b4e9cbd733a027762b2f6bf8693.css" type="text/css" rel="stylesheet" integrity="sha256-LxaTcWkL8TAWFQWeHJ7OqoSoEXXaYapNIS+TCvGNf48=" crossorigin="anonymous">))
44
- end
45
- end
46
- end
47
- end
48
- end
@@ -1,42 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- RSpec.describe "assets", type: :integration do
4
- describe "fingerprint mode" do
5
- it "servers assets with fingerprint url" do
6
- with_project do
7
- generate "action web home#index --url=/"
8
-
9
- write "apps/web/assets/javascripts/app.css", <<~EOF
10
- body { color: #333 };
11
- EOF
12
- rewrite "apps/web/templates/app.html.erb", <<~EOF
13
- <!DOCTYPE html>
14
- <html>
15
- <head>
16
- <title>Web</title>
17
- <%= favicon %>
18
- <%= stylesheet 'app' %>
19
- </head>
20
- <body>
21
- <%= yield %>
22
- </body>
23
- </html>
24
- EOF
25
- #
26
- # Precompile
27
- #
28
- RSpec::Support::Env["HANAMI_ENV"] = "production"
29
- RSpec::Support::Env["DATABASE_URL"] = "sqlite://#{Pathname.new('db').join('bookshelf.sqlite')}"
30
- RSpec::Support::Env["SMTP_HOST"] = "localhost"
31
- RSpec::Support::Env["SMTP_PORT"] = "25"
32
- hanami "assets precompile"
33
-
34
- server do
35
- visit "/"
36
-
37
- expect(page.body).to include(%(<link href="/assets/app-5df86b4e9cbd733a027762b2f6bf8693.css" type="text/css" rel="stylesheet" integrity="sha256-LxaTcWkL8TAWFQWeHJ7OqoSoEXXaYapNIS+TCvGNf48=" crossorigin="anonymous">))
38
- end
39
- end
40
- end
41
- end
42
- end
@@ -1,50 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- RSpec.describe "assets", type: :integration do
4
- describe "helpers" do
5
- it "renders assets tags" do
6
- with_project do
7
- generate "action web home#index --url=/"
8
-
9
- rewrite "apps/web/templates/app.html.erb", <<~EOF
10
- <!DOCTYPE html>
11
- <html>
12
- <head>
13
- <title>Web</title>
14
- <%= favicon %>
15
- <%= stylesheet 'app' %>
16
- </head>
17
- <body>
18
- <%= yield %>
19
- <%= javascript 'app' %>
20
- </body>
21
- </html>
22
- EOF
23
-
24
- rewrite "apps/web/templates/home/index.html.erb", <<~EOF
25
- <%= image('app.jpg') %>
26
- <%= video('movie.mp4') %>
27
- <%=
28
- video do
29
- text "Your browser does not support the video tag"
30
- source src: view.asset_path('movie.mp4'), type: 'video/mp4'
31
- source src: view.asset_path('movie.ogg'), type: 'video/ogg'
32
- end
33
- %>
34
- EOF
35
-
36
- server do
37
- visit "/"
38
-
39
- expect(page.body).to include(%(<link href="/assets/favicon.ico" rel="shortcut icon" type="image/x-icon">))
40
- expect(page.body).to include(%(<link href="/assets/app.css" type="text/css" rel="stylesheet">))
41
- expect(page.body).to include(%(<script src="/assets/app.js" type="text/javascript"></script>))
42
-
43
- expect(page.body).to include(%(<img src="/assets/app.jpg" alt="App">))
44
- expect(page.body).to include(%(<video src="/assets/movie.mp4"></video>))
45
- expect(page.body).to include(%(<video>\nYour browser does not support the video tag\n<source src="/assets/movie.mp4" type="video/mp4">\n<source src="/assets/movie.ogg" type="video/ogg">\n</video>))
46
- end
47
- end
48
- end
49
- end
50
- end
@@ -1,70 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- RSpec.describe "assets", type: :integration do
4
- describe "serve" do
5
- it "compiles and serves assets in development mode" do
6
- project = "bookshelf_serve_assets"
7
-
8
- with_project(project, gems: ['sassc']) do
9
- generate "action web home#index --url=/"
10
-
11
- write "apps/web/assets/javascripts/app.css.sass", <<~EOF
12
- $font-family: Helvetica, sans-serif
13
-
14
- body
15
- font: 100% $font-family
16
- EOF
17
- rewrite "apps/web/templates/app.html.erb", <<~EOF
18
- <!DOCTYPE html>
19
- <html>
20
- <head>
21
- <title>Web</title>
22
- <%= favicon %>
23
- <%= stylesheet 'app' %>
24
- </head>
25
- <body>
26
- <%= yield %>
27
- </body>
28
- </html>
29
- EOF
30
-
31
- server do
32
- visit "/"
33
- expect(page.body).to include(%(<link href="/assets/app.css" type="text/css" rel="stylesheet">))
34
-
35
- visit "/assets/app.css"
36
- expect(page.body).to include(%(body {\n font: 100% Helvetica, sans-serif; }\n))
37
- end
38
- end
39
- end
40
-
41
- it "serve assets with prefixes" do
42
- with_project do
43
- generate "action web home#index --url=/"
44
-
45
- replace(
46
- "apps/web/app.rb",
47
- "# Specify sources for assets",
48
- "prefix '/library/assets'\n# Specify sources for assets"
49
- )
50
-
51
- replace(
52
- "apps/web/config/routes.rb",
53
- "/",
54
- "namespace :library { get '/', to: 'home#index' }"
55
- )
56
-
57
- write "apps/web/assets/javascripts/app.js", <<~EOF
58
- console.log('test');
59
- EOF
60
-
61
- hanami "assets precompile"
62
-
63
- server do
64
- visit "/library/assets/app.js"
65
- expect(page).to have_content("console.log('test');")
66
- end
67
- end
68
- end
69
- end
70
- end
@@ -1,54 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require "json"
4
-
5
- RSpec.describe "assets", type: :integration do
6
- describe "subresource integrity" do
7
- it "precompiles assets with checksums calculated with given algorithms" do
8
- with_project do
9
- generate "action web home#index --url=/"
10
-
11
- write "apps/web/assets/javascripts/app.css", <<~EOF
12
- body { font: Helvetica; }
13
- EOF
14
- rewrite "apps/web/templates/app.html.erb", <<~EOF
15
- <!DOCTYPE html>
16
- <html>
17
- <head>
18
- <title>Web</title>
19
- <%= favicon %>
20
- <%= stylesheet 'app' %>
21
- </head>
22
- <body>
23
- <%= yield %>
24
- </body>
25
- </html>
26
- EOF
27
-
28
- replace "apps/web/app.rb", "subresource_integrity :sha256", "subresource_integrity :sha256, :sha512"
29
-
30
- #
31
- # Precompile
32
- #
33
- RSpec::Support::Env["HANAMI_ENV"] = "production"
34
- # FIXME: database connection shouldn't be required for `assets precompile`
35
- RSpec::Support::Env["DATABASE_URL"] = "sqlite://#{Pathname.new('db').join('bookshelf.sqlite')}"
36
- RSpec::Support::Env["SMTP_HOST"] = "localhost"
37
- RSpec::Support::Env["SMTP_PORT"] = "25"
38
-
39
- hanami "assets precompile"
40
-
41
- manifest = File.read("public/assets.json")
42
- expect(JSON.parse(manifest)).to be_kind_of(Hash) # assert it's a well-formed JSON
43
-
44
- expect(manifest).to include(%("/assets/app.css":{"target":"/assets/app-068e7d97b3671a14824bc20437ac5d06.css","sri":["sha256-cHgODQTP2nNk9ER+ViDGp+lC+ddHRmuLgJk05glJ4+w=","sha512-TDyxo1Ow7UjBib6ykALJh7J1OHEcE0yX4X21s1714ZBAhwdOz7k9t8+QQDAwWAmeH97bNaZGY7oTfVrwyTQ3cw=="]}))
45
- expect(manifest).to include(%("/assets/favicon.ico":{"target":"/assets/favicon-b0979f93c7f7246ac70949a80f7cbdfd.ico","sri":["sha256-PLEDhpDsTBpxl1KtXjzBjg+PUG67zpf05B1z2db4iJU=","sha512-9NvaW7aVAywbLPPi3fw5s4wtWwd37i8VpzgfEo9uCOyr/mDT2dbYJtGNjfTJa4R8TOw69yHr4NhazPQsLt1WHw=="]}))
46
-
47
- server do
48
- visit "/"
49
- expect(page.body).to include(%(<link href="/assets/app-068e7d97b3671a14824bc20437ac5d06.css" type="text/css" rel="stylesheet" integrity="sha256-cHgODQTP2nNk9ER+ViDGp+lC+ddHRmuLgJk05glJ4+w= sha512-TDyxo1Ow7UjBib6ykALJh7J1OHEcE0yX4X21s1714ZBAhwdOz7k9t8+QQDAwWAmeH97bNaZGY7oTfVrwyTQ3cw==" crossorigin="anonymous">))
50
- end
51
- end
52
- end
53
- end
54
- end
@@ -1,50 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- RSpec.describe "body parsers", type: :integration do
4
- it "parses JSON payload for non-GET requests" do
5
- with_project do
6
- generate_action
7
- enable_json_body_parser
8
-
9
- server do
10
- post "/books", %({"book": {"title": "CLI apps with Ruby"}}), "CONTENT_TYPE" => "app/json", "HTTP_ACCEPT" => "app/json"
11
- expect(last_response.body).to eq(%({"book":{"title":"CLI apps with Ruby"}}))
12
- end
13
- end
14
- end
15
-
16
- it "doesn't eval untrusted JSON" do
17
- with_project do
18
- generate_action
19
- enable_json_body_parser
20
-
21
- server do
22
- post "/books", %({"json_class": "Foo"}), "CONTENT_TYPE" => "app/json", "HTTP_ACCEPT" => "app/json"
23
- expect(last_response.body).to eq(%({"json_class":"Foo"}))
24
- end
25
- end
26
- end
27
-
28
- private
29
-
30
- def generate_action
31
- generate "action web books#create --url=/books --method=POST"
32
-
33
- rewrite "apps/web/controllers/books/create.rb", <<~EOF
34
- require 'hanami/utils/json'
35
- module Web::Controllers::Books
36
- class Create
37
- include Web::Action
38
-
39
- def call(params)
40
- self.body = Hanami::Utils::Json.generate(params.to_hash)
41
- end
42
- end
43
- end
44
- EOF
45
- end
46
-
47
- def enable_json_body_parser
48
- inject_line_after "apps/web/app.rb", "configure do", "body_parsers :json"
49
- end
50
- end
@@ -1,147 +0,0 @@
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