1
0
зеркало из https://github.com/glebtv/telegram-bot.git synced 2026-08-28 15:26:18 +03:00

Сравнить коммиты

..

17 Коммитов

Автор SHA1 Сообщение Дата
Max Melentiev
88178113d7 Support (edited_)channel_post updates, add api methods from 2.3, 2.3.1 2016-12-09 13:23:58 +03:00
printercu
1a2ac0dd83 Update README.md 2016-11-16 21:31:02 +03:00
Max Melentiev
fa6e385ca1 v0.10.0 2016-11-16 20:51:41 +03:00
Max Melentiev
1098118826 Fix integration spec for Rails 4 2016-11-16 14:34:42 +03:00
Max Melentiev
0c9a4a5fa0 Inegration context for RSpec
ActionDispatch::Testing::Integration requires smth else and
defines Rails, so had to change `defined?(Rails)` all over the code.
2016-11-16 14:18:45 +03:00
printercu
5c299887bb Merge pull request #18 from bob-frost/ruby2.2.0
Error "can't dup Fixnum (TypeError)"
2016-11-13 19:16:59 +03:00
bob-frost
9f2234c132 Fix "can't dup Fixnum (TypeError)" for Ruby 2.2.0 2016-11-13 09:47:01 +06:00
Max Melentiev
ec1d5bad7d v0.9.0 2016-11-07 20:24:01 +03:00
Max Melentiev
194fc78202 RSpec matchers 2016-11-07 20:17:34 +03:00
Max Melentiev
ececfa660e [Docs] Note about queue adapters 2016-10-19 14:20:39 +03:00
printercu
9e67122465 Merge pull request #2 from telegram-bot-rb/async
Async requests
2016-10-19 14:00:26 +03:00
Max Melentiev
caee9809d0 More docs on async mode 2016-10-19 13:59:54 +03:00
Max Melentiev
4b511f51a7 update changelog 2016-10-19 13:36:03 +03:00
Max Melentiev
d2d6202fa7 API methods from 2016-10-03 update
https://core.telegram.org/bots/api-changelog#october-3-2016
2016-10-17 17:43:13 +03:00
Max Melentiev
dd38cfea93 Take chat from message for callback queries 2016-10-07 12:45:16 +03:00
Max Melentiev
3cb6e930b8 Fix typo in module name: CallbackQueyContext -> CallbackQueryContext 2016-09-22 01:12:19 +03:00
Max Melentiev
e42a293804 edit_message_* methods 2016-09-21 22:53:06 +03:00
21 изменённых файлов: 546 добавлений и 31 удалений

Просмотреть файл

@@ -1,6 +1,22 @@
# Unreleased
# 0.10.1
- Support `(edited_)channel_post` updates.
- New methods from 2.3, 2.3.1 API updates.
# 0.10.0
- Integration helpers for RSpec.
- Fix for ruby 2.2.0 bug by @bob-frost.
# 0.9.0
- Async API requests.
- One more description for StaleChat error.
- edit_message_* methods.
- API methods from 2016-10-03 update
- Fix typo in module name: CallbackQueyContext -> CallbackQueryContext.
- Take `chat` from `message` for callback queries
- RSpec matchers.
# 0.8.0

Просмотреть файл

@@ -13,9 +13,9 @@ group :development do
gem 'pry', '~> 0.10.1'
gem 'pry-byebug', '~> 3.2.0'
gem 'telegram-bot-types', '~> 0.2.0'
gem 'telegram-bot-types', '~> 0.3.0'
gem 'rspec', '~> 3.3.0'
gem 'rspec', '~> 3.5.0'
gem 'rspec-its', '~> 1.1.0'
gem 'rubocop', '~> 0.37.0'

Просмотреть файл

@@ -17,12 +17,16 @@ Package contains:
- Middleware and routes helpers for production env.
- Poller with automatic source-reloader for development env.
- Rake tasks to update webhook urls.
- Async requests for Telegram and/or Botan API. Let the queue adapter handle errors!
- __[Async mode](#async-mode)__ for Telegram and/or Botan API.
Let the queue adapter handle network errors!
Here is sample [telegram_bot_app](https://github.com/telegram-bot-rb/telegram_bot_app)
with session, keyboards and inline queries.
Run it on your local machine in 1 minute!
And here is [app teamplate](https://github.com/telegram-bot-rb/rails_template)
to generate clean app in seconds.
## Installation
Add this line to your application's Gemfile:
@@ -132,6 +136,7 @@ class Telegram::WebhookController < Telegram::Bot::UpdatesController
# do_smth_with(data)
# There are `chat` & `from` shortcut methods.
# For callback queries `chat` if taken from `message` when it's available.
response = from ? "Hello #{from['username']}!" : 'Hi there!'
# There is `respond_with` helper to set `chat_id` from received message:
respond_with :message, text: response
@@ -246,7 +251,7 @@ class Telegram::WebhookController < Telegram::Bot::UpdatesController
end
```
You can use `CallbackQueyContext` in the similar way to split `#callback_query` into
You can use `CallbackQueryContext` in the similar way to split `#callback_query` into
several specific methods. It doesn't require session support, and takes context from
data. If data has a prefix with colon like this `my_ctx:smth...` it'll call
`my_ctx_callback_query('smth...')` when there is such action method. Otherwise
@@ -321,18 +326,51 @@ To stub all possible clients use `Telegram::Bot::ClientStub.stub_all!` before
initializing clients. Most likely you'll want something like this:
```ruby
# environments/test.rb
# Make sure to run it before defining routes or storing bot to some place in app!
Telegram.reset_bots
Telegram::Bot::ClientStub.stub_all!
# rails_helper.rb
RSpec.configure do |config|
# ...
Telegram.reset_bots
Telegram::Bot::ClientStub.stub_all!
config.after { Telegram.bot.reset }
# ...
end
```
There are also some helpers for controller tests.
Check out `telegram/bot/updates_controller/rspec_helpers` and
`telegram/bot/updates_controller/testing`.
There are integration and controller contexts for RSpec and some built-in matchers:
```ruby
# spec/requests/telegram_webhooks_spec.rb
require 'telegram/bot/rspec/integration'
RSpec.describe TelegramWebhooksController, :telegram_bot do
# for old rspec add:
# include_context 'telegram/bot/integration'
describe '#start' do
subject { -> { dispatch_command :start } }
it { should respond_with_message 'Hi there!' }
end
end
# For controller specs use
require 'telegram/bot/updates_controller/rspec_helpers'
RSpec.describe TelegramWebhooksController, type: :telegram_bot_controller do
# for old rspec add:
# include_context 'telegram/bot/updates_controller'
end
# Matchers are available for custom specs:
include Telegram::Bot::RSpec::ClientMatchers
expect(&process_update).to send_telegram_message(bot, /msg regexp/, some: :option)
expect(&process_update).
to make_telegram_request(bot, :sendMessage, hash_including(text: 'msg text'))
```
See sample app for more examples.
### Deploying
@@ -384,11 +422,28 @@ you can implement your own worker class to handle such requests. This allows:
- Handle and retry network and other errors with queue adapter.
- ???
Instead of performing request instantly client serializes it, pushes to queue,
and immediately return control back. The job is then fetched with a worker
and real API request is performed. And this all is absolutely transparent for the app.
To enable this mode add `async: true` to bot's and botan's config.
For more information and custom configuration check out
[docs](http://www.rubydoc.info/github/telegram-bot-rb/telegram-bot/master/Telegram/Bot/Async) or
[source](https://github.com/telegram-bot-rb/telegram-bot/blob/master/lib/telegram/bot/async.rb).
If you want async mode, but don't want to setup queue, know that Rails 5 are shipped
with Async adapter by default, and there is
[Sucker Punch](https://github.com/brandonhilkert/sucker_punch) for Rails 4.
Be aware of some limitations:
- Client will not return API response.
- Sending files is not available in async mode [now],
because them can not be serialized.
To disable async mode for the block of code use `bot.async(false) { bot.send_photo }`.
Yes, it's threadsafe too.
## Development
After checking out the repo, run `bin/setup` to install dependencies.

Просмотреть файл

@@ -34,6 +34,7 @@ module Telegram
autoload :DebugClient, 'telegram/bot/debug_client'
autoload :Initializers, 'telegram/bot/initializers'
autoload :Middleware, 'telegram/bot/middleware'
autoload :RSpec, 'telegram/bot/rspec'
autoload :UpdatesController, 'telegram/bot/updates_controller'
autoload :UpdatesPoller, 'telegram/bot/updates_poller'
end

Просмотреть файл

@@ -116,7 +116,7 @@ module Telegram
attr_reader :id
def initialize(*, id: nil, async: nil, **)
def initialize(*, id: nil, async: nil, **options)
@id = id
self.async = async
super

Просмотреть файл

@@ -5,7 +5,7 @@ module Telegram
module ClientHelpers
attr_reader :botan
def initialize(*, botan: nil, **)
def initialize(*, botan: nil, **options)
super
@botan = Botan.wrap(botan, id: id) if botan
end

Просмотреть файл

@@ -60,9 +60,14 @@ module Telegram
raise Error, err_msg
end
# Splited to the sections similar to API docs.
%w(
deleteWebhook
getUpdates
getWebhookInfo
setWebhook
answerCallbackQuery
answerInlineQuery
forwardMessage
getChat
getChatAdministrators
@@ -70,7 +75,6 @@ module Telegram
getChatMembersCount
getFile
getMe
getUpdates
getUserProfilePhotos
kickChatMember
leaveChat
@@ -85,8 +89,17 @@ module Telegram
sendVenue
sendVideo
sendVoice
setWebhook
unbanChatMember
editMessageCaption
editMessageReplyMarkup
editMessageText
answerInlineQuery
getGameHighScores
sendGame
setGameScore
).each do |method|
define_method(method.underscore) { |*args| request(method, *args) }
end

Просмотреть файл

@@ -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

Просмотреть файл

@@ -20,7 +20,7 @@ module Telegram
def bot_poller_mode?
return @bot_poller_mode if defined?(@bot_poller_mode)
@bot_poller_mode = ENV.fetch('BOT_POLLER_MODE') do
Rails.env.development? if defined?(Rails)
Rails.env.development? if defined?(Rails.env)
end
end
@@ -47,7 +47,7 @@ module Telegram
# Can be overwritten with .bots_config=
def bots_config
@bots_config ||=
if defined?(Rails)
if defined?(Rails.application)
telegram_config = Rails.application.secrets[:telegram] || {}
(telegram_config['bots'] || {}).symbolize_keys.tap do |config|
default = telegram_config['bot']

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 Обычный файл
Просмотреть файл

@@ -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 = {})
description = "send telegram message #{text.inspect}"
text = a_string_matching(text) if text.is_a?(Regexp)
options = options.merge(text: text) if text
MakeTelegramRequest.new(bot, :sendMessage, description: description).
with(hash_including(options))
end
end
end
end
end

49
lib/telegram/bot/rspec/integration.rb Обычный файл
Просмотреть файл

@@ -0,0 +1,49 @@
RSpec.shared_context 'telegram/bot/integration' do
let(:bot) { Telegram.bot }
let(:from_id) { 123 }
let(:chat_id) { 456 }
let(:default_message_options) { {from: {id: from_id}, chat: {id: chat_id}} }
let(:controller_path) do
route_name = Telegram::Bot::RoutesHelper.route_name_for_bot(bot)
Rails.application.routes.url_helpers.public_send("#{route_name}_path")
end
let(:request_headers) do
{
'ACCEPT' => 'application/json',
'Content-Type' => 'application/json',
}
end
let(:clear_session?) { described_class.respond_to?(:session_store) }
before { described_class.session_store.clear if clear_session? }
include Telegram::Bot::RSpec::ClientMatchers
def dispatch(update)
if ActionPack::VERSION::MAJOR >= 5
post(controller_path, params: update.to_json, headers: request_headers)
else
post(controller_path, update.to_json, request_headers)
end
end
def dispatch_message(text, options = {})
dispatch message: default_message_options.merge(options).merge(text: text)
end
def dispatch_command(*args)
options = args.last.is_a?(Hash) ? args.pop : {}
dispatch_message("/#{args.join ' '}", options)
end
# Matcher to check response. Make sure to define `let(:chat_id)`.
def respond_with_message(expected)
raise 'Define chat_id to use respond_with_message' unless defined?(chat_id)
send_telegram_message(bot, expected, chat_id: chat_id)
end
end
RSpec.configure do |config|
if config.respond_to?(:include_context)
config.include_context 'telegram/bot/integration', :telegram_bot
end
end

Просмотреть файл

@@ -50,14 +50,14 @@ 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'
require 'telegram/bot/updates_controller/log_subscriber'
require 'telegram/bot/updates_controller/instrumentation'
require 'telegram/bot/updates_controller/reply_helpers'
autoload :CallbackQueyContext, 'telegram/bot/updates_controller/callback_query_context'
autoload :CallbackQueryContext, 'telegram/bot/updates_controller/callback_query_context'
autoload :MessageContext, 'telegram/bot/updates_controller/message_context'
include AbstractController::Callbacks
@@ -80,10 +80,12 @@ module Telegram
PAYLOAD_TYPES = %w(
message
edited_message
channel_post
edited_channel_post
inline_query
chosen_inline_result
callback_query
edited_message
).freeze
CMD_REGEX = %r{\A/([a-z\d_]{,31})(@(\S+))?(\s|$)}i
CONFLICT_CMD_REGEX = Regexp.new("^(#{PAYLOAD_TYPES.join('|')}|\\d)")
@@ -140,10 +142,12 @@ module Telegram
@_payload, @_payload_type = payload_data
end
# Accessor to `'chat'` field of payload. Can be overriden with `chat` option
# for #initialize.
# Accessor to `'chat'` field of payload. Also tries `'chat'` in `'message'`
# when there is no such field in payload.
#
# Can be overriden with `chat` option for #initialize.
def chat
@_chat ||= payload && payload['chat']
@_chat ||= payload.try! { |x| x['chat'] || x['message'] && x['message']['chat'] }
end
# Accessor to `'from'` field of payload. Can be overriden with `from` option

Просмотреть файл

@@ -3,7 +3,7 @@ module Telegram
class UpdatesController
# Use separate actions for different callback queries.
# It doesn't require session support. Simply add `%{context}:` prefix to data.
module CallbackQueyContext
module CallbackQueryContext
protected
# Uses #context_from_callback_query as context name.

Просмотреть файл

@@ -13,13 +13,18 @@ RSpec.shared_context 'telegram/bot/updates_controller' do
let(:bot) { Telegram::Bot::ClientStub.new(bot_name) }
let(:bot_name) { 'bot' }
let(:session) { controller.send(:session) }
let(:from_id) { 123 }
let(:chat_id) { 456 }
let(:default_message_options) { {from: {id: from_id}, chat: {id: chat_id}} }
include Telegram::Bot::RSpec::ClientMatchers
def dispatch(bot = self.bot, update = self.update)
controller.dispatch_again(bot, update)
end
def dispatch_message(text, options = {})
update = build_update :message, options.merge(text: text)
update = build_update :message, default_message_options.merge(options).merge(text: text)
dispatch bot, update
end
@@ -34,4 +39,15 @@ 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
RSpec.configure do |config|
if config.respond_to?(:include_context)
config.include_context 'telegram/bot/updates_controller', type: :telegram_bot_controller
end
end

Просмотреть файл

@@ -27,12 +27,12 @@ module Telegram
attr_reader :bot, :controller, :timeout, :offset, :logger, :running, :reload
def initialize(bot, controller, **options)
@logger = options.fetch(:logger) { defined?(Rails) && Rails.logger }
@logger = options.fetch(:logger) { defined?(Rails.logger) && Rails.logger }
@bot = bot
@controller = controller
@timeout = options.fetch(:timeout) { DEFAULT_TIMEOUT }
@offset = options[:offset]
@reload = options.fetch(:reload) { defined?(Rails) && Rails.env.development? }
@reload = options.fetch(:reload) { defined?(Rails.env) && Rails.env.development? }
end
def log(&block)
@@ -85,7 +85,7 @@ module Telegram
end
end
if defined?(Rails) && Rails.application.respond_to?(:reloader)
if defined?(Rails.application) && Rails.application.respond_to?(:reloader)
def reloading_code
Rails.application.reloader.wrap do
yield

Просмотреть файл

@@ -1,6 +1,6 @@
module Telegram
module Bot
VERSION = '0.9.0.alpha2'.freeze
VERSION = '0.10.1'.freeze
def self.gem_version
Gem::Version.new VERSION

Просмотреть файл

@@ -0,0 +1,87 @@
RSpec.describe Telegram::Bot::RSpec::ClientMatchers do
let(:bot) { Telegram::Bot::ClientStub.new('TestBot') }
let(:other_bot) { Telegram::Bot::ClientStub.new('OtherTestBot') }
include described_class
describe '#make_telegram_request' do
context 'without args' do
it 'works for matching' do
block = ->(*) { bot.send_message(text: 'test') }
expect(&block).to make_telegram_request(bot, :sendMessage)
expect { 3.times(&block) }.to make_telegram_request(bot, :sendMessage).exactly(3).times
expect { 3.times(&block) }.to make_telegram_request(bot, :sendMessage).at_least(2).times
expect { 3.times(&block) }.to make_telegram_request(bot, :sendMessage).at_most(4).times
end
it 'works for not-matching' do
block = ->(*) { bot.get_me }
expect {}.to_not make_telegram_request(bot, :getMe)
expect { other_bot.get_me }.to_not make_telegram_request(bot, :getMe)
expect { 3.times(&block) }.to_not make_telegram_request(bot, :getMe)
expect { 3.times(&block) }.to_not make_telegram_request(bot, :getMe).exactly(2).times
expect { 3.times(&block) }.to_not make_telegram_request(bot, :getMe).exactly(4).times
expect { 3.times(&block) }.to_not make_telegram_request(bot, :getMe).at_least(4).times
expect { 3.times(&block) }.to_not make_telegram_request(bot, :getMe).at_most(2).times
end
end
context 'with args' do
it 'works for exact matching' do
args = {text: 'test', parseMode: :Markdown}
block = ->(*) { bot.send_message(args) }
expect(&block).to make_telegram_request(bot, :sendMessage).with(args)
expect(&block).to_not make_telegram_request(bot, :sendMessage).with(args.except(:text))
expect { 3.times(&block) }.to make_telegram_request(bot, :sendMessage).
with(args).exactly(3).times
end
it 'works for block matchers' do
args = {text: 'test', parseMode: :Markdown}
block = ->(*) { bot.send_message(args) }
expect(&block).to make_telegram_request(bot, :sendMessage).
with { |actual| expect(actual).to eq(args) }
# It ignores block's result! Custom expectations must be used inside block.
expect(&block).to make_telegram_request(bot, :sendMessage).
with { |actual| actual == {} }
expect do
expect(&block).to_not make_telegram_request(bot, :sendMessage).
with { |actual| expect(actual).to eq({}) }
end.to raise_error RSpec::Expectations::ExpectationNotMetError
n = -1
expect { 3.times { |i| bot.send_message text: i } }.
to make_telegram_request(bot, :sendMessage).exactly(3).times.
with { |actual| expect(actual).to eq(text: n += 1) }
end
it 'works for RSpec::Mocks matchers' do
args = {text: 'test', parseMode: :Markdown}
block = ->(*) { bot.send_message(args) }
expect(&block).to make_telegram_request(bot, :sendMessage).with(hash_including(args))
expect(&block).to make_telegram_request(bot, :sendMessage).with(
text: a_string_matching(/est$/),
parseMode: :Markdown,
)
end
end
end
describe '#send_telegram_message' do
let(:args) { {text: 'test', parseMode: :Markdown} }
let(:block) { ->(*) { bot.send_message(args) } }
it 'works for matching' do
expect(&block).to send_telegram_message(bot, 'test')
expect(&block).to send_telegram_message(bot, /^tes/)
expect(&block).to send_telegram_message(bot, 'test', parseMode: :Markdown)
expect(&block).to send_telegram_message(bot, a_string_including('es'))
end
it 'works for not-matching' do
expect(&block).to_not send_telegram_message(bot, 'test!')
expect(&block).to_not send_telegram_message(bot, /tes$/)
expect(&block).to_not send_telegram_message(bot, 'test', parseMode: :HTML)
expect(&block).to_not send_telegram_message(bot, a_string_including('smth'))
end
end
end

71
spec/telegram/bot/rspec/integration_spec.rb Обычный файл
Просмотреть файл

@@ -0,0 +1,71 @@
require 'telegram/bot/rspec/integration'
require 'action_controller'
require 'action_dispatch'
require 'action_dispatch/testing/integration'
RSpec.describe 'Integrations helper', :telegram_bot do
include ActionDispatch::Integration::Runner
def reset_template_assertion; end
let(:app) do
app = Telegram::Bot::Middleware.new(bot, controller)
if ActionPack::VERSION::MAJOR >= 5
app
else
require 'action_dispatch/middleware/params_parser'
ActionDispatch::ParamsParser.new(app)
end
end
let(:bot) { Telegram::Bot::ClientStub.new('token') }
let(:controller_path) { '/' }
let(:controller) do
Class.new(Telegram::Bot::UpdatesController) do
def start(*args)
respond_with :message, text: "Start: #{args.inspect}, option: #{payload[:option]}"
end
end
end
describe '#default_message_options' do
subject { default_message_options }
it { should eq from: {id: from_id}, chat: {id: chat_id} }
end
describe '#dispatch' do
subject { -> { dispatch message: {text: '/start', **default_message_options} } }
it { should respond_with_message 'Start: [], option: ' }
end
describe '#dispatch_message' do
subject { -> { dispatch_message "/start #{args.join ' '}", options } }
let(:args) { %w(asd qwe) }
let(:options) { {} }
it { should respond_with_message "Start: #{args.inspect}, option: " }
context 'with options' do
let(:options) { {option: 1} }
it { should respond_with_message "Start: #{args.inspect}, option: 1" }
context 'and chat_id is not set' do
let(:options) { super().merge(chat: nil) }
it { should raise_error(/chat is not present/) }
end
end
end
describe '#dispatch_command' do
subject { -> { dispatch_command :start, *args } }
let(:args) { [] }
it { should respond_with_message "Start: #{args.inspect}, option: " }
context 'with args' do
let(:args) { %w(asd qwe) }
it { should respond_with_message "Start: #{args.inspect}, option: " }
end
context 'with options' do
let(:args) { ['asd', 'qwe', option: 1] }
it { should respond_with_message "Start: #{args[0...-1].inspect}, option: 1" }
end
end
end

Просмотреть файл

@@ -1,4 +1,4 @@
RSpec.describe Telegram::Bot::UpdatesController::CallbackQueyContext do
RSpec.describe Telegram::Bot::UpdatesController::CallbackQueryContext do
include_context 'telegram/bot/updates_controller'
let(:controller_class) do
described_class = self.described_class

Просмотреть файл

@@ -293,4 +293,49 @@ RSpec.describe Telegram::Bot::UpdatesController do
end
end
end
describe '#chat' do
subject { controller.chat }
let(:payload_type) { :message }
let(:payload) { {chat: 'test_value'} }
it { should eq payload[:chat] }
context 'when payload is not set' do
let(:payload) {}
it { should eq nil }
end
context 'when payload has no such field' do
let(:payload) { {smth: 'other'} }
it { should eq nil }
context 'but has `message`' do
let(:payload) { {message: message} }
let(:message) { {text: 'Hello bot!'} }
it { should eq nil }
context 'with `chat` set' do
let(:message) { super().merge(chat: 'test value') }
it { should eq message[:chat] }
end
end
end
end
describe '#from' do
subject { controller.from }
let(:payload_type) { :message }
let(:payload) { {from: 'test_value'} }
it { should eq payload[:from] }
context 'when payload is not set' do
let(:payload) {}
it { should eq nil }
end
context 'when payload has no such field' do
let(:payload) { {smth: 'other'} }
it { should eq nil }
end
end
end