1
0
зеркало из https://github.com/glebtv/telegram-bot.git synced 2026-09-03 09:46:17 +03:00

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

...

7 Коммитов

Автор 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
14 изменённых файлов: 205 добавлений и 40 удалений

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

@@ -1,3 +1,13 @@
# 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 # 0.9.0
- Async API requests. - Async API requests.

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

@@ -13,9 +13,9 @@ group :development do
gem 'pry', '~> 0.10.1' gem 'pry', '~> 0.10.1'
gem 'pry-byebug', '~> 3.2.0' 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 'rspec-its', '~> 1.1.0'
gem 'rubocop', '~> 0.37.0' gem 'rubocop', '~> 0.37.0'

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

@@ -24,6 +24,9 @@ Here is sample [telegram_bot_app](https://github.com/telegram-bot-rb/telegram_bo
with session, keyboards and inline queries. with session, keyboards and inline queries.
Run it on your local machine in 1 minute! 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 ## Installation
Add this line to your application's Gemfile: Add this line to your application's Gemfile:
@@ -323,36 +326,52 @@ To stub all possible clients use `Telegram::Bot::ClientStub.stub_all!` before
initializing clients. Most likely you'll want something like this: initializing clients. Most likely you'll want something like this:
```ruby ```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| RSpec.configure do |config|
# ... # ...
Telegram.reset_bots
Telegram::Bot::ClientStub.stub_all!
config.after { Telegram.bot.reset } config.after { Telegram.bot.reset }
# ... # ...
end end
``` ```
There are also some helpers for controller tests. There are integration and controller contexts for RSpec and some built-in matchers:
Check out `telegram/bot/updates_controller/rspec_helpers` and
`telegram/bot/updates_controller/testing`.
Built-in RSpec matchers will help you to write tests fast:
```ruby ```ruby
include Telegram::Bot::RSpec::ClientMatchers # no need if you already use controller herlpers # 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 send_telegram_message(bot, /msg regexp/, some: :option)
expect(&process_update). expect(&process_update).
to make_telegram_request(bot, :sendMessage, hash_including(text: 'msg text')) to make_telegram_request(bot, :sendMessage, hash_including(text: 'msg text'))
# controller specs are even simplier:
describe '#start' do
subject { -> { dispatch_message '/start' } }
it { should respond_with_message(/Hello/) }
end
# See sample app for more examples.
``` ```
See sample app for more examples.
### Deploying ### Deploying
Use `rake telegram:bot:set_webhook` to update webhook url for all configured bots. Use `rake telegram:bot:set_webhook` to update webhook url for all configured bots.

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

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

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

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

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

@@ -60,30 +60,28 @@ module Telegram
raise Error, err_msg raise Error, err_msg
end end
# Splited to the sections similar to API docs.
%w( %w(
deleteWebhook
getUpdates
getWebhookInfo
setWebhook
answerCallbackQuery answerCallbackQuery
answerInlineQuery
editMessageCaption
editMessageReplyMarkup
editMessageText
forwardMessage forwardMessage
getChat getChat
getChatAdministrators getChatAdministrators
getChatMember getChatMember
getChatMembersCount getChatMembersCount
getFile getFile
getGameHighScores
getMe getMe
getUpdates
getUserProfilePhotos getUserProfilePhotos
getWebhookInfo
kickChatMember kickChatMember
leaveChat leaveChat
sendAudio sendAudio
sendChatAction sendChatAction
sendContact sendContact
sendDocument sendDocument
sendGame
sendLocation sendLocation
sendMessage sendMessage
sendPhoto sendPhoto
@@ -91,9 +89,17 @@ module Telegram
sendVenue sendVenue
sendVideo sendVideo
sendVoice sendVoice
setGameScore
setWebhook
unbanChatMember unbanChatMember
editMessageCaption
editMessageReplyMarkup
editMessageText
answerInlineQuery
getGameHighScores
sendGame
setGameScore
).each do |method| ).each do |method|
define_method(method.underscore) { |*args| request(method, *args) } define_method(method.underscore) { |*args| request(method, *args) }
end end

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

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

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

@@ -139,9 +139,9 @@ module Telegram
# Helper for asserting message is sent. Note that options are checked # Helper for asserting message is sent. Note that options are checked
# with `hash_including`. For strict checks use #make_telegram_request. # with `hash_including`. For strict checks use #make_telegram_request.
def send_telegram_message(bot, text = nil, options = {}) def send_telegram_message(bot, text = nil, options = {})
description = "send telegram message #{text.inspect}"
text = a_string_matching(text) if text.is_a?(Regexp) text = a_string_matching(text) if text.is_a?(Regexp)
options = options.merge(text: text) if text options = options.merge(text: text) if text
description = "send telegram message #{text.inspect}"
MakeTelegramRequest.new(bot, :sendMessage, description: description). MakeTelegramRequest.new(bot, :sendMessage, description: description).
with(hash_including(options)) with(hash_including(options))
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

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

@@ -80,10 +80,12 @@ module Telegram
PAYLOAD_TYPES = %w( PAYLOAD_TYPES = %w(
message message
edited_message
channel_post
edited_channel_post
inline_query inline_query
chosen_inline_result chosen_inline_result
callback_query callback_query
edited_message
).freeze ).freeze
CMD_REGEX = %r{\A/([a-z\d_]{,31})(@(\S+))?(\s|$)}i CMD_REGEX = %r{\A/([a-z\d_]{,31})(@(\S+))?(\s|$)}i
CONFLICT_CMD_REGEX = Regexp.new("^(#{PAYLOAD_TYPES.join('|')}|\\d)") CONFLICT_CMD_REGEX = Regexp.new("^(#{PAYLOAD_TYPES.join('|')}|\\d)")

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

@@ -13,6 +13,9 @@ RSpec.shared_context 'telegram/bot/updates_controller' do
let(:bot) { Telegram::Bot::ClientStub.new(bot_name) } let(:bot) { Telegram::Bot::ClientStub.new(bot_name) }
let(:bot_name) { 'bot' } let(:bot_name) { 'bot' }
let(:session) { controller.send(:session) } 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 include Telegram::Bot::RSpec::ClientMatchers
@@ -20,9 +23,8 @@ RSpec.shared_context 'telegram/bot/updates_controller' do
controller.dispatch_again(bot, update) controller.dispatch_again(bot, update)
end end
def dispatch_message(text, options = nil) def dispatch_message(text, options = {})
options ||= respond_to?(:default_message_options) ? default_message_options : {} update = build_update :message, default_message_options.merge(options).merge(text: text)
update = build_update :message, options.merge(text: text)
dispatch bot, update dispatch bot, update
end end
@@ -43,3 +45,9 @@ RSpec.shared_context 'telegram/bot/updates_controller' do
send_telegram_message(bot, expected, chat_id: chat_id) send_telegram_message(bot, expected, chat_id: chat_id)
end end
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 attr_reader :bot, :controller, :timeout, :offset, :logger, :running, :reload
def initialize(bot, controller, **options) def initialize(bot, controller, **options)
@logger = options.fetch(:logger) { defined?(Rails) && Rails.logger } @logger = options.fetch(:logger) { defined?(Rails.logger) && Rails.logger }
@bot = bot @bot = bot
@controller = controller @controller = controller
@timeout = options.fetch(:timeout) { DEFAULT_TIMEOUT } @timeout = options.fetch(:timeout) { DEFAULT_TIMEOUT }
@offset = options[:offset] @offset = options[:offset]
@reload = options.fetch(:reload) { defined?(Rails) && Rails.env.development? } @reload = options.fetch(:reload) { defined?(Rails.env) && Rails.env.development? }
end end
def log(&block) def log(&block)
@@ -85,7 +85,7 @@ module Telegram
end end
end end
if defined?(Rails) && Rails.application.respond_to?(:reloader) if defined?(Rails.application) && Rails.application.respond_to?(:reloader)
def reloading_code def reloading_code
Rails.application.reloader.wrap do Rails.application.reloader.wrap do
yield yield

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

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

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