|
@@ -0,0 +1,507 @@
|
|
|
+# Copyright (C) 2012-2022 Zammad Foundation, https://zammad-foundation.org/
|
|
|
+
|
|
|
+require 'rails_helper'
|
|
|
+
|
|
|
+RSpec.describe 'External Credentials > Twitter', required_envs: %w[TWITTER_CONSUMER_KEY TWITTER_CONSUMER_SECRET TWITTER_OAUTH_TOKEN TWITTER_OAUTH_TOKEN_SECRET TWITTER_DEV_ENVIRONMENT], type: :request do
|
|
|
+ let(:admin) { create(:admin) }
|
|
|
+
|
|
|
+ let(:valid_credentials) { attributes_for(:twitter_credential)[:credentials] }
|
|
|
+ let(:invalid_credentials) { attributes_for(:twitter_credential, :invalid)[:credentials] }
|
|
|
+
|
|
|
+ let(:webhook_url) { "#{Setting.get('http_type')}://#{Setting.get('fqdn')}#{Rails.configuration.api_path}/channels_twitter_webhook" }
|
|
|
+
|
|
|
+ def body_forbidden
|
|
|
+ {
|
|
|
+ errors: [
|
|
|
+ {
|
|
|
+ code: 403,
|
|
|
+ message: 'Forbidden.',
|
|
|
+ },
|
|
|
+ ],
|
|
|
+ }.to_json
|
|
|
+ end
|
|
|
+
|
|
|
+ def headers
|
|
|
+ { content_type: 'application/json; charset=utf-8' }
|
|
|
+ end
|
|
|
+
|
|
|
+ def oauth_request_token
|
|
|
+ stub_post('https://api.twitter.com/oauth/request_token').to_return(
|
|
|
+ status: 200,
|
|
|
+ body: 'oauth_token=DY8E9gAAAAABCFc9AAABcP4JGzI&oauth_token_secret=gAR1aD2RGw3klpbxNtMuwvALohChdLDR&oauth_callback_confirmed=true',
|
|
|
+ )
|
|
|
+ end
|
|
|
+
|
|
|
+ def oauth_request_token_unauthorized
|
|
|
+ stub_post('https://api.twitter.com/oauth/request_token').to_return(
|
|
|
+ status: [ 401, 'Unauthorized' ],
|
|
|
+ body: '',
|
|
|
+ )
|
|
|
+ end
|
|
|
+
|
|
|
+ def oauth_request_token_forbidden
|
|
|
+ stub_post('https://api.twitter.com/oauth/request_token').to_return(
|
|
|
+ status: [ 403, 'Forbidden' ],
|
|
|
+ body: '',
|
|
|
+ )
|
|
|
+ end
|
|
|
+
|
|
|
+ def oauth_access_token
|
|
|
+ stub_post('https://api.twitter.com/oauth/access_token').to_return(
|
|
|
+ body: 'oauth_token=DY8E9gAAAAABCFc9AAABcP4JGzI&oauth_token_secret=15DOeRkjP4JkOSVqULkTKA1SCuIPP105&user_id=1408314039470538752&screen_name=APITesting001'
|
|
|
+ )
|
|
|
+ end
|
|
|
+
|
|
|
+ def webhook_data(app, valid)
|
|
|
+ {
|
|
|
+ id: '1234567890',
|
|
|
+ url: "https://#{app}.example.com/api/v1/channels_twitter_webhook",
|
|
|
+ valid: valid,
|
|
|
+ created_at: '2022-10-11T07:30:00Z',
|
|
|
+ }
|
|
|
+ end
|
|
|
+
|
|
|
+ def webhooks_forbidden
|
|
|
+ stub_get('https://api.twitter.com/1.1/account_activity/all/webhooks.json').to_return(
|
|
|
+ status: 403,
|
|
|
+ body: body_forbidden,
|
|
|
+ headers: headers,
|
|
|
+ )
|
|
|
+ end
|
|
|
+
|
|
|
+ def webhooks_ok
|
|
|
+ stub_get('https://api.twitter.com/1.1/account_activity/all/webhooks.json').to_return(
|
|
|
+ status: 200,
|
|
|
+ body: {
|
|
|
+ environments: [
|
|
|
+ environment_name: 'Integration',
|
|
|
+ webhooks: [ webhook_data('zammad', true) ],
|
|
|
+ ],
|
|
|
+ }.to_json,
|
|
|
+ headers: headers,
|
|
|
+ )
|
|
|
+ end
|
|
|
+
|
|
|
+ def webhooks_env_empty(env: 'zammad')
|
|
|
+ stub_get("https://api.twitter.com/1.1/account_activity/all/#{env}/webhooks.json").to_return(
|
|
|
+ status: 200,
|
|
|
+ body: [].to_json,
|
|
|
+ headers: headers,
|
|
|
+ )
|
|
|
+ end
|
|
|
+
|
|
|
+ def webhooks_env_forbidden(env: 'zammad')
|
|
|
+ stub_get("https://api.twitter.com/1.1/account_activity/all/#{env}/webhooks.json").to_return(
|
|
|
+ status: 403,
|
|
|
+ body: body_forbidden,
|
|
|
+ headers: headers,
|
|
|
+ )
|
|
|
+ end
|
|
|
+
|
|
|
+ def webhooks_env_another_app
|
|
|
+ webhooks_env_ok(valid: true, app: 'another-app')
|
|
|
+ end
|
|
|
+
|
|
|
+ def webhooks_env_invalid
|
|
|
+ webhooks_env_ok(valid: false)
|
|
|
+ end
|
|
|
+
|
|
|
+ def webhooks_env_ok(valid: true, app: 'zammad')
|
|
|
+ stub_get('https://api.twitter.com/1.1/account_activity/all/zammad/webhooks.json').to_return(
|
|
|
+ status: 200,
|
|
|
+ body: [ webhook_data(app, valid) ].to_json,
|
|
|
+ headers: headers,
|
|
|
+ )
|
|
|
+ end
|
|
|
+
|
|
|
+ def register_webhook
|
|
|
+ stub_post('https://api.twitter.com/1.1/account_activity/all/zammad/webhooks.json').to_return(
|
|
|
+ status: 200,
|
|
|
+ body: webhook_data('zammad', true).to_json,
|
|
|
+ headers: headers,
|
|
|
+ )
|
|
|
+ end
|
|
|
+
|
|
|
+ def delete_webhook
|
|
|
+ stub_delete('https://api.twitter.com/1.1/account_activity/all/zammad/webhooks/1234567890.json').to_return(
|
|
|
+ status: 204,
|
|
|
+ body: nil,
|
|
|
+ )
|
|
|
+ end
|
|
|
+
|
|
|
+ def crc_webhook
|
|
|
+ stub_put('https://api.twitter.com/1.1/account_activity/all/zammad/webhooks/1234567890.json').to_return(
|
|
|
+ status: 204,
|
|
|
+ body: nil,
|
|
|
+ )
|
|
|
+ end
|
|
|
+
|
|
|
+ def account_verify_credentials
|
|
|
+ stub_get('https://api.twitter.com/1.1/account/verify_credentials.json').to_return(
|
|
|
+ body: Rails.root.join('spec/fixtures/files/external_credentials/twitter/zammad_testing.json').read,
|
|
|
+ headers: { content_type: 'application/json; charset=utf-8' },
|
|
|
+ )
|
|
|
+ end
|
|
|
+
|
|
|
+ def env_subscriptions(env: 'zammad')
|
|
|
+ stub_post("https://api.twitter.com/1.1/account_activity/all/#{env}/subscriptions.json").to_return(
|
|
|
+ status: 204,
|
|
|
+ headers: { content_type: 'application/json; charset=utf-8' },
|
|
|
+ )
|
|
|
+ end
|
|
|
+
|
|
|
+ describe 'POST /api/v1/external_credentials/twitter/app_verify' do
|
|
|
+ before do
|
|
|
+ authenticated_as(admin, via: :browser)
|
|
|
+ end
|
|
|
+
|
|
|
+ context 'when permission for Twitter channel is deactivated' do
|
|
|
+ before do
|
|
|
+ Permission.find_by(name: 'admin.channel_twitter').update(active: false)
|
|
|
+ end
|
|
|
+
|
|
|
+ it 'blocks the request', :aggregate_failures do
|
|
|
+ post '/api/v1/external_credentials/twitter/app_verify', params: {}, as: :json
|
|
|
+
|
|
|
+ expect(response).to have_http_status(:forbidden)
|
|
|
+ expect(json_response).to include('error' => 'Not authorized (user)!')
|
|
|
+ end
|
|
|
+ end
|
|
|
+
|
|
|
+ context 'with no credentials' do
|
|
|
+ it 'blocks the request', :aggregate_failures do
|
|
|
+ post '/api/v1/external_credentials/twitter/app_verify', params: {}, as: :json
|
|
|
+
|
|
|
+ expect(response).to have_http_status(:ok)
|
|
|
+ expect(json_response).to include('error' => "The required parameter 'consumer_key' is missing.")
|
|
|
+ end
|
|
|
+ end
|
|
|
+
|
|
|
+ context 'with invalid credential params' do
|
|
|
+ before do
|
|
|
+ oauth_request_token_unauthorized
|
|
|
+ end
|
|
|
+
|
|
|
+ it 'blocks the request', :aggregate_failures do
|
|
|
+ post '/api/v1/external_credentials/twitter/app_verify', params: invalid_credentials, as: :json
|
|
|
+
|
|
|
+ expect(response).to have_http_status(:ok)
|
|
|
+ expect(json_response).to include('error' => '401 Unauthorized (Invalid credentials may be to blame.)')
|
|
|
+ end
|
|
|
+ end
|
|
|
+
|
|
|
+ context 'with valid credential params but misconfigured callback URL' do
|
|
|
+ before do
|
|
|
+ oauth_request_token_forbidden
|
|
|
+ end
|
|
|
+
|
|
|
+ it 'blocks the request', :aggregate_failures do
|
|
|
+ post '/api/v1/external_credentials/twitter/app_verify', params: valid_credentials, as: :json
|
|
|
+
|
|
|
+ expect(response).to have_http_status(:ok)
|
|
|
+ expect(json_response).to include('error' => "403 Forbidden (Your app's callback URL configuration on developer.twitter.com may be to blame.)")
|
|
|
+ end
|
|
|
+ end
|
|
|
+
|
|
|
+ context 'with valid credential params and callback URL but no dev env registered' do
|
|
|
+ before do
|
|
|
+ oauth_request_token
|
|
|
+ webhooks_forbidden
|
|
|
+ webhooks_env_forbidden
|
|
|
+ end
|
|
|
+
|
|
|
+ it 'blocks the request', :aggregate_failures do
|
|
|
+ post '/api/v1/external_credentials/twitter/app_verify', params: valid_credentials, as: :json
|
|
|
+
|
|
|
+ expect(response).to have_http_status(:ok)
|
|
|
+ expect(json_response).to include('error' => 'Forbidden. Are you sure you created a development environment on developer.twitter.com?')
|
|
|
+ end
|
|
|
+ end
|
|
|
+
|
|
|
+ context 'with valid credential params and callback URL but wrong dev env label' do
|
|
|
+ before do
|
|
|
+ oauth_request_token
|
|
|
+ webhooks_ok
|
|
|
+ webhooks_env_forbidden(env: 'foo')
|
|
|
+ end
|
|
|
+
|
|
|
+ it 'blocks the request', :aggregate_failures do
|
|
|
+ post '/api/v1/external_credentials/twitter/app_verify', params: valid_credentials.merge(env: 'foo'), as: :json
|
|
|
+
|
|
|
+ expect(response).to have_http_status(:ok)
|
|
|
+ expect(json_response).to include('error' => "Dev Environment Label invalid. Please use an existing one [\"#{ENV.fetch('TWITTER_DEV_ENVIRONMENT', 'Integration')}\"], or create a new one.")
|
|
|
+ end
|
|
|
+ end
|
|
|
+
|
|
|
+ context 'with valid credential params, callback URL, and dev env label' do
|
|
|
+ before do
|
|
|
+ oauth_request_token
|
|
|
+
|
|
|
+ Setting.set('http_type', 'https')
|
|
|
+ Setting.set('fqdn', 'zammad.example.com')
|
|
|
+ end
|
|
|
+
|
|
|
+ context 'with no existing webhooks' do
|
|
|
+ before do
|
|
|
+ webhooks_env_empty
|
|
|
+ register_webhook
|
|
|
+ end
|
|
|
+
|
|
|
+ it 'registers a new webhook', :aggregate_failures do
|
|
|
+ post '/api/v1/external_credentials/twitter/app_verify', params: valid_credentials, as: :json
|
|
|
+
|
|
|
+ expect(a_post('https://api.twitter.com/1.1/account_activity/all/zammad/webhooks.json').with(body: "url=#{CGI.escape(webhook_url)}")).to have_been_made.once
|
|
|
+
|
|
|
+ expect(response).to have_http_status(:ok)
|
|
|
+ expect(json_response).to match('attributes' => hash_including('webhook_id' => '1234567890'))
|
|
|
+ end
|
|
|
+ end
|
|
|
+
|
|
|
+ context 'with an existing webhook registered to another app' do
|
|
|
+ before do
|
|
|
+ webhooks_env_another_app
|
|
|
+ delete_webhook
|
|
|
+ register_webhook
|
|
|
+ end
|
|
|
+
|
|
|
+ it 'deletes all existing webhooks and registers a new one', :aggregate_failures do
|
|
|
+ post '/api/v1/external_credentials/twitter/app_verify', params: valid_credentials, as: :json
|
|
|
+
|
|
|
+ expect(a_delete('https://api.twitter.com/1.1/account_activity/all/zammad/webhooks/1234567890.json'))
|
|
|
+ .to have_been_made.once
|
|
|
+
|
|
|
+ expect(response).to have_http_status(:ok)
|
|
|
+ expect(json_response).to match('attributes' => hash_including('webhook_id' => '1234567890'))
|
|
|
+ end
|
|
|
+ end
|
|
|
+
|
|
|
+ context 'with an existing, invalid webhook registered to Zammad' do
|
|
|
+ before do
|
|
|
+ webhooks_env_invalid
|
|
|
+ crc_webhook
|
|
|
+ end
|
|
|
+
|
|
|
+ it 'revalidates by manually triggering a challenge-response check', :aggregate_failures do
|
|
|
+ post '/api/v1/external_credentials/twitter/app_verify', params: valid_credentials, as: :json
|
|
|
+
|
|
|
+ expect(a_put('https://api.twitter.com/1.1/account_activity/all/zammad/webhooks/1234567890.json')).to have_been_made.once
|
|
|
+
|
|
|
+ expect(response).to have_http_status(:ok)
|
|
|
+ expect(json_response).to match('attributes' => hash_including('webhook_id' => '1234567890'))
|
|
|
+ end
|
|
|
+ end
|
|
|
+
|
|
|
+ context 'with an existing, valid webhook registered to Zammad' do
|
|
|
+ before do
|
|
|
+ webhooks_env_ok
|
|
|
+ end
|
|
|
+
|
|
|
+ it 'uses the existing webhook' do
|
|
|
+ post '/api/v1/external_credentials/twitter/app_verify', params: valid_credentials, as: :json
|
|
|
+
|
|
|
+ expect(a_post('https://api.twitter.com/1.1/account_activity/all/zammad/webhooks.json').with(body: "url=#{CGI.escape(webhook_url)}")).not_to have_been_made
|
|
|
+ end
|
|
|
+ end
|
|
|
+ end
|
|
|
+ end
|
|
|
+
|
|
|
+ describe 'GET /api/v1/external_credentials/twitter/link_account' do
|
|
|
+ before do
|
|
|
+ authenticated_as(admin, via: :browser)
|
|
|
+ end
|
|
|
+
|
|
|
+ context 'with no Twitter app' do
|
|
|
+ it 'returns an error message', :aggregate_failures do
|
|
|
+ get '/api/v1/external_credentials/twitter/link_account', as: :json
|
|
|
+
|
|
|
+ expect(response).to have_http_status(:unprocessable_entity)
|
|
|
+ expect(json_response).to include('error' => 'There is no Twitter app configured.')
|
|
|
+ end
|
|
|
+ end
|
|
|
+
|
|
|
+ context 'with invalid Twitter app (configured with invalid credentials)' do
|
|
|
+ before do
|
|
|
+ create(:twitter_credential, :invalid)
|
|
|
+ oauth_request_token_unauthorized
|
|
|
+ end
|
|
|
+
|
|
|
+ it 'returns an error message', :aggregate_failures do
|
|
|
+ get '/api/v1/external_credentials/twitter/link_account', as: :json
|
|
|
+
|
|
|
+ expect(response).to have_http_status(:internal_server_error)
|
|
|
+ expect(json_response).to include('error' => '401 Unauthorized (Invalid credentials may be to blame.)')
|
|
|
+ end
|
|
|
+ end
|
|
|
+
|
|
|
+ context 'with a valid Twitter app but misconfigured callback URL' do
|
|
|
+ before do
|
|
|
+ create(:twitter_credential)
|
|
|
+ oauth_request_token_forbidden
|
|
|
+ end
|
|
|
+
|
|
|
+ it 'returns an error message', :aggregate_failures do
|
|
|
+ get '/api/v1/external_credentials/twitter/link_account', as: :json
|
|
|
+
|
|
|
+ expect(response).to have_http_status(:internal_server_error)
|
|
|
+ expect(json_response).to include('error' => "403 Forbidden (Your app's callback URL configuration on developer.twitter.com may be to blame.)")
|
|
|
+ end
|
|
|
+ end
|
|
|
+
|
|
|
+ context 'with a valid Twitter app and callback URL' do
|
|
|
+ let(:twitter_credential) { create(:twitter_credential) }
|
|
|
+
|
|
|
+ before do
|
|
|
+ twitter_credential
|
|
|
+ oauth_request_token
|
|
|
+
|
|
|
+ Setting.set('http_type', 'https')
|
|
|
+ Setting.set('fqdn', 'zammad.example.com')
|
|
|
+ end
|
|
|
+
|
|
|
+ it 'returns authorization data in the headers' do
|
|
|
+ get '/api/v1/external_credentials/twitter/link_account', as: :json
|
|
|
+
|
|
|
+ expect(
|
|
|
+ a_post('https://api.twitter.com/oauth/request_token').with(headers: { 'Authorization' => %r{oauth_consumer_key="#{twitter_credential.credentials[:consumer_key]}"} })
|
|
|
+ ).to have_been_made.once
|
|
|
+ end
|
|
|
+
|
|
|
+ it 'redirects to Twitter authorization URL' do
|
|
|
+ get '/api/v1/external_credentials/twitter/link_account', as: :json
|
|
|
+
|
|
|
+ expect(response).to redirect_to(%r{^https://api.twitter.com/oauth/authorize\?oauth_token=\w+$})
|
|
|
+ end
|
|
|
+
|
|
|
+ it 'saves request token to session hash' do
|
|
|
+ get '/api/v1/external_credentials/twitter/link_account', as: :json
|
|
|
+
|
|
|
+ expect(session[:request_token]).to be_a(OAuth::RequestToken)
|
|
|
+ end
|
|
|
+ end
|
|
|
+ end
|
|
|
+
|
|
|
+ describe 'GET /api/v1/external_credentials/twitter/callback' do
|
|
|
+ before do
|
|
|
+ authenticated_as(admin, via: :browser)
|
|
|
+ end
|
|
|
+
|
|
|
+ context 'with no Twitter app' do
|
|
|
+ it 'returns an error message', :aggregate_failures do
|
|
|
+ get '/api/v1/external_credentials/twitter/callback', as: :json
|
|
|
+
|
|
|
+ expect(response).to have_http_status(:unprocessable_entity)
|
|
|
+ expect(json_response).to include('error' => 'There is no Twitter app configured.')
|
|
|
+ end
|
|
|
+ end
|
|
|
+
|
|
|
+ context 'with valid Twitter app but no request token' do
|
|
|
+ before do
|
|
|
+ create(:twitter_credential)
|
|
|
+ end
|
|
|
+
|
|
|
+ it 'returns an error message', :aggregate_failures do
|
|
|
+ get '/api/v1/external_credentials/twitter/callback', as: :json
|
|
|
+
|
|
|
+ expect(response).to have_http_status(:unprocessable_entity)
|
|
|
+ expect(json_response).to include('error' => "The required parameter 'request_token' is missing.")
|
|
|
+ end
|
|
|
+ end
|
|
|
+
|
|
|
+ context 'with valid Twitter app and request token but non-matching OAuth token (via params)' do
|
|
|
+ before do
|
|
|
+ create(:twitter_credential)
|
|
|
+
|
|
|
+ Setting.set('http_type', 'https')
|
|
|
+ Setting.set('fqdn', 'zammad.example.com')
|
|
|
+
|
|
|
+ oauth_request_token
|
|
|
+ get '/api/v1/external_credentials/twitter/link_account', as: :json, headers: { 'X-Forwarded-Proto' => 'https' }
|
|
|
+ end
|
|
|
+
|
|
|
+ it 'returns an error message', :aggregate_failures do
|
|
|
+ get '/api/v1/external_credentials/twitter/callback', as: :json
|
|
|
+
|
|
|
+ expect(response).to have_http_status(:unprocessable_entity)
|
|
|
+ expect(json_response).to include('error' => "The provided 'oauth_token' is invalid.")
|
|
|
+ end
|
|
|
+ end
|
|
|
+
|
|
|
+ context 'with valid Twitter app, request token, and matching OAuth token (via params)' do
|
|
|
+ let(:twitter_credential) { create(:twitter_credential) }
|
|
|
+ let(:params) { { oauth_token: 'DY8E9gAAAAABCFc9AAABcP4JGzI', oauth_verifier: '15DOeRkjP4JkOSVqULkTKA1SCuIPP105' } }
|
|
|
+
|
|
|
+ before do
|
|
|
+ twitter_credential
|
|
|
+ Setting.set('http_type', 'https')
|
|
|
+ Setting.set('fqdn', 'zammad.example.com')
|
|
|
+
|
|
|
+ oauth_request_token
|
|
|
+ get '/api/v1/external_credentials/twitter/link_account', as: :json, headers: { 'X-Forwarded-Proto' => 'https' }
|
|
|
+
|
|
|
+ oauth_access_token
|
|
|
+ account_verify_credentials
|
|
|
+ env_subscriptions
|
|
|
+ end
|
|
|
+
|
|
|
+ it 'creates a new channel', :aggregate_failures do
|
|
|
+ expect { get '/api/v1/external_credentials/twitter/callback', as: :json, params: params, headers: { 'X-Forwarded-Proto' => 'https' } }.to change(Channel, :count).by(1)
|
|
|
+
|
|
|
+ expect(Channel.last.options).to include('adapter' => 'twitter')
|
|
|
+ .and include('user' => hash_including('id', 'screen_name', 'name'))
|
|
|
+ .and include('auth' => hash_including('external_credential_id', 'oauth_token', 'oauth_token_secret'))
|
|
|
+ end
|
|
|
+
|
|
|
+ it 'redirects to the newly created channel', :aggregate_failures do
|
|
|
+ expect { get '/api/v1/external_credentials/twitter/callback', as: :json, params: params, headers: { 'X-Forwarded-Proto' => 'https' } }.to change(Channel, :count).by(1)
|
|
|
+
|
|
|
+ expect(response).to redirect_to(%r{/#channels/twitter/#{Channel.last.id}$})
|
|
|
+ end
|
|
|
+
|
|
|
+ it 'clears the :request_token session variable', :aggregate_failures do
|
|
|
+ expect { get '/api/v1/external_credentials/twitter/callback', as: :json, params: params, headers: { 'X-Forwarded-Proto' => 'https' } }.to change(Channel, :count).by(1)
|
|
|
+
|
|
|
+ expect(session[:request_token]).to be_nil
|
|
|
+ end
|
|
|
+
|
|
|
+ it 'subscribes to webhooks', :aggregate_failures do
|
|
|
+ expect { get '/api/v1/external_credentials/twitter/callback', as: :json, params: params, headers: { 'X-Forwarded-Proto' => 'https' } }.to change(Channel, :count).by(1)
|
|
|
+
|
|
|
+ expect(
|
|
|
+ a_post("https://api.twitter.com/1.1/account_activity/all/#{twitter_credential.credentials[:env]}/subscriptions.json").with(body: {})
|
|
|
+ ).to have_been_made.once
|
|
|
+
|
|
|
+ expect(Channel.last.options['subscribed_to_webhook_id']).to eq(twitter_credential.credentials[:webhook_id])
|
|
|
+ end
|
|
|
+
|
|
|
+ context 'when Twitter account has already been added' do
|
|
|
+ let(:channel) { create(:twitter_channel) }
|
|
|
+
|
|
|
+ before do
|
|
|
+ channel
|
|
|
+ end
|
|
|
+
|
|
|
+ it 'uses the existing channel' do
|
|
|
+ expect do
|
|
|
+ get '/api/v1/external_credentials/twitter/callback', as: :json, params: params, headers: { 'X-Forwarded-Proto' => 'https' }
|
|
|
+ end.not_to change(Channel, :count)
|
|
|
+ end
|
|
|
+
|
|
|
+ it 'updates channel properties' do
|
|
|
+ expect { get '/api/v1/external_credentials/twitter/callback', as: :json, params: params, headers: { 'X-Forwarded-Proto' => 'https' } }.to change { channel.reload.updated_at }
|
|
|
+ .and change { channel.reload.options[:auth][:external_credential_id] }
|
|
|
+ .and change { channel.reload.options[:auth][:oauth_token] }
|
|
|
+ .and change { channel.reload.options[:auth][:oauth_token_secret] }
|
|
|
+ end
|
|
|
+
|
|
|
+ it 'subscribes to webhooks', :aggregate_failures do
|
|
|
+ get '/api/v1/external_credentials/twitter/callback', as: :json, params: params, headers: { 'X-Forwarded-Proto' => 'https' }
|
|
|
+
|
|
|
+ expect(
|
|
|
+ a_post("https://api.twitter.com/1.1/account_activity/all/#{twitter_credential.credentials[:env]}/subscriptions.json").with(body: {})
|
|
|
+ ).to have_been_made.once
|
|
|
+ expect(channel.reload.options['subscribed_to_webhook_id']).to eq(twitter_credential.credentials[:webhook_id])
|
|
|
+ end
|
|
|
+ end
|
|
|
+ end
|
|
|
+ end
|
|
|
+end
|