From 85abb738d8cf0044febec26bb49af93b7ed34055 Mon Sep 17 00:00:00 2001 From: Martin Edenhofer Date: Wed, 1 Mar 2017 16:10:15 +0100 Subject: [PATCH] Moved to webmock for telegram integration tests. --- .gitlab-ci.yml | 12 ++ Gemfile | 3 + Gemfile.lock | 9 ++ app/controllers/application_controller.rb | 9 +- lib/telegram.rb | 38 +----- test/integration/telegram_controller_test.rb | 120 ++++++++++++++----- 6 files changed, 125 insertions(+), 66 deletions(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 064d3caab..adb7fb768 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -255,6 +255,18 @@ test:integration:sipgate: - ruby -I test test/integration/sipgate_controller_test.rb - rake db:drop +test:integration:telegram: + stage: test + tags: + - core + script: + - export RAILS_ENV=test + - rake db:create + - rake db:migrate + - rake db:seed + - ruby -I test test/integration/telegram_controller_test.rb + - rake db:drop + test:integration:es_mysql: stage: test tags: diff --git a/Gemfile b/Gemfile index 6fc764e0c..055aad243 100644 --- a/Gemfile +++ b/Gemfile @@ -122,6 +122,9 @@ group :development, :test do # Use Factory Girl for generating random test data gem 'factory_girl_rails' + + # mock http calls + gem 'webmock' end gem 'puma', group: :puma diff --git a/Gemfile.lock b/Gemfile.lock index b2d2e72c8..46d4c71b0 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -82,6 +82,8 @@ GEM term-ansicolor (~> 1.3.0) thor (~> 0.19.1) tins (>= 1.6.0, < 2) + crack (0.4.3) + safe_yaml (~> 1.0.0) daemons (1.2.4) delayed_job (4.1.2) activesupport (>= 3.0, < 5.1) @@ -151,6 +153,7 @@ GEM guard (~> 2.8) guard-compat (~> 1.0) multi_json (~> 1.8) + hashdiff (0.3.2) hashie (3.4.4) htmlentities (4.3.4) http (1.0.4) @@ -325,6 +328,7 @@ GEM ruby-progressbar (1.8.1) ruby_dep (1.4.0) rubyzip (1.2.0) + safe_yaml (1.0.4) sass (3.4.22) sass-rails (5.0.6) railties (>= 4.0.0, < 6) @@ -398,6 +402,10 @@ GEM unicorn (5.2.0) kgio (~> 2.6) raindrops (~> 0.7) + webmock (2.3.2) + addressable (>= 2.3.6) + crack (>= 0.3.2) + hashdiff websocket (1.2.3) writeexcel (1.0.5) zendesk_api (1.14.0) @@ -480,6 +488,7 @@ DEPENDENCIES twitter uglifier unicorn + webmock writeexcel zendesk_api diff --git a/app/controllers/application_controller.rb b/app/controllers/application_controller.rb index a29ee8f05..8501ed37a 100644 --- a/app/controllers/application_controller.rb +++ b/app/controllers/application_controller.rb @@ -113,14 +113,15 @@ class ApplicationController < ActionController::Base session[:ping] = Time.zone.now.iso8601 # check if remote ip need to be updated - if !session[:remote_ip] || session[:remote_ip] != request.remote_ip - session[:remote_ip] = request.remote_ip - session[:geo] = Service::GeoIp.location(request.remote_ip) + if session[:user_id] + if !session[:remote_ip] || session[:remote_ip] != request.remote_ip + session[:remote_ip] = request.remote_ip + session[:geo] = Service::GeoIp.location(request.remote_ip) + end end # fill user agent return if session[:user_agent] - session[:user_agent] = request.env['HTTP_USER_AGENT'] end diff --git a/lib/telegram.rb b/lib/telegram.rb index 3f0a09a3b..ac4ac15fe 100644 --- a/lib/telegram.rb +++ b/lib/telegram.rb @@ -79,7 +79,11 @@ returns end # generate randam callback token - callback_token = SecureRandom.urlsafe_base64(10) + callback_token = if Rails.env.test? + 'callback_token' + else + SecureRandom.urlsafe_base64(10) + end # set webhook / callback url for this bot @ telegram callback_url = "#{Setting.get('http_type')}://#{Setting.get('fqdn')}/api/v1/channels_telegram_webhook/#{callback_token}?bid=#{bot['id']}" @@ -599,16 +603,6 @@ returns end def download_file(file_id) - if Rails.env.test? - result = Result.new( - success: true, - body: 'ok', - data: 'ok', - code: 200, - content_type: 'application/stream', - ) - return result - end document = @api.getFile(file_id) url = "https://api.telegram.org/file/bot#{@token}/#{document['file_path']}" UserAgent.get( @@ -621,26 +615,4 @@ returns ) end - class Result - - attr_reader :error - attr_reader :body - attr_reader :data - attr_reader :code - attr_reader :content_type - - def initialize(options) - @success = options[:success] - @body = options[:body] - @data = options[:data] - @code = options[:code] - @content_type = options[:content_type] - @error = options[:error] - end - - def success? - return true if @success - false - end - end end diff --git a/test/integration/telegram_controller_test.rb b/test/integration/telegram_controller_test.rb index 2acc4496b..25d0d5604 100644 --- a/test/integration/telegram_controller_test.rb +++ b/test/integration/telegram_controller_test.rb @@ -1,41 +1,76 @@ # encoding: utf-8 require 'test_helper' require 'rexml/document' +require 'webmock/minitest' class TelegramControllerTest < ActionDispatch::IntegrationTest setup do @headers = { 'ACCEPT' => 'application/json', 'CONTENT_TYPE' => 'application/json' } - - # configure telegram channel - token = ENV['TELEGRAM_TOKEN'] - group_id = Group.find_by(name: 'Users').id - #bot = Telegram.check_token(token) - #Setting.set('http_type', 'http') - Setting.set('http_type', 'https') - Setting.set('fqdn', 'me.zammad.com') - Channel.where(area: 'Telegram::Bot').destroy_all - UserInfo.current_user_id = 1 - @channel = Telegram.create_or_update_channel(token, { group_id: group_id, welcome: 'hi!' }) - - groups = Group.where(name: 'Users') - roles = Role.where(name: %w(Agent)) - agent = User.create_or_update( - login: 'telegram-agent@example.com', - firstname: 'E', - lastname: 'S', - email: 'telegram-agent@example.com', - password: 'agentpw', - active: true, - roles: roles, - groups: groups, - ) - UserInfo.current_user_id = nil - end test 'basic call' do Ticket.destroy_all + # configure telegram channel + token = 'valid_token' + bot_id = 123_456_789 + group_id = Group.find_by(name: 'Users').id + + UserInfo.current_user_id = 1 + Channel.where(area: 'Telegram::Bot').destroy_all + + # try with invalid token + stub_request(:get, 'https://api.telegram.org/botnot_existing/getMe') + .to_return(status: 404, body: '{"ok":false,"error_code":404,"description":"Not Found"}', headers: {}) + + assert_raises(RuntimeError) { + Telegram.check_token('not_existing') + } + + # try valid token + stub_request(:get, "https://api.telegram.org/bot#{token}/getMe") + .to_return(status: 200, body: "{\"ok\":true,\"result\":{\"id\":#{bot_id},\"first_name\":\"Chrispresso Customer Service\",\"username\":\"ChrispressoBot\"}}", headers: {}) + + bot = Telegram.check_token(token) + assert_equal(bot_id, bot['id']) + + stub_request(:get, "https://api.telegram.org/bot#{token}/getMe") + .to_return(status: 200, body: "{\"ok\":true,\"result\":{\"id\":#{bot_id},\"first_name\":\"Chrispresso Customer Service\",\"username\":\"ChrispressoBot\"}}", headers: {}) + + Setting.set('http_type', 'http') + assert_raises(RuntimeError) { + Telegram.create_or_update_channel(token, { group_id: group_id, welcome: 'hi!' }) + } + + # try invalid port + stub_request(:get, "https://api.telegram.org:443/bot#{token}/getMe") + .to_return(status: 200, body: "{\"ok\":true,\"result\":{\"id\":#{bot_id},\"first_name\":\"Chrispresso Customer Service\",\"username\":\"ChrispressoBot\"}}", headers: {}) + stub_request(:get, "https://api.telegram.org:443/bot#{token}/setWebhook?url=https://somehost.example.com:12345/api/v1/channels_telegram_webhook/callback_token?bid=#{bot_id}") + .to_return(status: 400, body: '{"ok":false,"error_code":400,"description":"Bad Request: bad webhook: Webhook can be set up only on ports 80, 88, 443 or 8443"}', headers: {}) + + Setting.set('http_type', 'https') + Setting.set('fqdn', 'somehost.example.com:12345') + assert_raises(RuntimeError) { + Telegram.create_or_update_channel(token, { group_id: group_id, welcome: 'hi!' }) + } + + # try invalid host + stub_request(:get, "https://api.telegram.org:443/bot#{token}/setWebhook?url=https://somehost.example.com/api/v1/channels_telegram_webhook/callback_token?bid=#{bot_id}") + .to_return(status: 400, body: '{"ok":false,"error_code":400,"description":"Bad Request: bad webhook: getaddrinfo: Name or service not known"}', headers: {}) + + Setting.set('fqdn', 'somehost.example.com') + assert_raises(RuntimeError) { + Telegram.create_or_update_channel(token, { group_id: group_id, welcome: 'hi!' }) + } + + # valid token, host and port + stub_request(:get, "https://api.telegram.org:443/bot#{token}/setWebhook?url=https://example.com/api/v1/channels_telegram_webhook/callback_token?bid=#{bot_id}") + .to_return(status: 200, body: '{"ok":true,"result":true,"description":"Webhook was set"}', headers: {}) + + Setting.set('fqdn', 'example.com') + channel = Telegram.create_or_update_channel(token, { group_id: group_id, welcome: 'hi!' }) + UserInfo.current_user_id = nil + # start communication #1 post '/api/v1/channels/telegram_webhook', read_messaage('personal1_message_start'), @headers assert_response(404) @@ -46,13 +81,13 @@ class TelegramControllerTest < ActionDispatch::IntegrationTest result = JSON.parse(@response.body) assert_equal('bot param missing', result['error']) - callback_url = "/api/v1/channels_telegram_webhook/not_existing?bid=#{@channel.options[:bot][:id]}" + callback_url = "/api/v1/channels_telegram_webhook/not_existing?bid=#{channel.options[:bot][:id]}" post callback_url, read_messaage('personal1_message_start'), @headers assert_response(422) result = JSON.parse(@response.body) assert_equal('invalid callback token', result['error']) - callback_url = "/api/v1/channels_telegram_webhook/#{@channel.options[:callback_token]}?bid=#{@channel.options[:bot][:id]}" + callback_url = "/api/v1/channels_telegram_webhook/#{channel.options[:callback_token]}?bid=#{channel.options[:bot][:id]}" post callback_url, read_messaage('personal1_message_start'), @headers assert_response(200) @@ -139,6 +174,11 @@ class TelegramControllerTest < ActionDispatch::IntegrationTest assert_equal('text/plain', ticket.articles.last.content_type) # send message2 + stub_request(:get, "https://api.telegram.org/bot#{token}/getFile?file_id=ABC-123VabcOcv123w0ABHywrcPqfrbAYIABC") + .to_return(status: 200, body: '{"result":{"file_size":123,"file_id":"ABC-123VabcOcv123w0ABHywrcPqfrbAYIABC","file_path":"abc123"}}', headers: {}) + stub_request(:get, "https://api.telegram.org/file/bot#{token}/abc123") + .to_return(status: 200, body: 'ABC1', headers: {}) + post callback_url, read_messaage('personal3_message_content2'), @headers assert_response(200) assert_equal(3, Ticket.count) @@ -150,6 +190,13 @@ class TelegramControllerTest < ActionDispatch::IntegrationTest assert_equal('text/html', ticket.articles.last.content_type) # send message3 + stub_request(:get, "https://api.telegram.org/bot#{token}/getFile?file_id=AAQCABO0I4INAATATQAB5HWPq4XgxQACAg") + .to_return(status: 200, body: '{"result":{"file_size":123,"file_id":"ABC-123AAQCABO0I4INAATATQAB5HWPq4XgxQACAg","file_path":"abc123"}}', headers: {}) + stub_request(:get, "https://api.telegram.org/file/bot#{token}/abc123") + .to_return(status: 200, body: 'ABC2', headers: {}) + stub_request(:get, "https://api.telegram.org/bot#{token}/getFile?file_id=BQADAgADDgAD7x6ZSC_-1LMkOEmoAg") + .to_return(status: 200, body: '{"result":{"file_size":123,"file_id":"ABC-123BQADAgADDgAD7x6ZSC_-1LMkOEmoAg","file_path":"abc123"}}', headers: {}) + post callback_url, read_messaage('personal3_message_content3'), @headers assert_response(200) assert_equal(3, Ticket.count) @@ -177,6 +224,9 @@ class TelegramControllerTest < ActionDispatch::IntegrationTest assert_equal('text/plain', ticket.articles.first.content_type) # send voice5 + stub_request(:get, "https://api.telegram.org/bot#{token}/getFile?file_id=AwADAgADVQADCEIYSZwyOmSZK9iZAg") + .to_return(status: 200, body: '{"result":{"file_size":123,"file_id":"ABC-123AwADAgADVQADCEIYSZwyOmSZK9iZAg","file_path":"abc123"}}', headers: {}) + post callback_url, read_messaage('personal3_message_content5'), @headers assert_response(200) assert_equal(3, Ticket.count) @@ -188,11 +238,20 @@ class TelegramControllerTest < ActionDispatch::IntegrationTest assert_equal(1, ticket.articles.last.attachments.count) # start communication #4 - with sticker + stub_request(:get, "https://api.telegram.org/bot#{token}/getFile?file_id=AAQDABO3-e4qAASs6ZOjJUT7tQ4lAAIC") + .to_return(status: 200, body: '{"result":{"file_size":123,"file_id":"ABC-123AAQDABO3-e4qAASs6ZOjJUT7tQ4lAAIC","file_path":"abc123"}}', headers: {}) + stub_request(:get, "https://api.telegram.org/bot#{token}/getFile?file_id=BQADAwAD0QIAAqbJWAAB8OkQqgtDQe0C") + .to_return(status: 200, body: '{"result":{"file_size":123,"file_id":"ABC-123BQADAwAD0QIAAqbJWAAB8OkQqgtDQe0C","file_path":"abc123"}}', headers: {}) + post callback_url, read_messaage('personal4_message_content1'), @headers assert_response(200) assert_equal(4, Ticket.count) ticket = Ticket.last - assert_equal('💻', ticket.title) + if Rails.application.config.db_4bytes_utf8 + assert_equal('💻', ticket.title) + else + assert_equal('', ticket.title) + end assert_equal('new', ticket.state.name) assert_equal(1, ticket.articles.count) assert_match(/