require 'rails_helper' describe Agents::TelegramAgent do before do default_options = { auth_token: 'xxxxxxxxx:xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx', chat_id: 'xxxxxxxx', caption: '{{ caption }}', disable_web_page_preview: '{{ disable_web_page_preview }}', disable_notification: '{{ silent }}', long_message: '{{ long }}', parse_mode: 'html' } @checker = Agents::TelegramAgent.new name: 'Telegram Tester', options: default_options @checker.user = users(:bob) @checker.save! end def event_with_payload(payload) event = Event.new event.agent = agents(:bob_weather_agent) event.payload = payload event.save! event end def stub_methods allow_any_instance_of(Agents::TelegramAgent).to receive(:send_message) do |agent, method, params| @sent_messages << { method => params } end end describe 'validation' do before do expect(@checker).to be_valid end it 'should validate presence of auth_token' do @checker.options[:auth_token] = '' expect(@checker).not_to be_valid end it 'should validate presence of chat_id' do @checker.options[:chat_id] = '' expect(@checker).not_to be_valid end it 'should validate value of caption' do @checker.options[:caption] = 'a' * 1025 expect(@checker).not_to be_valid end it 'should validate value of disable_web_page_preview' do @checker.options[:disable_web_page_preview] = 'invalid' expect(@checker).not_to be_valid end it 'should validate value of disable_notification' do @checker.options[:disable_notification] = 'invalid' expect(@checker).not_to be_valid end it 'should validate value of long_message' do @checker.options[:long_message] = 'invalid' expect(@checker).not_to be_valid end it 'should validate value of parse_mode' do @checker.options[:parse_mode] = 'invalid' expect(@checker).not_to be_valid end end describe '#receive' do before do stub_methods @sent_messages = [] end it 'processes multiple events properly' do event_0 = event_with_payload silent: 'true', text: 'Looks like it is going to rain' event_1 = event_with_payload disable_web_page_preview: 'true', long: 'split', text: "#{'a' * 4095} #{'b' * 6}" event_2 = event_with_payload disable_web_page_preview: 'true', long: 'split', text: "#{'a' * 4096}#{'b' * 6}" event_3 = event_with_payload long: 'split', text: "#{'a' * 2142} #{'b' * 2142}" @checker.receive [event_0, event_1, event_2, event_3] expect(@sent_messages).to eq([ { text: { chat_id: 'xxxxxxxx', disable_notification: 'true', parse_mode: 'html', text: 'Looks like it is going to rain' } }, { text: { chat_id: 'xxxxxxxx', disable_web_page_preview: 'true', parse_mode: 'html', text: 'a' * 4095 } }, { text: { chat_id: 'xxxxxxxx', disable_web_page_preview: 'true', parse_mode: 'html', text: 'b' * 6 } }, { text: { chat_id: 'xxxxxxxx', disable_web_page_preview: 'true', parse_mode: 'html', text: 'a' * 4096 } }, { text: { chat_id: 'xxxxxxxx', disable_web_page_preview: 'true', parse_mode: 'html', text: 'b' * 6 } }, { text: { chat_id: 'xxxxxxxx', parse_mode: 'html', text: 'a' * 2142 } }, { text: { chat_id: 'xxxxxxxx', parse_mode: 'html', text: 'b' * 2142 } } ]) end it 'accepts audio key and uses :send_audio to send the file with truncated caption' do event = event_with_payload audio: 'https://example.com/sound.mp3', caption: 'a' * 1025 @checker.receive [event] expect(@sent_messages).to eq([{ audio: { audio: 'https://example.com/sound.mp3', caption: 'a'* 1024, chat_id: 'xxxxxxxx' } }]) end it 'accepts document key and uses :send_document to send the file and the full caption' do event = event_with_payload caption: "#{'a' * 1023} #{'b' * 6}", document: 'https://example.com/document.pdf', long: 'split' @checker.receive [event] expect(@sent_messages).to eq([ { document: { caption: 'a' * 1023, chat_id: 'xxxxxxxx', document: 'https://example.com/document.pdf' } }, { text: { chat_id: 'xxxxxxxx', parse_mode: 'html', text: 'b' * 6 } } ]) end it 'accepts photo key and uses :send_photo to send the file' do event = event_with_payload photo: 'https://example.com/image.png' @checker.receive [event] expect(@sent_messages).to eq([{ photo: { chat_id: 'xxxxxxxx', photo: 'https://example.com/image.png' } }]) end it 'accepts photo key with no caption when long:split is set' do event = event_with_payload photo: 'https://example.com/image.png', long: 'split', caption: nil @checker.receive [event] end it 'accepts video key and uses :send_video to send the file' do event = event_with_payload video: 'https://example.com/video.avi' @checker.receive [event] expect(@sent_messages).to eq([{ video: { chat_id: 'xxxxxxxx', video: 'https://example.com/video.avi' } }]) end it 'accepts group key and uses :send_media_group to send the file' do event = event_with_payload group: [{ type: 'photo', media: 'https://example.com/photo1.jpg' }, { type: 'photo', media: 'https://example.com/photo2.jpg' }] @checker.receive [event] expect(@sent_messages).to eq([{ group: { chat_id: 'xxxxxxxx', media: [{ 'type' => 'photo', 'media' => 'https://example.com/photo1.jpg' }, { 'type' => 'photo', 'media' => 'https://example.com/photo2.jpg' }] } }]) end it 'creates a log entry when no key of the received event was useable' do event = event_with_payload test: '1234' expect { @checker.receive [event] }.to change(AgentLog, :count).by(1) end end it 'creates an error log if the request fails' do event = event_with_payload text: 'hello' stub_request(:post, "https://api.telegram.org/botxxxxxxxxx:xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx/sendMessage"). with(headers: {'Content-type'=>'application/json'}). to_return(status: 200, body: '{"ok": false}', headers: {'Content-Type' => 'application/json'}) expect { @checker.receive [event] }.to change(AgentLog, :count).by(1) end describe '#working?' do it 'is not working without having received an event' do expect(@checker).not_to be_working end it 'is working after receiving an event without error' do @checker.last_receive_at = Time.now expect(@checker).to be_working end end describe '#complete_chat_id' do it 'returns a list of all recents chats, groups and channels' do stub_request(:post, "https://api.telegram.org/botxxxxxxxxx:xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx/getUpdates"). to_return(status: 200, body: '{"ok":true,"result":[{"update_id":252965475,"message":{"message_id":15,"from":{"id":97201077,"is_bot":false,"first_name":"Dominik","last_name":"Sander","language_code":"en-US"},"chat":{"id":97201077,"first_name":"Dominik","last_name":"Sander","type":"private"},"date":1506774710,"text":"test"}},{"update_id":252965476,"channel_post":{"message_id":4,"chat":{"id":-1001144599139,"title":"Much channel","type":"channel"},"date":1506782283,"text":"channel"}},{"update_id":252965477,"message":{"message_id":18,"from":{"id":97201077,"is_bot":false,"first_name":"Dominik","last_name":"Sander","language_code":"en-US"},"chat":{"id":-217850512,"title":"Just a test","type":"group","all_members_are_administrators":true},"date":1506782504,"left_chat_participant":{"id":136508315,"is_bot":true,"first_name":"Huginn","username":"HuginnNotificationBot"},"left_chat_member":{"id":136508315,"is_bot":true,"first_name":"Huginn","username":"HuginnNotificationBot"}}}]}', headers: {'Content-Type' => 'application/json'}) expect(@checker.complete_chat_id).to eq([{:id=>97201077, :text=>"Dominik Sander"}, {:id=>-1001144599139, :text=>"Much channel"}, {:id=>-217850512, :text=>"Just a test"}]) end end describe '#validate_auth_token' do it 'returns true if the token is valid' do stub_request(:post, "https://api.telegram.org/botxxxxxxxxx:xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx/getMe"). to_return(status: 200, body: '{"ok": true}', headers: {'Content-Type' => 'application/json'}) expect(@checker.validate_auth_token).to be_truthy end it 'returns false if the token is invalid' do stub_request(:post, "https://api.telegram.org/botxxxxxxxxx:xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx/getMe"). to_return(status: 200, body: "{}") expect(@checker.validate_auth_token).to be_falsy end end end