mirror of
https://github.com/nasa/openmct.git
synced 2025-06-06 01:11:41 +00:00
[Framework] Complete ServiceCompositor spec
WTD-518.
This commit is contained in:
parent
5d4f1f2008
commit
2dde62cb79
@ -28,7 +28,7 @@ define(
|
|||||||
" ",
|
" ",
|
||||||
extension.key,
|
extension.key,
|
||||||
" from bundle ",
|
" from bundle ",
|
||||||
extension.bundle.path,
|
(extension.bundle || { path: "unknown bundle" }).path,
|
||||||
"; skipping."
|
"; skipping."
|
||||||
].join(""));
|
].join(""));
|
||||||
}
|
}
|
||||||
@ -165,6 +165,11 @@ define(
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Register composite services in phases:
|
||||||
|
// * Register providers
|
||||||
|
// * Register aggregators (which use providers)
|
||||||
|
// * Register decorators (which use anything)
|
||||||
|
// Then, register the latest candidate as a plain service.
|
||||||
function registerComposites(providers, aggregators, decorators) {
|
function registerComposites(providers, aggregators, decorators) {
|
||||||
providers.forEach(registerProvider);
|
providers.forEach(registerProvider);
|
||||||
registerProviderSets();
|
registerProviderSets();
|
||||||
@ -173,6 +178,7 @@ define(
|
|||||||
registerLatest();
|
registerLatest();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Initial point of entry; just separate components by type
|
||||||
function registerCompositeServices(components) {
|
function registerCompositeServices(components) {
|
||||||
registerComposites(
|
registerComposites(
|
||||||
components.filter(hasType("provider")),
|
components.filter(hasType("provider")),
|
||||||
|
@ -1,14 +1,197 @@
|
|||||||
/*global define,Promise,describe,it,expect,beforeEach*/
|
/*global define,Promise,describe,it,expect,beforeEach,jasmine*/
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* ServiceCompositorSpec. Created by vwoeltje on 11/6/14.
|
* ServiceCompositorSpec. Created by vwoeltje on 11/6/14.
|
||||||
*/
|
*/
|
||||||
define(
|
define(
|
||||||
[],
|
["../../src/register/ServiceCompositor"],
|
||||||
function () {
|
function (ServiceCompositor) {
|
||||||
"use strict";
|
"use strict";
|
||||||
|
|
||||||
describe("", function () {
|
describe("The service compositor", function () {
|
||||||
|
var registered,
|
||||||
|
mockApp,
|
||||||
|
mockLog,
|
||||||
|
compositor;
|
||||||
|
|
||||||
|
|
||||||
|
beforeEach(function () {
|
||||||
|
registered = {};
|
||||||
|
|
||||||
|
mockApp = jasmine.createSpyObj("app", [ "service" ]);
|
||||||
|
mockLog = jasmine.createSpyObj("$log", [ "error", "warn", "info", "debug" ]);
|
||||||
|
|
||||||
|
mockApp.service.andCallFake(function (name, value) {
|
||||||
|
var factory = value[value.length - 1];
|
||||||
|
|
||||||
|
registered[name] = {
|
||||||
|
depends: value.slice(0, value.length - 1),
|
||||||
|
callback: value[value.length - 1]
|
||||||
|
};
|
||||||
|
|
||||||
|
// Track what name it was registered under
|
||||||
|
factory.registeredName = name;
|
||||||
|
});
|
||||||
|
|
||||||
|
compositor = new ServiceCompositor(mockApp, mockLog);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("allows composite services to be registered", function () {
|
||||||
|
compositor.registerCompositeServices([
|
||||||
|
{ type: "provider", provides: "testService" }
|
||||||
|
]);
|
||||||
|
|
||||||
|
expect(mockApp.service).toHaveBeenCalled();
|
||||||
|
});
|
||||||
|
|
||||||
|
it("allows composite services to be registered", function () {
|
||||||
|
// Prepare components that look like resolved extensions
|
||||||
|
var components, name;
|
||||||
|
function MyDecorator() { return {}; }
|
||||||
|
function MyOtherDecorator() { return {}; }
|
||||||
|
function MyProvider() { return {}; }
|
||||||
|
function MyOtherProvider() { return {}; }
|
||||||
|
function MyAggregator() { return {}; }
|
||||||
|
|
||||||
|
components = [
|
||||||
|
MyDecorator,
|
||||||
|
MyProvider,
|
||||||
|
MyAggregator,
|
||||||
|
MyOtherDecorator,
|
||||||
|
MyOtherProvider
|
||||||
|
];
|
||||||
|
|
||||||
|
MyDecorator.type = "decorator";
|
||||||
|
MyOtherDecorator.type = "decorator";
|
||||||
|
MyProvider.type = "provider";
|
||||||
|
MyOtherProvider.type = "provider";
|
||||||
|
MyAggregator.type = "aggregator";
|
||||||
|
components.forEach(function (c) { c.provides = "testService"; });
|
||||||
|
|
||||||
|
// Add some test dependencies, to check prepending
|
||||||
|
MyOtherDecorator.depends = [ "someOtherService" ];
|
||||||
|
MyAggregator.depends = [ "tests[]" ];
|
||||||
|
|
||||||
|
// Register!
|
||||||
|
compositor.registerCompositeServices(components);
|
||||||
|
|
||||||
|
expect(mockApp.service).toHaveBeenCalled();
|
||||||
|
|
||||||
|
// Verify some interesting spots on dependency graph
|
||||||
|
expect(registered.testService.depends).toEqual([
|
||||||
|
MyOtherDecorator.registeredName
|
||||||
|
]);
|
||||||
|
expect(registered[MyOtherDecorator.registeredName].depends).toEqual([
|
||||||
|
"someOtherService",
|
||||||
|
MyDecorator.registeredName
|
||||||
|
]);
|
||||||
|
expect(registered[MyAggregator.registeredName].depends.length).toEqual(2);
|
||||||
|
// Get the name of the group of providers
|
||||||
|
name = registered[MyAggregator.registeredName].depends[1];
|
||||||
|
// ...it should depend on both providers
|
||||||
|
expect(registered[name].depends).toEqual([
|
||||||
|
MyProvider.registeredName,
|
||||||
|
MyOtherProvider.registeredName
|
||||||
|
]);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("allows registered composite services to be instantiated", function () {
|
||||||
|
// Prepare components that look like resolved extensions
|
||||||
|
var components, name;
|
||||||
|
function MyProvider() { return {}; }
|
||||||
|
function MyOtherProvider() { return {}; }
|
||||||
|
function MyAggregator() { return {}; }
|
||||||
|
|
||||||
|
components = [ MyProvider, MyAggregator, MyOtherProvider ];
|
||||||
|
|
||||||
|
MyProvider.type = "provider";
|
||||||
|
MyOtherProvider.type = "provider";
|
||||||
|
MyAggregator.type = "aggregator";
|
||||||
|
components.forEach(function (c) { c.provides = "testService"; });
|
||||||
|
|
||||||
|
// Register!
|
||||||
|
compositor.registerCompositeServices(components);
|
||||||
|
|
||||||
|
expect(mockApp.service).toHaveBeenCalled();
|
||||||
|
|
||||||
|
// Test service should just be a reflecting dependency;
|
||||||
|
// it will depend upon (then return) the aggregator.
|
||||||
|
expect(registered.testService.callback("hello")).toEqual("hello");
|
||||||
|
|
||||||
|
// The aggregated provider dependencies should be similar,
|
||||||
|
// except they should reflect back the array of arguments.
|
||||||
|
// Get the name of the group of providers
|
||||||
|
name = registered[MyAggregator.registeredName].depends[0];
|
||||||
|
// ...it should depend on both providers
|
||||||
|
expect(registered[name].callback(1, 2, "hello")).toEqual([1, 2, "hello"]);
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
it("warns and skips components with no service type", function () {
|
||||||
|
// Prepare components that look like resolved extensions
|
||||||
|
var components;
|
||||||
|
function MyProvider() { return {}; }
|
||||||
|
function MyDecorator() { return {}; }
|
||||||
|
function MyAggregator() { return {}; }
|
||||||
|
|
||||||
|
components = [ MyProvider, MyAggregator, MyDecorator ];
|
||||||
|
|
||||||
|
MyProvider.type = "provider";
|
||||||
|
MyDecorator.type = "decorator";
|
||||||
|
MyAggregator.type = "aggregator";
|
||||||
|
|
||||||
|
// Notably, we don't do
|
||||||
|
// components.forEach(function (c) { c.provides = "testService"; });
|
||||||
|
|
||||||
|
// Try to register...
|
||||||
|
compositor.registerCompositeServices(components);
|
||||||
|
|
||||||
|
// Nothing should have gotten registered
|
||||||
|
expect(mockApp.service).not.toHaveBeenCalled();
|
||||||
|
|
||||||
|
// Should have gotten one warning for each skipped component
|
||||||
|
expect(mockLog.warn.calls.length).toEqual(3);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("warns about and skips aggregators with zero providers", function () {
|
||||||
|
// Prepare components that look like resolved extensions
|
||||||
|
var components;
|
||||||
|
function MyAggregator() { return {}; }
|
||||||
|
|
||||||
|
components = [ MyAggregator ];
|
||||||
|
|
||||||
|
MyAggregator.type = "aggregator";
|
||||||
|
MyAggregator.provides = "testService";
|
||||||
|
|
||||||
|
// Try to register...
|
||||||
|
compositor.registerCompositeServices(components);
|
||||||
|
|
||||||
|
// Nothing should have gotten registered
|
||||||
|
expect(mockApp.service).not.toHaveBeenCalled();
|
||||||
|
|
||||||
|
// Should have gotten a warning
|
||||||
|
expect(mockLog.warn).toHaveBeenCalled();
|
||||||
|
});
|
||||||
|
|
||||||
|
it("warns about and skips decorators with nothing to decorate", function () {
|
||||||
|
// Prepare components that look like resolved extensions
|
||||||
|
var components;
|
||||||
|
function MyDecorator() { return {}; }
|
||||||
|
|
||||||
|
components = [ MyDecorator ];
|
||||||
|
|
||||||
|
MyDecorator.type = "decorator";
|
||||||
|
MyDecorator.provides = "testService";
|
||||||
|
|
||||||
|
// Try to register...
|
||||||
|
compositor.registerCompositeServices(components);
|
||||||
|
|
||||||
|
// Nothing should have gotten registered
|
||||||
|
expect(mockApp.service).not.toHaveBeenCalled();
|
||||||
|
|
||||||
|
// Should have gotten a warning
|
||||||
|
expect(mockLog.warn).toHaveBeenCalled();
|
||||||
|
});
|
||||||
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user