зеркало из
https://github.com/glebtv/telegram-bot.git
synced 2026-09-07 19:35:52 +03:00
RSpec matchers
Этот коммит содержится в:
@@ -43,7 +43,7 @@ module Telegram
|
||||
@requests = Hash.new { |h, k| h[k] = [] }
|
||||
end
|
||||
|
||||
def request(action, body)
|
||||
def request(action, body = {})
|
||||
requests[action.to_sym] << body
|
||||
end
|
||||
end
|
||||
|
||||
7
lib/telegram/bot/rspec.rb
Обычный файл
7
lib/telegram/bot/rspec.rb
Обычный файл
@@ -0,0 +1,7 @@
|
||||
module Telegram
|
||||
module Bot
|
||||
module RSpec
|
||||
autoload :ClientMatchers, 'telegram/bot/rspec/client_matchers'
|
||||
end
|
||||
end
|
||||
end
|
||||
151
lib/telegram/bot/rspec/client_matchers.rb
Обычный файл
151
lib/telegram/bot/rspec/client_matchers.rb
Обычный файл
@@ -0,0 +1,151 @@
|
||||
module Telegram
|
||||
module Bot
|
||||
module RSpec
|
||||
# Proxy that uses RSpec::Mocks::ArgListMatcher when it's available.
|
||||
# Otherwise just performs `#==` match.
|
||||
#
|
||||
# Also allows to check argumets with custom block.
|
||||
class ArgListMatcher
|
||||
attr_reader :expected, :expected_proc
|
||||
|
||||
def initialize(*args, &block)
|
||||
@expected_proc = block if block_given?
|
||||
@expected =
|
||||
if mocks_matcher?
|
||||
::RSpec::Mocks::ArgumentListMatcher.new(*args)
|
||||
else
|
||||
args
|
||||
end
|
||||
end
|
||||
|
||||
def args_match?(*actual)
|
||||
if expected_proc
|
||||
expected_proc[*actual]
|
||||
true
|
||||
elsif mocks_matcher?
|
||||
expected.args_match?(*actual)
|
||||
else
|
||||
expected == actual
|
||||
end
|
||||
end
|
||||
|
||||
def args
|
||||
mocks_matcher? ? expected.args : expected
|
||||
end
|
||||
|
||||
def mocks_matcher?
|
||||
defined?(::RSpec::Mocks::ArgumentListMatcher)
|
||||
end
|
||||
|
||||
def to_s
|
||||
if mocks_matcher?
|
||||
expected.expected_args.inspect
|
||||
elsif expected_proc
|
||||
'(proc matcher)'
|
||||
else
|
||||
expected.inspect
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
# Matchers to test requests to Telegram API.
|
||||
#
|
||||
# Complex matchers requires `rspec-mocks` to be installed.
|
||||
module ClientMatchers
|
||||
class MakeTelegramRequest < ::RSpec::Matchers::BuiltIn::BaseMatcher
|
||||
EXPECTATION_TYPES = {
|
||||
exactly: :==,
|
||||
at_most: :>=,
|
||||
at_least: :<=,
|
||||
}.freeze
|
||||
|
||||
attr_reader :performed_requests, :description
|
||||
|
||||
def initialize(bot, action, description: nil)
|
||||
@bot = bot
|
||||
@action = action
|
||||
@description = description || "make #{action} telegram request"
|
||||
exactly(1)
|
||||
end
|
||||
|
||||
def matches?(proc) # rubocop:disable AbcSize
|
||||
raise ArgumentError, 'matcher only supports block expectations' unless proc.is_a?(Proc)
|
||||
original_requests_count = bot.requests[action].count
|
||||
proc.call
|
||||
@performed_requests = bot.requests[action].drop(original_requests_count)
|
||||
@matching_requests_count = performed_requests.count do |request|
|
||||
!arg_list_matcher || arg_list_matcher.args_match?(request)
|
||||
end
|
||||
expectation_method = EXPECTATION_TYPES[expectation_type]
|
||||
expected_number.public_send(expectation_method, matching_requests_count)
|
||||
end
|
||||
|
||||
def with(*args, &block)
|
||||
@arg_list_matcher = ArgListMatcher.new(*args, &block)
|
||||
self
|
||||
end
|
||||
|
||||
EXPECTATION_TYPES.each_key do |type|
|
||||
define_method type do |count|
|
||||
@expectation_type = type
|
||||
@expected_number = Integer(count)
|
||||
self
|
||||
end
|
||||
end
|
||||
|
||||
def times
|
||||
self
|
||||
end
|
||||
|
||||
def failure_message
|
||||
"expected to #{base_message}"
|
||||
end
|
||||
|
||||
def failure_message_when_negated
|
||||
"expected not to #{base_message}"
|
||||
end
|
||||
|
||||
def supports_block_expectations?
|
||||
true
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
attr_reader :bot, :action, :expectation_type, :expected_number,
|
||||
:arg_list_matcher, :matching_requests_count
|
||||
|
||||
def base_message
|
||||
"make #{expectation_type.to_s.tr('_', ' ')} #{expected_number} " \
|
||||
"#{bot.inspect}.#{action} requests,".tap do |msg|
|
||||
msg << " with #{arg_list_matcher}," if arg_list_matcher
|
||||
msg << " but made #{matching_requests_count}"
|
||||
if performed_requests
|
||||
actual_args = performed_requests.map(&:inspect).join(', ')
|
||||
msg << ", and #{performed_requests.count} with #{actual_args}"
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
# Check that bot performed request to telegram API:
|
||||
#
|
||||
# expect { dispatch_message('Hi!') }.
|
||||
# to make_telegram_request(bot, :sendMessage).
|
||||
# with(text: 'Hello!', chat_id: chat_id)
|
||||
def make_telegram_request(bot, action)
|
||||
MakeTelegramRequest.new(bot, action)
|
||||
end
|
||||
|
||||
# Helper for asserting message is sent. Note that options are checked
|
||||
# with `hash_including`. For strict checks use #make_telegram_request.
|
||||
def send_telegram_message(bot, text = nil, options = {})
|
||||
text = a_string_matching(text) if text.is_a?(Regexp)
|
||||
options = options.merge(text: text) if text
|
||||
description = "send telegram message #{text.inspect}"
|
||||
MakeTelegramRequest.new(bot, :sendMessage, description: description).
|
||||
with(hash_including(options))
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -50,7 +50,7 @@ module Telegram
|
||||
# ControllerClass.new(bot, from: telegram_user, chat: telegram_chat).
|
||||
# process(:help, *args)
|
||||
#
|
||||
class UpdatesController < AbstractController::Base # rubocop:disable ClassLength
|
||||
class UpdatesController < AbstractController::Base
|
||||
abstract!
|
||||
|
||||
require 'telegram/bot/updates_controller/session'
|
||||
|
||||
@@ -14,11 +14,14 @@ RSpec.shared_context 'telegram/bot/updates_controller' do
|
||||
let(:bot_name) { 'bot' }
|
||||
let(:session) { controller.send(:session) }
|
||||
|
||||
include Telegram::Bot::RSpec::ClientMatchers
|
||||
|
||||
def dispatch(bot = self.bot, update = self.update)
|
||||
controller.dispatch_again(bot, update)
|
||||
end
|
||||
|
||||
def dispatch_message(text, options = {})
|
||||
def dispatch_message(text, options = nil)
|
||||
options ||= respond_to?(:default_message_options) ? default_message_options : {}
|
||||
update = build_update :message, options.merge(text: text)
|
||||
dispatch bot, update
|
||||
end
|
||||
@@ -34,4 +37,9 @@ RSpec.shared_context 'telegram/bot/updates_controller' do
|
||||
else input
|
||||
end
|
||||
end
|
||||
|
||||
# Matcher to check response. Make sure to define `let(:chat_id)`.
|
||||
def respond_with_message(expected)
|
||||
send_telegram_message(bot, expected, chat_id: chat_id)
|
||||
end
|
||||
end
|
||||
|
||||
Ссылка в новой задаче
Block a user