hanami/spec/integration/rack_app/rack_app_spec.rb

525 lines
12 KiB
Ruby

# frozen_string_literal: true
require "rack/test"
RSpec.describe "Hanami web app", :app_integration do
include Rack::Test::Methods
let(:app) { Hanami.app }
specify "Hanami.app returns a rack builder" do
with_tmp_directory do
write "config/app.rb", <<~RUBY
require "hanami"
module TestApp
class App < Hanami::App
end
end
RUBY
write "config/routes.rb", <<~RUBY
module TestApp
class Routes < Hanami::Routes
define do
root to: ->(env) { [200, {}, ["OK"]] }
end
end
end
RUBY
require "hanami/boot"
expect(app).to be(TestApp::App)
end
end
specify "Has rack monitor preconfigured with default request logging" do
dir = Dir.mktmpdir
with_tmp_directory(dir) do
write "config/app.rb", <<~RUBY
require "hanami"
module TestApp
class App < Hanami::App
config.logger.stream = config.root.join("test.log")
end
end
RUBY
write "config/routes.rb", <<~RUBY
module TestApp
class Routes < Hanami::Routes
define do
end
end
end
RUBY
require "hanami/boot"
expect(Hanami.app["rack.monitor"]).to be_instance_of(Dry::Monitor::Rack::Middleware)
get "/"
logs = -> { Pathname(dir).join("test.log").realpath.read }
expect(logs.()).to match %r{GET 404 \d+ms 127.0.0.1 /}
end
end
describe "Request logging when using a slice" do
let(:app) { Main::Slice.rack_app }
specify "Has rack monitor preconfigured with default request logging (when used via a slice)" do
dir = Dir.mktmpdir
with_tmp_directory(dir) do
write "config/app.rb", <<~RUBY
require "hanami"
module TestApp
class App < Hanami::App
config.logger.stream = config.root.join("test.log")
end
end
RUBY
write "slices/main/config/routes.rb", <<~RUBY
module Main
class Routes < Hanami::Routes
define do
end
end
end
RUBY
require "hanami/boot"
get "/"
logs = -> { Pathname(dir).join("test.log").realpath.read }
expect(logs.()).to match %r{GET 404 \d+ms 127.0.0.1 /}
end
end
end
specify "Routing to actions based on their container identifiers" do
with_tmp_directory(Dir.mktmpdir) do
write "config/app.rb", <<~RUBY
require "hanami"
module TestApp
class App < Hanami::App
config.logger.stream = File.new("/dev/null", "w")
end
end
RUBY
write "config/routes.rb", <<~RUBY
module TestApp
class Routes < Hanami::Routes
define do
get "/health", to: "health.show"
get "/inline" do
"Inline"
end
slice :main, at: "/" do
root to: "home.index"
end
slice :admin, at: "/admin" do
get "/dashboard", to: "dashboard.show"
end
end
end
end
RUBY
write "app/actions/health/show.rb", <<~RUBY
require "hanami/action"
module TestApp
module Actions
module Health
class Show < Hanami::Action
def handle(*, res)
res.body = "Health, OK"
end
end
end
end
end
RUBY
write "slices/main/actions/home/index.rb", <<~RUBY
require "hanami/action"
module Main
module Actions
module Home
class Index < Hanami::Action
def handle(*, res)
res.body = "Hello world"
end
end
end
end
end
RUBY
write "slices/admin/actions/dashboard/show.rb", <<~RUBY
require "hanami/action"
module Admin
module Actions
module Dashboard
class Show < Hanami::Action
def handle(*, res)
res.body = "Admin dashboard here"
end
end
end
end
end
RUBY
require "hanami/boot"
get "/"
expect(last_response.status).to eq 200
expect(last_response.body).to eq "Hello world"
get "/inline"
expect(last_response.status).to eq 200
expect(last_response.body).to eq "Inline"
get "/health"
expect(last_response.status).to eq 200
expect(last_response.body).to eq "Health, OK"
get "/admin/dashboard"
expect(last_response.status).to eq 200
expect(last_response.body).to eq "Admin dashboard here"
end
end
# TODO: is this test even needed, given this is standard hanami-router behavior?
specify "It gives priority to the last declared route" do
with_tmp_directory(Dir.mktmpdir) do
write "config/app.rb", <<~RUBY
require "hanami"
module TestApp
class App < Hanami::App
config.logger.stream = File.new("/dev/null", "w")
end
end
RUBY
write "config/routes.rb", <<~RUBY
module TestApp
class Routes < Hanami::Routes
define do
root to: "home.index"
slice :main, at: "/" do
root to: "home.index"
end
end
end
end
RUBY
write "app/actions/home/index.rb", <<~RUBY
require "hanami/action"
module TestApp
module Actions
module Home
class Index < Hanami::Action
def handle(*, res)
res.body = "Hello from App"
end
end
end
end
end
RUBY
write "slices/main/actions/home/index.rb", <<~RUBY
require "hanami/action"
module Main
module Actions
module Home
class Index < Hanami::Action
def handle(*, res)
res.body = "Hello from Slice"
end
end
end
end
end
RUBY
require "hanami/boot"
get "/"
expect(last_response.status).to eq 200
expect(last_response.body).to eq "Hello from Slice"
end
end
specify "It does not choose actions from slice to route in app" do
with_tmp_directory(Dir.mktmpdir) do
write "config/app.rb", <<~RUBY
require "hanami"
module TestApp
class App < Hanami::App
config.logger.stream = File.new("/dev/null", "w")
end
end
RUBY
write "config/routes.rb", <<~RUBY
module TestApp
class Routes < Hanami::Routes
define do
get "/feedbacks", to: "feedbacks.index"
slice :api, at: "/api" do
get "/people", to: "people.index"
end
end
end
end
RUBY
write "app/action.rb", <<~RUBY
# auto_register: false
require "hanami/action"
module TestApp
class Action < Hanami::Action
end
end
RUBY
write "app/actions/feedbacks/index.rb", <<~RUBY
module TestApp
module Actions
module Feedbacks
class Index < TestApp::Action
def handle(*, res)
res.body = "Feedbacks"
end
end
end
end
end
RUBY
write "slices/api/action.rb", <<~RUBY
module API
class Action < TestApp::Action
end
end
RUBY
write "slices/api/actions/people/index.rb", <<~RUBY
module API
module Actions
module People
class Index < API::Action
def handle(*, res)
res.body = "People"
end
end
end
end
end
RUBY
require "hanami/boot"
get "/api/people"
expect(last_response.status).to eq 200
expect(last_response.body).to eq "People"
end
end
specify "For a booted app, rack_app raises an exception if a referenced action isn't registered in the app" do
with_tmp_directory(Dir.mktmpdir) do
write "config/app.rb", <<~RUBY
require "hanami"
module TestApp
class App < Hanami::App
end
end
RUBY
write "config/routes.rb", <<~RUBY
module TestApp
class Routes < Hanami::Routes
define do
get "/missing", to: "missing.action"
end
end
end
RUBY
require "hanami/boot"
expect { Hanami.app.rack_app }.to raise_error do |exception|
expect(exception).to be_kind_of(Hanami::Slice::Routing::UnknownActionError)
expect(exception.message).to include("missing.action")
end
end
end
specify "For a booted app, rack_app raises an error if a referenced action isn't registered in a slice" do
with_tmp_directory(Dir.mktmpdir) do
write "config/app.rb", <<~RUBY
require "hanami"
module TestApp
class App < Hanami::App
register_slice :admin
end
end
RUBY
write "config/routes.rb", <<~RUBY
module TestApp
class Routes < Hanami::Routes
define do
slice :admin, at: "/admin" do
get "/missing", to: "missing.action"
end
end
end
end
RUBY
require "hanami/boot"
expect { Hanami.app.rack_app }.to raise_error do |exception|
expect(exception).to be_kind_of(Hanami::Slice::Routing::UnknownActionError)
expect(exception.message).to include("missing.action")
end
end
end
specify "For a non-booted app, rack_app does not raise an error if a referenced action isn't registered in the app" do
with_tmp_directory(Dir.mktmpdir) do
write "config/app.rb", <<~RUBY
require "hanami"
module TestApp
class App < Hanami::App
end
end
RUBY
write "config/routes.rb", <<~RUBY
module TestApp
class Routes < Hanami::Routes
define do
get "/missing", to: "missing.action"
end
end
end
RUBY
require "hanami/prepare"
expect { Hanami.app.rack_app }.not_to raise_error
expect { get "/missing" }.to raise_error do |exception|
expect(exception).to be_kind_of(Hanami::Slice::Routing::UnknownActionError)
expect(exception.message).to include("missing.action")
end
end
end
specify "For a non-booted app, rack_app does not raise an error if a referenced action isn't registered in a slice" do
with_tmp_directory(Dir.mktmpdir) do
write "config/app.rb", <<~RUBY
require "hanami"
module TestApp
class App < Hanami::App
register_slice :admin
end
end
RUBY
write "config/routes.rb", <<~RUBY
module TestApp
class Routes < Hanami::Routes
define do
slice :admin, at: "/admin" do
get "/missing", to: "missing.action"
end
end
end
end
RUBY
require "hanami/prepare"
expect { Hanami.app.rack_app }.not_to raise_error
expect { get "/admin/missing" }.to raise_error do |exception|
expect(exception).to be_kind_of(Hanami::Slice::Routing::UnknownActionError)
expect(exception.message).to include("missing.action")
end
end
end
specify "rack_app raises an error if a referenced slice is not registered" do
with_tmp_directory(Dir.mktmpdir) do
write "config/app.rb", <<~RUBY
require "hanami"
module TestApp
class App < Hanami::App
end
end
RUBY
write "config/routes.rb", <<~RUBY
module TestApp
class Routes < Hanami::Routes
define do
slice :foo, at: "/foo" do
get "/bar", to: "bar.index"
end
end
end
end
RUBY
require "hanami/prepare"
expect { Hanami.app.rack_app }.to raise_error do |exception|
expect(exception).to be_kind_of(Hanami::SliceLoadError)
expect(exception.message).to include("Slice 'foo' not found")
end
end
end
end