# frozen_string_literal: true require 'rspec/roda/version' require 'rspec' require 'rspec/its' require 'rack/test' require 'inflecto' module RSpec # Module containing different contexts for Roda. module Roda # Module containing helpers for specifying Roda apps. module App include Rack::Test::Methods # @return [Class(Roda)] def roda_class described_class end # Rack-, and Rack::Test-compliant Roda app # @return [#call] def app roda_class.app.freeze end end # Module containing helpers for specifying Roda plugins. module Plugin # Class interface for plugin specs. module ClassInterface # @param [Module] child def included(child) super(child) roda end # @param [Symbol] plugin # @param [Proc] block def roda(plugin = metadata[:name], &block) let(:roda_class) do route_block = self.route_block self.class.const_set(:TestApp, Class.new(::Roda) do plugin plugin instance_exec(&block) if block route { |r| instance_exec(r, &route_block) } if route_block end) end end # @param [Proc] block def route(&block) let(:route_block) { block } roda # re-initiate app end private # @return [Symbol] def plugin_name @plugin_name ||= metadata[:name] || Inflecto.underscore( Inflecto.demodulize(described_class.name) ) end end end end end RSpec.shared_context 'Roda app', roda: :app do include RSpec::Roda::App let(:roda_instance) { roda_class.new(env) } let(:env) { {} } end RSpec.shared_context 'Roda plugin', roda: :plugin do extend RSpec::Roda::Plugin::ClassInterface include_context 'Roda app' let(:route_block) { proc { |r| } } end