Implement better HalResource types configuration

pull/4548/head
Alex Dik 8 years ago
parent 4ba08a912f
commit 3eac74bcdc
  1. 16
      frontend/app/components/api/api-v3/hal-resource-types-storage/hal-resource-types-storage.service.ts
  2. 22
      frontend/app/components/api/api-v3/hal-resource-types/hal-resource-types.config.ts
  3. 111
      frontend/app/components/api/api-v3/hal-resource-types/hal-resource-types.service.test.ts
  4. 34
      frontend/app/components/api/api-v3/hal-resource-types/hal-resource-types.service.ts
  5. 5
      frontend/app/components/api/api-v3/hal-resources/hal-resource.service.test.ts

@ -34,21 +34,29 @@ export class HalResourceTypesStorageService {
private config:any = {};
public get defaultClass() {
return this.config.__default__;
return this.config.__default__.cls;
}
public set defaultClass(cls:typeof HalResource) {
this.addTypeConfig('__default__', cls);
this.setResourceType('__default__', cls);
}
public addTypeConfig(typeName:string, cls:typeof HalResource, attrCls = {}) {
public setResourceType(typeName:string, cls:typeof HalResource) {
cls._type = typeName;
this.config[typeName] = {
cls: cls,
attrCls: attrCls
attrCls: {}
};
}
public setResourceTypeAttributes(typeName:string, attrTypes) {
Object.keys(attrTypes).forEach(attrName => {
attrTypes[attrName] = this.getResourceClassOfType(attrTypes[attrName]);
});
this.config[typeName].attrCls = attrTypes;
}
public getResourceClassOfType(type:string) {
return this.getTypeConfig(type).cls;
}

@ -30,21 +30,17 @@ import {opApiModule} from '../../../../angular-modules';
import {HalResourceTypesService} from './hal-resource-types.service';
function halResourceTypesStorage(halResourceTypes:HalResourceTypesService) {
halResourceTypes
.addType('WorkPackage', {
halResourceTypes.setResourceTypeConfig({
WorkPackage: {
className: 'WorkPackageResource',
attr: {
parent: 'WorkPackageResource',
children: 'WorkPackageResource'
attrTypes: {
parent: 'WorkPackage',
children: 'WorkPackage'
}
})
.addType('Error', {
className: 'ErrorResource'
})
.addType('Collection', {
className: 'CollectionResource'
});
},
Error: 'ErrorResource',
Collection: 'CollectionResource'
});
}
opApiModule.run(halResourceTypesStorage);

@ -35,72 +35,105 @@ const expect = chai.expect;
describe('halResourceTypes service', () => {
var halResourceTypes:HalResourceTypesService;
var halResourceTypesStorage:HalResourceTypesStorageService;
var config:any;
var compareCls:typeof HalResource;
class HalResource {
}
class OtherResource {
}
class FooResource {
}
beforeEach(angular.mock.module(opApiModule.name, $provide => {
$provide.value('HalResource', HalResource);
$provide.value('OtherResource', OtherResource);
$provide.value('FooResource', FooResource);
}));
beforeEach(angular.mock.inject((_halResourceTypes_, _halResourceTypesStorage_) => {
[halResourceTypes, halResourceTypesStorage] = arguments;
}));
const expectResourceClassAdded = () => {
it('should add the respective class object to the storage', () => {
const cls = halResourceTypesStorage.getResourceClassOfType('Other');
expect(cls).to.equal(compareCls);
});
};
const expectAttributeClassAdded = () => {
it('should add the attribute type config to the storage', () => {
const cls = halResourceTypesStorage.getResourceClassOfAttribute('Other', 'attr');
expect(cls).to.equal(compareCls);
});
};
it('should exist', () => {
expect(halResourceTypes).to.exist;
});
it('should have added HalResource as the default type', () => {
expect(halResourceTypesStorage.defaultClass).to.equal(HalResource);
});
describe('when adding configuration', () => {
var chained;
var commonTests = () => {
it('should return itself', () => {
expect(chained).to.equal(halResourceTypes);
});
it('should add the attribute type config', () => {
const resource = halResourceTypesStorage
.getResourceClassOfAttribute('Other', 'someResource');
expect(resource).to.equal(OtherResource);
});
};
describe('when no class name is provided and attributes are configured', () => {
beforeEach(() => {
chained = halResourceTypes.addType('Other', {
attr: {
someResource: 'OtherResource'
describe('when configuring the type with class and attributes', () => {
beforeEach(() => {
compareCls = OtherResource;
config = {
Other: {
className: 'OtherResource',
attrTypes: {
attr: 'Other'
}
});
});
}
};
halResourceTypes.setResourceTypeConfig(config);
});
it('should add the respective class object', () => {
expect(halResourceTypesStorage.getResourceClassOfType('Other')).to.equal(HalResource);
});
expectResourceClassAdded();
expectAttributeClassAdded();
});
commonTests();
describe('when configuring the type with the class name as value', () => {
beforeEach(() => {
compareCls = OtherResource;
config = {
Other: 'OtherResource'
};
halResourceTypes.setResourceTypeConfig(config);
});
describe('when a class name is provided and attribute types are configured', () => {
beforeEach(() => {
chained = halResourceTypes.addType('Other', {
className: 'OtherResource',
attr: {
someResource: 'OtherResource'
}
});
});
expectResourceClassAdded();
});
it('should have the default type', () => {
expect(halResourceTypesStorage.getResourceClassOfType('Other')).to.equal(OtherResource);
});
describe('when configuring the type with only the attribute types', () => {
beforeEach(() => {
compareCls = halResourceTypesStorage.defaultClass;
config = {
Other: {
attr: 'Other'
}
};
halResourceTypes.setResourceTypeConfig(config);
});
expectResourceClassAdded();
expectAttributeClassAdded();
});
commonTests();
describe('when an attribute has a type, that defined later in the config', () => {
beforeEach(() => {
compareCls = FooResource;
config = {
Other: {
attr: 'Foo'
},
Foo: 'FooResource',
};
halResourceTypes.setResourceTypeConfig(config);
});
expectAttributeClassAdded();
});
});

@ -36,18 +36,36 @@ export class HalResourceTypesService {
halResourceTypesStorage.defaultClass = HalResource;
}
public addType(typeName:string, config = {}) {
var {className = 'HalResource', attr = {}} = config;
const attrCls = {};
public setResourceTypeConfig(config) {
const types = Object.keys(config).map(typeName => {
const value = config[typeName];
const result = {
typeName: typeName,
className: value.className || this.halResourceTypesStorage.defaultClass.name,
attrTypes: value.attrTypes || {}
};
Object.keys(attr).forEach(attrName => {
const className = attr[attrName];
attrCls[attrName] = this.$injector.get(className);
if (angular.isString(value)) {
result.className = value;
}
if (!value.className && angular.isObject(value)) {
result.attrTypes = value;
}
return result;
});
this.halResourceTypesStorage.addTypeConfig(typeName, this.$injector.get(className), attrCls);
types.forEach(typeConfig => {
this.halResourceTypesStorage
.setResourceType(typeConfig.typeName, this.$injector.get(typeConfig.className));
});
return this;
types
.map(typeConfig => [typeConfig.typeName, typeConfig.attrTypes])
.forEach(typeAttrConfig => {
this.halResourceTypesStorage.setResourceTypeAttributes(...typeAttrConfig);
});
}
}

@ -90,8 +90,9 @@ describe('HalResource service', () => {
}
};
halResourceTypesStorage.addTypeConfig('Other', OtherResource, {
someResource: OtherResource
halResourceTypesStorage.setResourceType('Other', OtherResource);
halResourceTypesStorage.setResourceTypeAttributes('Other', {
someResource: 'Other'
});
resource = HalResource.create(source);

Loading…
Cancel
Save