diff --git a/functions/helpers/sendErrorMessageForUnsupportedMedia.private.ts b/functions/helpers/sendErrorMessageForUnsupportedMedia.private.ts index 5b33479d..1f3033a7 100644 --- a/functions/helpers/sendErrorMessageForUnsupportedMedia.private.ts +++ b/functions/helpers/sendErrorMessageForUnsupportedMedia.private.ts @@ -18,15 +18,15 @@ import { Context } from '@twilio-labs/serverless-runtime-types/types'; export type ConversationSid = `CH${string}`; -type SendErrorMessageForUnsupportedMediaEvent = { +type OnMessageAddedEvent = { + EventType: 'onMessageAdded'; Body?: string; ConversationSid: ConversationSid; - EventType?: string; Media?: Record; DateCreated: Date; }; -export type Event = SendErrorMessageForUnsupportedMediaEvent; +export type Event = OnMessageAddedEvent; const FALLBACK_ERROR_MESSAGE = 'Unsupported message type.'; const ERROR_MESSAGE_TRANSLATION_KEY = 'UnsupportedMediaErrorMsg'; @@ -56,17 +56,19 @@ export const sendConversationMessage = async ( }); export const sendErrorMessageForUnsupportedMedia = async (context: Context, event: Event) => { - const { EventType, Body, Media, ConversationSid } = event; + const { Body, Media, ConversationSid } = event; /* Valid message will have either a body/media. A message with no body or media implies that there was an error sending such message */ - if (EventType === 'onMessageAdded' && !Body && !Media) { + if (!Body && !Media) { + console.debug('Message has no text body or media, sending error.', ConversationSid); let messageText = FALLBACK_ERROR_MESSAGE; const serviceConfig = await context.getTwilioClient().flexApi.configuration.get().fetch(); const helplineLanguage = serviceConfig.attributes.helplineLanguage ?? 'en-US'; + console.debug('Helpline language to send error message: ', helplineLanguage, ConversationSid); if (helplineLanguage) { try { const response = await fetch( @@ -74,10 +76,13 @@ export const sendErrorMessageForUnsupportedMedia = async (context: Context, even ); const translation = await response.json(); const { [ERROR_MESSAGE_TRANSLATION_KEY]: translatedMessage } = translation; + + console.debug('Translated error message: ', translatedMessage, ConversationSid); messageText = translatedMessage || messageText; } catch { console.warn( `Couldn't retrieve ${ERROR_MESSAGE_TRANSLATION_KEY} message translation for ${helplineLanguage}`, + ConversationSid, ); } } @@ -87,6 +92,7 @@ export const sendErrorMessageForUnsupportedMedia = async (context: Context, even author: 'Bot', messageText, }); + console.info('Sent error message: ', messageText, ConversationSid); } }; diff --git a/functions/webhooks/serviceConversationListener.protected.ts b/functions/webhooks/serviceConversationListener.protected.ts index 5d37b44e..f9840b8e 100644 --- a/functions/webhooks/serviceConversationListener.protected.ts +++ b/functions/webhooks/serviceConversationListener.protected.ts @@ -15,24 +15,29 @@ */ import { Context, ServerlessCallback } from '@twilio-labs/serverless-runtime-types/types'; -import { responseWithCors, bindResolve, error500 } from '@tech-matters/serverless-helpers'; +import { responseWithCors, bindResolve, error500, success } from '@tech-matters/serverless-helpers'; import { Event, SendErrorMessageForUnsupportedMedia, } from '../helpers/sendErrorMessageForUnsupportedMedia.private'; export const handler = async (context: Context, event: Event, callback: ServerlessCallback) => { + console.info(`===== Service Conversation Listener (event: ${event.EventType})=====`); const response = responseWithCors(); const resolve = bindResolve(callback)(response); - // eslint-disable-next-line global-require,import/no-dynamic-require - const sendErrorMessageForUnsupportedMedia = require(Runtime.getFunctions()[ - 'helpers/sendErrorMessageForUnsupportedMedia' - ].path).sendErrorMessageForUnsupportedMedia as SendErrorMessageForUnsupportedMedia; + if (event.EventType === 'onMessageAdded') { + // eslint-disable-next-line global-require,import/no-dynamic-require + const sendErrorMessageForUnsupportedMedia = require(Runtime.getFunctions()[ + 'helpers/sendErrorMessageForUnsupportedMedia' + ].path).sendErrorMessageForUnsupportedMedia as SendErrorMessageForUnsupportedMedia; - try { - await sendErrorMessageForUnsupportedMedia(context, event); - } catch (err) { - if (err instanceof Error) resolve(error500(err)); - else resolve(error500(new Error(String(err)))); + try { + console.debug('New message, checking if we need to send error.'); + await sendErrorMessageForUnsupportedMedia(context, event); + } catch (err) { + if (err instanceof Error) return resolve(error500(err)); + return resolve(error500(new Error(String(err)))); + } } + return resolve(success(event)); }; diff --git a/tests/webhooks/serviceConversationListener.test.ts b/tests/webhooks/serviceConversationListener.test.ts index b7ee0c4f..9e01bd0f 100644 --- a/tests/webhooks/serviceConversationListener.test.ts +++ b/tests/webhooks/serviceConversationListener.test.ts @@ -49,77 +49,9 @@ describe('serviceConversationListener', () => { helpers.teardown(); }); - test('Should return status 400 if Body, Media or EventType are undefined', async () => { - const event1: Body = { - Body: undefined, - ConversationSid: 'CHxxxxxxx34EWS', - EventType: 'onMessageAdded', - Media: {}, - DateCreated: new Date(), - }; - - const event2: Body = { - Body: 'Test word', - ConversationSid: 'CHxxxxxxx34EWS', - EventType: 'onMessageAdded', - Media: undefined, - DateCreated: new Date(), - }; - - const event3: Body = { - Body: 'Test word', - ConversationSid: 'CHxxxxxxx34EWS', - EventType: undefined, - Media: {}, - DateCreated: new Date(), - }; - - const callback: ServerlessCallback = (err, result) => { - expect(result).toBeDefined(); - const response = result as MockedResponse; - expect(response.getStatus()).toBe(400); - }; - - await serviceConversationListener(baseContext, event1, callback); - await serviceConversationListener(baseContext, event2, callback); - await serviceConversationListener(baseContext, event3, callback); - }); - - test('Should return status 500 if object response is undefined', async () => { - const event1: Body = { - Body: 'Test word', - ConversationSid: 'CHxxxxxxx34EWS', - EventType: 'onMessageAdded', - Media: {}, - DateCreated: new Date(), - }; - - const callback1: ServerlessCallback = (err, result) => { - expect(result).toBeDefined(); - const response = result as MockedResponse; - expect(response.getStatus()).toBe(500); - }; - - await serviceConversationListener({ ...baseContext }, event1, callback1); - - const event2: Body = { - Body: 'Test word', - ConversationSid: 'CHxxxxxxx34EWS', - EventType: 'onMessageAdded', - Media: {}, - DateCreated: new Date(), - }; - - const callback2: ServerlessCallback = (err, result) => { - expect(result).toBeDefined(); - const response = result as MockedResponse; - expect(response.getStatus()).toBe(500); - }; - - await serviceConversationListener(baseContext, event2, callback2); - }); + // TODO: Test coverage for sending error message - test('Should return status 200', async () => { + test('Should return status 200 for valid message', async () => { const event1: Body = { Body: 'Test word', ConversationSid: 'CHxxxxxxx34EWS',