hanami 2.0.3 → 2.1.0.beta2
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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +37 -2
- data/LICENSE.md +1 -1
- data/README.md +26 -10
- data/hanami.gemspec +2 -2
- data/lib/hanami/app.rb +5 -0
- data/lib/hanami/config/actions.rb +4 -11
- data/lib/hanami/config/assets.rb +84 -0
- data/lib/hanami/config/null_config.rb +3 -0
- data/lib/hanami/config/views.rb +0 -4
- data/lib/hanami/config.rb +71 -5
- data/lib/hanami/extensions/action/slice_configured_action.rb +15 -7
- data/lib/hanami/extensions/action.rb +8 -6
- data/lib/hanami/extensions/router/errors.rb +58 -0
- data/lib/hanami/extensions/view/context.rb +129 -60
- data/lib/hanami/extensions/view/part.rb +26 -0
- data/lib/hanami/extensions/view/scope.rb +26 -0
- data/lib/hanami/extensions/view/slice_configured_context.rb +0 -2
- data/lib/hanami/extensions/view/slice_configured_helpers.rb +44 -0
- data/lib/hanami/extensions/view/slice_configured_view.rb +106 -21
- data/lib/hanami/extensions/view/standard_helpers.rb +18 -0
- data/lib/hanami/extensions.rb +10 -3
- data/lib/hanami/helpers/assets_helper.rb +752 -0
- data/lib/hanami/helpers/form_helper/form_builder.rb +1391 -0
- data/lib/hanami/helpers/form_helper/values.rb +75 -0
- data/lib/hanami/helpers/form_helper.rb +213 -0
- data/lib/hanami/middleware/assets.rb +21 -0
- data/lib/hanami/middleware/public_errors_app.rb +75 -0
- data/lib/hanami/middleware/render_errors.rb +90 -0
- data/lib/hanami/providers/assets.rb +44 -0
- data/lib/hanami/rake_tasks.rb +19 -18
- data/lib/hanami/settings.rb +1 -1
- data/lib/hanami/slice.rb +48 -2
- data/lib/hanami/slice_configurable.rb +3 -2
- data/lib/hanami/version.rb +1 -1
- data/lib/hanami/web/rack_logger.rb +1 -1
- data/lib/hanami.rb +3 -3
- data/spec/integration/action/view_rendering/view_context_spec.rb +221 -0
- data/spec/integration/action/view_rendering_spec.rb +0 -18
- data/spec/integration/assets/assets_spec.rb +101 -0
- data/spec/integration/assets/serve_static_assets_spec.rb +152 -0
- data/spec/integration/logging/exception_logging_spec.rb +115 -0
- data/spec/integration/logging/notifications_spec.rb +68 -0
- data/spec/integration/logging/request_logging_spec.rb +128 -0
- data/spec/integration/rack_app/middleware_spec.rb +22 -22
- data/spec/integration/rack_app/rack_app_spec.rb +3 -220
- data/spec/integration/rake_tasks_spec.rb +107 -0
- data/spec/integration/view/config/default_context_spec.rb +149 -0
- data/spec/integration/view/{inflector_spec.rb → config/inflector_spec.rb} +1 -1
- data/spec/integration/view/config/part_class_spec.rb +147 -0
- data/spec/integration/view/config/part_namespace_spec.rb +103 -0
- data/spec/integration/view/config/paths_spec.rb +119 -0
- data/spec/integration/view/config/scope_class_spec.rb +147 -0
- data/spec/integration/view/config/scope_namespace_spec.rb +103 -0
- data/spec/integration/view/config/template_spec.rb +38 -0
- data/spec/integration/view/context/assets_spec.rb +3 -9
- data/spec/integration/view/context/request_spec.rb +3 -7
- data/spec/integration/view/helpers/form_helper_spec.rb +174 -0
- data/spec/integration/view/helpers/part_helpers_spec.rb +124 -0
- data/spec/integration/view/helpers/scope_helpers_spec.rb +84 -0
- data/spec/integration/view/helpers/user_defined_helpers/part_helpers_spec.rb +162 -0
- data/spec/integration/view/helpers/user_defined_helpers/scope_helpers_spec.rb +119 -0
- data/spec/integration/view/slice_configuration_spec.rb +9 -9
- data/spec/integration/web/render_detailed_errors_spec.rb +107 -0
- data/spec/integration/web/render_errors_spec.rb +242 -0
- data/spec/spec_helper.rb +1 -1
- data/spec/support/app_integration.rb +46 -2
- data/spec/support/matchers.rb +32 -0
- data/spec/unit/hanami/config/actions/content_security_policy_spec.rb +24 -36
- data/spec/unit/hanami/config/actions/csrf_protection_spec.rb +4 -3
- data/spec/unit/hanami/config/actions/default_values_spec.rb +3 -6
- data/spec/unit/hanami/config/render_detailed_errors_spec.rb +25 -0
- data/spec/unit/hanami/config/render_errors_spec.rb +25 -0
- data/spec/unit/hanami/config/views_spec.rb +0 -18
- data/spec/unit/hanami/env_spec.rb +11 -25
- data/spec/unit/hanami/extensions/view/context_spec.rb +59 -0
- data/spec/unit/hanami/helpers/assets_helper/asset_url_spec.rb +109 -0
- data/spec/unit/hanami/helpers/assets_helper/audio_tag_spec.rb +132 -0
- data/spec/unit/hanami/helpers/assets_helper/favicon_link_tag_spec.rb +91 -0
- data/spec/unit/hanami/helpers/assets_helper/image_tag_spec.rb +92 -0
- data/spec/unit/hanami/helpers/assets_helper/javascript_tag_spec.rb +143 -0
- data/spec/unit/hanami/helpers/assets_helper/stylesheet_link_tag_spec.rb +126 -0
- data/spec/unit/hanami/helpers/assets_helper/video_tag_spec.rb +132 -0
- data/spec/unit/hanami/helpers/form_helper_spec.rb +2826 -0
- data/spec/unit/hanami/router/errors/not_allowed_error_spec.rb +27 -0
- data/spec/unit/hanami/router/errors/not_found_error_spec.rb +22 -0
- data/spec/unit/hanami/slice_configurable_spec.rb +18 -0
- data/spec/unit/hanami/version_spec.rb +1 -1
- data/spec/unit/hanami/web/rack_logger_spec.rb +1 -1
- metadata +95 -35
- data/lib/hanami/assets/app_config.rb +0 -61
- data/lib/hanami/assets/config.rb +0 -53
- data/spec/integration/action/view_integration_spec.rb +0 -165
- data/spec/integration/view/part_namespace_spec.rb +0 -96
- data/spec/integration/view/path_spec.rb +0 -56
- data/spec/integration/view/template_spec.rb +0 -68
- data/spec/isolation/hanami/application/already_configured_spec.rb +0 -19
- data/spec/isolation/hanami/application/inherit_anonymous_class_spec.rb +0 -10
- data/spec/isolation/hanami/application/inherit_concrete_class_spec.rb +0 -14
- data/spec/isolation/hanami/application/not_configured_spec.rb +0 -9
- data/spec/isolation/hanami/application/routes/configured_spec.rb +0 -44
- data/spec/isolation/hanami/application/routes/not_configured_spec.rb +0 -16
- data/spec/isolation/hanami/boot/success_spec.rb +0 -50
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "rack/test"
|
|
4
|
+
|
|
5
|
+
RSpec.describe "Logging / Notifications", :app_integration do
|
|
6
|
+
include Rack::Test::Methods
|
|
7
|
+
|
|
8
|
+
let(:app) { Hanami.app }
|
|
9
|
+
|
|
10
|
+
specify "Request logging continues even when notifications bus has already been used" do
|
|
11
|
+
dir = Dir.mktmpdir
|
|
12
|
+
|
|
13
|
+
with_tmp_directory(dir) do
|
|
14
|
+
write "config/app.rb", <<~RUBY
|
|
15
|
+
require "hanami"
|
|
16
|
+
|
|
17
|
+
module TestApp
|
|
18
|
+
class App < Hanami::App
|
|
19
|
+
config.actions.format :json
|
|
20
|
+
config.logger.options = {colorize: true}
|
|
21
|
+
config.logger.stream = config.root.join("test.log")
|
|
22
|
+
end
|
|
23
|
+
end
|
|
24
|
+
RUBY
|
|
25
|
+
|
|
26
|
+
write "config/routes.rb", <<~RUBY
|
|
27
|
+
module TestApp
|
|
28
|
+
class Routes < Hanami::Routes
|
|
29
|
+
post "/users", to: "users.create"
|
|
30
|
+
end
|
|
31
|
+
end
|
|
32
|
+
RUBY
|
|
33
|
+
|
|
34
|
+
write "app/actions/users/create.rb", <<~RUBY
|
|
35
|
+
module TestApp
|
|
36
|
+
module Actions
|
|
37
|
+
module Users
|
|
38
|
+
class Create < Hanami::Action
|
|
39
|
+
def handle(req, resp)
|
|
40
|
+
resp.body = req.params.to_h.keys
|
|
41
|
+
end
|
|
42
|
+
end
|
|
43
|
+
end
|
|
44
|
+
end
|
|
45
|
+
end
|
|
46
|
+
RUBY
|
|
47
|
+
|
|
48
|
+
require "hanami/prepare"
|
|
49
|
+
|
|
50
|
+
# Simulate any component interacting with the notifications bus such that it creates its
|
|
51
|
+
# internal bus with a duplicate copy of all currently registered events. This means that the
|
|
52
|
+
# class-level Dry::Monitor::Notification events implicitly registered by the
|
|
53
|
+
# Dry::Monitor::Rack::Middleware activated via the rack provider are ignored, unless our
|
|
54
|
+
# provider explicitly re-registers them on _instance_ of the notifications bus.
|
|
55
|
+
#
|
|
56
|
+
# See Hanami::Providers::Rack for more detail.
|
|
57
|
+
Hanami.app["notifications"].instrument(:sql)
|
|
58
|
+
|
|
59
|
+
logs = -> { Pathname(dir).join("test.log").realpath.read }
|
|
60
|
+
|
|
61
|
+
post "/users", JSON.generate(name: "jane", password: "secret"), {"CONTENT_TYPE" => "application/json"}
|
|
62
|
+
expect(logs.()).to match %r{POST 200 \d+(µs|ms) 127.0.0.1 /}
|
|
63
|
+
end
|
|
64
|
+
end
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
|
|
68
|
+
|
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "json"
|
|
4
|
+
require "rack/test"
|
|
5
|
+
require "stringio"
|
|
6
|
+
|
|
7
|
+
RSpec.describe "Logging / Request logging", :app_integration do
|
|
8
|
+
include Rack::Test::Methods
|
|
9
|
+
|
|
10
|
+
let(:app) { Hanami.app }
|
|
11
|
+
|
|
12
|
+
let(:logger_stream) { StringIO.new }
|
|
13
|
+
|
|
14
|
+
def configure_logger
|
|
15
|
+
Hanami.app.config.logger.stream = logger_stream
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
def logs
|
|
19
|
+
@logs ||= (logger_stream.rewind and logger_stream.read)
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
before do
|
|
23
|
+
with_directory(make_tmp_directory) do
|
|
24
|
+
write "config/app.rb", <<~RUBY
|
|
25
|
+
module TestApp
|
|
26
|
+
class App < Hanami::App
|
|
27
|
+
end
|
|
28
|
+
end
|
|
29
|
+
RUBY
|
|
30
|
+
|
|
31
|
+
require "hanami/setup"
|
|
32
|
+
configure_logger
|
|
33
|
+
|
|
34
|
+
before_prepare if respond_to?(:before_prepare)
|
|
35
|
+
require "hanami/prepare"
|
|
36
|
+
end
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
describe "app router" do
|
|
40
|
+
def before_prepare
|
|
41
|
+
write "config/routes.rb", <<~RUBY
|
|
42
|
+
module TestApp
|
|
43
|
+
class Routes < Hanami::Routes
|
|
44
|
+
root to: ->(env) { [200, {}, ["OK"]] }
|
|
45
|
+
end
|
|
46
|
+
end
|
|
47
|
+
RUBY
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
it "logs the requests" do
|
|
51
|
+
get "/"
|
|
52
|
+
|
|
53
|
+
expect(logs.split("\n").length).to eq 1
|
|
54
|
+
expect(logs).to match %r{GET 200 \d+(µs|ms) 127.0.0.1 /}
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
context "production env" do
|
|
58
|
+
around do |example|
|
|
59
|
+
@prev_hanami_env = ENV["HANAMI_ENV"]
|
|
60
|
+
ENV["HANAMI_ENV"] = "production"
|
|
61
|
+
example.run
|
|
62
|
+
ensure
|
|
63
|
+
ENV["HANAMI_ENV"] = @prev_hanami_env
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
it "logs the requests as JSON" do
|
|
67
|
+
get "/"
|
|
68
|
+
|
|
69
|
+
expect(logs.split("\n").length).to eq 1
|
|
70
|
+
|
|
71
|
+
json = JSON.parse(logs, symbolize_names: true)
|
|
72
|
+
expect(json).to include(
|
|
73
|
+
verb: "GET",
|
|
74
|
+
path: "/",
|
|
75
|
+
ip: "127.0.0.1",
|
|
76
|
+
elapsed: Integer,
|
|
77
|
+
elapsed_unit: a_string_matching(/(µs|ms)/),
|
|
78
|
+
)
|
|
79
|
+
end
|
|
80
|
+
end
|
|
81
|
+
end
|
|
82
|
+
|
|
83
|
+
describe "slice router" do
|
|
84
|
+
let(:app) { Main::Slice.rack_app }
|
|
85
|
+
|
|
86
|
+
def before_prepare
|
|
87
|
+
write "slices/main/config/routes.rb", <<~RUBY
|
|
88
|
+
module Main
|
|
89
|
+
class Routes < Hanami::Routes
|
|
90
|
+
root to: ->(env) { [200, {}, ["OK"]] }
|
|
91
|
+
end
|
|
92
|
+
end
|
|
93
|
+
RUBY
|
|
94
|
+
end
|
|
95
|
+
|
|
96
|
+
it "logs the requests" do
|
|
97
|
+
get "/"
|
|
98
|
+
|
|
99
|
+
expect(logs.split("\n").length).to eq 1
|
|
100
|
+
expect(logs).to match %r{GET 200 \d+(µs|ms) 127.0.0.1 /}
|
|
101
|
+
end
|
|
102
|
+
|
|
103
|
+
context "production env" do
|
|
104
|
+
around do |example|
|
|
105
|
+
@prev_hanami_env = ENV["HANAMI_ENV"]
|
|
106
|
+
ENV["HANAMI_ENV"] = "production"
|
|
107
|
+
example.run
|
|
108
|
+
ensure
|
|
109
|
+
ENV["HANAMI_ENV"] = @prev_hanami_env
|
|
110
|
+
end
|
|
111
|
+
|
|
112
|
+
it "logs the requests as JSON" do
|
|
113
|
+
get "/"
|
|
114
|
+
|
|
115
|
+
expect(logs.split("\n").length).to eq 1
|
|
116
|
+
|
|
117
|
+
json = JSON.parse(logs, symbolize_names: true)
|
|
118
|
+
expect(json).to include(
|
|
119
|
+
verb: "GET",
|
|
120
|
+
path: "/",
|
|
121
|
+
ip: "127.0.0.1",
|
|
122
|
+
elapsed: Integer,
|
|
123
|
+
elapsed_unit: a_string_matching(/(µs|ms)/),
|
|
124
|
+
)
|
|
125
|
+
end
|
|
126
|
+
end
|
|
127
|
+
end
|
|
128
|
+
end
|
|
@@ -244,6 +244,7 @@ RSpec.describe "Hanami web app", :app_integration do
|
|
|
244
244
|
module TestApp
|
|
245
245
|
class App < Hanami::App
|
|
246
246
|
config.logger.stream = File.new("/dev/null", "w")
|
|
247
|
+
config.render_errors = true
|
|
247
248
|
end
|
|
248
249
|
end
|
|
249
250
|
RUBY
|
|
@@ -317,7 +318,6 @@ RSpec.describe "Hanami web app", :app_integration do
|
|
|
317
318
|
get "/foo"
|
|
318
319
|
|
|
319
320
|
expect(last_response.status).to eq 404
|
|
320
|
-
expect(last_response.body).to eq "Not Found"
|
|
321
321
|
expect(last_response.headers).to_not have_key("X-Auth-User-ID")
|
|
322
322
|
end
|
|
323
323
|
|
|
@@ -330,12 +330,11 @@ RSpec.describe "Hanami web app", :app_integration do
|
|
|
330
330
|
expect(last_response.headers).to have_key("X-Auth-User-ID")
|
|
331
331
|
end
|
|
332
332
|
|
|
333
|
-
it "uses Rack middleware for not found paths" do
|
|
333
|
+
it "does not uses the Rack middleware for not found paths" do
|
|
334
334
|
get "/admin/users"
|
|
335
335
|
|
|
336
|
-
expect(last_response.status).to
|
|
337
|
-
expect(last_response.
|
|
338
|
-
expect(last_response.headers).to have_key("X-Auth-User-ID")
|
|
336
|
+
expect(last_response.status).to eq 404
|
|
337
|
+
expect(last_response.headers).not_to have_key("X-Auth-User-ID")
|
|
339
338
|
end
|
|
340
339
|
end
|
|
341
340
|
end
|
|
@@ -350,6 +349,7 @@ RSpec.describe "Hanami web app", :app_integration do
|
|
|
350
349
|
module TestApp
|
|
351
350
|
class App < Hanami::App
|
|
352
351
|
config.logger.stream = File.new("/dev/null", "w")
|
|
352
|
+
config.render_errors = true
|
|
353
353
|
end
|
|
354
354
|
end
|
|
355
355
|
RUBY
|
|
@@ -597,15 +597,15 @@ RSpec.describe "Hanami web app", :app_integration do
|
|
|
597
597
|
expect(last_response.headers).to_not have_key("X-API-Version")
|
|
598
598
|
end
|
|
599
599
|
|
|
600
|
-
it "
|
|
601
|
-
get "/
|
|
600
|
+
it "does not use Rack middleware for other paths" do
|
|
601
|
+
get "/__not_found__"
|
|
602
602
|
|
|
603
|
-
expect(last_response.status).to
|
|
604
|
-
expect(last_response.headers
|
|
605
|
-
expect(last_response.headers).
|
|
606
|
-
expect(last_response.headers).
|
|
607
|
-
expect(last_response.headers).
|
|
608
|
-
expect(last_response.headers).
|
|
603
|
+
expect(last_response.status).to eq 404
|
|
604
|
+
expect(last_response.headers).not_to have_key("X-Identifier-Root")
|
|
605
|
+
expect(last_response.headers).not_to have_key("X-Elapsed")
|
|
606
|
+
expect(last_response.headers).not_to have_key("X-Auth-User-ID")
|
|
607
|
+
expect(last_response.headers).not_to have_key("X-API-Rate-Limit-Quota")
|
|
608
|
+
expect(last_response.headers).not_to have_key("X-API-Version")
|
|
609
609
|
end
|
|
610
610
|
|
|
611
611
|
context "scoped" do
|
|
@@ -621,15 +621,15 @@ RSpec.describe "Hanami web app", :app_integration do
|
|
|
621
621
|
end
|
|
622
622
|
|
|
623
623
|
it "uses Rack middleware for other paths" do
|
|
624
|
-
get "/admin/
|
|
625
|
-
|
|
626
|
-
expect(last_response.status).to
|
|
627
|
-
expect(last_response.headers
|
|
628
|
-
expect(last_response.headers).
|
|
629
|
-
expect(last_response.headers).
|
|
630
|
-
expect(last_response.headers).
|
|
631
|
-
expect(last_response.headers).
|
|
632
|
-
expect(last_response.headers).
|
|
624
|
+
get "/admin/__not_found__"
|
|
625
|
+
|
|
626
|
+
expect(last_response.status).to eq 404
|
|
627
|
+
expect(last_response.headers).not_to have_key("X-Identifier-Admin")
|
|
628
|
+
expect(last_response.headers).not_to have_key("X-Elapsed")
|
|
629
|
+
expect(last_response.headers).not_to have_key("X-Elapsed")
|
|
630
|
+
expect(last_response.headers).not_to have_key("X-Auth-User-ID")
|
|
631
|
+
expect(last_response.headers).not_to have_key("X-API-Rate-Limit-Quota")
|
|
632
|
+
expect(last_response.headers).not_to have_key("X-API-Version")
|
|
633
633
|
end
|
|
634
634
|
|
|
635
635
|
# See: https://github.com/hanami/api/issues/8
|
|
@@ -33,226 +33,6 @@ RSpec.describe "Hanami web app", :app_integration do
|
|
|
33
33
|
end
|
|
34
34
|
end
|
|
35
35
|
|
|
36
|
-
specify "Has rack monitor preconfigured with default request logging" do
|
|
37
|
-
dir = Dir.mktmpdir
|
|
38
|
-
|
|
39
|
-
with_tmp_directory(dir) do
|
|
40
|
-
write "config/app.rb", <<~RUBY
|
|
41
|
-
require "hanami"
|
|
42
|
-
|
|
43
|
-
module TestApp
|
|
44
|
-
class App < Hanami::App
|
|
45
|
-
config.actions.format :json
|
|
46
|
-
config.logger.options = {colorize: true}
|
|
47
|
-
config.logger.stream = config.root.join("test.log")
|
|
48
|
-
end
|
|
49
|
-
end
|
|
50
|
-
RUBY
|
|
51
|
-
|
|
52
|
-
write "app/actions/users/index.rb", <<~RUBY
|
|
53
|
-
module TestApp
|
|
54
|
-
module Actions
|
|
55
|
-
module Users
|
|
56
|
-
class Index < Hanami::Action
|
|
57
|
-
def handle(req, _resp)
|
|
58
|
-
raise StandardError, "OH NOEZ"
|
|
59
|
-
end
|
|
60
|
-
end
|
|
61
|
-
end
|
|
62
|
-
end
|
|
63
|
-
end
|
|
64
|
-
RUBY
|
|
65
|
-
|
|
66
|
-
write "app/actions/users/create.rb", <<~RUBY
|
|
67
|
-
module TestApp
|
|
68
|
-
module Actions
|
|
69
|
-
module Users
|
|
70
|
-
class Create < Hanami::Action
|
|
71
|
-
def handle(req, resp)
|
|
72
|
-
resp.body = req.params.to_h.keys
|
|
73
|
-
end
|
|
74
|
-
end
|
|
75
|
-
end
|
|
76
|
-
end
|
|
77
|
-
end
|
|
78
|
-
RUBY
|
|
79
|
-
|
|
80
|
-
write "config/routes.rb", <<~RUBY
|
|
81
|
-
module TestApp
|
|
82
|
-
class Routes < Hanami::Routes
|
|
83
|
-
root to: ->(env) { [200, {}, ["OK"]] }
|
|
84
|
-
get "/users", to: "users.index"
|
|
85
|
-
post "/users", to: "users.create"
|
|
86
|
-
end
|
|
87
|
-
end
|
|
88
|
-
RUBY
|
|
89
|
-
|
|
90
|
-
require "hanami/prepare"
|
|
91
|
-
|
|
92
|
-
expect(Hanami.app["rack.monitor"]).to be_instance_of(Dry::Monitor::Rack::Middleware)
|
|
93
|
-
|
|
94
|
-
get "/"
|
|
95
|
-
|
|
96
|
-
logs = -> { Pathname(dir).join("test.log").realpath.read }
|
|
97
|
-
|
|
98
|
-
expect(logs.()).to match %r{GET 200 \d+(µs|ms) 127.0.0.1 /}
|
|
99
|
-
|
|
100
|
-
post "/users", JSON.generate(name: "jane", password: "secret"), {"CONTENT_TYPE" => "application/json"}
|
|
101
|
-
|
|
102
|
-
expect(logs.()).to match %r{POST 200 \d+(µs|ms) 127.0.0.1 /}
|
|
103
|
-
|
|
104
|
-
begin
|
|
105
|
-
get "/users"
|
|
106
|
-
rescue => e # rubocop:disable Style/RescueStandardError
|
|
107
|
-
raise unless e.to_s == "OH NOEZ"
|
|
108
|
-
end
|
|
109
|
-
|
|
110
|
-
err_log = logs.()
|
|
111
|
-
|
|
112
|
-
expect(err_log).to include("OH NOEZ")
|
|
113
|
-
expect(err_log).to include("app/actions/users/index.rb:6:in `handle'")
|
|
114
|
-
end
|
|
115
|
-
end
|
|
116
|
-
|
|
117
|
-
specify "Logging via the rack monitor even when notifications bus has already been used" do
|
|
118
|
-
dir = Dir.mktmpdir
|
|
119
|
-
|
|
120
|
-
with_tmp_directory(dir) do
|
|
121
|
-
write "config/app.rb", <<~RUBY
|
|
122
|
-
require "hanami"
|
|
123
|
-
|
|
124
|
-
module TestApp
|
|
125
|
-
class App < Hanami::App
|
|
126
|
-
config.actions.format :json
|
|
127
|
-
config.logger.options = {colorize: true}
|
|
128
|
-
config.logger.stream = config.root.join("test.log")
|
|
129
|
-
end
|
|
130
|
-
end
|
|
131
|
-
RUBY
|
|
132
|
-
|
|
133
|
-
write "config/routes.rb", <<~RUBY
|
|
134
|
-
module TestApp
|
|
135
|
-
class Routes < Hanami::Routes
|
|
136
|
-
post "/users", to: "users.create"
|
|
137
|
-
end
|
|
138
|
-
end
|
|
139
|
-
RUBY
|
|
140
|
-
|
|
141
|
-
write "app/actions/users/create.rb", <<~RUBY
|
|
142
|
-
module TestApp
|
|
143
|
-
module Actions
|
|
144
|
-
module Users
|
|
145
|
-
class Create < Hanami::Action
|
|
146
|
-
def handle(req, resp)
|
|
147
|
-
resp.body = req.params.to_h.keys
|
|
148
|
-
end
|
|
149
|
-
end
|
|
150
|
-
end
|
|
151
|
-
end
|
|
152
|
-
end
|
|
153
|
-
RUBY
|
|
154
|
-
|
|
155
|
-
require "hanami/prepare"
|
|
156
|
-
|
|
157
|
-
# Simulate any component interacting with the notifications bus such that it creates its
|
|
158
|
-
# internal bus with a duplicate copy of all currently registered events. This means that the
|
|
159
|
-
# class-level Dry::Monitor::Notification events implicitly registered by the
|
|
160
|
-
# Dry::Monitor::Rack::Middleware activated via the rack provider are ignored, unless our
|
|
161
|
-
# provider explicitly re-registers them on _instance_ of the notifications bus.
|
|
162
|
-
#
|
|
163
|
-
# See Hanami::Providers::Rack for more detail.
|
|
164
|
-
Hanami.app["notifications"].instrument(:sql)
|
|
165
|
-
|
|
166
|
-
logs = -> { Pathname(dir).join("test.log").realpath.read }
|
|
167
|
-
|
|
168
|
-
post "/users", JSON.generate(name: "jane", password: "secret"), {"CONTENT_TYPE" => "application/json"}
|
|
169
|
-
expect(logs.()).to match %r{POST 200 \d+(µs|ms) 127.0.0.1 /}
|
|
170
|
-
end
|
|
171
|
-
end
|
|
172
|
-
|
|
173
|
-
describe "Request logging when using slice router" do
|
|
174
|
-
let(:app) { Main::Slice.rack_app }
|
|
175
|
-
|
|
176
|
-
specify "Has rack monitor preconfigured with default request logging (when used via a slice)" do
|
|
177
|
-
dir = Dir.mktmpdir
|
|
178
|
-
|
|
179
|
-
with_tmp_directory(dir) do
|
|
180
|
-
write "config/app.rb", <<~RUBY
|
|
181
|
-
require "hanami"
|
|
182
|
-
|
|
183
|
-
module TestApp
|
|
184
|
-
class App < Hanami::App
|
|
185
|
-
config.logger.stream = config.root.join("test.log")
|
|
186
|
-
end
|
|
187
|
-
end
|
|
188
|
-
RUBY
|
|
189
|
-
|
|
190
|
-
write "slices/main/config/routes.rb", <<~RUBY
|
|
191
|
-
module Main
|
|
192
|
-
class Routes < Hanami::Routes
|
|
193
|
-
root to: ->(env) { [200, {}, ["OK"]] }
|
|
194
|
-
end
|
|
195
|
-
end
|
|
196
|
-
RUBY
|
|
197
|
-
|
|
198
|
-
require "hanami/prepare"
|
|
199
|
-
|
|
200
|
-
get "/"
|
|
201
|
-
|
|
202
|
-
logs = -> { Pathname(dir).join("test.log").realpath.read }
|
|
203
|
-
|
|
204
|
-
expect(logs.()).to match %r{GET 200 \d+(µs|ms) 127.0.0.1 /}
|
|
205
|
-
end
|
|
206
|
-
end
|
|
207
|
-
end
|
|
208
|
-
|
|
209
|
-
describe "Request logging on production" do
|
|
210
|
-
let(:app) { Main::Slice.rack_app }
|
|
211
|
-
|
|
212
|
-
around do |example|
|
|
213
|
-
ENV["HANAMI_ENV"] = "production"
|
|
214
|
-
example.run
|
|
215
|
-
ensure
|
|
216
|
-
ENV["HANAMI_ENV"] = "test"
|
|
217
|
-
end
|
|
218
|
-
|
|
219
|
-
specify "Has rack monitor preconfigured with default request logging (when used via a slice)" do
|
|
220
|
-
dir = Dir.mktmpdir
|
|
221
|
-
|
|
222
|
-
with_tmp_directory(dir) do
|
|
223
|
-
write "config/app.rb", <<~RUBY
|
|
224
|
-
require "hanami"
|
|
225
|
-
|
|
226
|
-
module TestApp
|
|
227
|
-
class App < Hanami::App
|
|
228
|
-
config.logger.stream = config.root.join("test.log")
|
|
229
|
-
end
|
|
230
|
-
end
|
|
231
|
-
RUBY
|
|
232
|
-
|
|
233
|
-
write "slices/main/config/routes.rb", <<~RUBY
|
|
234
|
-
module Main
|
|
235
|
-
class Routes < Hanami::Routes
|
|
236
|
-
root to: ->(env) { [200, {}, ["OK"]] }
|
|
237
|
-
end
|
|
238
|
-
end
|
|
239
|
-
RUBY
|
|
240
|
-
|
|
241
|
-
require "hanami/boot"
|
|
242
|
-
|
|
243
|
-
get "/"
|
|
244
|
-
|
|
245
|
-
logs = -> { Pathname(dir).join("test.log").realpath.read }
|
|
246
|
-
|
|
247
|
-
log_content = logs.()
|
|
248
|
-
|
|
249
|
-
expect(log_content).to match(%r["verb":"GET"])
|
|
250
|
-
expect(log_content).to match(%r["path":"/"])
|
|
251
|
-
expect(log_content).to match(%r[elapsed":\d+,"elapsed_unit":"µs"])
|
|
252
|
-
end
|
|
253
|
-
end
|
|
254
|
-
end
|
|
255
|
-
|
|
256
36
|
specify "Routing to actions based on their container identifiers" do
|
|
257
37
|
with_tmp_directory(Dir.mktmpdir) do
|
|
258
38
|
write "config/app.rb", <<~RUBY
|
|
@@ -569,6 +349,7 @@ RSpec.describe "Hanami web app", :app_integration do
|
|
|
569
349
|
|
|
570
350
|
module TestApp
|
|
571
351
|
class App < Hanami::App
|
|
352
|
+
config.render_detailed_errors = false
|
|
572
353
|
end
|
|
573
354
|
end
|
|
574
355
|
RUBY
|
|
@@ -600,6 +381,8 @@ RSpec.describe "Hanami web app", :app_integration do
|
|
|
600
381
|
|
|
601
382
|
module TestApp
|
|
602
383
|
class App < Hanami::App
|
|
384
|
+
config.render_detailed_errors = false
|
|
385
|
+
|
|
603
386
|
register_slice :admin
|
|
604
387
|
end
|
|
605
388
|
end
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "rake"
|
|
4
|
+
require "hanami/cli/bundler"
|
|
5
|
+
|
|
6
|
+
RSpec.describe "Rake tasks", :app_integration do
|
|
7
|
+
describe "assets:precompile" do
|
|
8
|
+
before do
|
|
9
|
+
allow(Hanami).to receive(:bundled?)
|
|
10
|
+
allow(Hanami).to receive(:bundled?).with("hanami-assets").and_return(hanami_assets_bundled)
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
context "when hanami-assets is bundled" do
|
|
14
|
+
let(:hanami_assets_bundled) { true }
|
|
15
|
+
|
|
16
|
+
xit "compiles assets" do
|
|
17
|
+
with_tmp_directory(Dir.mktmpdir) do
|
|
18
|
+
write "config/app.rb", <<~'RUBY'
|
|
19
|
+
require "hanami"
|
|
20
|
+
|
|
21
|
+
module TestApp
|
|
22
|
+
class App < Hanami::App
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
RUBY
|
|
26
|
+
|
|
27
|
+
write "Rakefile", <<~RUBY
|
|
28
|
+
# frozen_string_literal: true
|
|
29
|
+
|
|
30
|
+
require "hanami/rake_tasks"
|
|
31
|
+
RUBY
|
|
32
|
+
|
|
33
|
+
write "app/assets/js/app.js", <<~JS
|
|
34
|
+
console.log("Hello from index.js");
|
|
35
|
+
JS
|
|
36
|
+
|
|
37
|
+
before_prepare if respond_to?(:before_prepare)
|
|
38
|
+
require "hanami/prepare"
|
|
39
|
+
|
|
40
|
+
expect_any_instance_of(Hanami::CLI::Bundler).to receive(:hanami_exec).with("assets compile").and_return(true)
|
|
41
|
+
|
|
42
|
+
Rake::Task["assets:precompile"].invoke
|
|
43
|
+
end
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
it "doesn't list the task" do
|
|
47
|
+
with_tmp_directory(Dir.mktmpdir) do
|
|
48
|
+
write "config/app.rb", <<~'RUBY'
|
|
49
|
+
require "hanami"
|
|
50
|
+
|
|
51
|
+
module TestApp
|
|
52
|
+
class App < Hanami::App
|
|
53
|
+
end
|
|
54
|
+
end
|
|
55
|
+
RUBY
|
|
56
|
+
|
|
57
|
+
write "Rakefile", <<~RUBY
|
|
58
|
+
# frozen_string_literal: true
|
|
59
|
+
|
|
60
|
+
require "hanami/rake_tasks"
|
|
61
|
+
RUBY
|
|
62
|
+
|
|
63
|
+
before_prepare if respond_to?(:before_prepare)
|
|
64
|
+
require "hanami/prepare"
|
|
65
|
+
|
|
66
|
+
output = `bundle exec rake -T`
|
|
67
|
+
expect(output).to_not include("assets:precompile")
|
|
68
|
+
end
|
|
69
|
+
end
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
context "when hanami-assets is not bundled" do
|
|
73
|
+
let(:hanami_assets_bundled) { false }
|
|
74
|
+
|
|
75
|
+
it "raises error" do
|
|
76
|
+
with_tmp_directory(Dir.mktmpdir) do
|
|
77
|
+
write "config/app.rb", <<~'RUBY'
|
|
78
|
+
require "hanami"
|
|
79
|
+
|
|
80
|
+
module TestApp
|
|
81
|
+
class App < Hanami::App
|
|
82
|
+
end
|
|
83
|
+
end
|
|
84
|
+
RUBY
|
|
85
|
+
|
|
86
|
+
write "Rakefile", <<~RUBY
|
|
87
|
+
# frozen_string_literal: true
|
|
88
|
+
|
|
89
|
+
require "hanami/rake_tasks"
|
|
90
|
+
RUBY
|
|
91
|
+
|
|
92
|
+
write "app/assets/js/app.js", <<~JS
|
|
93
|
+
console.log("Hello from index.js");
|
|
94
|
+
JS
|
|
95
|
+
|
|
96
|
+
before_prepare if respond_to?(:before_prepare)
|
|
97
|
+
require "hanami/prepare"
|
|
98
|
+
|
|
99
|
+
expect { Rake::Task["assets:precompile"].invoke }.to raise_error do |exception|
|
|
100
|
+
expect(exception).to be_a(RuntimeError)
|
|
101
|
+
expect(exception.message).to match(/Don't know how to build task 'assets:precompile'/)
|
|
102
|
+
end
|
|
103
|
+
end
|
|
104
|
+
end
|
|
105
|
+
end
|
|
106
|
+
end
|
|
107
|
+
end
|