Feat: improve read receipts (#56)
* feat: add store in additional_attributes to conversation model * feat: set default mark_as_read to true in additional_attributes for conversation params * fix: remove mark_as_read from additional_attributes in conversation * refactor: move message read logic to mark_messages_as_read method in ConversationsController * feat: add 'Mark messages as read' option to WhatsApp channel settings * feat: add 'mark_as_read' option in factorie for WhatsApp channel * feat: integrate Checkbox component for 'mark as read' option in WhatsApp settings * fix: ensure 'mark_as_read' option is included in channel creation payload * feat: add 'Mark as read' settings for WhatsApp inbox, including UI and state management * chore: remove redundant content update test from IncomingMessageBaileysService spec * feat: update 'Mark as read' label to 'Read receipts' and replace Checkbox with Switch component in WhatsApp settings * fix: handle potential nil value for 'mark_as_read' in provider config * feat: refactor provider config to streamline channel creation with 'mark_as_read' option * feat: add test for MESSAGE_READ event dispatch in update_last_seen action * fix: update subheader for 'Mark as read' setting to read receipt behavior in WhatsApp * feat: update mark_messages_as_read behavior to handle false value in provider config * chore: update label for 'Mark as read' option * feat: update update_last_seen to send WhatsApp read receipt for WhatsApp channels * test: remove MESSAGE_READ event dispatch tests in wrong file * feat: enhance update_last_seen behavior for WhatsApp channel to conditionally dispatch messages.read event * feat: update update_last_seen to dispatch messages.read event * test: refactor update_last_seen tests * chore: refactor to ensure provider_service responds to read_messages before ensure the mark_as_read provider config * test: enhance #read_messages with provider config mark_as_read expected behaviors * chore: clarify test names and remove useless expect --------- Co-authored-by: gabrieljablonski <contact@gabrieljablonski.com>
This commit is contained in:
parent
8ec086f8d0
commit
a3effacc21
@ -110,9 +110,7 @@ class Api::V1::Accounts::ConversationsController < Api::V1::Accounts::BaseContro
|
|||||||
end
|
end
|
||||||
|
|
||||||
def update_last_seen
|
def update_last_seen
|
||||||
# NOTE: Use old `agent_last_seen_at`, so we reference messages received after that
|
dispatch_messages_read_event if assignee?
|
||||||
Rails.configuration.dispatcher.dispatch(Events::Types::MESSAGES_READ, Time.zone.now, conversation: @conversation,
|
|
||||||
last_seen_at: @conversation.agent_last_seen_at)
|
|
||||||
|
|
||||||
update_last_seen_on_conversation(DateTime.now.utc, assignee?)
|
update_last_seen_on_conversation(DateTime.now.utc, assignee?)
|
||||||
end
|
end
|
||||||
@ -206,6 +204,12 @@ class Api::V1::Accounts::ConversationsController < Api::V1::Accounts::BaseContro
|
|||||||
def assignee?
|
def assignee?
|
||||||
@conversation.assignee_id? && Current.user == @conversation.assignee
|
@conversation.assignee_id? && Current.user == @conversation.assignee
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def dispatch_messages_read_event
|
||||||
|
# NOTE: Use old `agent_last_seen_at`, so we reference messages received after that
|
||||||
|
Rails.configuration.dispatcher.dispatch(Events::Types::MESSAGES_READ, Time.zone.now, conversation: @conversation,
|
||||||
|
last_seen_at: @conversation.agent_last_seen_at)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
Api::V1::Accounts::ConversationsController.prepend_mod_with('Api::V1::Accounts::ConversationsController')
|
Api::V1::Accounts::ConversationsController.prepend_mod_with('Api::V1::Accounts::ConversationsController')
|
||||||
|
|||||||
@ -267,7 +267,10 @@
|
|||||||
"PROVIDER_URL": {
|
"PROVIDER_URL": {
|
||||||
"LABEL": "Provider URL",
|
"LABEL": "Provider URL",
|
||||||
"PLACEHOLDER": "If provider is not running locally, please provide the URL",
|
"PLACEHOLDER": "If provider is not running locally, please provide the URL",
|
||||||
"ERROR":"Please enter a valid URL"
|
"ERROR": "Please enter a valid URL"
|
||||||
|
},
|
||||||
|
"MARK_AS_READ": {
|
||||||
|
"LABEL": "Send read receipts"
|
||||||
},
|
},
|
||||||
"ADVANCED_OPTIONS": "Advanced options",
|
"ADVANCED_OPTIONS": "Advanced options",
|
||||||
"BAILEYS": {
|
"BAILEYS": {
|
||||||
@ -558,7 +561,10 @@
|
|||||||
"WHATSAPP_PROVIDER_URL_SUBHEADER": "If the provider is not running locally, please provide the URL.",
|
"WHATSAPP_PROVIDER_URL_SUBHEADER": "If the provider is not running locally, please provide the URL.",
|
||||||
"WHATSAPP_PROVIDER_URL_PLACEHOLDER": "Enter the provider URL",
|
"WHATSAPP_PROVIDER_URL_PLACEHOLDER": "Enter the provider URL",
|
||||||
"WHATSAPP_PROVIDER_URL_ERROR": "Please enter a valid URL",
|
"WHATSAPP_PROVIDER_URL_ERROR": "Please enter a valid URL",
|
||||||
"UPDATE_PRE_CHAT_FORM_SETTINGS": "Update Pre Chat Form Settings"
|
"UPDATE_PRE_CHAT_FORM_SETTINGS": "Update Pre Chat Form Settings",
|
||||||
|
"WHATSAPP_MARK_AS_READ_TITLE": "Read receipts",
|
||||||
|
"WHATSAPP_MARK_AS_READ_SUBHEADER": "If turned off, when a message is viewed in Chatwoot, a read receipt will not be sent to the sender. Your messages will still be able to receive read receipts from the sender.",
|
||||||
|
"WHATSAPP_MARK_AS_READ_LABEL": "Send read receipts"
|
||||||
},
|
},
|
||||||
"HELP_CENTER": {
|
"HELP_CENTER": {
|
||||||
"LABEL": "Help Center",
|
"LABEL": "Help Center",
|
||||||
|
|||||||
@ -267,7 +267,10 @@
|
|||||||
"PROVIDER_URL": {
|
"PROVIDER_URL": {
|
||||||
"LABEL": "URL do provedor",
|
"LABEL": "URL do provedor",
|
||||||
"PLACEHOLDER": "Se o provedor não está rodando localmente, por favor, insira a URL do provedor",
|
"PLACEHOLDER": "Se o provedor não está rodando localmente, por favor, insira a URL do provedor",
|
||||||
"ERROR":"Por favor, insira uma URL válida"
|
"ERROR": "Por favor, insira uma URL válida"
|
||||||
|
},
|
||||||
|
"MARK_AS_READ": {
|
||||||
|
"LABEL": "Enviar confirmações de leitura"
|
||||||
},
|
},
|
||||||
"ADVANCED_OPTIONS": "Opções avançadas",
|
"ADVANCED_OPTIONS": "Opções avançadas",
|
||||||
"BAILEYS": {
|
"BAILEYS": {
|
||||||
@ -558,7 +561,10 @@
|
|||||||
"WHATSAPP_PROVIDER_URL_SUBHEADER": "Se o provedor não estiver rodando localmente, por favor, forneça a URL.",
|
"WHATSAPP_PROVIDER_URL_SUBHEADER": "Se o provedor não estiver rodando localmente, por favor, forneça a URL.",
|
||||||
"WHATSAPP_PROVIDER_URL_PLACEHOLDER": "Digite a URL do provedor",
|
"WHATSAPP_PROVIDER_URL_PLACEHOLDER": "Digite a URL do provedor",
|
||||||
"WHATSAPP_PROVIDER_URL_ERROR": "Por favor, insira uma URL válida",
|
"WHATSAPP_PROVIDER_URL_ERROR": "Por favor, insira uma URL válida",
|
||||||
"UPDATE_PRE_CHAT_FORM_SETTINGS": "Atualizar configurações do Formulário Pre Chat"
|
"UPDATE_PRE_CHAT_FORM_SETTINGS": "Atualizar configurações do Formulário Pre Chat",
|
||||||
|
"WHATSAPP_MARK_AS_READ_TITLE": "Confirmações de leitura",
|
||||||
|
"WHATSAPP_MARK_AS_READ_SUBHEADER": "Se essa opção estiver desativada, ao visualizar uma mensagem pelo Chatwoot, não será enviada uma confirmação de leitura para o remetente. As suas mensagens ainda poderão receber confirmações de leitura.",
|
||||||
|
"WHATSAPP_MARK_AS_READ_LABEL": "Enviar confirmações de leitura"
|
||||||
},
|
},
|
||||||
"HELP_CENTER": {
|
"HELP_CENTER": {
|
||||||
"LABEL": "Centro de Ajuda",
|
"LABEL": "Centro de Ajuda",
|
||||||
|
|||||||
@ -8,10 +8,13 @@ import { isPhoneE164OrEmpty } from 'shared/helpers/Validators';
|
|||||||
import { isValidURL } from '../../../../../helper/URLHelper';
|
import { isValidURL } from '../../../../../helper/URLHelper';
|
||||||
|
|
||||||
import NextButton from 'dashboard/components-next/button/Button.vue';
|
import NextButton from 'dashboard/components-next/button/Button.vue';
|
||||||
|
import Switch from 'dashboard/components-next/switch/Switch.vue';
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
components: {
|
components: {
|
||||||
NextButton,
|
NextButton,
|
||||||
|
// eslint-disable-next-line vue/no-reserved-component-names
|
||||||
|
Switch,
|
||||||
},
|
},
|
||||||
setup() {
|
setup() {
|
||||||
return { v$: useVuelidate() };
|
return { v$: useVuelidate() };
|
||||||
@ -23,6 +26,7 @@ export default {
|
|||||||
apiKey: '',
|
apiKey: '',
|
||||||
providerUrl: '',
|
providerUrl: '',
|
||||||
showAdvancedOptions: false,
|
showAdvancedOptions: false,
|
||||||
|
markAsRead: true,
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
@ -47,6 +51,15 @@ export default {
|
|||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
const providerConfig = {
|
||||||
|
mark_as_read: this.markAsRead,
|
||||||
|
};
|
||||||
|
|
||||||
|
if (this.apiKey || this.providerUrl) {
|
||||||
|
providerConfig.api_key = this.apiKey;
|
||||||
|
providerConfig.url = this.providerUrl;
|
||||||
|
}
|
||||||
|
|
||||||
const whatsappChannel = await this.$store.dispatch(
|
const whatsappChannel = await this.$store.dispatch(
|
||||||
'inboxes/createChannel',
|
'inboxes/createChannel',
|
||||||
{
|
{
|
||||||
@ -55,13 +68,7 @@ export default {
|
|||||||
type: 'whatsapp',
|
type: 'whatsapp',
|
||||||
phone_number: this.phoneNumber,
|
phone_number: this.phoneNumber,
|
||||||
provider: 'baileys',
|
provider: 'baileys',
|
||||||
provider_config:
|
provider_config: providerConfig,
|
||||||
this.apiKey || this.providerUrl
|
|
||||||
? {
|
|
||||||
api_key: this.apiKey,
|
|
||||||
url: this.providerUrl,
|
|
||||||
}
|
|
||||||
: {},
|
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
@ -159,6 +166,17 @@ export default {
|
|||||||
</span>
|
</span>
|
||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<div class="w-[65%] flex-shrink-0 flex-grow-0 max-w-[65%]">
|
||||||
|
<label>
|
||||||
|
<div class="flex mb-2 items-center">
|
||||||
|
<span class="mr-2 text-sm">
|
||||||
|
{{ $t('INBOX_MGMT.ADD.WHATSAPP.MARK_AS_READ.LABEL') }}
|
||||||
|
</span>
|
||||||
|
<Switch id="markAsRead" v-model="markAsRead" />
|
||||||
|
</div>
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<div class="w-full">
|
<div class="w-full">
|
||||||
|
|||||||
@ -10,6 +10,7 @@ import { requiredIf } from '@vuelidate/validators';
|
|||||||
import { isValidURL } from '../../../../../helper/URLHelper';
|
import { isValidURL } from '../../../../../helper/URLHelper';
|
||||||
import WhatsappBaileysLinkDeviceModal from '../components/WhatsappBaileysLinkDeviceModal.vue';
|
import WhatsappBaileysLinkDeviceModal from '../components/WhatsappBaileysLinkDeviceModal.vue';
|
||||||
import InboxName from '../../../../../components/widgets/InboxName.vue';
|
import InboxName from '../../../../../components/widgets/InboxName.vue';
|
||||||
|
import Switch from 'dashboard/components-next/switch/Switch.vue';
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
components: {
|
components: {
|
||||||
@ -19,6 +20,8 @@ export default {
|
|||||||
NextButton,
|
NextButton,
|
||||||
WhatsappBaileysLinkDeviceModal,
|
WhatsappBaileysLinkDeviceModal,
|
||||||
InboxName,
|
InboxName,
|
||||||
|
// eslint-disable-next-line vue/no-reserved-component-names
|
||||||
|
Switch,
|
||||||
},
|
},
|
||||||
mixins: [inboxMixin],
|
mixins: [inboxMixin],
|
||||||
props: {
|
props: {
|
||||||
@ -36,6 +39,7 @@ export default {
|
|||||||
whatsAppInboxAPIKey: '',
|
whatsAppInboxAPIKey: '',
|
||||||
whatsAppProviderUrl: '',
|
whatsAppProviderUrl: '',
|
||||||
showBaileysLinkDeviceModal: false,
|
showBaileysLinkDeviceModal: false,
|
||||||
|
markAsRead: true,
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
validations() {
|
validations() {
|
||||||
@ -57,6 +61,7 @@ export default {
|
|||||||
methods: {
|
methods: {
|
||||||
setDefaults() {
|
setDefaults() {
|
||||||
this.hmacMandatory = this.inbox.hmac_mandatory || false;
|
this.hmacMandatory = this.inbox.hmac_mandatory || false;
|
||||||
|
this.markAsRead = this.inbox.provider_config.mark_as_read ?? true;
|
||||||
},
|
},
|
||||||
handleHmacFlag() {
|
handleHmacFlag() {
|
||||||
this.updateInbox();
|
this.updateInbox();
|
||||||
@ -114,6 +119,24 @@ export default {
|
|||||||
useAlert(this.$t('INBOX_MGMT.EDIT.API.ERROR_MESSAGE'));
|
useAlert(this.$t('INBOX_MGMT.EDIT.API.ERROR_MESSAGE'));
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
async updateWhatsAppMarkAsRead() {
|
||||||
|
try {
|
||||||
|
const payload = {
|
||||||
|
id: this.inbox.id,
|
||||||
|
formData: false,
|
||||||
|
channel: {
|
||||||
|
provider_config: {
|
||||||
|
...this.inbox.provider_config,
|
||||||
|
mark_as_read: this.markAsRead,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
await this.$store.dispatch('inboxes/updateInbox', payload);
|
||||||
|
useAlert(this.$t('INBOX_MGMT.EDIT.API.SUCCESS_MESSAGE'));
|
||||||
|
} catch (error) {
|
||||||
|
useAlert(this.$t('INBOX_MGMT.EDIT.API.ERROR_MESSAGE'));
|
||||||
|
}
|
||||||
|
},
|
||||||
onOpenBaileysLinkDeviceModal() {
|
onOpenBaileysLinkDeviceModal() {
|
||||||
this.showBaileysLinkDeviceModal = true;
|
this.showBaileysLinkDeviceModal = true;
|
||||||
},
|
},
|
||||||
@ -383,6 +406,23 @@ export default {
|
|||||||
</NextButton>
|
</NextButton>
|
||||||
</div>
|
</div>
|
||||||
</SettingsSection>
|
</SettingsSection>
|
||||||
|
<SettingsSection
|
||||||
|
:title="$t('INBOX_MGMT.SETTINGS_POPUP.WHATSAPP_MARK_AS_READ_TITLE')"
|
||||||
|
:sub-title="
|
||||||
|
$t('INBOX_MGMT.SETTINGS_POPUP.WHATSAPP_MARK_AS_READ_SUBHEADER')
|
||||||
|
"
|
||||||
|
>
|
||||||
|
<div class="flex items-center gap-2">
|
||||||
|
<Switch
|
||||||
|
id="markAsRead"
|
||||||
|
v-model="markAsRead"
|
||||||
|
@change="updateWhatsAppMarkAsRead"
|
||||||
|
/>
|
||||||
|
<label for="markAsRead">
|
||||||
|
{{ $t('INBOX_MGMT.SETTINGS_POPUP.WHATSAPP_MARK_AS_READ_LABEL') }}
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
</SettingsSection>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|||||||
@ -93,6 +93,8 @@ class Channel::Whatsapp < ApplicationRecord
|
|||||||
|
|
||||||
def read_messages(messages, conversation:)
|
def read_messages(messages, conversation:)
|
||||||
return unless provider_service.respond_to?(:read_messages)
|
return unless provider_service.respond_to?(:read_messages)
|
||||||
|
# NOTE: This is the default behavior, so `mark_as_read` being `nil` is the same as `true`.
|
||||||
|
return if provider_config&.dig('mark_as_read') == false
|
||||||
|
|
||||||
provider_service.read_messages(conversation.contact.phone_number, messages)
|
provider_service.read_messages(conversation.contact.phone_number, messages)
|
||||||
end
|
end
|
||||||
|
|||||||
@ -688,18 +688,33 @@ RSpec.describe 'Conversations API', type: :request do
|
|||||||
expect(conversation.reload.assignee_last_seen_at).not_to be_nil
|
expect(conversation.reload.assignee_last_seen_at).not_to be_nil
|
||||||
end
|
end
|
||||||
|
|
||||||
it 'dispatches messages.read event' do
|
it 'dispatches messages.read event when user is assignee' do
|
||||||
freeze_time
|
freeze_time
|
||||||
conversation.update!(agent_last_seen_at: 1.hour.ago)
|
|
||||||
|
previous_agent_last_seen_at = 1.hour.ago
|
||||||
|
conversation.update!(agent_last_seen_at: previous_agent_last_seen_at, assignee: agent)
|
||||||
|
|
||||||
allow(Rails.configuration.dispatcher).to receive(:dispatch)
|
allow(Rails.configuration.dispatcher).to receive(:dispatch)
|
||||||
.with(Events::Types::MESSAGES_READ, Time.zone.now, conversation: conversation, last_seen_at: conversation.agent_last_seen_at)
|
|
||||||
|
|
||||||
post "/api/v1/accounts/#{account.id}/conversations/#{conversation.display_id}/update_last_seen",
|
post "/api/v1/accounts/#{account.id}/conversations/#{conversation.display_id}/update_last_seen",
|
||||||
headers: agent.create_new_auth_token,
|
headers: agent.create_new_auth_token,
|
||||||
as: :json
|
as: :json
|
||||||
|
|
||||||
expect(response).to have_http_status(:success)
|
expect(response).to have_http_status(:success)
|
||||||
expect(Rails.configuration.dispatcher).to have_received(:dispatch)
|
expect(Rails.configuration.dispatcher)
|
||||||
|
.to have_received(:dispatch)
|
||||||
|
.with(Events::Types::MESSAGES_READ, Time.zone.now, conversation: conversation, last_seen_at: previous_agent_last_seen_at)
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'does not dispatch messages.read event when user is not assignee' do
|
||||||
|
allow(Rails.configuration.dispatcher).to receive(:dispatch)
|
||||||
|
|
||||||
|
post "/api/v1/accounts/#{account.id}/conversations/#{conversation.display_id}/update_last_seen",
|
||||||
|
headers: agent.create_new_auth_token,
|
||||||
|
as: :json
|
||||||
|
|
||||||
|
expect(response).to have_http_status(:success)
|
||||||
|
expect(Rails.configuration.dispatcher).not_to have_received(:dispatch)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@ -77,7 +77,7 @@ FactoryBot.define do
|
|||||||
channel_whatsapp.define_singleton_method(:validate_provider_config) { nil } unless options.validate_provider_config
|
channel_whatsapp.define_singleton_method(:validate_provider_config) { nil } unless options.validate_provider_config
|
||||||
if channel_whatsapp.provider == 'baileys'
|
if channel_whatsapp.provider == 'baileys'
|
||||||
channel_whatsapp.provider_config = channel_whatsapp.provider_config.merge({ 'api_key' => 'test_key', 'provider_url' => 'https://baileys.api',
|
channel_whatsapp.provider_config = channel_whatsapp.provider_config.merge({ 'api_key' => 'test_key', 'provider_url' => 'https://baileys.api',
|
||||||
'phone_number_id' => '123456789' })
|
'phone_number_id' => '123456789', 'mark_as_read' => true })
|
||||||
elsif channel_whatsapp.provider == 'whatsapp_cloud'
|
elsif channel_whatsapp.provider == 'whatsapp_cloud'
|
||||||
channel_whatsapp.provider_config = channel_whatsapp.provider_config.merge({ 'api_key' => 'test_key', 'phone_number_id' => '123456789',
|
channel_whatsapp.provider_config = channel_whatsapp.provider_config.merge({ 'api_key' => 'test_key', 'phone_number_id' => '123456789',
|
||||||
'business_account_id' => '123456789' })
|
'business_account_id' => '123456789' })
|
||||||
|
|||||||
@ -121,7 +121,9 @@ RSpec.describe Channel::Whatsapp do
|
|||||||
end
|
end
|
||||||
|
|
||||||
describe '#read_messages' do
|
describe '#read_messages' do
|
||||||
let(:channel) { create(:channel_whatsapp, provider: 'baileys', validate_provider_config: false, sync_templates: false) }
|
let(:channel) do
|
||||||
|
create(:channel_whatsapp, provider: 'baileys', provider_config: { mark_as_read: true }, validate_provider_config: false, sync_templates: false)
|
||||||
|
end
|
||||||
let(:conversation) { create(:conversation) }
|
let(:conversation) { create(:conversation) }
|
||||||
let(:message) { create(:message) }
|
let(:message) { create(:message) }
|
||||||
|
|
||||||
@ -137,13 +139,30 @@ RSpec.describe Channel::Whatsapp do
|
|||||||
expect(provider_double).to have_received(:read_messages)
|
expect(provider_double).to have_received(:read_messages)
|
||||||
end
|
end
|
||||||
|
|
||||||
it 'does not call method if provider service does not implement it' do
|
it 'call method when the provider config mark_as_read is nil' do
|
||||||
channel = create(:channel_whatsapp, provider: 'whatsapp_cloud', validate_provider_config: false, sync_templates: false)
|
channel.update!(provider_config: {})
|
||||||
provider_double = instance_double(Whatsapp::Providers::WhatsappCloudService)
|
provider_double = instance_double(Whatsapp::Providers::WhatsappBaileysService, read_messages: nil)
|
||||||
allow(Whatsapp::Providers::WhatsappCloudService).to receive(:new)
|
allow(provider_double).to receive(:read_messages).with([message], conversation.contact.phone_number)
|
||||||
|
allow(Whatsapp::Providers::WhatsappBaileysService).to receive(:new)
|
||||||
.with(whatsapp_channel: channel)
|
.with(whatsapp_channel: channel)
|
||||||
.and_return(provider_double)
|
.and_return(provider_double)
|
||||||
|
|
||||||
|
channel.read_messages([message], conversation: conversation)
|
||||||
|
|
||||||
|
expect(provider_double).to have_received(:read_messages)
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'does not call method if provider service does not implement it' do
|
||||||
|
channel.update!(provider: 'whatsapp_cloud')
|
||||||
|
|
||||||
|
expect do
|
||||||
|
channel.read_messages([message], conversation: conversation)
|
||||||
|
end.not_to raise_error
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'does not call method if provider config mark_as_read is false' do
|
||||||
|
channel.update!(provider_config: { mark_as_read: false })
|
||||||
|
|
||||||
expect do
|
expect do
|
||||||
channel.read_messages([message], conversation: conversation)
|
channel.read_messages([message], conversation: conversation)
|
||||||
end.not_to raise_error
|
end.not_to raise_error
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user