diff --git a/src/mocks/index.js b/src/mocks/index.js
index 0db16fe..5abecff 100644
--- a/src/mocks/index.js
+++ b/src/mocks/index.js
@@ -13,6 +13,7 @@ export { default as drivers } from './drivers';
export { default as externalApis } from './externalApis';
export { default as incidents } from './incidents';
export { default as messages } from './messages';
+export { default as messageChannels } from './messageChannels';
export { default as patterns } from './patterns';
export { default as reportingTickets } from './reportingTickets';
export { default as realTime } from './realTime';
diff --git a/src/mocks/messageChannels.js b/src/mocks/messageChannels.js
new file mode 100644
index 0000000..d4a5af1
--- /dev/null
+++ b/src/mocks/messageChannels.js
@@ -0,0 +1,23 @@
+// eslint-disable-next-line import/no-extraneous-dependencies
+import fetchMock from 'fetch-mock';
+import Client from '../Client';
+
+const messageChannels = {
+ setUpSuccessfulMock: (client) => {
+ const listResponse = () => new Response(
+ Client.toBlob(messageChannels.list), {
+ headers: {
+ Link: '1/SYNC/messages_channels>',
+ },
+ });
+ fetchMock
+ .get(client.resolve('/1/SYNC/message_channels'), listResponse);
+ },
+ getByName: name => messageChannels.list.find(v => v.name === name),
+ list: [{
+ href: '/1/SYNC/message_channels/Signs',
+ name: 'Signs',
+ }],
+};
+
+export default messageChannels;
diff --git a/src/resources/Customer.js b/src/resources/Customer.js
index 17fe148..5cc23e7 100644
--- a/src/resources/Customer.js
+++ b/src/resources/Customer.js
@@ -20,6 +20,7 @@ import EnplugScreenshot from './EnplugScreenshot';
import EnplugConfiguration from './EnplugConfiguration';
import Message from './Message';
import MessagesContext from './MessagesContext';
+import MessageChannels from './MessageChannels';
import Pattern from './Pattern';
import PatternsContext from './PatternsContext';
import ReportingTicket from './ReportingTicket';
@@ -233,6 +234,14 @@ class Customer extends Resource {
return this.resource(Incident, Incident.makeHref(this.code, id));
}
+ /**
+ * Gets a customers available message channels by its code.
+ * @returns {MessageChannels} for fetching this customer's message channels
+ */
+ messageChannels() {
+ return this.resource(MessageChannels, MessageChannels.makeHref(this.code));
+ }
+
/**
* Gets a context for querying this customer's messages
* @returns {MessagesContext} Context for querying this customer's messages
diff --git a/src/resources/MessageChannels.js b/src/resources/MessageChannels.js
new file mode 100644
index 0000000..a22a20c
--- /dev/null
+++ b/src/resources/MessageChannels.js
@@ -0,0 +1,54 @@
+import Resource from './Resource';
+
+/**
+ * MessageChannels resource
+ */
+class MessageChannels extends Resource {
+ /**
+ * Creates a new MessageChannels.
+ *
+ * Will populate itself with the values given to it after the client parameter
+ * @example
Assigning partial message channels data to a new instance
+ * const client = new Client();
+ * const partialMessageChannelsData = [{
+ * href: '/1/SYNC/message_channel/GTFS-RT',
+ * name: 'GTFS-RT',
+ * }];
+ * const messageChannel = new MessageChannel(client, partialMessageChannelsData);
+ * messageChannel.hydrated === true;
+ *
+ * @param {Client} client Instance of pre-configured client
+ * @param {Array} rest Remaining arguments to use in assigning values to this instance
+ */
+ constructor(client, ...rest) {
+ super(client);
+
+ const newProperties = Object.assign({}, ...rest);
+ const hydrated = !Object.keys(newProperties).every(k => k === 'href' || k === 'code');
+
+ Object.assign(this, newProperties, { hydrated });
+ }
+
+ /**
+ * Makes a href for a given customer code
+ * @param {string} customerCode Customer code
+ * @returns {{href: string}} URI to instance of messageChannels
+ */
+ static makeHref(customerCode) {
+ return {
+ href: `/1/${customerCode}/message_channels`,
+ };
+ }
+
+ /**
+ * Fetches the data for this message channel via the client
+ * @returns {Promise} If successful, a hydrated instance of this messageChannels
+ */
+ fetch() {
+ return this.client.get(this.href)
+ .then(response => response.json())
+ .then(messageChannels => new MessageChannels(this.client, this, messageChannels));
+ }
+}
+
+export default MessageChannels;
diff --git a/src/resources/MessageChannels.test.js b/src/resources/MessageChannels.test.js
new file mode 100644
index 0000000..a1e8cc5
--- /dev/null
+++ b/src/resources/MessageChannels.test.js
@@ -0,0 +1,34 @@
+import chai from 'chai';
+import fetchMock from 'fetch-mock';
+import chaiAsPromised from 'chai-as-promised';
+import Client from '../Client';
+import MessageChannels from './MessageChannels';
+import { messageChannels as mockMessageChannels } from '../mocks';
+
+chai.should();
+chai.use(chaiAsPromised);
+
+describe('When instantiating a message channel based on customer and name', () => {
+ const client = new Client();
+ const messageChannels = new MessageChannels(client, MessageChannels.makeHref('SYNC'));
+
+ it('should set the href', () => messageChannels.href.should.equal('/1/SYNC/message_channels'));
+ it('should not be hydrated', () => messageChannels.hydrated.should.equal(false));
+});
+
+describe('When fetching message channels based on customer', () => {
+ const client = new Client();
+
+ beforeEach(() => mockMessageChannels.setUpSuccessfulMock(client));
+ beforeEach(() => fetchMock.catch(503));
+ afterEach(fetchMock.restore);
+
+ let promise;
+ beforeEach(() => {
+ promise = new MessageChannels(client, MessageChannels.makeHref('SYNC')).fetch();
+ });
+
+ it('should resolve the promise', () => promise.should.be.fulfilled);
+ it('should set the href', () => promise.then(v => v.href).should.eventually.equal('/1/SYNC/message_channels'));
+ it('should be hydrated', () => promise.then(v => v.hydrated).should.eventually.equal(true));
+});