Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Added support for dynamicTemplateData #691

Merged
merged 3 commits into from
Jun 14, 2018
Merged
Show file tree
Hide file tree
Changes from 2 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
53 changes: 5 additions & 48 deletions packages/client/yarn.lock
Original file line number Diff line number Diff line change
@@ -1,10 +1,6 @@
# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY.
# yarn lockfile v1
"@sendgrid/helpers@^6.0.0":
version "6.0.0"
resolved "https://registry.yarnpkg.com/@sendgrid/helpers/-/helpers-6.0.0.tgz#b7ae9b927822e6a3a3e44abb2486e68d03e25220"
dependencies:
chalk "^2.0.1"


"@types/form-data@*":
version "2.2.0"
Expand All @@ -30,24 +26,18 @@ ajv@^4.9.1:
co "^4.6.0"
json-stable-stringify "^1.0.1"

ansi-styles@^3.1.0:
version "3.2.0"
resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-3.2.0.tgz#c159b8d5be0f9e5a6f346dab94f16ce022161b88"
dependencies:
color-convert "^1.9.0"

asn1@~0.2.3:
version "0.2.3"
resolved "https://registry.yarnpkg.com/asn1/-/asn1-0.2.3.tgz#dac8787713c9966849fc8180777ebe9c1ddf3b86"

assert-plus@1.0.0, assert-plus@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/assert-plus/-/assert-plus-1.0.0.tgz#f12e0f3c5d77b0b1cdd9146942e4e96c1e4dd525"

assert-plus@^0.2.0:
version "0.2.0"
resolved "https://registry.yarnpkg.com/assert-plus/-/assert-plus-0.2.0.tgz#d74e1b87e7affc0db8aadb7021f3fe48101ab234"

assert-plus@^1.0.0, assert-plus@1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/assert-plus/-/assert-plus-1.0.0.tgz#f12e0f3c5d77b0b1cdd9146942e4e96c1e4dd525"

asynckit@^0.4.0:
version "0.4.0"
resolved "https://registry.yarnpkg.com/asynckit/-/asynckit-0.4.0.tgz#c79ed97f7f34cb8f2ba1bc9790bcc366474b4b79"
Expand Down Expand Up @@ -76,28 +66,10 @@ caseless@~0.12.0:
version "0.12.0"
resolved "https://registry.yarnpkg.com/caseless/-/caseless-0.12.0.tgz#1b681c21ff84033c826543090689420d187151dc"

chalk@^2.0.1:
version "2.1.0"
resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.1.0.tgz#ac5becf14fa21b99c6c92ca7a7d7cfd5b17e743e"
dependencies:
ansi-styles "^3.1.0"
escape-string-regexp "^1.0.5"
supports-color "^4.0.0"

co@^4.6.0:
version "4.6.0"
resolved "https://registry.yarnpkg.com/co/-/co-4.6.0.tgz#6ea6bdf3d853ae54ccb8e47bfa0bf3f9031fb184"

color-convert@^1.9.0:
version "1.9.0"
resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-1.9.0.tgz#1accf97dd739b983bf994d56fec8f95853641b7a"
dependencies:
color-name "^1.1.1"

color-name@^1.1.1:
version "1.1.3"
resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.3.tgz#a7d0558bd89c42f795dd42328f740831ca53bc25"

combined-stream@^1.0.5, combined-stream@~1.0.5:
version "1.0.5"
resolved "https://registry.yarnpkg.com/combined-stream/-/combined-stream-1.0.5.tgz#938370a57b4a51dea2c77c15d5c5fdf895164009"
Expand Down Expand Up @@ -126,10 +98,6 @@ ecc-jsbn@~0.1.1:
dependencies:
jsbn "~0.1.0"

escape-string-regexp@^1.0.5:
version "1.0.5"
resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4"

extend@~3.0.0:
version "3.0.1"
resolved "https://registry.yarnpkg.com/extend/-/extend-3.0.1.tgz#a755ea7bc1adfcc5a31ce7e762dbaadc5e636444"
Expand Down Expand Up @@ -167,10 +135,6 @@ har-validator@~4.2.1:
ajv "^4.9.1"
har-schema "^1.0.5"

has-flag@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-2.0.0.tgz#e8207af1cc7b30d446cc70b734b5e8be18f88d51"

hawk@~3.1.3:
version "3.1.3"
resolved "https://registry.yarnpkg.com/hawk/-/hawk-3.1.3.tgz#078444bd7c1640b0fe540d2c9b73d59678e8e1c4"
Expand Down Expand Up @@ -312,12 +276,6 @@ stringstream@~0.0.4:
version "0.0.5"
resolved "https://registry.yarnpkg.com/stringstream/-/stringstream-0.0.5.tgz#4e484cd4de5a0bbbee18e46307710a8a81621878"

supports-color@^4.0.0:
version "4.2.1"
resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-4.2.1.tgz#65a4bb2631e90e02420dba5554c375a4754bb836"
dependencies:
has-flag "^2.0.0"

tough-cookie@~2.3.0:
version "2.3.2"
resolved "https://registry.yarnpkg.com/tough-cookie/-/tough-cookie-2.3.2.tgz#f081f76e4c85720e6c37a5faced737150d84072a"
Expand All @@ -343,4 +301,3 @@ verror@1.3.6:
resolved "https://registry.yarnpkg.com/verror/-/verror-1.3.6.tgz#cff5df12946d297d2baaefaa2689e25be01c005c"
dependencies:
extsprintf "1.0.2"

68 changes: 58 additions & 10 deletions packages/helpers/classes/mail.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ class Mail {
constructor(data) {

//Initialize array and object properties
this._isDynamic = false;
Copy link
Contributor

Choose a reason for hiding this comment

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

I'm thinking just us this.isDynamic for the flag, e.g. without the underscore.

this.personalizations = [];
this.attachments = [];
this.content = [];
Expand All @@ -35,6 +36,7 @@ class Mail {
//Helper properties
this.substitutions = null;
this.substitutionWrappers = null;
this.dynamicTemplateData = null;

//Process data if given
if (data) {
Expand All @@ -55,14 +57,14 @@ class Mail {
//Convert to camel case to make it workable, making a copy to prevent
//changes to the original objects
data = deepClone(data);
data = toCamelCase(data, ['substitutions', 'customArgs', 'headers']);
data = toCamelCase(data, ['substitutions', 'dynamicTemplateData', 'customArgs', 'headers']);

//Extract properties from data
const {
to, from, replyTo, cc, bcc, sendAt, subject, text, html, content,
templateId, personalizations, attachments, ipPoolName, batchId,
sections, headers, categories, category, customArgs, asm, mailSettings,
trackingSettings, substitutions, substitutionWrappers, isMultiple,
trackingSettings, substitutions, substitutionWrappers, dynamicTemplateData, isMultiple,
} = data;

//Set data
Expand All @@ -83,8 +85,13 @@ class Mail {
this.setAsm(asm);
this.setMailSettings(mailSettings);
this.setTrackingSettings(trackingSettings);
this.setSubstitutions(substitutions);
this.setSubstitutionWrappers(substitutionWrappers);

if (this._isDynamic) {
this.setDynamicTemplateData(dynamicTemplateData)
} else {
this.setSubstitutions(substitutions);
this.setSubstitutionWrappers(substitutionWrappers);
}

//Add contents from text/html properties
this.addTextContent(text);
Expand Down Expand Up @@ -153,7 +160,7 @@ class Mail {
}

/**
* Set template ID
* Set template ID, also checks if the template is dynamic or legacy
*/
setTemplateId(templateId) {
if (typeof templateId === 'undefined') {
Expand All @@ -162,6 +169,11 @@ class Mail {
if (typeof templateId !== 'string') {
throw new Error('String expected for `templateId`');
}

if (templateId.indexOf('d-') === 0) {
this._isDynamic = true;
}

this.templateId = templateId;
}

Expand Down Expand Up @@ -226,13 +238,27 @@ class Mail {
*/
addPersonalization(personalization) {

//We should either send substitutions or dynamicTemplateData
//depending on the templateId
if (this._isDynamic && personalization.substitutions) {
delete personalization.substitutions;
} else if (personalization.dynamicTemplateData) {
delete personalization.dynamicTemplateData;
}

//Convert to class if needed
if (!(personalization instanceof Personalization)) {
personalization = new Personalization(personalization);
}

//Apply substitutions and push to array
this.applySubstitutions(personalization);
//If this is dynamic, set dynamicTemplateData, or set substitutions
if (this._isDynamic) {
this.applyDynamicTemplateData(personalization);
} else {
this.applySubstitutions(personalization);
}

//Push personalization to array
this.personalizations.push(personalization);
}

Expand All @@ -247,7 +273,7 @@ class Mail {
) {
throw new Error('Provide at least one of to, cc or bcc');
}
this.addPersonalization(new Personalization({to, cc, bcc}));
Copy link
Contributor

Choose a reason for hiding this comment

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

The code style in this package doesn't use leading/trailing spaces after/before curly brackets, could you revert this change?

this.addPersonalization(new Personalization({ to, cc, bcc }));
}

/**
Expand Down Expand Up @@ -288,6 +314,28 @@ class Mail {
}
}

/**
* Helper which applies globally set dynamic_template_data to personalizations
*/
applyDynamicTemplateData(personalization) {
if (personalization instanceof Personalization) {
personalization.reverseMergeDynamicTemplateData(this.dynamicTemplateData);
}
}

/**
* Set substitutions
Copy link
Contributor

Choose a reason for hiding this comment

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

Fix comment to avoid confusion

*/
setDynamicTemplateData(dynamicTemplateData) {
if (typeof dynamicTemplateData === 'undefined') {
return;
}
if (typeof dynamicTemplateData !== 'object') {
throw new Error('Object expected for `dynamicTemplateData`');
}
this.dynamicTemplateData = dynamicTemplateData;
}

/**
* Set content
*/
Expand Down Expand Up @@ -377,7 +425,7 @@ class Mail {
categories = [categories];
}
if (!Array.isArray(categories) ||
!categories.every(cat => typeof cat === 'string')) {
!categories.every(cat => typeof cat === 'string')) {
throw new Error('Array of strings expected for `categories`');
}
this.categories = categories;
Expand Down Expand Up @@ -539,7 +587,7 @@ class Mail {
}

//Return as snake cased object
return toSnakeCase(json, ['substitutions', 'customArgs', 'headers']);
return toSnakeCase(json, ['substitutions', 'dynamicTemplateData', 'customArgs', 'headers']);
}

/**************************************************************************
Expand Down
120 changes: 117 additions & 3 deletions packages/helpers/classes/mail.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,10 @@ const Mail = require('./mail');
/**
* Tests
*/
describe('Mail', function() {
describe('Mail', function () {
Copy link
Contributor

Choose a reason for hiding this comment

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

Can you also undo these style corrections? Please respect the code style as indicated by the editor config and eslint config. If you enable ESLint in your editor it should automatically fix these issues.


describe('#527', function() {
it('shouldn\'t convert the headers to camel/snake case', function() {
describe('#527', function () {
it('shouldn\'t convert the headers to camel/snake case', function () {
const mail = new Mail({
personalizations: [{
to: 'test@example.com',
Expand Down Expand Up @@ -40,4 +40,118 @@ describe('Mail', function() {
.equal('<mailto:test@test.com>');
});
});
describe('#689', function () {

it('should detect dynamic template id', function () {
const mail = new Mail({
personalizations: [{
to: 'test@example.com',
headers: {
'test-header': 'test',
},
}],
from: {
email: 'test@example.com',
},
templateId: 'd-df80613cccc6441ea5cd7c95377bc1ef',
subject: 'test',
content: [{
type: 'text/plain',
value: 'test',
}]
});
expect(mail._isDynamic).to.equal(true);
});
it('should detect legacy template id', function () {
const mail = new Mail({
personalizations: [{
to: 'test@example.com',
headers: {
'test-header': 'test',
},
}],
from: {
email: 'test@example.com',
},
templateId: 'df80613cccc6441ea5cd7c95377bc1ef',
subject: 'test',
content: [{
type: 'text/plain',
value: 'test',
}]
});
expect(mail._isDynamic).to.equal(false);
});
it('should ignore substitutions if templateId is dynamic', function () {
const mail = new Mail({
personalizations: [{
to: 'test@example.com',
headers: {
'test-header': 'test',
},
substitutions: {
test2: 'Test2'
},
dynamicTemplateData: {
test2: 'Testy 2',
test3: 'Testy 3',
},
}],
dynamicTemplateData: {
test1: 'Test 1',
test2: 'Test 2',
},
substitutions: {
test1: 'Test1'
},
from: {
email: 'test@example.com',
},
templateId: 'd-df80613cccc6441ea5cd7c95377bc1ef',
subject: 'test',
content: [{
type: 'text/plain',
value: 'test',
}]
});
expect(mail.substitutions).to.equal(null);
expect(mail.personalizations[0].substitutions).to.deep.equal({});

expect(mail.dynamicTemplateData).to.deep.equal({ test1: 'Test 1', test2: 'Test 2' });
expect(mail.personalizations[0].dynamicTemplateData).to.deep.equal({ test1: 'Test 1', test2: 'Testy 2', test3: 'Testy 3' });

expect(mail.toJSON()).to.deep.equal({
"content": [
{
"type": "text/plain",
"value": "test"
}
],
"from": {
"email": "test@example.com"
},
"personalizations": [
{
"dynamic_template_data": {
"test1": "Test 1",
"test2": "Testy 2",
"test3": "Testy 3"
},
"headers": {
"test-header": "test"
},
"to": [
{
"email": "test@example.com",
"name": ""
}
]
}
],
"subject": "test",
"template_id": "d-df80613cccc6441ea5cd7c95377bc1ef"
});
});

})
});
Loading