зеркало из
https://github.com/glebtv/telegram-bot.git
synced 2026-09-03 17:55:52 +03:00
Use bang-methods as actions for commands
Этот коммит содержится в:
@@ -35,7 +35,7 @@ Rails.application.initialize!
|
||||
# # Controllers
|
||||
%w[default other named].each do |bot_name|
|
||||
controller = Class.new(Telegram::Bot::UpdatesController) do
|
||||
define_method :start do |*|
|
||||
define_method :start! do |*|
|
||||
respond_with :message, text: "from #{bot_name}"
|
||||
end
|
||||
end
|
||||
@@ -46,7 +46,7 @@ end
|
||||
klass.class_eval do
|
||||
use_session!
|
||||
|
||||
define_method :load_session do |*|
|
||||
define_method :load_session! do |*|
|
||||
session[:test]
|
||||
end
|
||||
end
|
||||
|
||||
@@ -2,7 +2,7 @@ RSpec.shared_examples 'shared integration examples' do
|
||||
let(:bot) { Telegram::Bot::ClientStub.new('token') }
|
||||
let(:controller_class) do
|
||||
Class.new(Telegram::Bot::UpdatesController) do
|
||||
def start(data = nil, *)
|
||||
def start!(data = nil, *)
|
||||
respond_with :message, text: "Hi #{data}"
|
||||
end
|
||||
|
||||
|
||||
@@ -69,7 +69,7 @@ RSpec.describe 'Integration: message helpers', telegram_bot: :poller do
|
||||
let(:bot) { Telegram::Bot::ClientStub.new('token') }
|
||||
let(:controller_class) do
|
||||
Class.new(Telegram::Bot::UpdatesController) do
|
||||
def start(*args)
|
||||
def start!(*args)
|
||||
respond_with :message, text: "Start: #{args.inspect}, option: #{payload['option']}"
|
||||
end
|
||||
end
|
||||
|
||||
111
spec/telegram/bot/updates_controller/commands_spec.rb
Обычный файл
111
spec/telegram/bot/updates_controller/commands_spec.rb
Обычный файл
@@ -0,0 +1,111 @@
|
||||
RSpec.describe Telegram::Bot::UpdatesController::Commands do
|
||||
describe '#action_for_command' do
|
||||
subject { ->(*args) { object.action_for_command(*args) } }
|
||||
let(:object) { Object.new.tap { |x| x.extend described_class } }
|
||||
|
||||
def assert_subject(input, expected)
|
||||
expect(subject.call input).to eq expected
|
||||
end
|
||||
|
||||
it 'bypasses and downcases not conflictint commands' do
|
||||
assert_subject 'test', 'test!'
|
||||
assert_subject 'TeSt', 'test!'
|
||||
assert_subject '_Te1St', '_te1st!'
|
||||
end
|
||||
end
|
||||
|
||||
describe '.command_from_text' do
|
||||
subject { ->(*args) { described_class.command_from_text(*args) } }
|
||||
|
||||
def assert_subject(input, cmd, *args)
|
||||
expected = cmd ? [cmd, args] : cmd
|
||||
expect(subject.call(*input)).to eq expected
|
||||
end
|
||||
|
||||
let(:max_cmd_size) { 32 }
|
||||
let(:long_cmd) { 'a' * (max_cmd_size - 1) }
|
||||
let(:too_long_cmd) { 'a' * max_cmd_size }
|
||||
|
||||
it 'works for simple commands' do
|
||||
assert_subject '/test', 'test'
|
||||
assert_subject '/tE_2_St', 'tE_2_St'
|
||||
assert_subject '/123', '123'
|
||||
assert_subject "/#{long_cmd}", long_cmd
|
||||
end
|
||||
|
||||
it 'works for simple messages' do
|
||||
assert_subject 'text', nil
|
||||
assert_subject ' ', nil
|
||||
assert_subject ' text', nil
|
||||
assert_subject ' 1', nil
|
||||
assert_subject ' /text', nil
|
||||
assert_subject '/te-xt', nil
|
||||
assert_subject 'text /cmd ', nil
|
||||
assert_subject "/#{too_long_cmd}", nil
|
||||
end
|
||||
|
||||
it 'works for mentioned commands' do
|
||||
assert_subject ['/test@bot', 'bot'], 'test'
|
||||
assert_subject ['/test@otherbot', 'bot'], nil
|
||||
assert_subject ['/test@Bot', 'bot'], nil
|
||||
assert_subject '/test@bot', nil
|
||||
assert_subject ['/test@bot', true], 'test'
|
||||
assert_subject ['/test@otherbot', true], 'test'
|
||||
end
|
||||
|
||||
it 'works for commands with args' do
|
||||
assert_subject '/test arg', 'test', 'arg'
|
||||
assert_subject '/test arg 1 2', 'test', 'arg', '1', '2'
|
||||
assert_subject ['/test@bot arg', 'bot'], 'test', 'arg'
|
||||
assert_subject ['/test@otherbot arg', 'bot'], nil
|
||||
assert_subject '/test@bot arg', nil
|
||||
end
|
||||
|
||||
it 'works for commands with multiline args' do
|
||||
assert_subject "/test arg\nother", 'test', 'arg', 'other'
|
||||
assert_subject "/test one\ntwo\n\nthree", 'test', 'one', 'two', 'three'
|
||||
end
|
||||
end
|
||||
|
||||
describe '#action_for_payload' do
|
||||
include_context 'telegram/bot/updates_controller'
|
||||
let(:controller_class) { Telegram::Bot::UpdatesController }
|
||||
subject { controller.action_for_payload }
|
||||
|
||||
%w[message channel_post].each do |type|
|
||||
context "when payload is edited_#{type}" do
|
||||
let(:payload_type) { "edited_#{type}" }
|
||||
it { should eq [payload_type, [payload]] }
|
||||
end
|
||||
|
||||
context 'when payload is message' do
|
||||
let(:payload_type) { type }
|
||||
let(:payload) { {'text' => text} }
|
||||
let(:text) { 'test' }
|
||||
|
||||
it { should eq [payload_type, [payload]] }
|
||||
|
||||
context 'with command' do
|
||||
let(:text) { "/test#{"@#{mention}" if mention} arg 1 2" }
|
||||
let(:mention) {}
|
||||
it { should eq [['test!', type: :command, command: 'test'], %w[arg 1 2]] }
|
||||
|
||||
context 'with mention' do
|
||||
let(:mention) { bot.username }
|
||||
it { should eq [['test!', type: :command, command: 'test'], %w[arg 1 2]] }
|
||||
end
|
||||
|
||||
context 'with mention for other bot' do
|
||||
let(:mention) { 'other_bot_name' }
|
||||
it { should eq [payload_type, [payload]] }
|
||||
end
|
||||
end
|
||||
|
||||
context 'without text' do
|
||||
let(:payload) { {'audio' => {'file_id' => 123}} }
|
||||
it { should eq [payload_type, [payload]] }
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -6,7 +6,7 @@ RSpec.describe Telegram::Bot::UpdatesController::Instrumentation do
|
||||
|
||||
let(:controller_class) do
|
||||
Class.new(Telegram::Bot::UpdatesController) do
|
||||
def start(*)
|
||||
def start!(*)
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -72,7 +72,7 @@ RSpec.describe Telegram::Bot::UpdatesController::Instrumentation do
|
||||
|
||||
describe '#respond_with' do
|
||||
before do
|
||||
def controller.start(*)
|
||||
def controller.start!(*)
|
||||
respond_with :message, text: 'sample response'
|
||||
end
|
||||
end
|
||||
|
||||
@@ -28,7 +28,7 @@ RSpec.describe Telegram::Bot::UpdatesController::MessageContext do
|
||||
[:method_result, *args]
|
||||
end
|
||||
|
||||
def action(*args)
|
||||
def action!(*args)
|
||||
[:action_result, *args]
|
||||
end
|
||||
|
||||
@@ -109,7 +109,7 @@ RSpec.describe Telegram::Bot::UpdatesController::MessageContext do
|
||||
end
|
||||
|
||||
context 'when context is action`s name but not mapped' do
|
||||
before { session[:context] = :action }
|
||||
before { session[:context] = :action! }
|
||||
its(:call) { should eq [:action_result, *text.split] }
|
||||
it { should_not change(controller, :filter_done) }
|
||||
it { should change { session[:context] }.to nil }
|
||||
|
||||
@@ -8,11 +8,11 @@ RSpec.describe Telegram::Bot::UpdatesController::Rescue do
|
||||
Class.new(Telegram::Bot::UpdatesController) do
|
||||
rescue_from ArgumentError, with: -> { respond_with :message, text: 'Rescued' }
|
||||
|
||||
def rescuable(*)
|
||||
def rescuable!(*)
|
||||
raise ArgumentError, 'rescuable'
|
||||
end
|
||||
|
||||
def not_rescuable(*)
|
||||
def not_rescuable!(*)
|
||||
raise 'not_rescuable'
|
||||
end
|
||||
end
|
||||
|
||||
@@ -19,11 +19,11 @@ RSpec.describe Telegram::Bot::UpdatesController::Session do
|
||||
controller_class.class_eval do
|
||||
self.session_store = :memory_store
|
||||
|
||||
def write(text)
|
||||
def write!(text)
|
||||
session[:text] = text
|
||||
end
|
||||
|
||||
def read
|
||||
def read!
|
||||
session[:text]
|
||||
end
|
||||
|
||||
|
||||
@@ -1,81 +1,5 @@
|
||||
RSpec.describe Telegram::Bot::UpdatesController do
|
||||
include_context 'telegram/bot/updates_controller'
|
||||
let(:other_bot_name) { 'other_bot' }
|
||||
|
||||
describe '.action_for_command' do
|
||||
subject { ->(*args) { described_class.action_for_command(*args) } }
|
||||
|
||||
def assert_subject(input, expected)
|
||||
expect(subject.call input).to eq expected
|
||||
end
|
||||
|
||||
it 'bypasses and downcases not conflictint commands' do
|
||||
assert_subject 'test', 'test'
|
||||
assert_subject 'TeSt', 'test'
|
||||
assert_subject '_Te1St', '_te1st'
|
||||
end
|
||||
|
||||
it 'adds _on to conflicting commands' do
|
||||
described_class::PAYLOAD_TYPES.each do |x|
|
||||
assert_subject x, "on_#{x}"
|
||||
assert_subject x.upcase, "on_#{x}"
|
||||
end
|
||||
assert_subject '1TeSt', 'on_1test'
|
||||
end
|
||||
end
|
||||
|
||||
describe '.command_from_text' do
|
||||
subject { ->(*args) { described_class.command_from_text(*args) } }
|
||||
|
||||
def assert_subject(input, cmd, *args)
|
||||
expected = cmd ? [cmd, args] : cmd
|
||||
expect(subject.call(*input)).to eq expected
|
||||
end
|
||||
|
||||
let(:max_cmd_size) { 32 }
|
||||
let(:long_cmd) { 'a' * (max_cmd_size - 1) }
|
||||
let(:too_long_cmd) { 'a' * max_cmd_size }
|
||||
|
||||
it 'works for simple commands' do
|
||||
assert_subject '/test', 'test'
|
||||
assert_subject '/tE_2_St', 'tE_2_St'
|
||||
assert_subject '/123', '123'
|
||||
assert_subject "/#{long_cmd}", long_cmd
|
||||
end
|
||||
|
||||
it 'works for simple messages' do
|
||||
assert_subject 'text', nil
|
||||
assert_subject ' ', nil
|
||||
assert_subject ' text', nil
|
||||
assert_subject ' 1', nil
|
||||
assert_subject ' /text', nil
|
||||
assert_subject '/te-xt', nil
|
||||
assert_subject 'text /cmd ', nil
|
||||
assert_subject "/#{too_long_cmd}", nil
|
||||
end
|
||||
|
||||
it 'works for mentioned commands' do
|
||||
assert_subject ['/test@bot', 'bot'], 'test'
|
||||
assert_subject ['/test@otherbot', 'bot'], nil
|
||||
assert_subject ['/test@Bot', 'bot'], nil
|
||||
assert_subject '/test@bot', nil
|
||||
assert_subject ['/test@bot', true], 'test'
|
||||
assert_subject ['/test@otherbot', true], 'test'
|
||||
end
|
||||
|
||||
it 'works for commands with args' do
|
||||
assert_subject '/test arg', 'test', 'arg'
|
||||
assert_subject '/test arg 1 2', 'test', 'arg', '1', '2'
|
||||
assert_subject ['/test@bot arg', 'bot'], 'test', 'arg'
|
||||
assert_subject ['/test@otherbot arg', 'bot'], nil
|
||||
assert_subject '/test@bot arg', nil
|
||||
end
|
||||
|
||||
it 'works for commands with multiline args' do
|
||||
assert_subject "/test arg\nother", 'test', 'arg', 'other'
|
||||
assert_subject "/test one\ntwo\n\nthree", 'test', 'one', 'two', 'three'
|
||||
end
|
||||
end
|
||||
|
||||
describe '#action_for_payload' do
|
||||
subject { controller.action_for_payload }
|
||||
@@ -87,60 +11,24 @@ RSpec.describe Telegram::Bot::UpdatesController do
|
||||
context 'when payload is inline_query' do
|
||||
let(:payload_type) { 'inline_query' }
|
||||
let(:payload) { stub_payload(:id, :from, :location, :query, :offset) }
|
||||
it { should eq [false, payload_type, payload.values_at(:query, :offset)] }
|
||||
it { should eq [payload_type, payload.values_at(:query, :offset)] }
|
||||
end
|
||||
|
||||
context 'when payload is chosen_inline_result' do
|
||||
let(:payload_type) { 'chosen_inline_result' }
|
||||
let(:payload) { stub_payload(:result_id, :from, :location, :inline_message_id, :query) }
|
||||
it { should eq [false, payload_type, payload.values_at(:result_id, :query)] }
|
||||
it { should eq [payload_type, payload.values_at(:result_id, :query)] }
|
||||
end
|
||||
|
||||
context 'when payload is callback_query' do
|
||||
let(:payload_type) { 'callback_query' }
|
||||
let(:payload) { stub_payload(:id, :from, :message, :inline_message_id, :data) }
|
||||
it { should eq [false, payload_type, payload.values_at(:data)] }
|
||||
it { should eq [payload_type, payload.values_at(:data)] }
|
||||
end
|
||||
|
||||
context 'when payload is not supported' do
|
||||
let(:payload_type) { '_unsupported_' }
|
||||
it { should eq [false, :unsupported_payload_type, []] }
|
||||
end
|
||||
|
||||
%w[message channel_post].each do |type|
|
||||
context "when payload is edited_#{type}" do
|
||||
let(:payload_type) { "edited_#{type}" }
|
||||
it { should eq [false, payload_type, [payload]] }
|
||||
end
|
||||
|
||||
context 'when payload is message' do
|
||||
let(:payload_type) { type }
|
||||
let(:payload) { {'text' => text} }
|
||||
let(:text) { 'test' }
|
||||
|
||||
it { should eq [false, payload_type, [payload]] }
|
||||
|
||||
context 'with command' do
|
||||
let(:text) { "/test#{"@#{mention}" if mention} arg 1 2" }
|
||||
let(:mention) {}
|
||||
it { should eq [true, 'test', %w[arg 1 2]] }
|
||||
|
||||
context 'with mention' do
|
||||
let(:mention) { bot.username }
|
||||
it { should eq [true, 'test', %w[arg 1 2]] }
|
||||
end
|
||||
|
||||
context 'with mention for other bot' do
|
||||
let(:mention) { other_bot_name }
|
||||
it { should eq [false, payload_type, [payload]] }
|
||||
end
|
||||
end
|
||||
|
||||
context 'without text' do
|
||||
let(:payload) { {'audio' => {'file_id' => 123}} }
|
||||
it { should eq [false, payload_type, [payload]] }
|
||||
end
|
||||
end
|
||||
it { should eq [:unsupported_payload_type, []] }
|
||||
end
|
||||
|
||||
custom_payload_types = %w[
|
||||
@@ -155,7 +43,7 @@ RSpec.describe Telegram::Bot::UpdatesController do
|
||||
(described_class::PAYLOAD_TYPES - custom_payload_types).each do |type|
|
||||
context "when payload is #{type}" do
|
||||
let(:payload_type) { type }
|
||||
it { should eq [false, payload_type, [payload]] }
|
||||
it { should eq [payload_type, [payload]] }
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
Ссылка в новой задаче
Block a user