require_relative "matchers/chat_route_matcher" require_relative "matchers/http_route_matcher" require_relative "matchers/event_route_matcher" require_relative "matchers/deprecated" module Lita module RSpec # Extras for +RSpec+ to facilitate testing Lita handlers. module Handler include Matchers::ChatRouteMatcher include Matchers::HTTPRouteMatcher include Matchers::EventRouteMatcher class << self # Sets up the RSpec environment to easily test Lita handlers. def included(base) base.send(:include, Lita::RSpec) prepare_handlers(base) prepare_let_blocks(base) prepare_subject(base) prepare_robot(base) end private # Stub Lita.handlers. def prepare_handlers(base) base.class_eval do before do handlers = Set.new( [described_class] + Array(base.metadata[:additional_lita_handlers]) ) if Lita.version_3_compatibility_mode? allow(Lita).to receive(:handlers).and_return(handlers) else handlers.each do |handler| registry.register_handler(handler) end end end end end # Create common test objects. def prepare_let_blocks(base) base.class_eval do let(:robot) { Robot.new(registry) } let(:source) { Source.new(user: user) } let(:user) { User.create("1", name: "Test User") } let(:replies) { [] } end end # Stub Lita::Robot#send_messages. def prepare_robot(base) base.class_eval do before do [:send_messages, :send_message].each do |message| allow(robot).to receive(message) do |_target, *strings| replies.concat(strings) end end end end end # Set up a working test subject. def prepare_subject(base) base.class_eval do subject { described_class.new(robot) } before { allow(described_class).to receive(:new).and_return(subject) } end end end # Sends a message to the robot. # @param body [String] The message to send. # @param as [Lita::User] The user sending the message. # @return [void] def send_message(body, as: user) message = if as == user Message.new(robot, body, source) else Message.new(robot, body, Source.new(user: as)) end robot.receive(message) end # Sends a "command" message to the robot. # @param body [String] The message to send. # @param as [Lita::User] The user sending the message. # @return [void] def send_command(body, as: user) send_message("#{robot.mention_name}: #{body}", as: as) end # Returns a Faraday connection hooked up to the currently running robot's Rack app. # @return [Faraday::Connection] The connection. # @since 4.0.0 def http begin require "rack/test" rescue LoadError raise LoadError, I18n.t("lita.rspec.rack_test_required") end unless Rack.const_defined?(:Test) Faraday::Connection.new { |c| c.adapter(:rack, robot.app) } end # Starts a chat routing test chain, asserting that a message should # trigger a route. # @param message [String] The message that should trigger the route. # @return [Matchers::Deprecated] A {Matchers::Deprecated} that should have +to+ # called on it to complete the test. # @deprecated Will be removed in Lita 5.0. Use +is_expected.to route+ instead. def routes(message) STDERR.puts I18n.t( "lita.rspec.matcher_deprecated", old_method: "routes", new_method: "is_expected.to route", ) Matchers::Deprecated.new(self, :route, true, message) end # Starts a chat routing test chain, asserting that a message should not # trigger a route. # @param message [String] The message that should not trigger the route. # @return [Matchers::Deprecated] A {Matchers::Deprecated} that should have +to+ # called on it to complete the test. # @deprecated Will be removed in Lita 5.0. Use +is_expected.not_to route+ instead. def does_not_route(message) STDERR.puts I18n.t( "lita.rspec.matcher_deprecated", old_method: "does_not_route", new_method: "is_expected.not_to route", ) Matchers::Deprecated.new(self, :route, false, message) end alias_method :doesnt_route, :does_not_route # Starts a chat routing test chain, asserting that a "command" message # should trigger a route. # @param message [String] The message that should trigger the route. # @return [Matchers::Deprecated] A {Matchers::Deprecated} that should have +to+ # called on it to complete the test. # @deprecated Will be removed in Lita 5.0. Use +is_expected.to route_command+ instead. def routes_command(message) STDERR.puts I18n.t( "lita.rspec.matcher_deprecated", old_method: "routes_command", new_method: "is_expected.to route_command", ) Matchers::Deprecated.new(self, :route_command, true, message) end # Starts a chat routing test chain, asserting that a "command" message # should not trigger a route. # @param message [String] The message that should not trigger the route. # @return [Matchers::Deprecated] A {Matchers::Deprecated} that should have +to+ # called on it to complete the test. # @deprecated Will be removed in Lita 5.0. Use +is_expected.not_to route_command+ instead. def does_not_route_command(message) STDERR.puts I18n.t( "lita.rspec.matcher_deprecated", old_method: "does_not_route_command", new_method: "is_expected.not_to route_command", ) Matchers::Deprecated.new(self, :route_command, false, message) end alias_method :doesnt_route_command, :does_not_route_command # Starts an HTTP routing test chain, asserting that a request to the given # path with the given HTTP request method will trigger a route. # @param http_method [Symbol] The HTTP request method that should trigger # the route. # @param path [String] The path URL component that should trigger the # route. # @return [Matchers::Deprecated] A {Matchers::Deprecated} that should # have +to+ called on it to complete the test. # @deprecated Will be removed in Lita 5.0. Use +is_expected.to route_http+ instead. def routes_http(http_method, path) STDERR.puts I18n.t( "lita.rspec.matcher_deprecated", old_method: "routes_http", new_method: "is_expected.to route_http", ) Matchers::Deprecated.new(self, :route_http, true, http_method, path) end # Starts an HTTP routing test chain, asserting that a request to the given # path with the given HTTP request method will not trigger a route. # @param http_method [Symbol] The HTTP request method that should not # trigger the route. # @param path [String] The path URL component that should not trigger the # route. # @return [Matchers::Deprecated] A {Matchers::Deprecated} that should # have +to+ called on it to complete the test. # @deprecated Will be removed in Lita 5.0. Use +is_expected.not_to route_http+ instead. def does_not_route_http(http_method, path) STDERR.puts I18n.t( "lita.rspec.matcher_deprecated", old_method: "does_not_route_http", new_method: "is_expected.not_to route_http", ) Matchers::Deprecated.new(self, :route_http, false, http_method, path) end alias_method :doesnt_route_http, :does_not_route_http # Starts an event subscription test chain, asserting that an event should # trigger the target method. # @param event_name [String, Symbol] The name of the event that should # be triggered. # @return [Matchers::Deprecated] A {Matchers::Deprecated} that # should have +to+ called on it to complete the test. # @deprecated Will be removed in Lita 5.0. Use +is_expected.to route_event+ instead. def routes_event(event_name) STDERR.puts I18n.t( "lita.rspec.matcher_deprecated", old_method: "routes_event", new_method: "is_expected.to route_event", ) Matchers::Deprecated.new(self, :route_event, true, event_name) end # Starts an event subscription test chain, asserting that an event should # not trigger the target method. # @param event_name [String, Symbol] The name of the event that should # not be triggered. # @return [Matchers::Deprecated] A {Matchers::Deprecated} that # should have +to+ called on it to complete the test. # @deprecated Will be removed in Lita 5.0. Use +is_expected.not_to route_event+ instead. def does_not_route_event(event_name) STDERR.puts I18n.t( "lita.rspec.matcher_deprecated", old_method: "does_not_route_event", new_method: "is_expected.not_to route_event", ) Matchers::Deprecated.new(self, :route_event, false, event_name) end alias_method :doesnt_route_event, :does_not_route_event end end end