Skip to content

Commit

Permalink
feat(rider_apps): Manage rider app config. (#97)
Browse files Browse the repository at this point in the history
Allows users to get and set the configuration for a customer's Rider
Apps.

Resolves EN-7246.

Signed-off-by: Jeff Cuevas-Koch <[email protected]>

Co-authored-by: Jeff Cuevas-Koch <[email protected]>
  • Loading branch information
cuevaskoch and Jeff Cuevas-Koch authored Apr 15, 2021
1 parent 2c315f1 commit f4336d1
Show file tree
Hide file tree
Showing 7 changed files with 223 additions and 0 deletions.
50 changes: 50 additions & 0 deletions src/examples/get_rider_app_config.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
import chai from 'chai';
import chaiAsPromised from 'chai-as-promised';
import fetchMock from 'fetch-mock';
import Track from '../index';
import { charlie, riderAppConfiguration as mocks } from '../mocks';

chai.should();
chai.use(chaiAsPromised);

describe('When retrieving a rider app configuration', () => {
const api = new Track({ autoRenew: false });

beforeEach(() => charlie.setUpSuccessfulMock(api.client));
beforeEach(() => mocks.setUpSuccessfulMock(api.client));
beforeEach(() => fetchMock.catch(503));
afterEach(fetchMock.restore);

it('should get a the configuration', () => {
api.logIn({ username: '[email protected]', password: 'securepassword' });

const configPromise = api.customer('SYNC').riderAppConfiguration()
.fetch()
.then(config => config); // Do things with config

return configPromise;
});
});

describe('When updating a rider app configuration', () => {
const api = new Track({ autoRenew: false });

beforeEach(() => charlie.setUpSuccessfulMock(api.client));
beforeEach(() => mocks.setUpSuccessfulMock(api.client));
beforeEach(() => fetchMock.catch(503));
afterEach(fetchMock.restore);

it('should update the configuration', () => {
api.logIn({ username: '[email protected]', password: 'securepassword' });

const configPromise = api.customer('SYNC').riderAppConfiguration()
.fetch()
.then((config) => {
// eslint-disable-next-line no-param-reassign
config.spash_image_url = 'https://example.com/updated.png';
return config.update();
});

return configPromise;
});
});
1 change: 1 addition & 0 deletions src/mocks/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ export { default as messageChannels } from './messageChannels';
export { default as patterns } from './patterns';
export { default as reportingTickets } from './reportingTickets';
export { default as realTime } from './realTime';
export { default as riderAppConfiguration } from './riderAppConfiguration';
export { default as roles } from './roles';
export { default as routes } from './routes';
export { default as runs } from './runs';
Expand Down
36 changes: 36 additions & 0 deletions src/mocks/riderAppConfiguration.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
// eslint-disable-next-line import/no-extraneous-dependencies
import fetchMock from 'fetch-mock';
import Client from '../Client';

const riderAppConfiguration = {
rawObject: {
href: '/1/SYNC/rider_app_configuration',
splash_image_url: 'https://example.com/logo.png',
accent_color: '#ABCDEF',
information: [{
title: 'Agency Information',
items: [
{
title: 'About Us',
link: 'https://example.com/about',
},
{
title: 'Routes',
link: 'https://example.com/routes',
},
],
}],
},
setUpSuccessfulMock: (client) => {
const url = client.resolve('/1/SYNC/rider_app_configuration');

const putResponse = () => new Response(undefined);
const getResponse = () => new Response(Client.toBlob(riderAppConfiguration.rawObject));

fetchMock
.put(url, putResponse)
.get(url, getResponse);
}
};

export default riderAppConfiguration;
11 changes: 11 additions & 0 deletions src/resources/Customer.js
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ import DispatchMessageStatus from './DispatchMessageStatus';
import Pattern from './Pattern';
import PatternsContext from './PatternsContext';
import ReportingTicket from './ReportingTicket';
import RiderAppConfiguration from './RiderAppConfiguration';
import Route from './Route';
import RoutesContext from './RoutesContext';
import Run from './Run';
Expand Down Expand Up @@ -296,6 +297,16 @@ class Customer extends Resource {
return this.resource(Message, { code: this.code, ...payload });
}

/**
* Gets a Rider App Configuration resource
* @param {Object} payload New properties with which to initialize the Rider App Configuration
* @returns {RiderAppConfiguration} RiderAppConfiguration resource
*/
riderAppConfiguration(payload = {}) {
const href = RiderAppConfiguration.makeHref(this.code);
return this.resource(RiderAppConfiguration, { code: this.code, ...href, ...payload });
}

/**
* Gets a reporting ticket resource
* @returns {ReportingTicket} ReportingTicket resource
Expand Down
2 changes: 2 additions & 0 deletions src/resources/Customer.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ import Message from './Message';
import MessagesContext from './MessagesContext';
import Pattern from './Pattern';
import PatternsContext from './PatternsContext';
import RiderAppConfiguration from './RiderAppConfiguration';
import ReportingTicket from './ReportingTicket';
import Route from './Route';
import RoutesContext from './RoutesContext';
Expand Down Expand Up @@ -75,6 +76,7 @@ describe('When getting resources related to a customer', () => {
it('should allow a message to be retrieved', () => customer.message().should.be.instanceof(Message));
it('should allow patterns to be searched', () => customer.patterns().should.be.instanceof(PatternsContext));
it('should allow a pattern to be retrieved', () => customer.pattern().should.be.instanceof(Pattern));
it('should allow a rider app configuration to be retrieved', () => customer.riderAppConfiguration().should.be.instanceOf(RiderAppConfiguration));
it('should allow a reporting ticket to be retrieved', () => customer.reportingTicket().should.be.instanceof(ReportingTicket));
it('should allow routes to be searched', () => customer.routes().should.be.instanceof(RoutesContext));
it('should allow a route to be retrieved', () => customer.route().should.be.instanceof(Route));
Expand Down
60 changes: 60 additions & 0 deletions src/resources/RiderAppConfiguration.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
import Resource from './Resource';

/**
* Rider App Configuration resource
*/
class RiderAppConfiguration extends Resource {
/**
* Creates a new RiderAppConfiguration.
*
* @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,
});
}

/**
* Creates an href for a given customer code
*
* @param {string} customerCode Customer code
* @returns {{href: string}} URI to instance of Rider App Configuration
*/
static makeHref(customerCode) {
return {
href: `/1/${customerCode}/rider_app_configuration`,
code: customerCode,
};
}

/**
* Fetches the Rider App Configuration for this customer data via the client
* @returns {Promise} If successful,a hydrated instance of Rider App Configuration
*/
fetch() {
return this.client.get(this.href)
.then(response => response.json())
.then(config => new RiderAppConfiguration(this.client, this, config));
}

/**
* Updates the Rider App Configuration for this customer via the client
* @returns {Promise} If successful, returns the updated Rider App Configuration
*/
update() {
// eslint-disable-next-line no-unused-vars
const { client, hydrated, code, ...body } = this;
const { href } = RiderAppConfiguration.makeHref(code);
return this.client.put(href, { body })
.then(() => new RiderAppConfiguration(this.client, { ...this }));
}
}

export default RiderAppConfiguration;
63 changes: 63 additions & 0 deletions src/resources/RiderAppConfiguration.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
import chai from 'chai';
import chaiAsPromised from 'chai-as-promised';
import fetchMock from 'fetch-mock';
import Client from '../Client';
import RiderAppConfiguration from './RiderAppConfiguration';
import { riderAppConfiguration as mocks } from '../mocks';

chai.should();
chai.use(chaiAsPromised);

describe('When instantiating a Rider App Configuration based on customer', () => {
const client = new Client();
const config = new RiderAppConfiguration(client, RiderAppConfiguration.makeHref('SYNC'));

it('should set the href', () => config.href.should.equal('/1/SYNC/rider_app_configuration'));
it('should not be hydrated', () => config.hydrated.should.equal(false));
});

describe('When instantiating a Rider App Configuration based on an object', () => {
const client = new Client();
const config = new RiderAppConfiguration(client, mocks.rawObject);

it('should set the href', () => config.href.should.equal('/1/SYNC/rider_app_configuration'));
it('should set the splash image url', () => config.splash_image_url.should.equal('https://example.com/logo.png'));
it('should set the accent color', () => config.accent_color.should.equal('#ABCDEF'));
it('should be hydrated', () => config.hydrated.should.equal(true));
});

describe('When fetching a Rider App Configuration based on customer', () => {
const client = new Client();

beforeEach(() => mocks.setUpSuccessfulMock(client));
beforeEach(() => fetchMock.catch(503));
afterEach(fetchMock.restore);

let promise;
beforeEach(() => {
promise = new RiderAppConfiguration(client, RiderAppConfiguration.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/rider_app_configuration'));
it('should be hydrated', () => promise.then(v => v.hydrated).should.eventually.equal(true));
});

describe('When updating a Rider App Configuration for a customer', () => {
const client = new Client();

beforeEach(() => mocks.setUpSuccessfulMock(client));
beforeEach(() => fetchMock.catch(503));
afterEach(fetchMock.restore);

let promise;
beforeEach(() => {
const config = new RiderAppConfiguration(client, RiderAppConfiguration.makeHref('SYNC'));
config.splash_image_url = 'https://example.com/logo.png';
config.accent_color = '#ABCDEF';
promise = config.update();
});

it('should resolve the promise', () => promise.should.be.fulfilled);
it('should set the href', () => promise.then(v => v.href).should.eventually.equal('/1/SYNC/rider_app_configuration'));
});

0 comments on commit f4336d1

Please sign in to comment.