export default function buildOwner(options = {}) { let ownerOptions = options.ownerOptions || {}; let resolver = options.resolver; let bootOptions = options.bootOptions || {}; let Owner = EmberObject.extend(RegistryProxyMixin, ContainerProxyMixin); let namespace = new EmberObject({ Resolver: new ResolverWrapper(resolver), }); let fallbackRegistry = Application.buildRegistry(namespace); fallbackRegistry.register('router:main', Router); let registry = new Registry({ fallback: fallbackRegistry, }); ApplicationInstance.setupRegistry(registry, bootOptions); let owner = Owner.create( { __registry__: registry, __container__: null, }, ownerOptions ); let container = registry.container({ owner }); owner.__container__ = container; return owner; }
QUnit.test('registry.has should not error for invalid fullNames)', function() { expect(1); var registry = new Registry(); ok(!registry.has('foo:bar:baz')); });
QUnit.test('`makeToString` will be handled by the resolver, then by the fallback registry, if available', function() { let fallback = { makeToString(fullName) { return `${fullName}-fallback`; } }; let resolver = { makeToString(fullName) { return `${fullName}-resolver`; } }; let registry = new Registry({ fallback, resolver }); equal(registry.makeToString('controller:post'), 'controller:post-resolver', '`makeToString` handled by the resolver first.'); registry.resolver = null; equal(registry.makeToString('controller:post'), 'controller:post-fallback', '`makeToString` handled by fallback registry next.'); registry.fallback = null; equal(registry.makeToString('controller:post'), 'controller:post', '`makeToString` by default returns argument.'); });
QUnit.test('The registered value returned from resolve is the same value each time even if the value is falsy', function() { let registry = new Registry(); registry.register('falsy:value', null, { instantiate: false }); strictEqual(registry.resolve('falsy:value'), registry.resolve('falsy:value'), 'The return of resolve is always the same'); });
QUnit.test('resolver.expandLocalLookup cache is busted when any unregister is called', function(assert) { assert.expect(4); let result; let resolver = { expandLocalLookup(targetFullName, sourceFullName) { assert.ok(true, 'expandLocalLookup is called on the resolver'); return 'foo:qux/bar'; } }; var registry = new Registry({ resolver }); result = registry.expandLocalLookup('foo:bar', { source: 'baz:qux' }); assert.equal(result, 'foo:qux/bar'); registry.unregister('foo:bar'); result = registry.expandLocalLookup('foo:bar', { source: 'baz:qux' }); assert.equal(result, 'foo:qux/bar'); });
test("The registered factory returned from resolve is the same factory each time", function() { var registry = new Registry(); var PostController = factory(); registry.register('controller:post', PostController); deepEqual(registry.resolve('controller:post'), registry.resolve('controller:post'), 'The return of resolve is always the same'); });
test("A registered factory returns true for `has` if an item is registered", function() { var registry = new Registry(); var PostController = factory(); registry.register('controller:post', PostController); equal(registry.has('controller:post'), true, "The `has` method returned true for registered factories"); equal(registry.has('controller:posts'), false, "The `has` method returned false for unregistered factories"); });
QUnit.test('Throw exception when trying to inject `type:thing` on all type(s)', function() { var registry = new Registry(); var PostController = factory(); registry.register('controller:post', PostController); throws(function() { registry.typeInjection('controller', 'injected', 'controller:post'); }, /Cannot inject a `controller:post` on other controller\(s\)\./); });
QUnit.test('`getFactoryInjections` includes factory injections from a fallback registry', function() { var fallback = new Registry(); var registry = new Registry({ fallback: fallback }); equal(registry.getFactoryInjections('model:user').length, 0, 'No factory injections in the primary registry'); fallback.factoryInjection('model:user', 'store', 'store:main'); equal(registry.getFactoryInjections('model:user').length, 1, 'Factory injections from the fallback registry are merged'); });
test("`getInjections` includes injections from a fallback registry", function() { var fallback = new Registry(); var registry = new Registry({ fallback: fallback }); equal(registry.getInjections('model:user').length, 0, "No injections in the primary registry"); fallback.injection('model:user', 'post', 'model:post'); equal(registry.getInjections('model:user').length, 1, "Injections from the fallback registry are merged"); });
test("`has` can be handled by a fallback registry", function() { var fallback = new Registry(); var registry = new Registry({ fallback: fallback }); var PostController = factory(); fallback.register('controller:post', PostController); equal(registry.has('controller:post'), true, "Fallback registry is checked for registration"); });
QUnit.test("`getTypeInjections` includes type injections from a fallback registry", function() { var fallback = new Registry(); var registry = new Registry({ fallback: fallback }); equal(registry.getTypeInjections('model').length, 0, "No injections in the primary registry"); fallback.injection('model', 'source', 'source:main'); equal(registry.getTypeInjections('model').length, 1, "Injections from the fallback registry are merged"); });
test("can re-register a factory", function(){ var registry = new Registry(); var FirstApple = factory('first'); var SecondApple = factory('second'); registry.register('controller:apple', FirstApple); registry.register('controller:apple', SecondApple); ok(registry.resolve('controller:apple').create() instanceof SecondApple); });
QUnit.test('registry.container creates a container', function() { var registry = new Registry(); var PostController = factory(); registry.register('controller:post', PostController); var container = registry.container(); var postController = container.lookup('controller:post'); ok(postController instanceof PostController, 'The lookup is an instance of the registered factory'); });
test("Throw exception when trying to inject `type:thing` on all type(s)", function(){ var registry = new Registry(); var PostController = factory(); registry.register('controller:post', PostController); throws(function(){ registry.typeInjection('controller', 'injected', 'controller:post'); }, 'Cannot inject a `controller:post` on other controller(s). Register the `controller:post` as a different type and perform the typeInjection.'); });
test("`getFactoryTypeInjections` includes factory type injections from a fallback registry", function() { var fallback = new Registry(); var registry = new Registry({ fallback: fallback }); equal(registry.getFactoryTypeInjections('model').length, 0, "No factory type injections in the primary registry"); fallback.factoryInjection('model', 'store', 'store:main'); equal(registry.getFactoryTypeInjections('model').length, 1, "Factory type injections from the fallback registry are merged"); });
test ("registry.container creates an associated container", function() { var registry = new Registry(); var PostController = factory(); registry.register('controller:post', PostController); var container = registry.container(); var postController = container.lookup('controller:post'); ok(postController instanceof PostController, "The lookup is an instance of the registered factory"); strictEqual(registry._defaultContainer, container, "_defaultContainer is set to the first created container and used for Ember 1.x Container compatibility"); });
test("A registered factory is returned from resolve", function() { var registry = new Registry(); var PostController = factory(); registry.register('controller:post', PostController); var PostControllerFactory = registry.resolve('controller:post'); ok(PostControllerFactory, 'factory is returned'); ok(PostControllerFactory.create() instanceof PostController, "The return of factory.create is an instance of PostController"); });
QUnit.test('`expandLocalLookup` is handled by the resolver, then by the fallback registry, if available', function(assert) { assert.expect(9); let fallbackResolver = { expandLocalLookup(targetFullName, sourceFullName) { assert.ok(true, 'expandLocalLookup is called on the fallback resolver'); assert.equal(targetFullName, 'foo:bar', 'the targetFullName was passed through'); assert.equal(sourceFullName, 'baz:qux', 'the sourceFullName was passed through'); return 'foo:qux/bar-fallback'; } }; let resolver = { expandLocalLookup(targetFullName, sourceFullName) { assert.ok(true, 'expandLocalLookup is called on the resolver'); assert.equal(targetFullName, 'foo:bar', 'the targetFullName was passed through'); assert.equal(sourceFullName, 'baz:qux', 'the sourceFullName was passed through'); return 'foo:qux/bar-resolver'; } }; let fallbackRegistry = new Registry({ resolver: fallbackResolver }); let registry = new Registry({ fallback: fallbackRegistry, resolver }); let result = registry.expandLocalLookup('foo:bar', { source: 'baz:qux' }); assert.equal(result, 'foo:qux/bar-resolver', 'handled by the resolver'); registry.resolver = null; result = registry.expandLocalLookup('foo:bar', { source: 'baz:qux' }); assert.equal(result, 'foo:qux/bar-fallback', 'handled by the fallback registry'); registry.fallback = null; result = registry.expandLocalLookup('foo:bar', { source: 'baz:qux' }); assert.equal(result, null, 'null is returned by default when no resolver or fallback registry is present'); });
test("The registry respect the resolver hook for `has`", function() { var registry = new Registry(); var PostController = factory(); registry.resolver = function(fullName) { if (fullName === 'controller:post') { return PostController; } }; ok(registry.has('controller:post'), "the `has` method uses the resolver hook"); });
test("The registry can take a hook to resolve factories lazily", function() { var registry = new Registry(); var PostController = factory(); registry.resolver = function(fullName) { if (fullName === 'controller:post') { return PostController; } }; strictEqual(registry.resolve('controller:post'), PostController, "The correct factory was provided"); });
QUnit.test('The value returned from resolver is the same value as the original value even if the value is falsy', function() { let resolver = { resolve(fullName) { if (fullName === 'falsy:value') { return null; } } }; let registry = new Registry({ resolver }); strictEqual(registry.resolve('falsy:value'), null); });
QUnit.test('The registry can take a hook to resolve factories lazily', function() { let PostController = factory(); let resolver = { resolve(fullName) { if (fullName === 'controller:post') { return PostController; } } }; let registry = new Registry({ resolver }); strictEqual(registry.resolve('controller:post'), PostController, 'The correct factory was provided'); });
test("The registry normalizes names when resolving", function() { var registry = new Registry(); var PostController = factory(); registry.normalizeFullName = function(fullName) { return 'controller:post'; }; registry.register('controller:post', PostController); var type = registry.resolve('controller:normalized'); strictEqual(type, PostController, "Normalizes the name when resolving"); });
QUnit.test('`knownForType` contains keys for each item of a given type', function() { let registry = new Registry(); registry.register('foo:bar-baz', 'baz'); registry.register('foo:qux-fez', 'fez'); let found = registry.knownForType('foo'); deepEqual(found, { 'foo:bar-baz': true, 'foo:qux-fez': true }); });
QUnit.test('resolver.expandLocalLookup is not required', function(assert) { assert.expect(1); var registry = new Registry({ resolver: { } }); let result = registry.expandLocalLookup('foo:bar', { source: 'baz:qux' }); assert.equal(result, null); });
QUnit.test('The registry respects the resolver hook for `has`', function() { let PostController = factory(); let resolver = { resolve(fullName) { if (fullName === 'controller:post') { return PostController; } } }; let registry = new Registry({ resolver }); ok(registry.has('controller:post'), 'the `has` method uses the resolver hook'); });
test("validateFullName throws an error if name is incorrect", function() { var registry = new Registry(); var PostController = factory(); registry.normalize = function(fullName) { return 'controller:post'; }; registry.register('controller:post', PostController); throws(function() { registry.resolve('post'); }, 'TypeError: Invalid Fullname, expected: `type:name` got: post'); });
test("The registry normalizes names when checking if the factory is registered", function() { var registry = new Registry(); var PostController = factory(); registry.normalizeFullName = function(fullName) { return 'controller:post'; }; registry.register('controller:post', PostController); var isPresent = registry.has('controller:normalized'); equal(isPresent, true, "Normalizes the name when checking if the factory or instance is present"); });
test("`resolve` can be handled by a fallback registry", function() { var fallback = new Registry(); var registry = new Registry({ fallback: fallback }); var PostController = factory(); fallback.register('controller:post', PostController); var PostControllerFactory = registry.resolve('controller:post'); ok(PostControllerFactory, 'factory is returned'); ok(PostControllerFactory.create() instanceof PostController, "The return of factory.create is an instance of PostController"); });