Skip to content

Commit

Permalink
feat: CMS-2555 group resource
Browse files Browse the repository at this point in the history
  • Loading branch information
simon-scherzinger committed Feb 13, 2017
1 parent bd5b9a7 commit 6d43a25
Show file tree
Hide file tree
Showing 10 changed files with 486 additions and 1 deletion.
45 changes: 44 additions & 1 deletion src/Accounts.js
Expand Up @@ -14,6 +14,8 @@ import ClientList from './resources/ClientList';
import ClientResource from './resources/ClientResource';
import InvalidPermissionsResource from './resources/InvalidPermissionsResource';
import InvitesResource from './resources/InvitesResource';
import GroupList from './resources/GroupList';
import GroupResource from './resources/GroupResource';
import TokenStoreFactory from './TokenStore';

const urls = {
Expand Down Expand Up @@ -376,7 +378,7 @@ export default class Accounts extends Core {
return Promise.resolve()
.then(() => {
if (!clientID) {
throw new Error('accountID must be defined');
throw new Error('clientID must be defined');
}
const request = this.newRequest()
.follow('ec:acc/clients/options')
Expand All @@ -399,4 +401,45 @@ export default class Accounts extends Core {
.then(([resource, traversal]) =>
new InvalidPermissionsResource(resource, this.environment, traversal));
}

/**
* Load the {@link GroupList}
*
* @param {filterOptions?} options filter options
* @returns {Promise<GroupList>} Promise resolving goup list
*/
groupList(options) {
return Promise.resolve()
.then(() => {
if (options && Object.keys(options).length === 1 && 'groupID' in options) {
throw new Error('Providing only an groupID in GroupList filter will result in single resource response. Please use Accounts#groupList');
}

const request = this.newRequest()
.follow('ec:acc/groups/options')
.withTemplateParameters(optionsToQuery(options));
return get(this.environment, request);
})
.then(([res, traversal]) => new GroupList(res, this.environment, traversal));
}

/**
* Load a single group
*
* @param {string} groupID the id of the group
* @returns {Promise<GroupResource>} Promise resolving to the group
*/
group(groupID) {
return Promise.resolve()
.then(() => {
if (!groupID) {
throw new Error('groupID must be defined');
}
const request = this.newRequest()
.follow('ec:acc/clients/options')
.withTemplateParameters({ groupid: groupID });
return get(this.environment, request);
})
.then(([res, traversal]) => new GroupResource(res, this.environment, traversal));
}
}
22 changes: 22 additions & 0 deletions src/resources/GroupList.js
@@ -0,0 +1,22 @@
import ListResource from './ListResource';
import GroupResource from './GroupResource';

/**
* GroupList list class
*
* @class
*/
export default class GroupList extends ListResource {
/**
* Creates a new {@link GroupList}.
*
* @param {object} resource resource loaded from the API.
* @param {string} environment the environment this resource is associated to.
* @param {?object} traversal traversal from which traverson can continue.
*/
constructor(resource, environment, traversal) {
super(resource, environment, 'ec:acc/groups', traversal);
this.ListClass = GroupList;
this.ItemClass = GroupResource;
}
}
79 changes: 79 additions & 0 deletions src/resources/GroupResource.js
@@ -0,0 +1,79 @@
import Resource from './Resource';

/**
* GroupResource class
*
* @class
*/
export default class GroupResource extends Resource {
/**
* Will return groupID property.
*
* @returns {string} the groupID.
*/
getGroupID() {
return this.getProperty('groupID');
}

/**
* Will return name property.
*
* @returns {string} the name.
*/
getName() {
return this.getProperty('name');
}

/**
* Set a new value to name property.
*
* @param {string} value the value to assign.
* @returns {GroupResource} this Resource for chainability
*/
setName(value) {
if (!value) {
throw new Error('name must be defined');
}

return this.setProperty('name', value);
}

/**
* Will return permissions property.
*
* @returns {array<string>} the config.
*/
getPermissions() {
return this.getProperty('permissions');
}

/**
* Set a new value to permissions property.
*
* @param {array<string>} value the value to assign.
* @returns {GroupResource} this Resource for chainability
*/
setPermissions(value) {
if (!value) {
throw new Error('permissions must be defined');
}

return this.setProperty('permissions', value);
}

/**
* Adds a new permission to permissions array.
*
* @param {string} value the permission to add.
* @returns {AccountResource} this Resource for chainability
*/
addPermission(value) {
if (!value) {
throw new Error('permission must be defined');
}

const current = this.getPermissions();
current.push(value);
return this.setPermissions(current);
}
}
38 changes: 38 additions & 0 deletions test/Account.test.js
Expand Up @@ -13,6 +13,8 @@ const AccountList = require('../lib/resources/AccountList').default;
const AccountResource = require('../lib/resources/AccountResource').default;
const ClientList = require('../lib/resources/ClientList').default;
const ClientResource = require('../lib/resources/ClientResource').default;
const GroupList = require('../lib/resources/GroupList').default;
const GroupResource = require('../lib/resources/GroupResource').default;
const InvitesResource = require('../lib/resources/InvitesResource').default;
const InvalidPermissionsResource = require('../lib/resources/InvalidPermissionsResource').default;
const Resource = require('../lib/resources/Resource').default;
Expand Down Expand Up @@ -347,6 +349,42 @@ describe('Accounts class', () => {
throw err;
});
});
it('should return list on clientList', () => {
const accounts = new Accounts('live');
const stub = sinon.stub(helper, 'get');
stub.returns(resolver('group-list.json'));

return accounts.groupList()
.then((list) => {
list.should.be.instanceof(GroupList);
stub.restore();
})
.catch((err) => {
stub.restore();
throw err;
});
});
it('should be rejected on clientList only with clientID', () => {
return new Accounts().groupList({ groupID: 'id' }).should.be.rejectedWith(Error);
});
it('should return resource on group', () => {
const accounts = new Accounts('live');
const stub = sinon.stub(helper, 'get');
stub.returns(resolver('group-list.json'));

return accounts.group('aID')
.then((resource) => {
resource.should.be.instanceof(GroupResource);
stub.restore();
})
.catch((err) => {
stub.restore();
throw err;
});
});
it('should be rejected on group with undefiend id', () => {
return new Accounts().group().should.be.rejectedWith(Error);
});
});

describe('Account ListResource', () => {
Expand Down
119 changes: 119 additions & 0 deletions test/GroupResource.test.js
@@ -0,0 +1,119 @@
/* eslint no-unused-expressions:0 */

const chai = require('chai');
const sinon = require('sinon');
const sinonChai = require('sinon-chai');
const fs = require('fs');

const GroupResource = require('../lib/resources/GroupResource').default;
const GroupList = require('../lib/resources/GroupList').default;
const Resource = require('../lib/resources/Resource').default;
const ListResource = require('../lib/resources/ListResource').default;

const should = chai.should();
chai.use(sinonChai);

function capitalizeFirstLetter(string) {
return string.charAt(0).toUpperCase() + string.slice(1);
}

describe('Group ListResource', () => {
let listJson;
let list;
before(() => {
return new Promise((resolve, reject) => {
fs.readFile(`${__dirname}/mocks/group-list.json`, 'utf-8', (err, res) => {
if (err) {
return reject(err);
}
return resolve(JSON.parse(res));
});
})
.then((json) => {
listJson = json;
});
});
beforeEach(() => {
list = new GroupList(listJson);
});
afterEach(() => {
list = null;
});
it('should be instance of ListResource', () => {
list.should.be.instanceOf(ListResource);
});
it('should be instance of GroupList', () => {
list.should.be.instanceOf(GroupList);
});
it('should have TokenResource items', () => {
list.getAllItems().forEach(item => item.should.be.instanceOf(GroupResource));
});
});

describe('Group Resource', () => {
let resourceJson;
let resource;
before(() => {
return new Promise((resolve, reject) => {
fs.readFile(`${__dirname}/mocks/group-single.json`, 'utf-8', (err, res) => {
if (err) {
return reject(err);
}
return resolve(JSON.parse(res));
});
})
.then((json) => {
resourceJson = json;
});
});
beforeEach(() => {
resource = new GroupResource(resourceJson);
});
afterEach(() => {
resource = null;
});
it('should be instance of Resource', () => {
resource.should.be.instanceOf(Resource);
});
it('should be instance of GroupResource', () => {
resource.should.be.instanceOf(GroupResource);
});
it('should add single permission', () => {
resource.getPermissions().should.have.property('length', 2);
resource.addPermission('acc:something');
resource.getPermissions().should.have.property('length', 3);
});

const getter = [
'groupID', 'name', 'permissions',
];
getter.forEach((name) => {
it(`should call resource.getProperty with ${name}`, () => {
const spy = sinon.spy(resource, 'getProperty');

const property = resource[`get${capitalizeFirstLetter(name)}`]();
spy.should.have.been.called.once;
spy.should.have.been.calledWith(name);
property.should.be.equal(resource.getProperty(name));

spy.restore();
});
});

const setter = ['name', 'permissions'];
setter.forEach((name) => {
it(`should call resource.setProperty with ${name}`, () => {
const spy = sinon.spy(resource, 'setProperty');

resource[`set${capitalizeFirstLetter(name)}`](resource.getProperty(name));
spy.should.have.been.called.once;
spy.should.have.been.calledWith(name, resource.getProperty(name));

spy.restore();
});
it(`should throw on set${capitalizeFirstLetter(name)} with undefined value`, () => {
const throws = () => resource[`set${capitalizeFirstLetter(name)}`]();
throws.should.throw(Error);
});
});
});

0 comments on commit 6d43a25

Please sign in to comment.