# frozen_string_literal: true
# Copyright 2022 Felix Freeman <libsys@hacktivista.org>
#
# This file is part of "LeanWeb" and licensed under the terms of the Hacktivista
# General Public License version 0.1 or (at your option) any later version. You
# should have received a copy of this license along with the software. If not,
# see <https://hacktivista.org/licenses/>.
require 'rack'
require 'test_helper'
# Route tests.
class RouteTest < Minitest::Test
def test_new__path_only
route = LeanWeb::Route.new(path: '/')
assert_equal(
['/', 'GET', %w[main MainController index_get], true],
route_to_array(route)
)
end
def test_new__action_string
route = LeanWeb::Route.new(path: '/', action: 'action')
assert_equal(
%w[main MainController action],
Array(route.action)
)
end
def test_new__action_tuple
route = LeanWeb::Route.new(path: '/', action: { 'controller' => 'action' })
assert_equal(
%w[controller ControllerController action],
Array(route.action)
)
end
def test_new__action_file_only_hash
route = LeanWeb::Route.new(path: '/', action: { file: 'file' })
assert_equal(
%w[file FileController index_get],
Array(route.action)
)
end
def test_new__action_controller_only_hash
route = LeanWeb::Route.new(path: '/', action: { controller: 'controller' })
assert_equal(
%w[main controller index_get],
Array(route.action)
)
end
def test_new__action_action_only_hash
route = LeanWeb::Route.new(path: '/', action: { action: 'action' })
assert_equal(
%w[main MainController action],
Array(route.action)
)
end
def test_new__action_full_hash
route = LeanWeb::Route.new(
path: '/',
action: { file: 'file', controller: 'controller', action: 'action' }
)
assert_equal(
%w[file controller action],
Array(route.action)
)
end
def test_new__all_params
route = LeanWeb::Route.new(
path: '/path', method: 'POST', action: 'path_post', static: false
)
assert_equal(
['/path', 'POST', %w[main MainController path_post], false],
route_to_array(route)
)
end
def test_path_basename__simple
route = LeanWeb::Route.new(path: '/simple_path')
assert_equal('simple_path', route.path_basename)
end
def test_path_basename__nested
route = LeanWeb::Route.new(path: '/a/nested/path')
assert_equal('path', route.path_basename)
end
def test_path_basename__index
route = LeanWeb::Route.new(path: '/')
assert_equal('index', route.path_basename)
end
def test_path_basename__nested_index
route = LeanWeb::Route.new(path: '/nested/')
assert_equal('index', route.path_basename)
end
def test_respond__method_no_params
write_controller(
'Rack::Response.new("default_action").finish'
) do |action|
route = LeanWeb::Route.new(path: '/', action: action)
assert_equal(
[200, {}, ['default_action']],
route.respond(Rack::Request.new(env('/')))
)
end
end
def test_respond__method_positional_params
write_controller(
'Rack::Response.new("#{param1} #{param2}").finish', # rubocop: disable all
'positional_get(param1, param2)'
) do |action|
route = LeanWeb::Route.new(
path: %r{^/method/pos/([^/]+)/(.+)$},
action: action
)
assert_equal(
[200, {}, ['dynamic route']],
route.respond(Rack::Request.new(env('/method/pos/dynamic/route')))
)
end
end
def test_respond__method_keyword_params
write_controller(
'Rack::Response.new("#{named1} #{named2}").finish', # rubocop: disable all
'named_get(named1:, named2:)'
) do |action|
route = LeanWeb::Route.new(
path: %r{^/method/named/(?<named1>[^/]+)/(?<named2>.+)$},
action: action
)
assert_equal(
[200, {}, ['dynamic route']],
route.respond(Rack::Request.new(env('/method/named/dynamic/route')))
)
end
end
def test_respond__proc
route = LeanWeb::Route.new(
path: '/',
action: -> { Rack::Response.new('proc_response').finish }
)
assert_equal(
[200, {}, ['proc_response']],
route.respond(Rack::Request.new(env('/')))
)
end
def test_respond__proc_positional_params
route = LeanWeb::Route.new(
path: %r{^/proc/positional/([^/]+)/(.+)$},
action: lambda do |param1, param2|
Rack::Response.new("#{param1} #{param2}").finish
end
)
assert_equal(
[200, {}, ['dynamic route']],
route.respond(Rack::Request.new(env('/proc/positional/dynamic/route')))
)
end
def test_respond__proc_keyword_params
route = LeanWeb::Route.new(
path: %r{^/proc/named/(?<named1>[^/]+)/(?<named2>.+)$},
action: lambda do |named1:, named2:|
Rack::Response.new("#{named1} #{named2}").finish
end
)
assert_equal(
[200, {}, ['dynamic route']],
route.respond(Rack::Request.new(env('/proc/named/dynamic/route')))
)
end
def test_seed_path__hash
route = LeanWeb::Route.new(path: %r{^/(?<named1>[^/]+)/(?<named2>.+)$})
assert_equal(
'/hash/path',
route.seed_path({ named1: 'hash', named2: 'path' })
)
end
def test_seed_path__array
route = LeanWeb::Route.new(path: %r{^/([^/]+)/(.+)$})
assert_equal('/hash/path', route.seed_path(%w[hash path]))
end
protected
def route_to_array(route)
[route.path, route.method, Array(route.action), route.static]
end
def random_word(length = 10)
chars = [*('a'..'z')]
word = ''
length.times { word += chars[rand(chars.size)] }
word
end
# Writes a controller on a random file and opens a block for working with it.
# @param response [String] Code to be evaluated inside action.
# @param action [String] Defaults to random word. You can use params too.
# @param controller [String] Defaults to random word.
# @yieldparam [Hash] ready-to-use Route action hash.
# @yieldparam [Tempfile] this controller file.
def write_controller(
response, action = random_word, controller = random_word.capitalize
)
FileUtils.mkdir_p(LeanWeb::CONTROLLER_PATH)
Tempfile.create(['', '.rb'], LeanWeb::CONTROLLER_PATH) do |file|
file.write(
<<~RUBY
require 'leanweb'
require 'rack'
class #{controller} < LeanWeb::Controller
def #{action}
#{response}
end
end
RUBY
)
file.rewind
yield({ file: File.basename(file.path, '.rb'),
controller: controller,
action: action.sub(/\(.*/, '') }, file)
end
end
end