[Core] Complete spec for capailities

Complete specs for capabilities introduced in platform/core,
part of ongoing transition of this bundle. WTD-573.
This commit is contained in:
Victor Woeltjen 2014-11-21 16:59:03 -08:00
parent 2b82262775
commit 99f9203e71
7 changed files with 214 additions and 7 deletions

View File

@ -14,7 +14,7 @@
"provides": "capabilityService",
"type": "provider",
"implementation": "capabilities/CoreCapabilityProvider.js",
"depends": [ "capabilities[]" ]
"depends": [ "capabilities[]", "$log" ]
},
{
"provides": "modelService",
@ -131,7 +131,8 @@
},
{
"key": "delegation",
"implementation": "capabilities/DelegationCapability.js"
"implementation": "capabilities/DelegationCapability.js",
"depends": [ "$q" ]
}
],
"roots": [

View File

@ -18,7 +18,7 @@ define(
*
* @constructor
*/
function CoreCapabilityProvider(capabilities) {
function CoreCapabilityProvider(capabilities, $log) {
// Filter by invoking the capability's appliesTo method
function filterCapabilities(model) {
return capabilities.filter(function (capability) {
@ -32,7 +32,11 @@ define(
function packageCapabilities(capabilities) {
var result = {};
capabilities.forEach(function (capability) {
result[capability.key] = capability;
if (capability.key) {
result[capability.key] = capability;
} else {
$log.warn("No key defined for capability; skipping.");
}
});
return result;
}

View File

@ -1,4 +1,4 @@
/*global define,Promise*/
/*global define*/
/**
* Module defining DelegationCapability. Created by vwoeltje on 11/18/14.
@ -27,7 +27,7 @@ define(
* @param domainObject
* @constructor
*/
function DelegationCapability(domainObject) {
function DelegationCapability($q, domainObject) {
var delegateCapabilities = {},
type = domainObject.getCapability("type");
@ -52,7 +52,7 @@ define(
promiseChildren().then(
filterObjectsWithCapability(capability)
) :
[];
$q.when([]);
}
// Generate set for easy lookup of capability delegation

View File

@ -9,6 +9,62 @@ define(
"use strict";
describe("The core capability provider", function () {
var mockLog,
provider;
function BasicCapability() { return; }
BasicCapability.key = "basic";
function ApplicableCapability() { return; }
ApplicableCapability.key = "applicable";
ApplicableCapability.appliesTo = function (model) {
return !model.isNotApplicable;
};
function KeylessCapability() { return; }
beforeEach(function () {
mockLog = jasmine.createSpyObj(
"$log",
["error", "warn", "info", "debug"]
);
provider = new CoreCapabilityProvider([
BasicCapability,
ApplicableCapability,
KeylessCapability
], mockLog);
});
it("returns capabilities for models, from extensions", function () {
expect(provider.getCapabilities({})).toEqual({
basic: BasicCapability,
applicable: ApplicableCapability
});
});
it("filters out capabilities which do not apply to models", function () {
expect(provider.getCapabilities({ isNotApplicable: true })).toEqual({
basic: BasicCapability
});
});
it("logs a warning when capability extensions have not defined keys", function () {
// Verify precondition
expect(mockLog.warn).not.toHaveBeenCalled();
provider.getCapabilities({});
expect(mockLog.warn).toHaveBeenCalled();
});
it("does not log a warning when all capability extensions are valid", function () {
KeylessCapability.key = "someKey";
provider.getCapabilities({});
expect(mockLog.warn).not.toHaveBeenCalled();
});
});
}

View File

@ -9,7 +9,71 @@ define(
"use strict";
describe("The delegation capability", function () {
var captured,
typeDef = {},
type,
capabilities,
children = [],
object = {},
delegation;
function capture(k) { return function (v) { captured[k] = v; }; }
function TestDomainObject(caps, id) {
return {
getId: function () {
return id;
},
getCapability: function (name) {
return caps[name];
},
useCapability: function (name) {
return this.getCapability(name).invoke();
},
hasCapability: function (name) {
return this.getCapability(name) !== undefined;
}
};
}
function mockPromise(value) {
return {
then: function (callback) {
return value.then ?
value : mockPromise(callback(value));
}
};
}
beforeEach(function () {
captured = {};
typeDef = {};
typeDef.delegates = [ "foo" ];
type = { getDefinition: function () { return typeDef; } };
children = [];
capabilities = {
type: type,
composition: { invoke: function () { return mockPromise(children); } }
};
object = new TestDomainObject(capabilities);
delegation = new DelegationCapability({ when: mockPromise }, object);
});
it("provides a list of children which expose a desired capability", function () {
children = [
new TestDomainObject({ foo: true }, 'has-capability'),
new TestDomainObject({ }, 'does-not-have-capability')
];
// Look up delegates
delegation.getDelegates('foo').then(capture('delegates'));
// Expect only the first child to be a delegate
expect(captured.delegates.length).toEqual(1);
expect(captured.delegates[0].getId()).toEqual('has-capability');
});
});
}
);

View File

@ -9,7 +9,50 @@ define(
"use strict";
describe("The mutation capability", function () {
var testModel,
domainObject = { getModel: function () { return testModel; } },
mutation;
function mockPromise(value) {
return {
then: function (callback) {
return (value && value.then) ?
value : mockPromise(callback(value));
}
};
}
beforeEach(function () {
testModel = { number: 6 };
mutation = new MutationCapability(
{ when: mockPromise }, // $q
domainObject
);
});
it("allows mutation of a model", function () {
mutation.invoke(function (m) {
m.number = m.number * 7;
});
expect(testModel.number).toEqual(42);
});
it("allows setting a model", function () {
mutation.invoke(function (m) {
return { someKey: "some value" };
});
expect(testModel.number).toBeUndefined();
expect(testModel.someKey).toEqual("some value");
});
it("allows model mutation to be aborted", function () {
mutation.invoke(function (m) {
m.number = m.number * 7;
return false; // Should abort change
});
// Number should not have been changed
expect(testModel.number).toEqual(6);
});
});
}
);

View File

@ -9,6 +9,45 @@ define(
"use strict";
describe("The persistence capability", function () {
var mockPersistenceService,
mockDomainObject,
id = "object id",
model = { someKey: "some value"},
SPACE = "some space",
persistence;
beforeEach(function () {
mockPersistenceService = jasmine.createSpyObj(
"persistenceService",
[ "updateObject" ]
);
mockDomainObject = {
getId: function () { return id; },
getModel: function () { return model; }
};
persistence = new PersistenceCapability(
mockPersistenceService,
SPACE,
mockDomainObject
);
});
it("makes a call to the persistence service when invoked", function () {
// Verify precondition; no call made during constructor
expect(mockPersistenceService.updateObject).not.toHaveBeenCalled();
persistence.persist();
expect(mockPersistenceService.updateObject).toHaveBeenCalledWith(
SPACE,
id,
model
);
});
it("reports which persistence space an object belongs to", function () {
expect(persistence.getSpace()).toEqual(SPACE);
});
});
}