hanami 2.0.2 → 2.1.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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +31 -0
- data/LICENSE.md +1 -1
- data/README.md +25 -9
- data/hanami.gemspec +2 -2
- data/lib/hanami/config/actions.rb +0 -4
- data/lib/hanami/config/logger.rb +1 -1
- data/lib/hanami/config/views.rb +0 -4
- data/lib/hanami/config.rb +54 -0
- data/lib/hanami/extensions/action/slice_configured_action.rb +15 -7
- data/lib/hanami/extensions/action.rb +4 -4
- 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 +14 -0
- data/lib/hanami/extensions.rb +10 -3
- 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/public_errors_app.rb +75 -0
- data/lib/hanami/middleware/render_errors.rb +93 -0
- data/lib/hanami/slice.rb +28 -2
- data/lib/hanami/slice_configurable.rb +3 -2
- data/lib/hanami/version.rb +1 -1
- data/lib/hanami/web/rack_logger.rb +8 -20
- data/lib/hanami.rb +1 -1
- 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/rack_app/middleware_spec.rb +23 -23
- data/spec/integration/rack_app/rack_app_spec.rb +5 -1
- data/spec/integration/slices/slice_registrations_spec.rb +80 -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/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 +90 -0
- data/spec/integration/web/render_errors_spec.rb +240 -0
- data/spec/spec_helper.rb +1 -1
- data/spec/support/matchers.rb +32 -0
- data/spec/unit/hanami/config/actions/default_values_spec.rb +0 -4
- data/spec/unit/hanami/config/logger_spec.rb +9 -0
- 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/extensions/view/context_spec.rb +59 -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 +67 -33
- 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
@@ -3,7 +3,7 @@
|
|
3
3
|
RSpec.describe "App view / Slice configuration", :app_integration do
|
4
4
|
before do
|
5
5
|
with_directory(@dir = make_tmp_directory) do
|
6
|
-
write "config/app.rb", <<~
|
6
|
+
write "config/app.rb", <<~RUBY
|
7
7
|
require "hanami"
|
8
8
|
|
9
9
|
module TestApp
|
@@ -12,7 +12,7 @@ RSpec.describe "App view / Slice configuration", :app_integration do
|
|
12
12
|
end
|
13
13
|
RUBY
|
14
14
|
|
15
|
-
write "app/view.rb", <<~
|
15
|
+
write "app/view.rb", <<~RUBY
|
16
16
|
require "hanami/view"
|
17
17
|
|
18
18
|
module TestApp
|
@@ -60,7 +60,7 @@ RSpec.describe "App view / Slice configuration", :app_integration do
|
|
60
60
|
describe "subclass in app" do
|
61
61
|
before do
|
62
62
|
with_directory(@dir) do
|
63
|
-
write "app/views/articles/index.rb", <<~
|
63
|
+
write "app/views/articles/index.rb", <<~RUBY
|
64
64
|
module TestApp
|
65
65
|
module Views
|
66
66
|
module Articles
|
@@ -100,7 +100,7 @@ RSpec.describe "App view / Slice configuration", :app_integration do
|
|
100
100
|
describe "subclass in slice" do
|
101
101
|
before do
|
102
102
|
with_directory(@dir) do
|
103
|
-
write "slices/admin/views/articles/index.rb", <<~
|
103
|
+
write "slices/admin/views/articles/index.rb", <<~RUBY
|
104
104
|
module Admin
|
105
105
|
module Views
|
106
106
|
module Articles
|
@@ -141,7 +141,7 @@ RSpec.describe "App view / Slice configuration", :app_integration do
|
|
141
141
|
describe "inheriting from a slice-level base class, in turn inheriting from an app-level base class" do
|
142
142
|
before do
|
143
143
|
with_directory(@dir) do
|
144
|
-
write "slices/admin/view.rb", <<~
|
144
|
+
write "slices/admin/view.rb", <<~RUBY
|
145
145
|
module Admin
|
146
146
|
class View < TestApp::View
|
147
147
|
end
|
@@ -177,7 +177,7 @@ RSpec.describe "App view / Slice configuration", :app_integration do
|
|
177
177
|
context "slice views config present" do
|
178
178
|
before do
|
179
179
|
with_directory(@dir) do
|
180
|
-
write "config/slices/admin.rb", <<~
|
180
|
+
write "config/slices/admin.rb", <<~RUBY
|
181
181
|
module Admin
|
182
182
|
class Slice < Hanami::Slice
|
183
183
|
config.views.layout = "slice_layout"
|
@@ -215,7 +215,7 @@ RSpec.describe "App view / Slice configuration", :app_integration do
|
|
215
215
|
describe "subclass in slice" do
|
216
216
|
before do
|
217
217
|
with_directory(@dir) do
|
218
|
-
write "slices/admin/views/articles/index.rb", <<~
|
218
|
+
write "slices/admin/views/articles/index.rb", <<~RUBY
|
219
219
|
module Admin
|
220
220
|
module Views
|
221
221
|
module Articles
|
@@ -245,7 +245,7 @@ RSpec.describe "App view / Slice configuration", :app_integration do
|
|
245
245
|
|
246
246
|
it "applies views config from the slice" do
|
247
247
|
with_directory(@dir) do
|
248
|
-
write "config/slices/admin.rb", <<~
|
248
|
+
write "config/slices/admin.rb", <<~RUBY
|
249
249
|
module Admin
|
250
250
|
class Slice < Hanami::Slice
|
251
251
|
config.views.layout = "slice_layout"
|
@@ -269,7 +269,7 @@ RSpec.describe "App view / Slice configuration", :app_integration do
|
|
269
269
|
|
270
270
|
it "prefers config from the slice base class over views config from the slice" do
|
271
271
|
with_directory(@dir) do
|
272
|
-
write "config/slices/admin.rb", <<~
|
272
|
+
write "config/slices/admin.rb", <<~RUBY
|
273
273
|
module Admin
|
274
274
|
class Slice < Hanami::Slice
|
275
275
|
config.views.layout = "slice_layout"
|
@@ -0,0 +1,90 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "json"
|
4
|
+
require "rack/test"
|
5
|
+
|
6
|
+
RSpec.describe "Web / Rendering detailed errors", :app_integration do
|
7
|
+
include Rack::Test::Methods
|
8
|
+
|
9
|
+
let(:app) { Hanami.app }
|
10
|
+
|
11
|
+
before do
|
12
|
+
with_directory(@dir = make_tmp_directory) do
|
13
|
+
write "config/app.rb", <<~RUBY
|
14
|
+
require "hanami"
|
15
|
+
|
16
|
+
module TestApp
|
17
|
+
class App < Hanami::App
|
18
|
+
config.logger.stream = File.new("/dev/null", "w")
|
19
|
+
config.render_detailed_errors = true
|
20
|
+
end
|
21
|
+
end
|
22
|
+
RUBY
|
23
|
+
|
24
|
+
write "config/routes.rb", <<~RUBY
|
25
|
+
module TestApp
|
26
|
+
class Routes < Hanami::Routes
|
27
|
+
get "error", to: "error"
|
28
|
+
end
|
29
|
+
end
|
30
|
+
RUBY
|
31
|
+
|
32
|
+
write "app/actions/error.rb", <<~RUBY
|
33
|
+
module TestApp
|
34
|
+
module Actions
|
35
|
+
class Error < Hanami::Action
|
36
|
+
def handle(*)
|
37
|
+
raise "oops"
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
RUBY
|
43
|
+
|
44
|
+
before_prepare if respond_to?(:before_prepare)
|
45
|
+
require "hanami/prepare"
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
describe "HTML request" do
|
50
|
+
it "renders a detailed HTML error page" do
|
51
|
+
get "/error", {}, "HTTP_ACCEPT" => "text/html"
|
52
|
+
|
53
|
+
expect(last_response.status).to eq 500
|
54
|
+
|
55
|
+
html = Capybara.string(last_response.body)
|
56
|
+
expect(html).to have_selector("header", text: "RuntimeError at /error")
|
57
|
+
expect(html).to have_selector("ul.frames li.application", text: "app/actions/error.rb")
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
describe "Other request types" do
|
62
|
+
it "renders a detailed error page in text" do
|
63
|
+
get "/error", {}, "HTTP_ACCEPT" => "application/json"
|
64
|
+
|
65
|
+
expect(last_response.status).to eq 500
|
66
|
+
|
67
|
+
expect(last_response.body).to include "RuntimeError at /error"
|
68
|
+
expect(last_response.body).to match %r{App backtrace.+app/actions/error.rb}m
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
describe "render_detailed_errors config disabled" do
|
73
|
+
def before_prepare
|
74
|
+
write "config/app.rb", <<~RUBY
|
75
|
+
require "hanami"
|
76
|
+
|
77
|
+
module TestApp
|
78
|
+
class App < Hanami::App
|
79
|
+
config.logger.stream = File.new("/dev/null", "w")
|
80
|
+
config.render_detailed_errors = false
|
81
|
+
end
|
82
|
+
end
|
83
|
+
RUBY
|
84
|
+
end
|
85
|
+
|
86
|
+
it "raises errors from within the app" do
|
87
|
+
expect { get "/error" }.to raise_error(RuntimeError, "oops")
|
88
|
+
end
|
89
|
+
end
|
90
|
+
end
|
@@ -0,0 +1,240 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "json"
|
4
|
+
require "rack/test"
|
5
|
+
|
6
|
+
RSpec.describe "Web / Rendering errors", :app_integration do
|
7
|
+
include Rack::Test::Methods
|
8
|
+
|
9
|
+
let(:app) { Hanami.app }
|
10
|
+
|
11
|
+
before do
|
12
|
+
with_directory(@dir = make_tmp_directory) do
|
13
|
+
write "config/app.rb", <<~RUBY
|
14
|
+
require "hanami"
|
15
|
+
|
16
|
+
module TestApp
|
17
|
+
class App < Hanami::App
|
18
|
+
config.logger.stream = File.new("/dev/null", "w")
|
19
|
+
config.render_errors = true
|
20
|
+
config.render_detailed_errors = false
|
21
|
+
end
|
22
|
+
end
|
23
|
+
RUBY
|
24
|
+
|
25
|
+
write "config/routes.rb", <<~RUBY
|
26
|
+
module TestApp
|
27
|
+
class Routes < Hanami::Routes
|
28
|
+
get "index", to: "index"
|
29
|
+
get "error", to: "error"
|
30
|
+
end
|
31
|
+
end
|
32
|
+
RUBY
|
33
|
+
|
34
|
+
write "app/actions/index.rb", <<~RUBY
|
35
|
+
module TestApp
|
36
|
+
module Actions
|
37
|
+
class Index < Hanami::Action
|
38
|
+
def handle(*, response)
|
39
|
+
response.body = "Hello"
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
RUBY
|
45
|
+
|
46
|
+
write "app/actions/error.rb", <<~RUBY
|
47
|
+
module TestApp
|
48
|
+
module Actions
|
49
|
+
class Error < Hanami::Action
|
50
|
+
def handle(*)
|
51
|
+
raise "oops"
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
56
|
+
RUBY
|
57
|
+
|
58
|
+
before_prepare if respond_to?(:before_prepare)
|
59
|
+
require "hanami/prepare"
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
describe "HTML request" do
|
64
|
+
context "error pages present" do
|
65
|
+
def before_prepare
|
66
|
+
write "public/404.html", <<~HTML
|
67
|
+
<h1>Not found</h1>
|
68
|
+
HTML
|
69
|
+
|
70
|
+
write "public/500.html", <<~HTML
|
71
|
+
<h1>Error</h1>
|
72
|
+
HTML
|
73
|
+
end
|
74
|
+
|
75
|
+
it "responds with the HTML for a 404 from a not found error" do
|
76
|
+
get "/__not_found__"
|
77
|
+
|
78
|
+
expect(last_response.status).to eq 404
|
79
|
+
expect(last_response.body.strip).to eq "<h1>Not found</h1>"
|
80
|
+
expect(last_response.get_header("Content-Type")).to eq "text/html; charset=utf-8"
|
81
|
+
expect(last_response.get_header("Content-Length")).to eq "19"
|
82
|
+
end
|
83
|
+
|
84
|
+
it "responds with the HTML for a 404 from a method not allowed error" do
|
85
|
+
post "/index"
|
86
|
+
|
87
|
+
expect(last_response.status).to eq 404
|
88
|
+
expect(last_response.body.strip).to eq "<h1>Not found</h1>"
|
89
|
+
expect(last_response.get_header("Content-Type")).to eq "text/html; charset=utf-8"
|
90
|
+
expect(last_response.get_header("Content-Length")).to eq "19"
|
91
|
+
end
|
92
|
+
|
93
|
+
it "responds with the HTML for a 500" do
|
94
|
+
get "/error"
|
95
|
+
|
96
|
+
expect(last_response.status).to eq 500
|
97
|
+
expect(last_response.body.strip).to eq "<h1>Error</h1>"
|
98
|
+
expect(last_response.get_header("Content-Type")).to eq "text/html; charset=utf-8"
|
99
|
+
expect(last_response.get_header("Content-Length")).to eq "15"
|
100
|
+
end
|
101
|
+
end
|
102
|
+
|
103
|
+
context "error pages missing" do
|
104
|
+
it "responds with default text for a 404 from a not found error" do
|
105
|
+
get "/__not_found__"
|
106
|
+
|
107
|
+
expect(last_response.status).to eq 404
|
108
|
+
expect(last_response.body.strip).to eq "Not Found"
|
109
|
+
expect(last_response.get_header("Content-Type")).to eq "text/html; charset=utf-8"
|
110
|
+
expect(last_response.get_header("Content-Length")).to eq "9"
|
111
|
+
end
|
112
|
+
|
113
|
+
it "responds with default text for a 404 from a metohd not allowed error" do
|
114
|
+
post "/index"
|
115
|
+
|
116
|
+
expect(last_response.status).to eq 404
|
117
|
+
expect(last_response.body.strip).to eq "Not Found"
|
118
|
+
expect(last_response.get_header("Content-Type")).to eq "text/html; charset=utf-8"
|
119
|
+
expect(last_response.get_header("Content-Length")).to eq "9"
|
120
|
+
end
|
121
|
+
|
122
|
+
it "responds with default text for a 500" do
|
123
|
+
get "/error"
|
124
|
+
|
125
|
+
expect(last_response.status).to eq 500
|
126
|
+
expect(last_response.body.strip).to eq "Internal Server Error"
|
127
|
+
expect(last_response.get_header("Content-Type")).to eq "text/html; charset=utf-8"
|
128
|
+
expect(last_response.get_header("Content-Length")).to eq "21"
|
129
|
+
end
|
130
|
+
end
|
131
|
+
end
|
132
|
+
|
133
|
+
describe "JSON request" do
|
134
|
+
it "renders a JSON response for a 404 from a not found error" do
|
135
|
+
get "/__not_found__", {}, "HTTP_ACCEPT" => "application/json"
|
136
|
+
|
137
|
+
expect(last_response.status).to eq 404
|
138
|
+
expect(last_response.body.strip).to eq %({"status":404,"error":"Not Found"})
|
139
|
+
expect(last_response.get_header("Content-Type")).to eq "application/json; charset=utf-8"
|
140
|
+
expect(last_response.get_header("Content-Length")).to eq "34"
|
141
|
+
end
|
142
|
+
|
143
|
+
it "renders a JSON response for a 404 from a metnod not allowed error" do
|
144
|
+
post "/index", {}, "HTTP_ACCEPT" => "application/json"
|
145
|
+
|
146
|
+
expect(last_response.status).to eq 404
|
147
|
+
expect(last_response.body.strip).to eq %({"status":404,"error":"Not Found"})
|
148
|
+
expect(last_response.get_header("Content-Type")).to eq "application/json; charset=utf-8"
|
149
|
+
expect(last_response.get_header("Content-Length")).to eq "34"
|
150
|
+
end
|
151
|
+
|
152
|
+
it "renders a JSON response for a 500" do
|
153
|
+
get "/error", {}, "HTTP_ACCEPT" => "application/json"
|
154
|
+
|
155
|
+
expect(last_response.status).to eq 500
|
156
|
+
expect(last_response.body.strip).to eq %({"status":500,"error":"Internal Server Error"})
|
157
|
+
expect(last_response.get_header("Content-Type")).to eq "application/json; charset=utf-8"
|
158
|
+
expect(last_response.get_header("Content-Length")).to eq "46"
|
159
|
+
end
|
160
|
+
end
|
161
|
+
|
162
|
+
describe "configuring error responses" do
|
163
|
+
def before_prepare
|
164
|
+
write "config/app.rb", <<~RUBY
|
165
|
+
require "hanami"
|
166
|
+
|
167
|
+
module TestApp
|
168
|
+
CustomNotFoundError = Class.new(StandardError)
|
169
|
+
|
170
|
+
class App < Hanami::App
|
171
|
+
config.logger.stream = File.new("/dev/null", "w")
|
172
|
+
config.render_errors = true
|
173
|
+
config.render_error_responses["TestApp::CustomNotFoundError"] = :not_found
|
174
|
+
config.render_detailed_errors = false
|
175
|
+
end
|
176
|
+
end
|
177
|
+
RUBY
|
178
|
+
|
179
|
+
write "app/actions/error.rb", <<~RUBY
|
180
|
+
module TestApp
|
181
|
+
module Actions
|
182
|
+
class Error < Hanami::Action
|
183
|
+
def handle(*)
|
184
|
+
raise CustomNotFoundError
|
185
|
+
end
|
186
|
+
end
|
187
|
+
end
|
188
|
+
end
|
189
|
+
RUBY
|
190
|
+
|
191
|
+
write "public/404.html", <<~HTML
|
192
|
+
<h1>Not found</h1>
|
193
|
+
HTML
|
194
|
+
end
|
195
|
+
|
196
|
+
it "uses the configured errors to determine the response" do
|
197
|
+
get "/error"
|
198
|
+
|
199
|
+
expect(last_response.status).to eq 404
|
200
|
+
expect(last_response.body.strip).to eq "<h1>Not found</h1>"
|
201
|
+
end
|
202
|
+
end
|
203
|
+
|
204
|
+
describe "render_errors config disabled" do
|
205
|
+
def before_prepare
|
206
|
+
write "config/app.rb", <<~RUBY
|
207
|
+
require "hanami"
|
208
|
+
|
209
|
+
module TestApp
|
210
|
+
class App < Hanami::App
|
211
|
+
config.logger.stream = File.new("/dev/null", "w")
|
212
|
+
config.render_errors = false
|
213
|
+
config.render_detailed_errors = false
|
214
|
+
end
|
215
|
+
end
|
216
|
+
RUBY
|
217
|
+
|
218
|
+
# Include error pages here to prove they are _not_ used
|
219
|
+
write "public/404.html", <<~HTML
|
220
|
+
<h1>Not found</h1>
|
221
|
+
HTML
|
222
|
+
|
223
|
+
write "public/500.html", <<~HTML
|
224
|
+
<h1>Error</h1>
|
225
|
+
HTML
|
226
|
+
end
|
227
|
+
|
228
|
+
it "raises a Hanami::Router::NotFoundError for a 404" do
|
229
|
+
expect { get "/__not_found__" }.to raise_error(Hanami::Router::NotFoundError)
|
230
|
+
end
|
231
|
+
|
232
|
+
it "raises a Hanami::Router::NotAllowedError for a 405" do
|
233
|
+
expect { post "/index" }.to raise_error(Hanami::Router::NotAllowedError)
|
234
|
+
end
|
235
|
+
|
236
|
+
it "raises the original error for a 500" do
|
237
|
+
expect { get "/error" }.to raise_error(RuntimeError, "oops")
|
238
|
+
end
|
239
|
+
end
|
240
|
+
end
|
data/spec/spec_helper.rb
CHANGED
@@ -23,6 +23,6 @@ RSpec.configure do |config|
|
|
23
23
|
# TODO: Find out what causes logger to create this dir when running specs.
|
24
24
|
# There's probably a test app class being created somewhere with root
|
25
25
|
# not pointing to a tmp dir.
|
26
|
-
FileUtils.
|
26
|
+
FileUtils.rm_rf(LOG_DIR) if LOG_DIR.exist?
|
27
27
|
end
|
28
28
|
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module RSpec
|
4
|
+
module Support
|
5
|
+
module Matchers
|
6
|
+
module HTML
|
7
|
+
def squish_html(str)
|
8
|
+
str
|
9
|
+
.gsub(/^[[:space:]]+/, "")
|
10
|
+
.gsub(/>[[:space:]]+</m, "><")
|
11
|
+
.strip
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
RSpec::Matchers.define :eq_html do |expected_html|
|
19
|
+
include RSpec::Support::Matchers::HTML
|
20
|
+
|
21
|
+
match do |actual_html|
|
22
|
+
squish_html(actual_html) == squish_html(expected_html)
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
RSpec::Matchers.define :include_html do |expected_html|
|
27
|
+
include RSpec::Support::Matchers::HTML
|
28
|
+
|
29
|
+
match do |actual_html|
|
30
|
+
squish_html(actual_html).include?(squish_html(expected_html))
|
31
|
+
end
|
32
|
+
end
|
@@ -13,10 +13,6 @@ RSpec.describe Hanami::Config::Actions, "default values" do
|
|
13
13
|
specify { expect(config.name_inference_base).to eq "actions" }
|
14
14
|
end
|
15
15
|
|
16
|
-
describe "view_context_identifier" do
|
17
|
-
specify { expect(config.view_context_identifier).to eq "views.context" }
|
18
|
-
end
|
19
|
-
|
20
16
|
describe "view_name_inferrer" do
|
21
17
|
specify { expect(config.view_name_inferrer).to eq Hanami::Slice::ViewNameInferrer }
|
22
18
|
end
|
@@ -182,5 +182,14 @@ RSpec.describe Hanami::Config do
|
|
182
182
|
.to change { config.logger_instance }
|
183
183
|
.to logger_instance
|
184
184
|
end
|
185
|
+
|
186
|
+
context "unrecognized :env" do
|
187
|
+
let(:env) { :staging }
|
188
|
+
|
189
|
+
it "provides a fail-safe configuration" do
|
190
|
+
expect { config.logger_instance }.to_not raise_error
|
191
|
+
expect(config.logger_instance).to be_a(Dry::Logger::Dispatcher)
|
192
|
+
end
|
193
|
+
end
|
185
194
|
end
|
186
195
|
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "dry/inflector"
|
4
|
+
|
5
|
+
RSpec.describe Hanami::Config, "#render_detailed_errors" do
|
6
|
+
let(:config) { described_class.new(app_name: app_name, env: env) }
|
7
|
+
let(:app_name) { Hanami::SliceName.new(double(name: "MyApp::App"), inflector: Dry::Inflector.new) }
|
8
|
+
|
9
|
+
subject(:render_detailed_errors) { config.render_detailed_errors }
|
10
|
+
|
11
|
+
context "development mode" do
|
12
|
+
let(:env) { :development }
|
13
|
+
it { is_expected.to be true }
|
14
|
+
end
|
15
|
+
|
16
|
+
context "test mode" do
|
17
|
+
let(:env) { :test }
|
18
|
+
it { is_expected.to be true }
|
19
|
+
end
|
20
|
+
|
21
|
+
context "production mode" do
|
22
|
+
let(:env) { :production }
|
23
|
+
it { is_expected.to be false }
|
24
|
+
end
|
25
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "dry/inflector"
|
4
|
+
|
5
|
+
RSpec.describe Hanami::Config, "#render_errors" do
|
6
|
+
let(:config) { described_class.new(app_name: app_name, env: env) }
|
7
|
+
let(:app_name) { Hanami::SliceName.new(double(name: "MyApp::App"), inflector: Dry::Inflector.new) }
|
8
|
+
|
9
|
+
subject(:render_errors) { config.render_errors }
|
10
|
+
|
11
|
+
context "development mode" do
|
12
|
+
let(:env) { :development }
|
13
|
+
it { is_expected.to be false }
|
14
|
+
end
|
15
|
+
|
16
|
+
context "test mode" do
|
17
|
+
let(:env) { :test }
|
18
|
+
it { is_expected.to be false }
|
19
|
+
end
|
20
|
+
|
21
|
+
context "production mode" do
|
22
|
+
let(:env) { :production }
|
23
|
+
it { is_expected.to be true }
|
24
|
+
end
|
25
|
+
end
|
@@ -39,20 +39,6 @@ RSpec.describe Hanami::Config, "#views" do
|
|
39
39
|
end
|
40
40
|
|
41
41
|
describe "specialised default values" do
|
42
|
-
describe "paths" do
|
43
|
-
it 'is ["templates"]' do
|
44
|
-
expect(views.paths).to match [
|
45
|
-
an_object_satisfying { |path| path.dir.to_s == "templates" }
|
46
|
-
]
|
47
|
-
end
|
48
|
-
end
|
49
|
-
|
50
|
-
describe "template_inference_base" do
|
51
|
-
it 'is "views"' do
|
52
|
-
expect(views.template_inference_base).to eq "views"
|
53
|
-
end
|
54
|
-
end
|
55
|
-
|
56
42
|
describe "layout" do
|
57
43
|
it 'is "app"' do
|
58
44
|
expect(views.layout).to eq "app"
|
@@ -69,10 +55,6 @@ RSpec.describe Hanami::Config, "#views" do
|
|
69
55
|
expect(views).to be_frozen
|
70
56
|
end
|
71
57
|
|
72
|
-
it "does not allow changes to locally defined settings" do
|
73
|
-
expect { views.parts_path = "parts" }.to raise_error(Dry::Configurable::FrozenConfigError)
|
74
|
-
end
|
75
|
-
|
76
58
|
it "does not allow changes to base view settings" do
|
77
59
|
expect { views.paths = [] }.to raise_error(Dry::Configurable::FrozenConfigError)
|
78
60
|
end
|
@@ -0,0 +1,59 @@
|
|
1
|
+
require "hanami/view"
|
2
|
+
require "hanami/view/context"
|
3
|
+
require "hanami/extensions/view/context"
|
4
|
+
|
5
|
+
RSpec.describe(Hanami::View::Context) do
|
6
|
+
subject(:context) { described_class.new(**args) }
|
7
|
+
let(:args) { {} }
|
8
|
+
|
9
|
+
describe "#assets" do
|
10
|
+
context "assets given" do
|
11
|
+
let(:args) { {assets: assets} }
|
12
|
+
let(:assets) { double(:assets) }
|
13
|
+
|
14
|
+
it "returns the assets" do
|
15
|
+
expect(context.assets).to be assets
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
context "no assets given" do
|
20
|
+
it "raises a Hanami::ComponentLoadError" do
|
21
|
+
expect { context.assets }.to raise_error Hanami::ComponentLoadError
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
describe "#request" do
|
27
|
+
context "request given" do
|
28
|
+
let(:args) { {request: request} }
|
29
|
+
let(:request) { double(:request) }
|
30
|
+
|
31
|
+
it "returns the request" do
|
32
|
+
expect(context.request).to be request
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
context "no request given" do
|
37
|
+
it "raises a Hanami::ComponentLoadError" do
|
38
|
+
expect { context.request }.to raise_error Hanami::ComponentLoadError
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
describe "#routes" do
|
44
|
+
context "routes given" do
|
45
|
+
let(:args) { {routes: routes} }
|
46
|
+
let(:routes) { double(:routes) }
|
47
|
+
|
48
|
+
it "returns the routes" do
|
49
|
+
expect(context.routes).to be routes
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
context "no routes given" do
|
54
|
+
it "raises a Hanami::ComponentLoadError" do
|
55
|
+
expect { context.routes }.to raise_error Hanami::ComponentLoadError
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|