Skip to content

Commit

Permalink
Merge pull request #21 from ShellMonkeys/feature/adding-tags-to-messages
Browse files Browse the repository at this point in the history
Feature/adding tags to messages
  • Loading branch information
radTuti authored Jul 6, 2017
2 parents 246c6ac + d840e0e commit 51c4fad
Show file tree
Hide file tree
Showing 20 changed files with 281 additions and 207 deletions.
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@
"eslint-plugin-jsx-a11y": "^4.0.0",
"eslint-plugin-react": "^6.10.0",
"nyc": "^10.1.2",
"sinon": "^1.17.7",
"sinon": "^2.1.0",
"tap-spec": "^4.1.1",
"tape": "^4.6.3",
"tape-catch": "^1.0.6"
Expand Down
4 changes: 4 additions & 0 deletions src/client/client.js
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,10 @@ export default class Client {
notification_type: notificationType,
};

if (message.tag) {
facebookEnvelope.tag = message.tag;
}

return this.proxyFetchFacebook(`${this.baseURL}/me/messages?access_token=${this.pageAccessToken}`, { body: JSON.stringify(facebookEnvelope) })
.catch((error) => {
log.error(error);
Expand Down
2 changes: 1 addition & 1 deletion src/message/buttons/shareButton.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ export default class ShareButton extends Button {
setContents(content) {
validate.oneOf(content.constructor.name, [GenericTemplate.name], 'share_contents', 'ShareButton.setContents');
// TODO: A generic template with up to one URL button
this.share_contents = content;
this.share_contents = content.getMessage();
return this;
}
}
14 changes: 7 additions & 7 deletions src/message/contentTypes/attachment.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import validate from '../../util/validate';
class Attachment extends Message {
constructor(type, url, attachmentId = null) {
super();
this.attachment = {
this.state.attachment = {
type: type,
payload: {},
};
Expand All @@ -19,25 +19,25 @@ class Attachment extends Message {

setUrl(url) {
if (!validate.null(url)) {
validate.isNull(this.attachment.payload.attachment_id, 'attachment_id', `${this.constructor.name}.setUrl`);
validate.isNull(this.state.attachment.payload.attachment_id, 'attachment_id', `${this.constructor.name}.setUrl`);
validate.url(url, `${this.constructor.name}.setUrl`);
this.attachment.payload.url = url;
this.state.attachment.payload.url = url;
}
return this;
}

setAttachmentId(id) {
if (!validate.null(id)) {
validate.isNull(this.attachment.payload.url, 'url', `${this.constructor.name}.setAttachmentId`);
validate.isNull(this.state.attachment.payload.url, 'url', `${this.constructor.name}.setAttachmentId`);
validate.isString(id, 'attachment_id', `${this.constructor.name}.setAttachmentId`);
this.attachment.payload.attachment_id = id;
this.state.attachment.payload.attachment_id = id;
}
return this;
}

forUpload() {
validate.required(this, 'attachment.payload.url', `${this.constructor.name}.forUpload`);
this.attachment.payload.is_reusable = true;
validate.required(this.state, 'attachment.payload.url', `${this.constructor.name}.forUpload`);
this.state.attachment.payload.is_reusable = true;
return this;
}
}
Expand Down
8 changes: 7 additions & 1 deletion src/message/contentTypes/textMessage.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,13 @@ export default class TextMessage extends Message {

setText(text) {
validate.stringLength(text, null, 640, 'text', 'TextMessage.setText');
this.text = text;
this.state.text = text;
return this;
}

withTag(tag) {
validate.oneOf(tag, ['ISSUE_RESOLUTION'], 'tag', 'TextMessage.withTag');
this.tag = tag;
return this;
}
}
15 changes: 8 additions & 7 deletions src/message/message.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,15 +4,16 @@ const MAX_QR = 11;

export default class Message {
constructor() {
this.state = {};
return this;
}

getMessage() {
if ((this.text && this.attachment) || (!this.text && !this.attachment)) {
if ((this.state.text && this.state.attachment) || (!this.state.text && !this.state.attachment)) {
throw new Error(`${this.constructor.name}.getMessage: You cannot send a text and an attachment together, please read the Send API Reference for more details`);
}

return { ...this };
return { ...this.state };
}

validateQuickReplies(quickReplies, max = MAX_QR) {
Expand All @@ -22,17 +23,17 @@ export default class Message {

setQuickReplies(quickReplies) {
this.validateQuickReplies(quickReplies);
this.quick_replies = quickReplies;
this.state.quick_replies = quickReplies;
return this;
}

addQuickReply(quickReply) {
if (!this.quick_replies) {
this.quick_replies = [];
if (!this.state.quick_replies) {
this.state.quick_replies = [];
}
this.validateQuickReplies(this.quick_replies, MAX_QR - 1);
this.validateQuickReplies(this.state.quick_replies, MAX_QR - 1);

this.quick_replies.push(quickReply);
this.state.quick_replies.push(quickReply);
return this;
}
}
8 changes: 4 additions & 4 deletions src/message/templates/buttonTemplate.js
Original file line number Diff line number Diff line change
Expand Up @@ -27,20 +27,20 @@ export default class ButtonTemplate extends Template {

addButton(button) {
this.validateButton(button);
this.validateButtons(this.attachment.payload.buttons, 2);
this.attachment.payload.buttons.push(button);
this.validateButtons(this.state.attachment.payload.buttons, 2);
this.state.attachment.payload.buttons.push(button);
return this;
}

setButtons(buttons) {
this.validateButtons(buttons);
this.attachment.payload.buttons = buttons;
this.state.attachment.payload.buttons = buttons;
return this;
}

setText(text) {
validate.stringLength(text, null, 640, 'text', 'ButtonTemplate.setText');
this.attachment.payload.text = text;
this.state.attachment.payload.text = text;
return this;
}
}
14 changes: 10 additions & 4 deletions src/message/templates/genericTemplate.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ export default class GenericTemplate extends Template {

setImageAspectRatio(aspectRatio) {
validate.oneOf(aspectRatio, ['horizontal', 'square'], 'image_aspect_ratio', 'GenericTemplate.constructor');
this.attachment.payload.image_aspect_ratio = aspectRatio;
this.state.attachment.payload.image_aspect_ratio = aspectRatio;
return this;
}

Expand All @@ -33,14 +33,20 @@ export default class GenericTemplate extends Template {

setElements(elements) {
this.validateElements(elements);
this.attachment.payload.elements = elements;
this.state.attachment.payload.elements = elements;
return this;
}

addElement(element) {
this.validateElement(element);
this.validateElements(this.attachment.payload.elements, MAX - 1);
this.attachment.payload.elements.push(element);
this.validateElements(this.state.attachment.payload.elements, MAX - 1);
this.state.attachment.payload.elements.push(element);
return this;
}

withTag(tag) {
validate.oneOf(tag, ['SHIPPING_UPDATE', 'RESERVATION_UPDATE', 'ISSUE_RESOLUTION'], 'tag', 'GenericTemplate.withTag');
this.tag = tag;
return this;
}
}
12 changes: 6 additions & 6 deletions src/message/templates/listTemplate.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,13 +16,13 @@ export default class ListTemplate extends Template {
setTopElementStyle(style) {
validate.oneOf(style, ['large', 'compact'], 'top_element_style', 'ListTemplate.setTopElementStyle');
this.validateTopElement(style);
this.attachment.payload.top_element_style = style;
this.state.attachment.payload.top_element_style = style;
return this;
}

validateTopElement(style) {
if (style === 'large') {
const firstElement = this.attachment.payload.elements[0];
const firstElement = this.state.attachment.payload.elements[0];
if (validate.null(firstElement.image_url)) {
throw new Error('ListTemplate.setTopElementStyle: image_url is required for the first element if top_element_style is large or not specified');
}
Expand All @@ -48,14 +48,14 @@ export default class ListTemplate extends Template {

setElements(elements) {
this.validateElements(elements);
this.attachment.payload.elements = elements;
this.state.attachment.payload.elements = elements;
return this;
}

addElement(element) {
this.validateElement(element);
this.validateElements(this.attachment.payload.elements, 3);
this.attachment.payload.elements.push(element);
this.validateElements(this.state.attachment.payload.elements, 3);
this.state.attachment.payload.elements.push(element);
return this;
}

Expand All @@ -70,7 +70,7 @@ export default class ListTemplate extends Template {

setButtons(buttons) {
this.validateButtons(buttons);
this.attachment.payload.buttons = buttons;
this.state.attachment.payload.buttons = buttons;
return this;
}
}
34 changes: 17 additions & 17 deletions src/message/templates/receiptTemplate.js
Original file line number Diff line number Diff line change
Expand Up @@ -50,43 +50,43 @@ export default class ReceiptTemplate extends Template {

setRecipientName(name) {
validate.isString(name, 'recipient_name', 'ReceiptTemplate.setRecipientName');
this.attachment.payload.recipient_name = name;
this.state.attachment.payload.recipient_name = name;
return this;
}

setMerchantName(name) {
validate.isString(name, 'merchant_name', 'ReceiptTemplate.setMerchantName');
this.attachment.payload.merchant_name = name;
this.state.attachment.payload.merchant_name = name;
return this;
}

setOrderNumber(number) {
validate.isString(number, 'order_number', 'ReceiptTemplate.setOrderNumber');
this.attachment.payload.order_number = number;
this.state.attachment.payload.order_number = number;
return this;
}

setCurrency(currency) {
validate.isString(currency, 'currency', 'ReceiptTemplate.setCurrency');
this.attachment.payload.currency = currency;
this.state.attachment.payload.currency = currency;
return this;
}

setPaymentMethod(method) {
validate.isString(method, 'payment_method', 'ReceiptTemplate.setPaymentMethod');
this.attachment.payload.payment_method = method;
this.state.attachment.payload.payment_method = method;
return this;
}

setTimestamp(timestamp) {
validate.isString(timestamp, 'timestamp', 'ReceiptTemplate.setTimestamp');
this.attachment.payload.timestamp = timestamp;
this.state.attachment.payload.timestamp = timestamp;
return this;
}

setOrderUrl(url) {
validate.url(url, 'ReceiptElement.setOrderUrl');
this.attachment.payload.order_url = url;
this.state.attachment.payload.order_url = url;
return this;
}

Expand All @@ -105,41 +105,41 @@ export default class ReceiptTemplate extends Template {

addElement(element) {
this.validateElement(element);
if (validate.null(this.attachment.payload.elements)) {
this.attachment.payload.elements = [];
if (validate.null(this.state.attachment.payload.elements)) {
this.state.attachment.payload.elements = [];
}
else {
this.validateElements(this.attachment.payload.elements, MAX - 1);
this.validateElements(this.state.attachment.payload.elements, MAX - 1);
}
this.attachment.payload.elements.push(element);
this.state.attachment.payload.elements.push(element);
return this;
}

setAddress(country, state, postalCode, city, street1, street2 = '') {
this.attachment.payload.address = {
this.state.attachment.payload.address = {
street_1: street1,
street_2: street2,
city: city,
postal_code: postalCode,
state: state,
country: country,
};
validate.required(this.attachment.payload.address, ['street_1', 'city', 'postal_code', 'state', 'country'], 'ReceiptTemplate.setAddress');
validate.required(this.state.attachment.payload.address, ['street_1', 'city', 'postal_code', 'state', 'country'], 'ReceiptTemplate.setAddress');
return this;
}

setSummary(summary) {
validate.oneOf(summary.constructor.name, Summary.name, 'summary', 'ReceiptTemplate.setSummary');
this.attachment.payload.summary = summary;
this.state.attachment.payload.summary = summary;
}

addAdjustment(name, amount) {
validate.isString(name, 'adjustment.name', 'ReceiptTemplate.addAdjustment');
validate.isNumber(amount, 'adjustment.amount', 'ReceiptTemplate.addAdjustment');
if (validate.null(this.attachment.payload.adjustments)) {
this.attachment.payload.adjustments = [];
if (validate.null(this.state.attachment.payload.adjustments)) {
this.state.attachment.payload.adjustments = [];
}
this.attachment.payload.adjustments.push({
this.state.attachment.payload.adjustments.push({
name: name,
amount: amount,
});
Expand Down
2 changes: 1 addition & 1 deletion src/message/templates/template.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ export default class Template extends Message {
constructor(type) {
super();
validate.oneOf(type, validTemplates, 'template_type', 'Template.constructor');
this.attachment = {
this.state.attachment = {
type: 'template',
payload: {
template_type: type,
Expand Down
19 changes: 19 additions & 0 deletions test/client/client.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,15 @@ test('Client.constructor - with proxy', (expect) => {
expect.end();
});

test('Client.sendMessage - with tag', (expect) => {
expect.plan(1);
sinon.stub(fetch, 'Promise')
.returns(Promise.resolve(testResponse.generic));
const testClient = new Client('PAGE_ACCESS_TOKEN');
testClient.sendMessage(new TextMessage('hello, world!').withTag('ISSUE_RESOLUTION'), 'USER_ID')
.then(resp => expect.same(resp, testResponse.generic.json(), 'should return test response'));
tearDown();
});

test('Client.sendMessage - error', (expect) => {
expect.plan(1);
Expand All @@ -93,6 +102,16 @@ test('Client.getUserProfile', (expect) => {
tearDown();
});

test('Client.getUserProfile - error', (expect) => {
expect.plan(1);
sinon.stub(fetch, 'Promise').rejects(testResponse.errorCode);
const testClient = new Client('PAGE_ACCESS_TOKEN');
testClient.getUserProfile('USER_ID')
.catch(e => expect.same(e, new Error(testResponse.errorCode.json()
.error.name), 'should return test response'));
tearDown();
});

test('Client.markSeen', (expect) => {
expect.plan(1);
sinon.stub(fetch, 'Promise')
Expand Down
Loading

0 comments on commit 51c4fad

Please sign in to comment.