feat: Instagram reauthorization (#11221)
This PR is part of https://github.com/chatwoot/chatwoot/pull/11054 to make the review cycle easier.
This commit is contained in:
@@ -26,9 +26,14 @@ class Instagram::CallbacksController < ApplicationController
|
|||||||
)
|
)
|
||||||
|
|
||||||
@long_lived_token_response = exchange_for_long_lived_token(@response.token)
|
@long_lived_token_response = exchange_for_long_lived_token(@response.token)
|
||||||
inbox, = create_channel_with_inbox
|
inbox, already_exists = find_or_create_inbox
|
||||||
|
|
||||||
|
if already_exists
|
||||||
|
redirect_to app_instagram_inbox_settings_url(account_id: account_id, inbox_id: inbox.id)
|
||||||
|
else
|
||||||
redirect_to app_instagram_inbox_agents_url(account_id: account_id, inbox_id: inbox.id)
|
redirect_to app_instagram_inbox_agents_url(account_id: account_id, inbox_id: inbox.id)
|
||||||
end
|
end
|
||||||
|
end
|
||||||
|
|
||||||
# Handle all errors that might occur during authorization
|
# Handle all errors that might occur during authorization
|
||||||
# https://developers.facebook.com/docs/instagram-platform/instagram-api-with-instagram-login/business-login#sample-rejected-response
|
# https://developers.facebook.com/docs/instagram-platform/instagram-api-with-instagram-login/business-login#sample-rejected-response
|
||||||
@@ -82,11 +87,44 @@ class Instagram::CallbacksController < ApplicationController
|
|||||||
)
|
)
|
||||||
end
|
end
|
||||||
|
|
||||||
def create_channel_with_inbox
|
def find_or_create_inbox
|
||||||
ActiveRecord::Base.transaction do
|
user_details = fetch_instagram_user_details(@long_lived_token_response['access_token'])
|
||||||
|
channel_instagram = find_channel_by_instagram_id(user_details['user_id'].to_s)
|
||||||
|
channel_exists = channel_instagram.present?
|
||||||
|
|
||||||
|
if channel_instagram
|
||||||
|
update_channel(channel_instagram, user_details)
|
||||||
|
else
|
||||||
|
channel_instagram = create_channel_with_inbox(user_details)
|
||||||
|
end
|
||||||
|
|
||||||
|
# reauthorize channel, this code path only triggers when instagram auth is successful
|
||||||
|
# reauthorized will also update cache keys for the associated inbox
|
||||||
|
channel_instagram.reauthorized!
|
||||||
|
|
||||||
|
[channel_instagram.inbox, channel_exists]
|
||||||
|
end
|
||||||
|
|
||||||
|
def find_channel_by_instagram_id(instagram_id)
|
||||||
|
Channel::Instagram.find_by(instagram_id: instagram_id, account: account)
|
||||||
|
end
|
||||||
|
|
||||||
|
def update_channel(channel_instagram, user_details)
|
||||||
expires_at = Time.current + @long_lived_token_response['expires_in'].seconds
|
expires_at = Time.current + @long_lived_token_response['expires_in'].seconds
|
||||||
|
|
||||||
user_details = fetch_instagram_user_details(@long_lived_token_response['access_token'])
|
channel_instagram.update!(
|
||||||
|
access_token: @long_lived_token_response['access_token'],
|
||||||
|
expires_at: expires_at
|
||||||
|
)
|
||||||
|
|
||||||
|
# Update inbox name if username changed
|
||||||
|
channel_instagram.inbox.update!(name: user_details['username'])
|
||||||
|
channel_instagram
|
||||||
|
end
|
||||||
|
|
||||||
|
def create_channel_with_inbox(user_details)
|
||||||
|
ActiveRecord::Base.transaction do
|
||||||
|
expires_at = Time.current + @long_lived_token_response['expires_in'].seconds
|
||||||
|
|
||||||
channel_instagram = Channel::Instagram.create!(
|
channel_instagram = Channel::Instagram.create!(
|
||||||
access_token: @long_lived_token_response['access_token'],
|
access_token: @long_lived_token_response['access_token'],
|
||||||
@@ -100,6 +138,8 @@ class Instagram::CallbacksController < ApplicationController
|
|||||||
channel: channel_instagram,
|
channel: channel_instagram,
|
||||||
name: user_details['username']
|
name: user_details['username']
|
||||||
)
|
)
|
||||||
|
|
||||||
|
channel_instagram
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ export const INBOX_TYPES = {
|
|||||||
TELEGRAM: 'Channel::Telegram',
|
TELEGRAM: 'Channel::Telegram',
|
||||||
LINE: 'Channel::Line',
|
LINE: 'Channel::Line',
|
||||||
SMS: 'Channel::Sms',
|
SMS: 'Channel::Sms',
|
||||||
|
INSTAGRAM: 'Channel::Instagram',
|
||||||
};
|
};
|
||||||
|
|
||||||
const INBOX_ICON_MAP_FILL = {
|
const INBOX_ICON_MAP_FILL = {
|
||||||
@@ -20,6 +21,7 @@ const INBOX_ICON_MAP_FILL = {
|
|||||||
[INBOX_TYPES.EMAIL]: 'i-ri-mail-fill',
|
[INBOX_TYPES.EMAIL]: 'i-ri-mail-fill',
|
||||||
[INBOX_TYPES.TELEGRAM]: 'i-ri-telegram-fill',
|
[INBOX_TYPES.TELEGRAM]: 'i-ri-telegram-fill',
|
||||||
[INBOX_TYPES.LINE]: 'i-ri-line-fill',
|
[INBOX_TYPES.LINE]: 'i-ri-line-fill',
|
||||||
|
[INBOX_TYPES.INSTAGRAM]: 'i-ri-instagram-fill',
|
||||||
};
|
};
|
||||||
|
|
||||||
const DEFAULT_ICON_FILL = 'i-ri-chat-1-fill';
|
const DEFAULT_ICON_FILL = 'i-ri-chat-1-fill';
|
||||||
@@ -33,6 +35,7 @@ const INBOX_ICON_MAP_LINE = {
|
|||||||
[INBOX_TYPES.EMAIL]: 'i-ri-mail-line',
|
[INBOX_TYPES.EMAIL]: 'i-ri-mail-line',
|
||||||
[INBOX_TYPES.TELEGRAM]: 'i-ri-telegram-line',
|
[INBOX_TYPES.TELEGRAM]: 'i-ri-telegram-line',
|
||||||
[INBOX_TYPES.LINE]: 'i-ri-line-line',
|
[INBOX_TYPES.LINE]: 'i-ri-line-line',
|
||||||
|
[INBOX_TYPES.INSTAGRAM]: 'i-ri-instagram-line',
|
||||||
};
|
};
|
||||||
|
|
||||||
const DEFAULT_ICON_LINE = 'i-ri-chat-1-line';
|
const DEFAULT_ICON_LINE = 'i-ri-chat-1-line';
|
||||||
@@ -118,6 +121,9 @@ export const getInboxClassByType = (type, phoneNumber) => {
|
|||||||
case INBOX_TYPES.LINE:
|
case INBOX_TYPES.LINE:
|
||||||
return 'brand-line';
|
return 'brand-line';
|
||||||
|
|
||||||
|
case INBOX_TYPES.INSTAGRAM:
|
||||||
|
return 'brand-instagram';
|
||||||
|
|
||||||
default:
|
default:
|
||||||
return 'chat';
|
return 'chat';
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -49,7 +49,7 @@
|
|||||||
"CONTINUE_WITH_INSTAGRAM": "Continue with Instagram",
|
"CONTINUE_WITH_INSTAGRAM": "Continue with Instagram",
|
||||||
"HELP": "To add your Instagram profile as a channel, you need to authenticate your Instagram Profile by clicking on 'Continue with Instagram' ",
|
"HELP": "To add your Instagram profile as a channel, you need to authenticate your Instagram Profile by clicking on 'Continue with Instagram' ",
|
||||||
"ERROR_MESSAGE": "There was an error connecting to Instagram, please try again",
|
"ERROR_MESSAGE": "There was an error connecting to Instagram, please try again",
|
||||||
"ERROR_AUTH": "Something went wrong with your Instagram authentication, please try again"
|
"ERROR_AUTH": "There was an error connecting to Instagram, please try again"
|
||||||
},
|
},
|
||||||
"TWITTER": {
|
"TWITTER": {
|
||||||
"HELP": "To add your Twitter profile as a channel, you need to authenticate your Twitter Profile by clicking on 'Sign in with Twitter' ",
|
"HELP": "To add your Twitter profile as a channel, you need to authenticate your Twitter Profile by clicking on 'Sign in with Twitter' ",
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ import SettingIntroBanner from 'dashboard/components/widgets/SettingIntroBanner.
|
|||||||
import SettingsSection from '../../../../components/SettingsSection.vue';
|
import SettingsSection from '../../../../components/SettingsSection.vue';
|
||||||
import inboxMixin from 'shared/mixins/inboxMixin';
|
import inboxMixin from 'shared/mixins/inboxMixin';
|
||||||
import FacebookReauthorize from './facebook/Reauthorize.vue';
|
import FacebookReauthorize from './facebook/Reauthorize.vue';
|
||||||
|
import InstagramReauthorize from './channels/instagram/Reauthorize.vue';
|
||||||
import MicrosoftReauthorize from './channels/microsoft/Reauthorize.vue';
|
import MicrosoftReauthorize from './channels/microsoft/Reauthorize.vue';
|
||||||
import GoogleReauthorize from './channels/google/Reauthorize.vue';
|
import GoogleReauthorize from './channels/google/Reauthorize.vue';
|
||||||
import PreChatFormSettings from './PreChatForm/Settings.vue';
|
import PreChatFormSettings from './PreChatForm/Settings.vue';
|
||||||
@@ -36,6 +37,7 @@ export default {
|
|||||||
MicrosoftReauthorize,
|
MicrosoftReauthorize,
|
||||||
GoogleReauthorize,
|
GoogleReauthorize,
|
||||||
NextButton,
|
NextButton,
|
||||||
|
InstagramReauthorize,
|
||||||
},
|
},
|
||||||
mixins: [inboxMixin],
|
mixins: [inboxMixin],
|
||||||
setup() {
|
setup() {
|
||||||
@@ -202,6 +204,9 @@ export default {
|
|||||||
return true;
|
return true;
|
||||||
return false;
|
return false;
|
||||||
},
|
},
|
||||||
|
instagramUnauthorized() {
|
||||||
|
return this.isAInstagramChannel && this.inbox.reauthorization_required;
|
||||||
|
},
|
||||||
microsoftUnauthorized() {
|
microsoftUnauthorized() {
|
||||||
return this.isAMicrosoftInbox && this.inbox.reauthorization_required;
|
return this.isAMicrosoftInbox && this.inbox.reauthorization_required;
|
||||||
},
|
},
|
||||||
@@ -383,10 +388,11 @@ export default {
|
|||||||
/>
|
/>
|
||||||
</woot-tabs>
|
</woot-tabs>
|
||||||
</SettingIntroBanner>
|
</SettingIntroBanner>
|
||||||
<section class="max-w-6xl mx-auto w-full">
|
<section class="w-full max-w-6xl mx-auto">
|
||||||
<MicrosoftReauthorize v-if="microsoftUnauthorized" :inbox="inbox" />
|
<MicrosoftReauthorize v-if="microsoftUnauthorized" :inbox="inbox" />
|
||||||
<FacebookReauthorize v-if="facebookUnauthorized" :inbox="inbox" />
|
<FacebookReauthorize v-if="facebookUnauthorized" :inbox="inbox" />
|
||||||
<GoogleReauthorize v-if="googleUnauthorized" :inbox="inbox" />
|
<GoogleReauthorize v-if="googleUnauthorized" :inbox="inbox" />
|
||||||
|
<InstagramReauthorize v-if="instagramUnauthorized" :inbox="inbox" />
|
||||||
<div v-if="selectedTabKey === 'inbox_settings'" class="mx-8">
|
<div v-if="selectedTabKey === 'inbox_settings'" class="mx-8">
|
||||||
<SettingsSection
|
<SettingsSection
|
||||||
:title="$t('INBOX_MGMT.SETTINGS_POPUP.INBOX_UPDATE_TITLE')"
|
:title="$t('INBOX_MGMT.SETTINGS_POPUP.INBOX_UPDATE_TITLE')"
|
||||||
|
|||||||
@@ -0,0 +1,37 @@
|
|||||||
|
<script setup>
|
||||||
|
import { ref } from 'vue';
|
||||||
|
import InboxReconnectionRequired from '../../components/InboxReconnectionRequired.vue';
|
||||||
|
|
||||||
|
import instagramClient from 'dashboard/api/channel/instagramClient';
|
||||||
|
|
||||||
|
import { useI18n } from 'vue-i18n';
|
||||||
|
import { useAlert } from 'dashboard/composables';
|
||||||
|
|
||||||
|
const { t } = useI18n();
|
||||||
|
|
||||||
|
const isRequestingAuthorization = ref(false);
|
||||||
|
|
||||||
|
async function requestAuthorization() {
|
||||||
|
try {
|
||||||
|
isRequestingAuthorization.value = true;
|
||||||
|
const response = await instagramClient.generateAuthorization();
|
||||||
|
|
||||||
|
const {
|
||||||
|
data: { url },
|
||||||
|
} = response;
|
||||||
|
|
||||||
|
window.location.href = url;
|
||||||
|
} catch (error) {
|
||||||
|
useAlert(t('INBOX_MGMT.ADD.INSTAGRAM.ERROR_AUTH'));
|
||||||
|
} finally {
|
||||||
|
isRequestingAuthorization.value = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<InboxReconnectionRequired
|
||||||
|
class="mx-8 mt-5"
|
||||||
|
@reauthorize="requestAuthorization"
|
||||||
|
/>
|
||||||
|
</template>
|
||||||
@@ -28,6 +28,7 @@ const i18nMap = {
|
|||||||
'Channel::Telegram': 'TELEGRAM',
|
'Channel::Telegram': 'TELEGRAM',
|
||||||
'Channel::Line': 'LINE',
|
'Channel::Line': 'LINE',
|
||||||
'Channel::Api': 'API',
|
'Channel::Api': 'API',
|
||||||
|
'Channel::Instagram': 'INSTAGRAM',
|
||||||
};
|
};
|
||||||
|
|
||||||
const twilioChannelName = () => {
|
const twilioChannelName = () => {
|
||||||
|
|||||||
@@ -121,6 +121,9 @@ export default {
|
|||||||
this.isATwilioWhatsAppChannel
|
this.isATwilioWhatsAppChannel
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
|
isAInstagramChannel() {
|
||||||
|
return this.channelType === INBOX_TYPES.INSTAGRAM;
|
||||||
|
},
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
inboxHasFeature(feature) {
|
inboxHasFeature(feature) {
|
||||||
|
|||||||
@@ -4,6 +4,11 @@ class AdministratorNotifications::ChannelNotificationsMailer < AdministratorNoti
|
|||||||
send_notification(subject, action_url: inbox_url(inbox))
|
send_notification(subject, action_url: inbox_url(inbox))
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def instagram_disconnect(inbox)
|
||||||
|
subject = 'Your Instagram connection has expired'
|
||||||
|
send_notification(subject, action_url: inbox_url(inbox))
|
||||||
|
end
|
||||||
|
|
||||||
def whatsapp_disconnect(inbox)
|
def whatsapp_disconnect(inbox)
|
||||||
subject = 'Your Whatsapp connection has expired'
|
subject = 'Your Whatsapp connection has expired'
|
||||||
send_notification(subject, action_url: inbox_url(inbox))
|
send_notification(subject, action_url: inbox_url(inbox))
|
||||||
|
|||||||
@@ -19,6 +19,8 @@ class Channel::Instagram < ApplicationRecord
|
|||||||
include Reauthorizable
|
include Reauthorizable
|
||||||
self.table_name = 'channel_instagram'
|
self.table_name = 'channel_instagram'
|
||||||
|
|
||||||
|
AUTHORIZATION_ERROR_THRESHOLD = 1
|
||||||
|
|
||||||
validates :access_token, presence: true
|
validates :access_token, presence: true
|
||||||
validates :instagram_id, uniqueness: true, presence: true
|
validates :instagram_id, uniqueness: true, presence: true
|
||||||
|
|
||||||
|
|||||||
@@ -39,18 +39,7 @@ module Reauthorizable
|
|||||||
def prompt_reauthorization!
|
def prompt_reauthorization!
|
||||||
::Redis::Alfred.set(reauthorization_required_key, true)
|
::Redis::Alfred.set(reauthorization_required_key, true)
|
||||||
|
|
||||||
case self.class.name
|
reauthorization_handlers[self.class.name]&.call(self)
|
||||||
when 'Integrations::Hook'
|
|
||||||
process_integration_hook_reauthorization_emails
|
|
||||||
when 'Channel::FacebookPage'
|
|
||||||
send_channel_reauthorization_email(:facebook_disconnect)
|
|
||||||
when 'Channel::Whatsapp'
|
|
||||||
send_channel_reauthorization_email(:whatsapp_disconnect)
|
|
||||||
when 'Channel::Email'
|
|
||||||
send_channel_reauthorization_email(:email_disconnect)
|
|
||||||
when 'AutomationRule'
|
|
||||||
handle_automation_rule_reauthorization
|
|
||||||
end
|
|
||||||
|
|
||||||
invalidate_inbox_cache unless instance_of?(::AutomationRule)
|
invalidate_inbox_cache unless instance_of?(::AutomationRule)
|
||||||
end
|
end
|
||||||
@@ -82,6 +71,17 @@ module Reauthorizable
|
|||||||
|
|
||||||
private
|
private
|
||||||
|
|
||||||
|
def reauthorization_handlers
|
||||||
|
{
|
||||||
|
'Integrations::Hook' => ->(obj) { obj.process_integration_hook_reauthorization_emails },
|
||||||
|
'Channel::FacebookPage' => ->(obj) { obj.send_channel_reauthorization_email(:facebook_disconnect) },
|
||||||
|
'Channel::Instagram' => ->(obj) { obj.send_channel_reauthorization_email(:instagram_disconnect) },
|
||||||
|
'Channel::Whatsapp' => ->(obj) { obj.send_channel_reauthorization_email(:whatsapp_disconnect) },
|
||||||
|
'Channel::Email' => ->(obj) { obj.send_channel_reauthorization_email(:email_disconnect) },
|
||||||
|
'AutomationRule' => ->(obj) { obj.handle_automation_rule_reauthorization }
|
||||||
|
}
|
||||||
|
end
|
||||||
|
|
||||||
def invalidate_inbox_cache
|
def invalidate_inbox_cache
|
||||||
inbox.update_account_cache if inbox.present?
|
inbox.update_account_cache if inbox.present?
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -107,7 +107,11 @@ class Inbox < ApplicationRecord
|
|||||||
end
|
end
|
||||||
|
|
||||||
def instagram?
|
def instagram?
|
||||||
facebook? && channel.instagram_id.present?
|
(facebook? || instagram_direct?) && channel.instagram_id.present?
|
||||||
|
end
|
||||||
|
|
||||||
|
def instagram_direct?
|
||||||
|
channel_type == 'Channel::Instagram'
|
||||||
end
|
end
|
||||||
|
|
||||||
def web_widget?
|
def web_widget?
|
||||||
|
|||||||
@@ -54,6 +54,9 @@ if resource.facebook?
|
|||||||
json.reauthorization_required resource.channel.try(:reauthorization_required?)
|
json.reauthorization_required resource.channel.try(:reauthorization_required?)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
## Instagram Attributes
|
||||||
|
json.reauthorization_required resource.channel.try(:reauthorization_required?) if resource.instagram?
|
||||||
|
|
||||||
## Twilio Attributes
|
## Twilio Attributes
|
||||||
json.messaging_service_sid resource.channel.try(:messaging_service_sid)
|
json.messaging_service_sid resource.channel.try(:messaging_service_sid)
|
||||||
json.phone_number resource.channel.try(:phone_number)
|
json.phone_number resource.channel.try(:phone_number)
|
||||||
|
|||||||
@@ -0,0 +1,8 @@
|
|||||||
|
<p>Hello,</p>
|
||||||
|
|
||||||
|
<p>Your Instagram Inbox Access has expired. </p>
|
||||||
|
<p>Please reconnect Instagram to continue receiving messages.</p>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
Click <a href="{{action_url}}">here</a> to re-connect.
|
||||||
|
</p>
|
||||||
@@ -22,6 +22,7 @@ Rails.application.routes.draw do
|
|||||||
get '/app/accounts/:account_id/settings/inboxes/new/:inbox_id/agents', to: 'dashboard#index', as: 'app_twitter_inbox_agents'
|
get '/app/accounts/:account_id/settings/inboxes/new/:inbox_id/agents', to: 'dashboard#index', as: 'app_twitter_inbox_agents'
|
||||||
get '/app/accounts/:account_id/settings/inboxes/new/:inbox_id/agents', to: 'dashboard#index', as: 'app_email_inbox_agents'
|
get '/app/accounts/:account_id/settings/inboxes/new/:inbox_id/agents', to: 'dashboard#index', as: 'app_email_inbox_agents'
|
||||||
get '/app/accounts/:account_id/settings/inboxes/new/:inbox_id/agents', to: 'dashboard#index', as: 'app_instagram_inbox_agents'
|
get '/app/accounts/:account_id/settings/inboxes/new/:inbox_id/agents', to: 'dashboard#index', as: 'app_instagram_inbox_agents'
|
||||||
|
get '/app/accounts/:account_id/settings/inboxes/:inbox_id', to: 'dashboard#index', as: 'app_instagram_inbox_settings'
|
||||||
get '/app/accounts/:account_id/settings/inboxes/:inbox_id', to: 'dashboard#index', as: 'app_email_inbox_settings'
|
get '/app/accounts/:account_id/settings/inboxes/:inbox_id', to: 'dashboard#index', as: 'app_email_inbox_settings'
|
||||||
|
|
||||||
resource :widget, only: [:show]
|
resource :widget, only: [:show]
|
||||||
|
|||||||
@@ -44,4 +44,18 @@ RSpec.describe AdministratorNotifications::ChannelNotificationsMailer do
|
|||||||
expect(mail.to).to eq([administrator.email])
|
expect(mail.to).to eq([administrator.email])
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
describe 'instagram_disconnect' do
|
||||||
|
let!(:instagram_channel) { create(:channel_instagram, account: account) }
|
||||||
|
let!(:instagram_inbox) { create(:inbox, channel: instagram_channel, account: account) }
|
||||||
|
let(:mail) { described_class.with(account: account).instagram_disconnect(instagram_inbox).deliver_now }
|
||||||
|
|
||||||
|
it 'renders the subject' do
|
||||||
|
expect(mail.subject).to eq('Your Instagram connection has expired')
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'renders the receiver email' do
|
||||||
|
expect(mail.to).to eq([administrator.email])
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
# frozen_string_literal: true
|
# frozen_string_literal: true
|
||||||
|
|
||||||
require 'rails_helper'
|
require 'rails_helper'
|
||||||
|
require Rails.root.join 'spec/models/concerns/reauthorizable_shared.rb'
|
||||||
|
|
||||||
RSpec.describe Channel::Instagram do
|
RSpec.describe Channel::Instagram do
|
||||||
let(:channel) { create(:channel_instagram) }
|
let(:channel) { create(:channel_instagram) }
|
||||||
@@ -14,4 +15,21 @@ RSpec.describe Channel::Instagram do
|
|||||||
it 'has a valid name' do
|
it 'has a valid name' do
|
||||||
expect(channel.name).to eq('Instagram')
|
expect(channel.name).to eq('Instagram')
|
||||||
end
|
end
|
||||||
|
|
||||||
|
describe 'concerns' do
|
||||||
|
it_behaves_like 'reauthorizable'
|
||||||
|
|
||||||
|
context 'when prompt_reauthorization!' do
|
||||||
|
it 'calls channel notifier mail for instagram' do
|
||||||
|
admin_mailer = double
|
||||||
|
mailer_double = double
|
||||||
|
|
||||||
|
expect(AdministratorNotifications::ChannelNotificationsMailer).to receive(:with).and_return(admin_mailer)
|
||||||
|
expect(admin_mailer).to receive(:instagram_disconnect).with(channel.inbox).and_return(mailer_double)
|
||||||
|
expect(mailer_double).to receive(:deliver_later)
|
||||||
|
|
||||||
|
channel.prompt_reauthorization!
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -48,10 +48,12 @@ shared_examples_for 'reauthorizable' do
|
|||||||
facebook_mailer_response = instance_double(ActionMailer::MessageDelivery, deliver_later: true)
|
facebook_mailer_response = instance_double(ActionMailer::MessageDelivery, deliver_later: true)
|
||||||
whatsapp_mailer_response = instance_double(ActionMailer::MessageDelivery, deliver_later: true)
|
whatsapp_mailer_response = instance_double(ActionMailer::MessageDelivery, deliver_later: true)
|
||||||
email_mailer_response = instance_double(ActionMailer::MessageDelivery, deliver_later: true)
|
email_mailer_response = instance_double(ActionMailer::MessageDelivery, deliver_later: true)
|
||||||
|
instagram_mailer_response = instance_double(ActionMailer::MessageDelivery, deliver_later: true)
|
||||||
allow(AdministratorNotifications::ChannelNotificationsMailer).to receive(:with).and_return(channel_mailer)
|
allow(AdministratorNotifications::ChannelNotificationsMailer).to receive(:with).and_return(channel_mailer)
|
||||||
allow(channel_mailer).to receive(:facebook_disconnect).and_return(facebook_mailer_response)
|
allow(channel_mailer).to receive(:facebook_disconnect).and_return(facebook_mailer_response)
|
||||||
allow(channel_mailer).to receive(:whatsapp_disconnect).and_return(whatsapp_mailer_response)
|
allow(channel_mailer).to receive(:whatsapp_disconnect).and_return(whatsapp_mailer_response)
|
||||||
allow(channel_mailer).to receive(:email_disconnect).and_return(email_mailer_response)
|
allow(channel_mailer).to receive(:email_disconnect).and_return(email_mailer_response)
|
||||||
|
allow(channel_mailer).to receive(:instagram_disconnect).and_return(instagram_mailer_response)
|
||||||
end
|
end
|
||||||
|
|
||||||
describe 'prompt_reauthorization!' do
|
describe 'prompt_reauthorization!' do
|
||||||
|
|||||||
Reference in New Issue
Block a user