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

Feature/mjml support #56

Open
wants to merge 10 commits into
base: master
Choose a base branch
from
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.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
3 changes: 3 additions & 0 deletions .gitignore
Expand Up @@ -29,3 +29,6 @@ build/Release
node_modules
config.json
npmrc

# Email template files
templates/*
84 changes: 84 additions & 0 deletions apiary.apib
Expand Up @@ -568,6 +568,90 @@ __optionals__ | String | Optional | Object containing all send options (onlyGcm
}


# Group Templates

## Create email template [/api/notification/template]

### Create an HTML email template [POST]
Generates a new HTML email template from a non-HTML input.

**Currently supported formats are .mjml files, using the format specified by [MJML](https://mjml.io/)**

#### Attributes for the json body parameter

Name | Type | Required | Description
--- | --- | --- | ---
__filename__ | String | Required | Name of the email template to be generated
__content__ | String | Required | Input text that will be transformed into HTML
__type__ | String | Required | The input type. Currently can be ´mjml´ **only**

+ Request (application/json; charset=utf-8)

+ Body

{
"filename": "custom-template",
"content": "<mj-body><mj-section><mj-column><mj-text font-size="20px" color="#F45E43" font-family="helvetica">Hello World!</mj-text></mj-column></mj-section></mj-body>",
"type": "mjml"
}

+ Response 200

{
"output": "done"
}

+ Response 400 (application/json; charset=utf-8)

{
"code": "BadRequestError",
"message": "Missing or invalid parameters: content, filename, type"
}

## Email template listing [/api/notification/template/list]

### Fetch list of email templates [GET]
Returns a list of the email template filenames currently available

+ Request (application/json; charset=utf-8)

+ Body

{}

+ Response 200

[
{
"name": "my-template-1",
"type": "html",
},
{
"name": "my-template-2",
"type": "html"
}
]

## Email template details [/api/notification/template/details/:templateName.:type]

### Fetch email template details [GET]
Returns a the content of an email template (either HTML or other) and the placeholders it has in its content.

+ Request (application/json; charset=utf-8)

+ Response 200

{
"html": "<mj-body><mj-section><mj-column><mj-text font-size="20px" color="#F45E43" font-family="helvetica">Hello World!</mj-text></mj-column></mj-section></mj-body>",
"placeholders": ["USER"]
}

+ Response 404

{
"code": "NotFoundError",
"message": "Template not found"
}

# Data Structures

Expand Down
26 changes: 22 additions & 4 deletions cucumber/features/email_features/email_send.feature
@@ -1,19 +1,28 @@
Feature: the server receives a request to send an email

Scenario Outline: send batch Email to an identity objects
Scenario Outline: send in-body HTML batch Email to identity objects
Given an authenticated identity in the app with <identity_id>
Then a request is sent to <endpoint> to send an email <email> and returns <response>

Examples:
| identity_id | endpoint | email | response |
| identity_id | endpoint | email | response |
| 01f0000000000000003f0001 | /api/notification/email | email/batch/valid_email_over_batch_limit.json | email/valid_email_response.json |
| 01f0000000000000003f0001 | /api/notification/email | email/batch/valid_email_under_batch_limit.json | email/valid_email_response.json |
| 01f0000000000000003f0002 | /api/notification/email | email/batch/invalid_to_email.json | email/invalid_to_email_response.json |
| 01f0000000000000003f0003 | /api/notification/email | email/batch/invalid_from_email.json | email/invalid_from_email_response.json |
| 01f0000000000000003f0001 | /api/notification/email | email/batch/empty_email.json | email/empty_email_response.json |
| 01f0000000000000003f0002 | /api/notification/email | email/batch/missing_email_message.json | email/missing_email_message_response.json |

Scenario Outline: send email to a single email address
Scenario Outline: send custom HTML template batch Email to identity objects
Given an authenticated identity in the app with <identity_id>
Then a request is sent to <endpoint> to send a custom email template <template> for <email> and returns <response>

Examples:
| identity_id | endpoint | template | email | response |
| 01f0000000000000003f0001 | /api/notification/email | email/successful_template_read.json | email/batch/valid_custom_template_email.json | email/valid_email_response.json |
| 01f0000000000000003f0002 | /api/notification/email | email/errored_template_read.json | email/batch/invalid_custom_template_email.json | email/invalid_template_email_response.json |

Scenario Outline: send in-body HTML email to a single email address
Given an authenticated identity in the app with <identity_id>
Then a request is sent to <endpoint> to send an email <email> and returns <response>

Expand All @@ -23,4 +32,13 @@ Feature: the server receives a request to send an email
| 01f0000000000000003f0002 | /api/notification/singleEmail | email/single/invalid_to_single_email.json | email/invalid_to_email_response.json |
| 01f0000000000000003f0003 | /api/notification/singleEmail | email/single/missing_from_single_email.json | email/valid_email_response.json |
| 01f0000000000000003f0001 | /api/notification/singleEmail | email/single/empty_single_email.json | email/empty_email_response.json |
| 01f0000000000000003f0002 | /api/notification/singleEmail | email/single/missing_single_email_message.json | email/missing_email_message_response.json |
| 01f0000000000000003f0002 | /api/notification/singleEmail | email/single/missing_single_email_message.json | email/missing_email_message_response.json |

Scenario Outline: send custom HTML template email to a single email address
Given an authenticated identity in the app with <identity_id>
Then a request is sent to <endpoint> to send a custom email template <template> for <email> and returns <response>

Examples:
| identity_id | endpoint | template | email | response |
| 01f0000000000000003f0001 | /api/notification/singleEmail | email/successful_template_read.json | email/single/valid_custom_template_email.json | email/valid_email_response.json |
| 01f0000000000000003f0002 | /api/notification/singleEmail | email/errored_template_read.json | email/single/invalid_custom_template_email.json | email/invalid_template_email_response.json |
47 changes: 44 additions & 3 deletions cucumber/features/step_definitions/email_steps.js
@@ -1,9 +1,17 @@
'use strict';
const config = require('config');
const nock = require('nock');
const sinon = require('sinon');
const fileHandler = require('../../../lib/util/file_handler');
const errors = require('../../../lib/util/errors');

let fileHandlerStub;
nock.disableNetConnect();


const MAILGUN_MESSAGES_BASE_URL = 'https://api.mailgun.net';
const MAILGUN_MESSAGES_ENDPOINT_URL = '/v3/' + config.get('transport.mailgun.domain') + '/messages';

module.exports = function() {

this.World = require('../support/world').World;
Expand All @@ -14,9 +22,6 @@ module.exports = function() {
let emailObj = _this.readJSONResource(email);
let res = _this.readJSONResource(response);

const MAILGUN_MESSAGES_BASE_URL = 'https://api.mailgun.net';
const MAILGUN_MESSAGES_ENDPOINT_URL = '/v3/' + config.get('transport.mailgun.domain') + '/messages';

nock(MAILGUN_MESSAGES_BASE_URL)
.persist() // Required since multiple requests can be made in parallel from the platform
.post(MAILGUN_MESSAGES_ENDPOINT_URL)
Expand All @@ -31,4 +36,40 @@ module.exports = function() {
.expect(res.status)
.end(callback);
});

this.Then(/^a request is sent to (.*) to send a custom email template (.*) for (.*) and returns (.*)$/, function(endpoint, templateFile, email, response, callback) {
let _this = this;

let template = _this.readJSONResource(templateFile);
let emailObj = _this.readJSONResource(email);
let res = _this.readJSONResource(response);
fileHandlerStub = sinon.stub(fileHandler, 'readFile');

if (template.success) {
fileHandlerStub.returns(template.success);
} else {
fileHandlerStub.returns({error: new errors.NotFoundError(template.error.message)});
}

nock(MAILGUN_MESSAGES_BASE_URL)
.persist() // Required since multiple requests can be made in parallel from the platform
.post(MAILGUN_MESSAGES_ENDPOINT_URL)
.reply(200, res.data);

let request = this.buildRequest('POST', endpoint, {
'x-user-id': this.get('identity')
});

request
.send(emailObj)
.expect(res.status)
.end(function(err) {
fileHandlerStub.restore();
if (err) {
return callback(err);
}

return callback();
});
});
};
90 changes: 90 additions & 0 deletions cucumber/features/step_definitions/template_steps.js
@@ -0,0 +1,90 @@
'use strict';
const expect = require('chai').expect;
const sinon = require('sinon');
const templatePlatform = require('../../../lib/platforms/template');

let templatePlatformStub = {};

module.exports = function() {

this.World = require('../support/world').World;

this.Then(/^a template object (.*) is sent to (.*) yielding (.*)/, function(requestBody, endpoint, response, callback) {
let _this = this;

let requestBodyObj = _this.readJSONResource(requestBody);
let res = _this.readJSONResource(response);

templatePlatformStub.generateHtmlTemplate = sinon.stub(templatePlatform, 'generateHtmlTemplate');
templatePlatformStub.generateHtmlTemplate.yields(res.stubbed.error, res.stubbed.output);

let request = this.buildRequest('POST', endpoint, {
'x-user-id': this.get('identity')
});

request
.send(requestBodyObj)
.expect(res.result.status)
.end(function(err, output) {
templatePlatformStub.generateHtmlTemplate.restore();
if (err) {
return callback(err);
}

expect(output.body).to.deep.equal(res.result.body);
return callback();
});
});

this.Then(/^a request for template listing is sent to (.*) yielding (.*)$/, function(endpoint, response, callback) {
let _this = this;

let res = _this.readJSONResource(response);

templatePlatformStub.getListOfHtmlTemplates = sinon.stub(templatePlatform, 'getListOfHtmlTemplates');
templatePlatformStub.getListOfHtmlTemplates.yields(res.stubbed.error, res.stubbed.output);

let request = this.buildRequest('GET', endpoint, {
'x-user-id': this.get('identity')
});

request
.send()
.expect(res.result.status)
.end(function(err, output) {
templatePlatformStub.getListOfHtmlTemplates.restore();
if (err) {
return callback(err);
}

expect(output.body).to.deep.equal(res.result.body);
return callback();
});
});

this.Then(/^a request for template details is sent to (.*) yielding (.*)$/, function(endpoint, response, callback) {
let _this = this;

let res = _this.readJSONResource(response);

templatePlatformStub.getTemplateDetails = sinon.stub(templatePlatform, 'getTemplateDetails');
templatePlatformStub.getTemplateDetails.yields(res.stubbed.error, res.stubbed.output);

let request = this.buildRequest('GET', endpoint, {
'x-user-id': this.get('identity')
});

request
.send()
.expect(res.result.status)
.end(function(err, output) {
templatePlatformStub.getTemplateDetails.restore();
if (err) {
return callback(err);
}

expect(output.body).to.deep.equal(res.result.body);
return callback();
});
});
};
10 changes: 10 additions & 0 deletions cucumber/features/template_features/template_create.feature
@@ -0,0 +1,10 @@
Feature: the server receives a request to create a new email template

Scenario Outline: generate an HTML email template based on the request item
Given an authenticated identity in the app with <identity_id>
Then a template object <body> is sent to <endpoint> yielding <response>

Examples:
| identity_id | endpoint | body | response |
| 01f0000000000000003f0001 | /api/notification/template | template/valid_template_creation_body.json | template/valid_template_creation_response.js |
| 01f0000000000000003f0001 | /api/notification/template | template/invalid_template_creation_body.json | template/invalid_template_creation_response.js |
11 changes: 11 additions & 0 deletions cucumber/features/template_features/template_details.feature
@@ -0,0 +1,11 @@
Feature: the server receives a request to send a the details of a given email template

Scenario Outline: return successfully the details associated to a given email template
Given an authenticated identity in the app with <identity_id>
Then a request for template details is sent to <endpoint> yielding <response>

Examples:
| identity_id | endpoint | response |
| 01f0000000000000003f0001 | /api/notification/template/details/some-template.html | template/valid_template_details_response.js |
| 01f0000000000000003f0001 | /api/notification/template/details/no-file.html | template/invalid_template_details_response.js |
| 01f0000000000000003f0001 | /api/notification/template/details/invalid-format | template/missing_type_template_details_response.js |
12 changes: 12 additions & 0 deletions cucumber/features/template_features/template_list.feature
@@ -0,0 +1,12 @@

Feature: the server receives a request to send a list of the available email templates

Scenario Outline: list successfully the names of the generated email templates
Given an authenticated identity in the app with <identity_id>
Then a request for template listing is sent to <endpoint> yielding <response>

Examples:
| identity_id | endpoint | response |
| 01f0000000000000003f0001 | /api/notification/template/list | template/valid_template_list_response.js |
| 01f0000000000000003f0001 | /api/notification/template/list | template/invalid_template_list_response.js |

15 changes: 15 additions & 0 deletions cucumber/test_files/email/batch/invalid_custom_template_email.json
@@ -0,0 +1,15 @@
{
"identities": ["01f0000000000000003f0002"],
"channels": ["buddies"],
"content": {
"to": "john@doe.com",
"from": "mac@into.sh",
"template": {
"filename": "no-file",
"placeholders": {}
},
"subject": "Testing"
}
}


17 changes: 17 additions & 0 deletions cucumber/test_files/email/batch/valid_custom_template_email.json
@@ -0,0 +1,17 @@
{
"identities": ["01f0000000000000003f0002"],
"channels": ["buddies"],
"content": {
"to": "john@doe.com",
"from": "mac@into.sh",
"template": {
"filename": "template",
"placeholders": {
"USER": "Mr. Invent"
}
},
"subject": "Testing"
}
}


10 changes: 10 additions & 0 deletions cucumber/test_files/email/errored_template_read.json
@@ -0,0 +1,10 @@
{
"error": {
"message": "Template not found",
"statusCode": 404,
"body": {
"code": "NotFoundError",
"message": "Template not found"
}
}
}
@@ -0,0 +1,3 @@
{
"status": 404
}