Skip to content

Commit

Permalink
feat(voip): Add user filters for call state. (#62)
Browse files Browse the repository at this point in the history
Allows API consumers to retrieve notifications of updated call state restricted
by a set of vehicles, users, or both.  Restrictions are independent of one
another, so specifying a users filter still returns all vehicles and vice
versa.

Feature added to support VOIP scenarios where the same user is accessing VOIP
features from different browser windows or computers.

Signed-off-by: Jeff Cuevas-Koch <[email protected]>
  • Loading branch information
cuevaskoch authored Aug 20, 2019
1 parent d1b9d96 commit fbda1c4
Show file tree
Hide file tree
Showing 3 changed files with 71 additions and 5 deletions.
18 changes: 15 additions & 3 deletions src/examples/subscribe_call_states.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ describe('When subscribing to call states', () => {
afterEach(fetchMock.restore);
after(() => server.close());

it('should get updated call states for a single vehicle', () => {
it('should get updated call states for a single vehicle and all users', () => {
const vehicleHref = '1/SYNC/vehicles/123';

api.logIn({ username: '[email protected]', password: 'securepassword' });
Expand All @@ -33,19 +33,31 @@ describe('When subscribing to call states', () => {
.on('update', callState => callState); // do things with callState
});

it('should get updated call states for multiple vehicles', () => {
it('should get updated call states for multiple vehicles and a single user', () => {
const vehicles = [
{ href: '1/SYNC/vehicles/123' },
{ href: '1/SYNC/vehicles/456' },
{ href: '1/SYNC/vehicles/789' },
];

const user = { href: '1/SYNC/users/1' };

api.logIn({ username: '[email protected]', password: 'securepassword' });
return api.customer('SYNC')
.realTime()
.callStates()
.forVehicles(vehicles)
.forUser(user)
.on('update', callState => callState); // do things with callState
});

it('should get updated call states for all vehicles and a single user', () => {
const user = { href: '1/SYNC/users/1' };

api.logIn({ username: '[email protected]', password: 'securepassword' });
return api.customer('SYNC')
.realTime()
.callStates()
.forUser(user)
.on('update', callState => callState); // do things with callState
})
});
25 changes: 25 additions & 0 deletions src/resources/CallStatesRealTimeContext.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,11 +14,13 @@ class CallStatesRealTimeContext extends RealTimeContext {
super(realTimeClient, entityName, customerCode);
this.filters = {
vehicles: [],
users: [],
};
}

/**
* Restrict subscriptions created by this context to a single vehicle.
* Vehicle restrictions are independent of user subscriptions.
* @param {Resource|string} vehicle Href or resource representation of a Vehicle.
* @returns {CallStatesRealTimeContext} Context with filter applied.
*/
Expand All @@ -28,6 +30,7 @@ class CallStatesRealTimeContext extends RealTimeContext {

/**
* Restrict subscriptions created by this context to a set of vehicles.
* Vehicle restrictions are independent of user subscriptions.
* @param {Array.<Resource|string>} vehicles Array of href or resource representations of
* Vehicles.
* @returns {CallStatesRealTimeContext} Context with filter applied.
Expand All @@ -37,6 +40,28 @@ class CallStatesRealTimeContext extends RealTimeContext {
this.filters.vehicles = vehicles.map(RealTimeContext.resolveHref);
return this;
}

/**
* Restrict subscriptions created by this context to a single user.
* User restrictions are independent of vehicle subscriptions.
* @param {Resource|string} user Href or resource representation of a Vehicle.
* @returns {CallStatesRealTimeContext} Context with filter applied.
*/
forUser(user) {
return this.forUsers([user]);
}

/**
* Restrict subscriptions created by this context to a set of users.
* User restrictions are independent of vehicle subscriptions.
* @param {Array.<Resource|string>} users Array of href or resource representations of Users.
* @returns {CallStatesRealTimeContext} Context with filter applied.
*/
forUsers(users) {
this.assertSubscriptionNotStarted();
this.filters.users = users.map(RealTimeContext.resolveHref);
return this;
}
}

export default CallStatesRealTimeContext;
33 changes: 31 additions & 2 deletions src/resources/CallStatesRealTimeContext.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ describe('When creating a subscription for Call States', () => {
const subject = new CallStatesRealTimeContext(realTimeClient, customerCode);

const vehicleHref = '123';
const expectedFilters = { vehicles: [vehicleHref] };
const expectedFilters = { vehicles: [vehicleHref], users: [] };
subject.forVehicle(vehicleHref).on('update', () => { });

const options = { closeConnection: true, realTimeClient };
Expand All @@ -31,7 +31,7 @@ describe('When creating a subscription for Call States', () => {
const subject = new CallStatesRealTimeContext(realTimeClient, customerCode);

const vehicleHrefs = ['123', '456', '489'];
const expectedFilters = { vehicles: vehicleHrefs };
const expectedFilters = { vehicles: vehicleHrefs, users: [] };

subject.forVehicles(vehicleHrefs).on('update', () => { });

Expand All @@ -40,6 +40,35 @@ describe('When creating a subscription for Call States', () => {
.should.eventually.become(expectedFilters);
});

it('can add filters for a single user', () => {
const server = mock.getServer();
const realTimeClient = new RealTimeClient(mock.authenticatedClient, mock.options);
const subject = new CallStatesRealTimeContext(realTimeClient, customerCode);

const userHref = '123';
const expectedFilters = { users: [userHref], vehicles: [] };
subject.forUser(userHref).on('update', () => { });

const options = { closeConnection: true, realTimeClient };
return server.verifySubscription(entity, options)
.should.eventually.become(expectedFilters);
});

it('can add filters for multiple users', () => {
const server = mock.getServer();
const realTimeClient = new RealTimeClient(mock.authenticatedClient, mock.options);
const subject = new CallStatesRealTimeContext(realTimeClient, customerCode);

const userHrefs = ['123', '456', '489'];
const expectedFilters = { users: userHrefs, vehicles: [] };

subject.forUsers(userHrefs).on('update', () => { });

const options = { closeConnection: true, realTimeClient };
return server.verifySubscription(entity, options)
.should.eventually.become(expectedFilters);
});

it('should handle entity updates', () => {
const server = mock.getServer();
const realTimeClient = new RealTimeClient(mock.authenticatedClient, mock.options);
Expand Down

0 comments on commit fbda1c4

Please sign in to comment.