README.md in telegram-bot-0.13.1 vs README.md in telegram-bot-0.14.0
- old
+ new
@@ -2,10 +2,12 @@
[![Gem Version](https://badge.fury.io/rb/telegram-bot.svg)](http://badge.fury.io/rb/telegram-bot)
[![Code Climate](https://codeclimate.com/github/telegram-bot-rb/telegram-bot/badges/gpa.svg)](https://codeclimate.com/github/telegram-bot-rb/telegram-bot)
[![Build Status](https://travis-ci.org/telegram-bot-rb/telegram-bot.svg)](https://travis-ci.org/telegram-bot-rb/telegram-bot)
+__Breaking changes in v0.14!__ See [upgrading guide](https://github.com/telegram-bot-rb/telegram-bot/wiki/Upgrading-to-0.14).
+
Tools for developing Telegram bots. Best used with Rails, but can be used in
[standalone app](https://github.com/telegram-bot-rb/telegram-bot/wiki/Not-rails-application).
Supposed to be used in webhook-mode in production, and poller-mode
in development, but you can use poller in production if you want.
@@ -152,18 +154,15 @@
# message(payload)
# inline_query(query, offset)
# chosen_inline_result(result_id, query)
# callback_query(data)
- # Define public methods to respond to commands.
+ # Define public methods ending with `!` to handle commands.
# Command arguments will be parsed and passed to the method.
# Be sure to use splat args and default values to not get errors when
# someone passed more or less arguments in the message.
- #
- # For some commands like /message or /123 method names should start with
- # `on_` to avoid conflicts.
- def start(data = nil, *)
+ def start!(data = nil, *)
# 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!'
@@ -190,12 +189,13 @@
```
#### Reply helpers
There are helpers to respond for basic actions. They just set chat/message/query
-identifiers from update. See [`ReplyHelpers`](https://github.com/telegram-bot-rb/telegram-bot/blob/master/lib/telegram/bot/updates_controller/reply_helpers.rb) module for more information.
-Here are this methods signatures:
+identifiers from update. See
+[`ReplyHelpers`](https://github.com/telegram-bot-rb/telegram-bot/blob/master/lib/telegram/bot/updates_controller/reply_helpers.rb)
+module for more information. Here are this methods signatures:
```ruby
def respond_with(type, params); end
def reply_with(type, params); end
def answer_inline_query(results, params = {}); end
@@ -254,15 +254,15 @@
use_session!
# You can override global config for this controller.
self.session_store = :file_store
- def write(text = nil, *)
+ def write!(text = nil, *)
session[:text] = text
end
- def read(*)
+ def read!(*)
respond_with :message, text: session[:text]
end
private
@@ -281,39 +281,32 @@
```ruby
class Telegram::WebhookController < Telegram::Bot::UpdatesController
include Telegram::Bot::UpdatesController::MessageContext
- def rename(*)
+ def rename!(*)
# set context for the next message
- save_context :rename
+ save_context :rename_from_message
respond_with :message, text: 'What name do you like?'
end
# register context handlers to handle this context
- context_handler :rename do |*words|
+ def rename_from_message(*words)
update_name words[0]
respond_with :message, text: 'Renamed!'
end
- # You can do it in other way:
- def rename(name = nil, *)
+ # You can use same action name as context name:
+ def rename!(name = nil, *)
if name
update_name name
respond_with :message, text: 'Renamed!'
else
- save_context :rename
+ save_context :rename!
respond_with :message, text: 'What name do you like?'
end
end
-
- # This will call #rename like if it is called with message '/rename %text%'
- context_handler :rename
-
- # If you have a lot of such methods you can call this method
- # to use context value as action name for all contexts which miss handlers:
- context_to_action!
end
```
#### Callback queries
@@ -392,15 +385,15 @@
Telegram::Bot::UpdatesPoller.start(bot, controller_class)
```
### Testing
-There is `Telegram::Bot::ClientStub` class to stub client for tests.
-Instead of performing API requests it stores them in `requests` hash.
+There is a `Telegram::Bot::ClientStub` class to stub client for tests.
+Instead of performing API requests it stores them in a `requests` hash.
To stub all possible clients use `Telegram::Bot::ClientStub.stub_all!` before
-initializing clients. Here is template for RSpec:
+initializing clients. Here is a template for RSpec:
```ruby
# environments/test.rb
# Make sure to run it before defining routes or accessing any bot in the app!
Telegram.reset_bots
@@ -414,50 +407,85 @@
config.after { Telegram.bots.each_value(&:reset) }
# ...
end
```
-There are integration and controller contexts for RSpec and some built-in matchers:
+RSpec contexts and helpers are included automatically for groups and examples with matching
+tags. In RSpec < 3.4 it's required to use `include_context` explicitly.
+See [list of available helpers](https://github.com/telegram-bot-rb/telegram-bot/tree/master/lib/telegram/bot/rspec)
+for details.
+There are 3 types of integration tests:
+
+- `:rails` - for testing bot in webhooks-mode in Rails application.
+ It simulates webhook requests POSTing data to controller's endpoint.
+ It works on the top of requests specs, so `rspec-rails` gem is required.
+- `:rack` - For testing bot in webhooks-mode in non-Rails application.
+ It uses `rack-test` gem to POST requests to bot's endpoint.
+- `:poller` - Calls `.dispatch` directly on controller class.
+
+Pick the appropriate one, then require `telegram/bot/rspec/integration/#{type}`
+and mark spec group with tag `telegram_bot: type`. See configuration options
+for each type in
+[telegram/bot/rspec/integration/](https://github.com/telegram-bot-rb/telegram-bot/tree/master/lib/telegram/bot/rspec/integration).
+
+Here is an example test for a Rails app:
+
```ruby
# spec/requests/telegram_webhooks_spec.rb
-require 'telegram/bot/rspec/integration'
+require 'telegram/bot/rspec/integration/rails'
-RSpec.describe TelegramWebhooksController, :telegram_bot do
- # for old rspec add:
- # include_context 'telegram/bot/integration'
+RSpec.describe TelegramWebhooksController, telegram_bot: :rails do
+ # for old RSpec:
+ # include_context 'telegram/bot/integration/rails'
- describe '#start' do
+ # Main method is #dispatch(update). Some helpers are:
+ # dispatch_message(text, options = {})
+ # dispatch_command(cmd, *args)
+
+ # Available matchers can be found in Telegram::Bot::RSpec::ClientMatchers.
+ it 'shows usage of basic matchers'
+ # The most basic one is #make_telegram_request(bot, endpoint, params_matcher)
+ expect { dispatch_command(:start) }.
+ to make_telegram_request(bot, :sendMessage, hash_including(text: 'msg text'))
+
+ # There are some shortcuts for dispatching basic updates and testing responses.
+ expect { dispatch_message('Hi') }.to send_telegram_message(bot, /msg regexp/, some: :option)
+ end
+
+ describe '#start!' do
subject { -> { dispatch_command :start } }
+ # Using built in matcher for `respond_to`:
it { should respond_with_message 'Hi there!' }
end
- # There is context for callback queries with related matchers.
+ # There is context for callback queries with related matchers,
+ # use :callback_query tag to include it.
describe '#hey_callback_query', :callback_query do
let(:data) { "hey:#{name}" }
let(:name) { 'Joe' }
it { should answer_callback_query('Hey Joe') }
it { should edit_current_message :text, text: 'Done' }
+ end
end
+```
-# For controller specs use
+There is a context for testing bot controller in the way similar to Rails controller tests.
+It's supposed to be a low-level alternative for integration tests. Among the differences is
+that controller tests use a single controller instance for all dispatches in specific exaple,
+session is stubbed (does not use configured store engine), and update is not serialized
+so it also supports mocks. This can be useful for unit testing, but should not be used as
+the default way to test the bot.
+
+```ruby
require 'telegram/bot/updates_controller/rspec_helpers'
RSpec.describe TelegramWebhooksController, type: :telegram_bot_controller do
- # for old rspec add:
+ # for old RSpec:
# 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'))
+ # Same helpers and matchers like dispatch_command, answer_callback_query are available here.
+end
```
-
-Place integration tests inside `spec/requests`
-when using RSpec's `infer_spec_type_from_file_location!`,
-or just add `type: :request` to `describe`.
See sample app for more examples.
### Deployment