Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 12 additions & 7 deletions __tests__/unit/handlers/add-note-to-case.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,16 +13,20 @@
const app = require('../../../src/core/app');
const lambda = require('../../../src/handlers/add-note-to-case');

const ErrorMessages = require('../../../src/constants/messages/error');
const SuccessMessages = require('../../../src/constants/messages/success');

describe('Test for add-note-to-case', function() {
test.each([
[1, 'cid', 'test1', 'John Doe', { data: { records: [{ id: 1 }] } }, { data: { record: { id: 1 } } }, true],
[1, 'cid', 'test2', '', { data: { records: [{ id: 1 }] } }, { data: { record: { id: 1 } } }, true],
[1, 'cid', 'test3', 'John Doe', { data: { records: [{ id: 1 }] } }, { data: {} }, false],
[1, 'cid', 'test4', 'John Doe', { data: { records: [] } }, { data: { record: { id: 1 } } }, false],
[1, 'cid', 'test5', 'John Doe', { data: { records: [] } }, { data: {} }, false]
[1, 'cid', 'test1', 'John Doe', { data: { records: [{ id: 1 }] } }, { data: { record: { id: 1 } } }, true, SuccessMessages.LAMBDA_FUNCTION_SUCCESS],
[1, 'cid', 'test2', null, { data: { records: [{ id: 1 }] } }, { data: { record: { id: 1 } } }, true, SuccessMessages.LAMBDA_FUNCTION_SUCCESS],
[1, 'cid', 'test3', 'John Doe', { data: { records: [{ id: 1 }] } }, { data: {} }, false, ErrorMessages.ERROR_NOTE_CREATE_FAILED],
[1, 'cid', 'test4', 'John Doe', { data: { records: [] } }, { data: { record: { id: 1 } } }, false, 'Unable to match any Case records'],
[1, 'cid', 'test5', 'John Doe', { data: { records: [] } }, { data: {} }, false, 'Unable to match any Case records'],
[1, 'cid', 'test6', 'John Doe', { data: { records: [{ id: 1 }, { id: 2 }] } }, { data: {} }, false, 'Matched multiple Case records']
])(
'Verify correct response whether or not case is returned by API and note is added',
async (number, cid, noteDescription, contactName, apiResponse1, apiResponse2, matched) => {
async (number, cid, noteDescription, contactName, apiResponse1, apiResponse2, matched, body) => {
process.env = {
sugarUrl: 'https://cs-829.msqa.sugarcrm.com'
};
Expand All @@ -45,7 +49,8 @@ describe('Test for add-note-to-case', function() {

let expected = {
statusCode: matched ? 200 : 500,
caseId: matched ? 1 : ''
caseId: matched ? 1 : '',
body: body
};
expect(result).toEqual(expected);
});
Expand Down
20 changes: 13 additions & 7 deletions __tests__/unit/handlers/case-status.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@
const app = require('../../../src/core/app');
const lambda = require('../../../src/handlers/case-status');

const SuccessMessages = require('../../../src/constants/messages/success');

describe('Test for case-status', function() {
test.each([
[1, 'cid', { data: { records: [{ id: 1, status: 'good' }] } }, true],
Expand All @@ -32,13 +34,17 @@ describe('Test for case-status', function() {
mockApi.mockReturnValue(apiResponse);
app.api.call = mockApi;
let result = await lambda.handler(evt);
let expected = matched ? {
statusCode: 200,
caseId: 1,
caseStatus: 'good'
} : {
statusCode: 404
};
let expected = matched
? {
statusCode: 200,
caseId: 1,
caseStatus: 'good',
body: SuccessMessages.LAMBDA_FUNCTION_SUCCESS
}
: {
statusCode: 404,
body: 'Unable to match exactly one Case record'
};
expect(result).toEqual(expected);
});
});
5 changes: 4 additions & 1 deletion __tests__/unit/handlers/create-case.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@

// Import all functions from createCase.js
const lambda = require('../../../src/handlers/create-case.js');
// Defined Constants
const SuccessMessages = require('../../../src/constants/messages/success');

// Mock bean.js
jest.mock('../../../src/core/bean.js', () => () => ({
Expand Down Expand Up @@ -46,7 +48,8 @@ describe('Test for create-case', function() {
const expectedResult = {
statusCode: 200,
caseId: 1,
caseNumber: 1
caseNumber: 1,
body: SuccessMessages.LAMBDA_FUNCTION_SUCCESS
};
// Compare the result with the expected result
expect(result).toEqual(expectedResult);
Expand Down
39 changes: 39 additions & 0 deletions __tests__/unit/utils/string-utils.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
/*
* Your installation or use of this SugarCRM file is subject to the applicable
* terms available at
* http://support.sugarcrm.com/Resources/Master_Subscription_Agreements/.
* If you do not agree to all of the applicable terms or do not have the
* authority to bind the entity as an authorized representative, then do not
* install or use this SugarCRM file.
*
* Copyright (C) SugarCRM Inc. All rights reserved.
*/
const strUtils = require('../../../src/utils/string-utils.js');

describe('generateMessage', function() {
test.each([
{
template: 'Single ${} test',
filler: 'dog',
expected: 'Single dog test'
},
{
template: 'Multiples ${} ${} test',
filler: ['dog', 'cat'],
expected: 'Multiples dog cat test'
},
{
template: 'Mismatched ${} ${} ${} too few fillers',
filler: ['dog', 'cat'],
expected: 'Mismatched dog cat ${} too few fillers'
},
{
template: 'Mismatch ${} too many fillers',
filler: ['dog', 'cat'],
expected: 'Mismatch dog too many fillers'
}
])('should fill the template string as expected', (values) => {
let actual = strUtils.generateMessage(values.template, values.filler);
expect(actual).toEqual(values.expected);
});
});
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,6 @@
},
"scripts": {
"test": "jest --watchAll",
"lint": "eslint ./src ./__tests__"
"lint": "eslint --ext .js src/* __tests__/unit/* --fix"
Copy link
Contributor Author

@jwelborn-sugar jwelborn-sugar Dec 16, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this allows us to auto-fix style errors before committing with npm run lint. All of the changes in this commit were from running this command

}
}
10 changes: 8 additions & 2 deletions src/constants/messages/error.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,15 @@
* Copyright (C) SugarCRM Inc. All rights reserved.
*/

module.exports = {
module.exports = {
/**
* Error messages
*/
ERROR_MULTIPLE_CALL_RECORDS_IN_RESPONSE: 'Unable to match to exactly one Call record'
ERROR_CANNOT_CREATE_CASE: 'Unable to create Case in SugarCRM',
ERROR_NOTE_CREATE_FAILED: 'Unable to link Note to Case in SugarCRM',

TPL_CANNOT_MATCH_RECORD: 'Unable to match exactly one ${} record',
TPL_MISSING_REQUIRED_PARAMETERS: 'Missing required parameters: ${}',
TPL_MULTIPLE_RECORDS_MATCHED: 'Matched multiple ${} records',
TPL_NO_RECORDS_MATCHED: 'Unable to match any ${} records'
};
17 changes: 17 additions & 0 deletions src/constants/messages/success.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
/*
* Your installation or use of this SugarCRM file is subject to the applicable
* terms available at
* http://support.sugarcrm.com/Resources/Master_Subscription_Agreements/.
* If you do not agree to all of the applicable terms or do not have the
* authority to bind the entity as an authorized representative, then do not
* install or use this SugarCRM file.
*
* Copyright (C) SugarCRM Inc. All rights reserved.
*/

module.exports = {
/**
* Success messages
*/
LAMBDA_FUNCTION_SUCCESS: 'Lambda Function Completed Successfully'
};
4 changes: 2 additions & 2 deletions src/constants/url.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,9 @@
* Copyright (C) SugarCRM Inc. All rights reserved.
*/

module.exports = {
module.exports = {
/**
* URL Partials
*/
HTTPS_PREFIX: 'https://',
HTTPS_PREFIX: 'https://'
};
3 changes: 3 additions & 0 deletions src/core/api.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
const axios = require('axios');

const { HttpStatus } = require('../constants/http-status.js');
const loggerUtils = require('../utils/logger-utils');
const { Secrets } = require('../utils/aws/secrets');

const methodToRequest = {
Expand Down Expand Up @@ -61,7 +62,9 @@ module.exports = () => {
request.params = params;
}
response = await axios(request);

if (response.data) {
loggerUtils.logSugarApiResponse(response.data);
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

log every return from the Sugar API for debugging purposes

return {
status: HttpStatus.ok,
data: response.data
Expand Down
2 changes: 1 addition & 1 deletion src/core/data.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
* Copyright (C) SugarCRM Inc. All rights reserved.
*/

var Bean = require('./bean.js');
let Bean = require('./bean.js');

module.exports = {
createBean: (module, data) => {
Expand Down
61 changes: 42 additions & 19 deletions src/handlers/add-note-to-case.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,13 +14,16 @@
*/
const app = require('../core/app.js');
/**
* Util class to log JSOn to Cloudwatch
* Util classes to write logs to Cloudwatch
*/
const loggerUtils = require('../utils/logger-utils');
const strUtils = require('../utils/string-utils');
/**
* HTTP status codes used in this function
* Defined Constants
*/
const { HttpStatus } = require('../constants/http-status');
const ErrorMessages = require('../constants/messages/error');
const SuccessMessages = require('../constants/messages/success');
/**
* Sugar Instance URL
*/
Expand All @@ -32,27 +35,44 @@ const baseUrl = process.env.sugarUrl;
* @param {Object} event
*/
const addNoteToCaseHandler = async (event) => {
loggerUtils.logContactFlowEvent(event);

let statusCode = HttpStatus.error;
let caseId = '';
let noteName = '';
let body = '';
Comment on lines +40 to +43
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I just moved these to the top to use them in every early return path for consistency


// input from the contact flow provided by the user
const caseNumber = event.Details.Parameters.caseNumber || '';
const contactId = event.Details.Parameters.contactId || '';

if (!caseNumber || !contactId) {
return {
statusCode: HttpStatus.preconditionFailed
};
let filler = caseNumber ? '' : 'caseNumber ';
filler += contactId ? '' : 'contactId';
body = strUtils.generateMessage(ErrorMessages.TPL_MISSING_REQUIRED_PARAMETERS, filler);
return loggerUtils.logReturnValue({
statusCode: HttpStatus.preconditionFailed,
caseId: caseId,
body: body
});
Comment on lines +53 to +57
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This pattern is used to log return values to cloudwatch for debugging.

}

const noteDescription = event.Details.Parameters.noteDescription;
const contactName = event.Details.Parameters.contactName;

// Use the given case number to get the relavant case id
const filterUrl = encodeURI(`${baseUrl}/rest/v11_10/Contact/${contactId}/Cases?filter[0][case_number]=${caseNumber}&fields=id`);
const idResponse = await app.api.call('read', filterUrl, null, null);
const caseBean = idResponse.data.records[0];

loggerUtils.logSugarApiResponse(idResponse);

let statusCode = HttpStatus.error;
let caseId = '';
let noteName = ''
if (idResponse.data.records.length > 1) {
body = strUtils.generateMessage(ErrorMessages.TPL_MULTIPLE_RECORDS_MATCHED, 'Case');
return loggerUtils.logReturnValue({
statusCode: statusCode,
caseId: caseId,
body: body
});
}
const caseBean = idResponse.data.records[0];

// if contact name is empty then default it to 'customer'
if (contactName === '' || contactName === undefined) {
Expand All @@ -70,26 +90,29 @@ const addNoteToCaseHandler = async (event) => {
'description': noteDescription,
'name': noteName
};

// add note to the case
const filterUrl = encodeURI(`${baseUrl}/rest/v11_10/Cases/${caseBean.id}/link/notes`);
const noteResponse = await app.api.call('create', filterUrl, null, notePayload);

loggerUtils.logSugarApiResponse(noteResponse);

const updateCaseBean = noteResponse.data.record;

// if the case was successfully updated
if (updateCaseBean && updateCaseBean.id !== '') {
statusCode = HttpStatus.ok;
caseId = updateCaseBean.id;
body = SuccessMessages.LAMBDA_FUNCTION_SUCCESS;
} else {
body = ErrorMessages.ERROR_NOTE_CREATE_FAILED;
}
} else {
body = strUtils.generateMessage(ErrorMessages.TPL_NO_RECORDS_MATCHED, 'Case');
}

return {
return loggerUtils.logReturnValue({
statusCode: statusCode,
caseId: caseId
};
caseId: caseId,
body: body
});
};

exports.handler = addNoteToCaseHandler;
16 changes: 9 additions & 7 deletions src/handlers/call-recording.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,43 +14,45 @@ const app = require('../core/app.js');
/**
* Utils
*/
const callRecordingUtils = require('../utils/sugar/call-record-utils');
const loggerUtils = require('../utils/logger-utils');
const s3Utils = require('../utils/aws/s3-utils');
const callRecordingUtils = require('../utils/sugar/call-record-utils');
const stringUtils = require('../utils/string-utils.js');

/**
* Defined constants
*/
const ErrorMessages = require('../constants/messages/error');
const CallsConstants = require('../constants/sugar-modules/calls');
const ErrorMessages = require('../constants/messages/error');
const { HttpStatus } = require('../constants/http-status.js');

/**
* Function to update a call record's call recording URL when the
* Function to update a call record's call recording URL when the
* audio file is ready
*
* @param {Object} event the S3 trigger event
*/
const handler = async (event) => {
// Log S3 Event to cloudwatch for debugging
loggerUtils.logS3Event(event);

let objectKey = s3Utils.getObjectKeyFromS3Event(event);
let contactId = s3Utils.getAwsConnectContactIdFromS3Key(objectKey);
let callRecord = await callRecordingUtils.getCallRecord(contactId);

if (!callRecord) {
return {
return loggerUtils.logReturnValue({
status: HttpStatus.preconditionFailed,
body: ErrorMessages.ERROR_MULTIPLE_CALL_RECORDS_IN_RESPONSE
};
body: stringUtils.generateMessage(ErrorMessages.TPL_CANNOT_MATCH_RECORD, 'Call')
});
}

let callRecordingUrl = callRecordingUtils.buildCallRecordingUrl(contactId);

let callBean = app.data.createBean('Calls', callRecord);
callBean.set(CallsConstants.CALLS_CALL_RECORDING_URL, callRecordingUrl);

return await callBean.save();
return loggerUtils.logReturnValue(await callBean.save());
};

exports.handler = handler;
Loading