hanami 2.0.0.beta4 → 2.0.0.rc1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (69) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +19 -0
  3. data/hanami.gemspec +8 -7
  4. data/lib/hanami/app.rb +47 -36
  5. data/lib/hanami/assets/app_config.rb +7 -15
  6. data/lib/hanami/assets/config.rb +5 -6
  7. data/lib/hanami/config/actions/content_security_policy.rb +1 -1
  8. data/lib/hanami/config/actions/cookies.rb +27 -0
  9. data/lib/hanami/config/actions/sessions.rb +42 -5
  10. data/lib/hanami/config/actions.rb +81 -17
  11. data/lib/hanami/config/logger.rb +112 -23
  12. data/lib/hanami/config/router.rb +0 -1
  13. data/lib/hanami/config/views.rb +6 -10
  14. data/lib/hanami/config.rb +235 -73
  15. data/lib/hanami/constants.rb +4 -0
  16. data/lib/hanami/errors.rb +17 -0
  17. data/lib/hanami/extensions/action/slice_configured_action.rb +9 -5
  18. data/lib/hanami/extensions/action.rb +59 -7
  19. data/lib/hanami/extensions/view/context.rb +3 -4
  20. data/lib/hanami/extensions/view/slice_configured_view.rb +4 -4
  21. data/lib/hanami/extensions/view.rb +7 -5
  22. data/lib/hanami/providers/inflector.rb +6 -0
  23. data/lib/hanami/providers/logger.rb +8 -0
  24. data/lib/hanami/providers/rack.rb +12 -0
  25. data/lib/hanami/providers/routes.rb +14 -4
  26. data/lib/hanami/routes.rb +36 -1
  27. data/lib/hanami/settings/env_store.rb +1 -1
  28. data/lib/hanami/settings.rb +102 -36
  29. data/lib/hanami/slice/router.rb +38 -16
  30. data/lib/hanami/slice/routing/middleware/stack.rb +66 -42
  31. data/lib/hanami/slice/routing/resolver.rb +10 -17
  32. data/lib/hanami/slice/view_name_inferrer.rb +1 -1
  33. data/lib/hanami/slice.rb +553 -14
  34. data/lib/hanami/slice_registrar.rb +20 -15
  35. data/lib/hanami/version.rb +2 -3
  36. data/lib/hanami/web/rack_logger.rb +14 -4
  37. data/lib/hanami.rb +122 -23
  38. data/spec/integration/action/csrf_protection_spec.rb +1 -1
  39. data/spec/integration/container/application_routes_helper_spec.rb +3 -1
  40. data/spec/integration/container/provider_lifecycle_spec.rb +61 -0
  41. data/spec/integration/container/standard_providers/rack_provider_spec.rb +44 -0
  42. data/spec/integration/container/{standard_bootable_components_spec.rb → standard_providers_spec.rb} +3 -3
  43. data/spec/integration/rack_app/body_parser_spec.rb +3 -0
  44. data/spec/integration/rack_app/middleware_spec.rb +427 -3
  45. data/spec/integration/rack_app/non_booted_rack_app_spec.rb +2 -1
  46. data/spec/integration/rack_app/rack_app_spec.rb +39 -11
  47. data/spec/integration/setup_spec.rb +4 -4
  48. data/spec/integration/slices/external_slice_spec.rb +2 -1
  49. data/spec/integration/slices/slice_configuration_spec.rb +3 -1
  50. data/spec/integration/slices/slice_loading_spec.rb +4 -4
  51. data/spec/integration/slices/slice_routing_spec.rb +4 -3
  52. data/spec/integration/slices_spec.rb +100 -0
  53. data/spec/isolation/hanami/boot/success_spec.rb +1 -1
  54. data/spec/support/app_integration.rb +2 -10
  55. data/spec/unit/hanami/config/actions/content_security_policy_spec.rb +7 -7
  56. data/spec/unit/hanami/config/actions/default_values_spec.rb +1 -1
  57. data/spec/unit/hanami/config/actions/sessions_spec.rb +1 -3
  58. data/spec/unit/hanami/config/actions_spec.rb +1 -12
  59. data/spec/unit/hanami/config/logger_spec.rb +38 -55
  60. data/spec/unit/hanami/config/router_spec.rb +1 -1
  61. data/spec/unit/hanami/config/views_spec.rb +3 -13
  62. data/spec/unit/hanami/settings_spec.rb +1 -1
  63. data/spec/unit/hanami/slice_configurable_spec.rb +5 -5
  64. data/spec/unit/hanami/slice_spec.rb +32 -0
  65. data/spec/unit/hanami/version_spec.rb +1 -1
  66. data/spec/unit/hanami/web/rack_logger_spec.rb +13 -2
  67. metadata +54 -45
  68. data/lib/hanami/config/sessions.rb +0 -50
  69. data/spec/unit/hanami/config_spec.rb +0 -43
@@ -1,6 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require "rack/test"
4
+ require "stringio"
4
5
 
5
6
  RSpec.describe "Hanami web app", :app_integration do
6
7
  include Rack::Test::Methods
@@ -50,7 +51,7 @@ RSpec.describe "Hanami web app", :app_integration do
50
51
 
51
52
  module TestApp
52
53
  class App < Hanami::App
53
- config.logger.stream = File.new("/dev/null", "w")
54
+ config.logger.stream = StringIO.new
54
55
 
55
56
  config.middleware.use Middlewares::AppendOne
56
57
  config.middleware.use Middlewares::Prepare, before: Middlewares::AppendOne
@@ -101,7 +102,7 @@ RSpec.describe "Hanami web app", :app_integration do
101
102
 
102
103
  module TestApp
103
104
  class App < Hanami::App
104
- config.logger.stream = File.new("/dev/null", "w")
105
+ config.logger.stream = StringIO.new
105
106
  end
106
107
  end
107
108
  RUBY
@@ -164,7 +165,7 @@ RSpec.describe "Hanami web app", :app_integration do
164
165
  end
165
166
 
166
167
  class App < Hanami::App
167
- config.logger.stream = File.new("/dev/null", "w")
168
+ config.logger.stream = StringIO.new
168
169
 
169
170
  config.middleware.use(TestApp::TestMiddleware) { |env| env["tested"] = "yes" }
170
171
  end
@@ -234,4 +235,427 @@ RSpec.describe "Hanami web app", :app_integration do
234
235
  }.to raise_error(Hanami::UnsupportedMiddlewareSpecError)
235
236
  end
236
237
  end
238
+
239
+ context "with simple app" do
240
+ before do
241
+ write "config/app.rb", <<~RUBY
242
+ require "hanami"
243
+
244
+ module TestApp
245
+ class App < Hanami::App
246
+ config.logger.stream = File.new("/dev/null", "w")
247
+ end
248
+ end
249
+ RUBY
250
+
251
+ write "lib/test_app/middleware/authentication.rb", <<~RUBY
252
+ module TestApp
253
+ module Middleware
254
+ class Authentication
255
+ def self.inspect
256
+ "<Middleware::Auth>"
257
+ end
258
+
259
+ def initialize(app)
260
+ @app = app
261
+ end
262
+
263
+ def call(env)
264
+ env["AUTH_USER_ID"] = user_id = "23"
265
+ status, headers, body = @app.call(env)
266
+ headers["X-Auth-User-ID"] = user_id
267
+
268
+ [status, headers, body]
269
+ end
270
+ end
271
+ end
272
+ end
273
+ RUBY
274
+
275
+ write "config/routes.rb", <<~RUBY
276
+ require "test_app/middleware/authentication"
277
+
278
+ module TestApp
279
+ class Routes < Hanami::Routes
280
+ root to: ->(*) { [200, {"Content-Length" => "4"}, ["Home"]] }
281
+
282
+ slice :admin, at: "/admin" do
283
+ use TestApp::Middleware::Authentication
284
+
285
+ root to: "home.show"
286
+ end
287
+ end
288
+ end
289
+ RUBY
290
+
291
+ write "slices/admin/actions/home/show.rb", <<~RUBY
292
+ module Admin
293
+ module Actions
294
+ module Home
295
+ class Show < Hanami::Action
296
+ def handle(req, res)
297
+ res.body = "Hello from admin (User ID " + req.env['AUTH_USER_ID'] + ")"
298
+ end
299
+ end
300
+ end
301
+ end
302
+ end
303
+ RUBY
304
+
305
+ require "hanami/boot"
306
+ end
307
+
308
+ it "excludes root scope" do
309
+ get "/"
310
+
311
+ expect(last_response.status).to eq 200
312
+ expect(last_response.body).to eq "Home"
313
+ expect(last_response.headers).to_not have_key("X-Auth-User-ID")
314
+ end
315
+
316
+ it "excludes not found routes in root scope" do
317
+ get "/foo"
318
+
319
+ expect(last_response.status).to eq 404
320
+ expect(last_response.body).to eq "Not Found"
321
+ expect(last_response.headers).to_not have_key("X-Auth-User-ID")
322
+ end
323
+
324
+ context "within slice" do
325
+ it "uses Rack middleware" do
326
+ get "/admin"
327
+
328
+ expect(last_response.status).to eq 200
329
+ expect(last_response.body).to eq "Hello from admin (User ID 23)"
330
+ expect(last_response.headers).to have_key("X-Auth-User-ID")
331
+ end
332
+
333
+ it "uses Rack middleware for not found paths" do
334
+ get "/admin/users"
335
+
336
+ expect(last_response.status).to be(404)
337
+ expect(last_response.body).to eq "Not Found"
338
+ expect(last_response.headers).to have_key("X-Auth-User-ID")
339
+ end
340
+ end
341
+ end
342
+
343
+ context "with complex app" do
344
+ let(:app_modules) { %i[TestApp Admin APIV1] }
345
+
346
+ before do
347
+ write "config/app.rb", <<~RUBY
348
+ require "hanami"
349
+
350
+ module TestApp
351
+ class App < Hanami::App
352
+ config.logger.stream = File.new("/dev/null", "w")
353
+ end
354
+ end
355
+ RUBY
356
+
357
+ write "lib/test_app/middleware/elapsed.rb", <<~RUBY
358
+ module TestApp
359
+ module Middleware
360
+ class Elapsed
361
+ def self.inspect
362
+ "<Middleware::Elapsed>"
363
+ end
364
+
365
+ def initialize(app)
366
+ @app = app
367
+ end
368
+
369
+ def call(env)
370
+ with_time_instrumentation do
371
+ @app.call(env)
372
+ end
373
+ end
374
+
375
+ private
376
+
377
+ def with_time_instrumentation
378
+ starting = now
379
+ status, headers, body = yield
380
+ ending = now
381
+
382
+ headers["X-Elapsed"] = (ending - starting).round(5).to_s
383
+ [status, headers, body]
384
+ end
385
+
386
+ def now
387
+ Process.clock_gettime(Process::CLOCK_MONOTONIC)
388
+ end
389
+ end
390
+ end
391
+ end
392
+ RUBY
393
+
394
+ write "lib/test_app/middleware/authentication.rb", <<~RUBY
395
+ module TestApp
396
+ module Middleware
397
+ class Authentication
398
+ def self.inspect
399
+ "<Middleware::Auth>"
400
+ end
401
+
402
+ def initialize(app)
403
+ @app = app
404
+ end
405
+
406
+ def call(env)
407
+ env["AUTH_USER_ID"] = user_id = "23"
408
+ status, headers, body = @app.call(env)
409
+ headers["X-Auth-User-ID"] = user_id
410
+
411
+ [status, headers, body]
412
+ end
413
+ end
414
+ end
415
+ end
416
+ RUBY
417
+
418
+ write "lib/test_app/middleware/rate_limiter.rb", <<~RUBY
419
+ module TestApp
420
+ module Middleware
421
+ class RateLimiter
422
+ def self.inspect
423
+ "<Middleware::API::Limiter>"
424
+ end
425
+
426
+ def initialize(app)
427
+ @app = app
428
+ end
429
+
430
+ def call(env)
431
+ status, headers, body = @app.call(env)
432
+ headers["X-API-Rate-Limit-Quota"] = "4000"
433
+
434
+ [status, headers, body]
435
+ end
436
+ end
437
+ end
438
+ end
439
+ RUBY
440
+
441
+ write "lib/test_app/middleware/api_version.rb", <<~RUBY
442
+ module TestApp
443
+ module Middleware
444
+ class ApiVersion
445
+ def self.inspect
446
+ "<Middleware::API::Version>"
447
+ end
448
+
449
+ def initialize(app)
450
+ @app = app
451
+ end
452
+
453
+ def call(env)
454
+ status, headers, body = @app.call(env)
455
+ headers["X-API-Version"] = "1"
456
+
457
+ [status, headers, body]
458
+ end
459
+ end
460
+ end
461
+ end
462
+ RUBY
463
+
464
+ write "lib/test_app/middleware/api_deprecation.rb", <<~RUBY
465
+ module TestApp
466
+ module Middleware
467
+ class ApiDeprecation
468
+ def self.inspect
469
+ "<Middleware::API::Deprecation>"
470
+ end
471
+
472
+ def initialize(app)
473
+ @app = app
474
+ end
475
+
476
+ def call(env)
477
+ status, headers, body = @app.call(env)
478
+ headers["X-API-Deprecated"] = "API v1 is deprecated"
479
+
480
+ [status, headers, body]
481
+ end
482
+ end
483
+ end
484
+ end
485
+ RUBY
486
+
487
+ write "lib/test_app/middleware/scope_identifier.rb", <<~RUBY
488
+ module TestApp
489
+ module Middleware
490
+ class ScopeIdentifier
491
+ def self.inspect
492
+ "<Middleware::API::ScopeIdentifier>"
493
+ end
494
+
495
+ def initialize(app, scope)
496
+ @app = app
497
+ @scope = scope
498
+ end
499
+
500
+ def call(env)
501
+ status, header, body = @app.call(env)
502
+ header["X-Identifier-" + @scope] = "true"
503
+ [status, header, body]
504
+ end
505
+
506
+ def inspect
507
+ "Scope identifier: " + @scope.inspect
508
+ end
509
+ end
510
+ end
511
+ end
512
+ RUBY
513
+
514
+ write "config/routes.rb", <<~RUBY
515
+ require "test_app/middleware/elapsed"
516
+ require "test_app/middleware/authentication"
517
+ require "test_app/middleware/rate_limiter"
518
+ require "test_app/middleware/api_version"
519
+ require "test_app/middleware/api_deprecation"
520
+ require "test_app/middleware/scope_identifier"
521
+
522
+ module TestApp
523
+ class Routes < Hanami::Routes
524
+ use TestApp::Middleware::Elapsed
525
+ use TestApp::Middleware::ScopeIdentifier, "Root"
526
+ root to: ->(*) { [200, {"Content-Length" => "4"}, ["Home (complex app)"]] }
527
+
528
+ mount ->(*) { [200, {"Content-Length" => "7"}, ["Mounted"]] }, at: "/mounted"
529
+
530
+ slice :admin, at: "/admin" do
531
+ use TestApp::Middleware::Authentication
532
+ use TestApp::Middleware::ScopeIdentifier, "Admin"
533
+
534
+ root to: "home.show"
535
+ end
536
+
537
+ # Without leading slash
538
+ # See: https://github.com/hanami/api/issues/8
539
+ scope "api" do
540
+ use TestApp::Middleware::RateLimiter
541
+ use TestApp::Middleware::ScopeIdentifier, "API"
542
+
543
+ root to: ->(*) { [200, {"Content-Length" => "3"}, ["API"]] }
544
+
545
+ slice :api_v1, at: "/v1" do
546
+ use TestApp::Middleware::ApiVersion
547
+ use TestApp::Middleware::ApiDeprecation
548
+ use TestApp::Middleware::ScopeIdentifier, "API-V1"
549
+
550
+ root to: "home.show"
551
+ end
552
+ end
553
+ end
554
+ end
555
+ RUBY
556
+
557
+ write "slices/admin/actions/home/show.rb", <<~RUBY
558
+ module Admin
559
+ module Actions
560
+ module Home
561
+ class Show < Hanami::Action
562
+ def handle(req, res)
563
+ res.body = "Hello from admin (User ID " + req.env['AUTH_USER_ID'] + ")"
564
+ end
565
+ end
566
+ end
567
+ end
568
+ end
569
+ RUBY
570
+
571
+ write "slices/api_v1/actions/home/show.rb", <<~RUBY
572
+ module APIV1
573
+ module Actions
574
+ module Home
575
+ class Show < Hanami::Action
576
+ def handle(req, res)
577
+ res.body = "API v1"
578
+ end
579
+ end
580
+ end
581
+ end
582
+ end
583
+ RUBY
584
+
585
+ require "hanami/boot"
586
+ end
587
+
588
+ it "uses Rack middleware" do
589
+ get "/"
590
+
591
+ expect(last_response.status).to be(200)
592
+ expect(last_response.body).to eq("Home (complex app)")
593
+ expect(last_response.headers["X-Identifier-Root"]).to eq("true")
594
+ expect(last_response.headers).to have_key("X-Elapsed")
595
+ expect(last_response.headers).to_not have_key("X-Auth-User-ID")
596
+ expect(last_response.headers).to_not have_key("X-API-Rate-Limit-Quota")
597
+ expect(last_response.headers).to_not have_key("X-API-Version")
598
+ end
599
+
600
+ it "uses Rack middleware for other paths" do
601
+ get "/foo"
602
+
603
+ expect(last_response.status).to be(404)
604
+ expect(last_response.headers["X-Identifier-Root"]).to eq("true")
605
+ expect(last_response.headers).to have_key("X-Elapsed")
606
+ expect(last_response.headers).to_not have_key("X-Auth-User-ID")
607
+ expect(last_response.headers).to_not have_key("X-API-Rate-Limit-Quota")
608
+ expect(last_response.headers).to_not have_key("X-API-Version")
609
+ end
610
+
611
+ context "scoped" do
612
+ it "uses Rack middleware" do
613
+ get "/admin"
614
+
615
+ expect(last_response.status).to be(200)
616
+ expect(last_response.headers["X-Identifier-Admin"]).to eq("true")
617
+ expect(last_response.headers).to have_key("X-Elapsed")
618
+ expect(last_response.headers).to have_key("X-Auth-User-ID")
619
+ expect(last_response.headers).to_not have_key("X-API-Rate-Limit-Quota")
620
+ expect(last_response.headers).to_not have_key("X-API-Version")
621
+ end
622
+
623
+ it "uses Rack middleware for other paths" do
624
+ get "/admin/users"
625
+
626
+ expect(last_response.status).to be(404)
627
+ expect(last_response.headers["X-Identifier-Admin"]).to eq("true")
628
+ expect(last_response.headers).to have_key("X-Elapsed")
629
+ expect(last_response.headers).to have_key("X-Elapsed")
630
+ expect(last_response.headers).to have_key("X-Auth-User-ID")
631
+ expect(last_response.headers).to_not have_key("X-API-Rate-Limit-Quota")
632
+ expect(last_response.headers).to_not have_key("X-API-Version")
633
+ end
634
+
635
+ # See: https://github.com/hanami/api/issues/8
636
+ it "uses Rack middleware for scope w/o leading slash" do
637
+ get "/api"
638
+
639
+ expect(last_response.status).to be(200)
640
+ expect(last_response.headers["X-Identifier-Api"]).to eq("true")
641
+ expect(last_response.headers).to have_key("X-Elapsed")
642
+ expect(last_response.headers).to_not have_key("X-Auth-User-ID")
643
+ expect(last_response.headers).to have_key("X-API-Rate-Limit-Quota")
644
+ expect(last_response.headers).to_not have_key("X-API-Version")
645
+ end
646
+
647
+ # See: https://github.com/hanami/api/issues/8
648
+ it "uses Rack middleware for nested scope w/o leading slash" do
649
+ get "/api/v1"
650
+
651
+ expect(last_response.status).to be(200)
652
+ expect(last_response.headers["X-Identifier-API-V1"]).to eq("true")
653
+ expect(last_response.headers).to have_key("X-Elapsed")
654
+ expect(last_response.headers).to_not have_key("X-Auth-User-ID")
655
+ expect(last_response.headers).to have_key("X-API-Rate-Limit-Quota")
656
+ expect(last_response.headers).to have_key("X-API-Deprecated")
657
+ expect(last_response.headers["X-API-Version"]).to eq("1")
658
+ end
659
+ end
660
+ end
237
661
  end
@@ -1,6 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require "rack/test"
4
+ require "stringio"
4
5
 
5
6
  RSpec.describe "Running a Rack app for a non-booted app", :app_integration do
6
7
  include Rack::Test::Methods
@@ -14,7 +15,7 @@ RSpec.describe "Running a Rack app for a non-booted app", :app_integration do
14
15
 
15
16
  module TestApp
16
17
  class App < Hanami::App
17
- config.logger.stream = File.new("/dev/null", "w")
18
+ config.logger.stream = StringIO.new
18
19
  end
19
20
  end
20
21
  RUBY
@@ -1,6 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require "rack/test"
4
+ require "stringio"
4
5
 
5
6
  RSpec.describe "Hanami web app", :app_integration do
6
7
  include Rack::Test::Methods
@@ -46,10 +47,25 @@ RSpec.describe "Hanami web app", :app_integration do
46
47
  end
47
48
  RUBY
48
49
 
50
+ write "app/actions/users/index.rb", <<~RUBY
51
+ module TestApp
52
+ module Actions
53
+ module Users
54
+ class Index < Hanami::Action
55
+ def handle(req, _resp)
56
+ raise StandardError, "OH NOEZ"
57
+ end
58
+ end
59
+ end
60
+ end
61
+ end
62
+ RUBY
63
+
49
64
  write "config/routes.rb", <<~RUBY
50
65
  module TestApp
51
66
  class Routes < Hanami::Routes
52
67
  root to: ->(env) { [200, {}, ["OK"]] }
68
+ get "/users", to: "users.index"
53
69
  end
54
70
  end
55
71
  RUBY
@@ -63,6 +79,14 @@ RSpec.describe "Hanami web app", :app_integration do
63
79
  logs = -> { Pathname(dir).join("test.log").realpath.read }
64
80
 
65
81
  expect(logs.()).to match %r{GET 200 \d+ms 127.0.0.1 /}
82
+
83
+ begin
84
+ get "/users"
85
+ rescue => e # rubocop:disable Style/RescueStandardError
86
+ raise unless e.to_s == "OH NOEZ"
87
+ end
88
+
89
+ expect(logs.()).to match %r{OH NOEZ}
66
90
  end
67
91
  end
68
92
 
@@ -109,7 +133,7 @@ RSpec.describe "Hanami web app", :app_integration do
109
133
 
110
134
  module TestApp
111
135
  class App < Hanami::App
112
- config.logger.stream = File.new("/dev/null", "w")
136
+ config.logger.stream = StringIO.new
113
137
  end
114
138
  end
115
139
  RUBY
@@ -214,7 +238,7 @@ RSpec.describe "Hanami web app", :app_integration do
214
238
 
215
239
  module TestApp
216
240
  class App < Hanami::App
217
- config.logger.stream = File.new("/dev/null", "w")
241
+ config.logger.stream = StringIO.new
218
242
  end
219
243
  end
220
244
  RUBY
@@ -279,7 +303,7 @@ RSpec.describe "Hanami web app", :app_integration do
279
303
 
280
304
  module TestApp
281
305
  class App < Hanami::App
282
- config.logger.stream = File.new("/dev/null", "w")
306
+ config.logger.stream = StringIO.new
283
307
  end
284
308
  end
285
309
  RUBY
@@ -372,8 +396,9 @@ RSpec.describe "Hanami web app", :app_integration do
372
396
  require "hanami/boot"
373
397
 
374
398
  expect { Hanami.app.rack_app }.to raise_error do |exception|
375
- expect(exception).to be_kind_of(Hanami::Slice::Routing::UnknownActionError)
376
- expect(exception.message).to include("missing.action")
399
+ expect(exception).to be_kind_of(Hanami::Routes::MissingActionError)
400
+ expect(exception.message).to include("Could not find action with key \"actions.missing.action\" in TestApp::App")
401
+ expect(exception.message).to match(%r{define the action class TestApp::Actions::Missing::Action.+actions/missing/action.rb})
377
402
  end
378
403
  end
379
404
  end
@@ -403,8 +428,9 @@ RSpec.describe "Hanami web app", :app_integration do
403
428
  require "hanami/boot"
404
429
 
405
430
  expect { Hanami.app.rack_app }.to raise_error do |exception|
406
- expect(exception).to be_kind_of(Hanami::Slice::Routing::UnknownActionError)
407
- expect(exception.message).to include("missing.action")
431
+ expect(exception).to be_kind_of(Hanami::Routes::MissingActionError)
432
+ expect(exception.message).to include("Could not find action with key \"actions.missing.action\" in Admin::Slice")
433
+ expect(exception.message).to match(%r{define the action class Admin::Actions::Missing::Action.+slices/admin/actions/missing/action.rb})
408
434
  end
409
435
  end
410
436
  end
@@ -433,8 +459,9 @@ RSpec.describe "Hanami web app", :app_integration do
433
459
  expect { Hanami.app.rack_app }.not_to raise_error
434
460
 
435
461
  expect { get "/missing" }.to raise_error do |exception|
436
- expect(exception).to be_kind_of(Hanami::Slice::Routing::UnknownActionError)
437
- expect(exception.message).to include("missing.action")
462
+ expect(exception).to be_kind_of(Hanami::Routes::MissingActionError)
463
+ expect(exception.message).to include("Could not find action with key \"actions.missing.action\" in TestApp::App")
464
+ expect(exception.message).to match(%r{define the action class TestApp::Actions::Missing::Action.+actions/missing/action.rb})
438
465
  end
439
466
  end
440
467
  end
@@ -466,8 +493,9 @@ RSpec.describe "Hanami web app", :app_integration do
466
493
  expect { Hanami.app.rack_app }.not_to raise_error
467
494
 
468
495
  expect { get "/admin/missing" }.to raise_error do |exception|
469
- expect(exception).to be_kind_of(Hanami::Slice::Routing::UnknownActionError)
470
- expect(exception.message).to include("missing.action")
496
+ expect(exception).to be_kind_of(Hanami::Routes::MissingActionError)
497
+ expect(exception.message).to include("Could not find action with key \"actions.missing.action\" in Admin::Slice")
498
+ expect(exception.message).to match(%r{define the action class Admin::Actions::Missing::Action.+slices/admin/actions/missing/action.rb})
471
499
  end
472
500
  end
473
501
  end
@@ -63,12 +63,12 @@ RSpec.describe "Hanami setup", :app_integration do
63
63
 
64
64
  with_tmp_directory(Dir.mktmpdir) do
65
65
  write "config/app.rb", <<~RUBY
66
- require "hanami"
66
+ require "hanami"
67
67
 
68
- module TestApp
69
- class App < Hanami::App
68
+ module TestApp
69
+ class App < Hanami::App
70
+ end
70
71
  end
71
- end
72
72
  RUBY
73
73
 
74
74
  expect { setup }.to change { Hanami.app? }.to true
@@ -1,6 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require "rack/test"
4
+ require "stringio"
4
5
 
5
6
  RSpec.describe "Slices / External slices", :app_integration do
6
7
  include Rack::Test::Methods
@@ -14,7 +15,7 @@ RSpec.describe "Slices / External slices", :app_integration do
14
15
 
15
16
  module TestApp
16
17
  class App < Hanami::App
17
- config.logger.stream = File.new("/dev/null", "w")
18
+ config.logger.stream = StringIO.new
18
19
 
19
20
  require "external/slice"
20
21
  register_slice(:external, External::Slice)
@@ -1,5 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require "stringio"
4
+
3
5
  RSpec.describe "Slices / Slice configuration", :app_integration do
4
6
  specify "Slices receive a copy of the app configuration, and can make distinct modifications" do
5
7
  with_tmp_directory(Dir.mktmpdir) do
@@ -8,7 +10,7 @@ RSpec.describe "Slices / Slice configuration", :app_integration do
8
10
 
9
11
  module TestApp
10
12
  class App < Hanami::App
11
- config.logger.stream = File.new("/dev/null", "w")
13
+ config.logger.stream = StringIO.new
12
14
 
13
15
  config.no_auto_register_paths << "structs"
14
16
  end
@@ -3,7 +3,7 @@
3
3
  require "rack/test"
4
4
 
5
5
  RSpec.describe "Slices / Slice loading", :app_integration, :aggregate_failures do
6
- let(:app_modules) { %i[TestApp Admin Editorial Main Shop] }
6
+ let(:app_modules) { %i[TestApp Admin Main] }
7
7
 
8
8
  describe "loading specific slices with config.slices" do
9
9
  describe "setup app" do
@@ -48,7 +48,7 @@ RSpec.describe "Slices / Slice loading", :app_integration, :aggregate_failures d
48
48
 
49
49
  expect { Admin::Slice.register_slice :editorial }.not_to(change { Admin::Slice.slices.keys })
50
50
  expect { Admin::Slice.register_slice :shop }.to change { Admin::Slice.slices.keys }.to [:shop]
51
- expect(Shop::Slice).to be
51
+ expect(Admin::Shop::Slice).to be
52
52
  end
53
53
  end
54
54
  end
@@ -123,9 +123,9 @@ RSpec.describe "Slices / Slice loading", :app_integration, :aggregate_failures d
123
123
  expect(Admin::Slice.slices.keys).to eq [:shop]
124
124
 
125
125
  expect(Admin::Slice).to be
126
- expect(Shop::Slice).to be
126
+ expect(Admin::Shop::Slice).to be
127
127
 
128
- expect { Editorial }.to raise_error(NameError)
128
+ expect { Admin::Editorial }.to raise_error(NameError)
129
129
  expect { Main }.to raise_error(NameError)
130
130
  end
131
131
  end