Skip to content

Commit

Permalink
Merge 1d5b5e0 into ff43ce9
Browse files Browse the repository at this point in the history
  • Loading branch information
victorshp committed Nov 23, 2020
2 parents ff43ce9 + 1d5b5e0 commit dcd7776
Show file tree
Hide file tree
Showing 5 changed files with 156 additions and 2 deletions.
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -137,6 +137,7 @@ The content support by channel is described below.
| Channel | TextContent | FileContent | LocationContent | ContactsContent | TemplateContent |
|----------| :---: | :---: | :---: | :---: | :---: |
| SMS | X | | | | |
| RCS | X | X | | | |
| WhatsApp | X | X | X | X | X |
| Facebook | X | X | | | |

Expand Down
28 changes: 28 additions & 0 deletions src/lib/channels/rcs.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
import { AbstractChannel } from './abstract-channel';
import { ContentType, IContent, ILoggerInstance } from '../../types';

/**
* Implementation of RCS channel.
*/
export class RcsChannel extends AbstractChannel {

private supportedContents: ContentType[];

/**
* Returns a new `RCSChannel` that is used to set the RCS channel.
*
* @param token Zenvia platform token.
* @param loggerInstance If you want, you can pass your log instance.
*/
constructor(token: string, loggerInstance?: ILoggerInstance) {
super(token, 'rcs', loggerInstance);
this.supportedContents = ['text', 'file'];
}

protected contentSupportValidation(content: IContent): void | never {
if (!this.supportedContents.includes(content.type)) {
throw new Error(`Content of type ${content.type} is not supported in RCS channel`);
}
}

}
2 changes: 2 additions & 0 deletions src/lib/client.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { Channel, IChannel, ILoggerInstance, ISubscription, IPartialSubscription, IPartialTemplate } from '../types';
import { Logger } from '../utils/logger';
import { SmsChannel } from './channels/sms';
import { RcsChannel } from './channels/rcs';
import { FacebookChannel } from './channels/facebook';
import { WhatsAppChannel } from './channels/whatsapp';
import * as request from '../utils/request';
Expand Down Expand Up @@ -36,6 +37,7 @@ export class Client {
getChannel(channel: Channel): IChannel {
switch (channel) {
case 'sms': return new SmsChannel(this.token, this.logger);
case 'rcs': return new RcsChannel(this.token, this.logger);
case 'facebook': return new FacebookChannel(this.token, this.logger);
case 'whatsapp': return new WhatsAppChannel(this.token, this.logger);
default: throw new Error('Unsupported channel');
Expand Down
6 changes: 4 additions & 2 deletions src/types/zenvia.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
// tslint:disable:prefer-array-literal
import { SmsChannel } from '../lib/channels/sms';
import { RcsChannel } from '../lib/channels/rcs';
import { FacebookChannel } from '../lib/channels/facebook';
import { WhatsAppChannel } from '../lib/channels/whatsapp';
import { TextContent } from '../lib/contents/text';
Expand All @@ -14,6 +15,7 @@ import { MessageStatusSubscription } from '../lib/subscriptions/message-status';

export {
SmsChannel,
RcsChannel,
FacebookChannel,
WhatsAppChannel,
TextContent,
Expand All @@ -27,7 +29,7 @@ export {
MessageStatusSubscription,
};

export type Channel = 'sms' | 'whatsapp' | 'facebook';
export type Channel = 'sms' | 'whatsapp' | 'facebook' | 'rcs';
export type ContentType = 'text' | 'file' | 'template' | 'contacts' | 'location' | 'json';
export type MessageType = 'message' | 'notification';
export type MessageDirection = 'IN' | 'OUT';
Expand Down Expand Up @@ -329,7 +331,7 @@ export interface IButtonsItems {
}

export interface IChannels {
type: 'WHATSAPP' | 'FACEBOOK' | 'SMS';
type: 'WHATSAPP' | 'FACEBOOK' | 'SMS' | 'RCS';
status: 'APPROVED' | 'REFUSED' | 'PENDING' | 'CANCELED';
senderId: string;
whatsapp: any;
Expand Down
121 changes: 121 additions & 0 deletions test/lib/client.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,127 @@ describe('Client', () => {

});

describe('RCS Channel', () => {

it('should send message with text content', async () => {
const expectedMessage = {
from: 'FROM',
to: 'TO',
contents: [
{
type: 'text',
text: 'some text message',
},
],
};
const zenviaNock = nock('https://api.zenvia.com')
.post('/v1/channels/rcs/messages', expectedMessage)
.matchHeader('X-API-Token', 'SOME_TOKEN')
.reply(200, expectedMessage);

const client = new Client('SOME_TOKEN');
const rcs = client.getChannel('rcs');
const content = new TextContent('some text message');
const actualMessageResponse = await rcs.sendMessage('FROM', 'TO', content);
zenviaNock.isDone().should.be.true;
actualMessageResponse.should.be.deep.equal(expectedMessage);
});

it('should send message with an array of text content', async () => {
const expectedMessage = {
from: 'FROM',
to: 'TO',
contents: [
{
type: 'text',
text: 'first text message',
},
{
type: 'text',
text: 'second text message',
},
],
};
const zenviaNock = nock('https://api.zenvia.com')
.post('/v1/channels/rcs/messages', expectedMessage)
.matchHeader('X-API-Token', 'SOME_TOKEN')
.reply(200, expectedMessage);

const client = new Client('SOME_TOKEN');
const rcs = client.getChannel('rcs');
const contents = [new TextContent('first text message'), new TextContent('second text message')];
const actualMessageResponse = await rcs.sendMessage('FROM', 'TO', ...contents);
zenviaNock.isDone().should.be.true;
actualMessageResponse.should.be.deep.equal(expectedMessage);
});

it('should send message with file content', async () => {
const expectedMessage = {
from: 'FROM',
to: 'TO',
contents: [
{
type: 'file',
fileUrl: 'http://server.com/file.jpeg',
fileMimeType: 'image/jpeg',
fileCaption: 'some file caption',
},
],
};
const zenviaNock = nock('https://api.zenvia.com')
.post('/v1/channels/rcs/messages', expectedMessage)
.matchHeader('X-API-Token', 'SOME_TOKEN')
.reply(200, expectedMessage);

const client = new Client('SOME_TOKEN');
const rcs = client.getChannel('rcs');
const content = new FileContent('http://server.com/file.jpeg', 'image/jpeg', 'some file caption');
const actualMessageResponse = await rcs.sendMessage('FROM', 'TO', content);
zenviaNock.isDone().should.be.true;
actualMessageResponse.should.be.deep.equal(expectedMessage);
});

it('should fail when trying to send template content', async () => {
const client = new Client('SOME_TOKEN');
const rcs = client.getChannel('rcs');
const content = new TemplateContent('templateId', {});

try {
await rcs.sendMessage('FROM', 'TO', content);
throw new Error('An expected error was not throwed');
} catch (error) {
error.message.should.be.deep.equal('Content of type template is not supported in RCS channel');
}
});

it('should fail when trying to send location content', async () => {
const client = new Client('SOME_TOKEN');
const rcs = client.getChannel('rcs');
const content = new LocationContent(-46.511170, -23.442930, 'Name of location', 'Address of location', 'URL');

try {
await rcs.sendMessage('FROM', 'TO', content);
throw new Error('An expected error was not throwed');
} catch (error) {
error.message.should.be.deep.equal('Content of type location is not supported in RCS channel');
}
});

it('should fail when trying to send contacts content', async () => {
const client = new Client('SOME_TOKEN');
const rcs = client.getChannel('rcs');
const content = new ContactsContent([]);

try {
await rcs.sendMessage('FROM', 'TO', content);
throw new Error('An expected error was not throwed');
} catch (error) {
error.message.should.be.deep.equal('Content of type contacts is not supported in RCS channel');
}
});

});

describe('Facebook Channel', () => {

it('should send message with text content', async () => {
Expand Down

0 comments on commit dcd7776

Please sign in to comment.