connect-platform
Version:
A platform to build backened code mostly in a visual manner.
302 lines (226 loc) • 9.49 kB
JavaScript
const assert = require('assert');
const base = require('../base');
const registry = require('../registry');
const { UnregisteredPath } = require('../errors');
const chai = require('chai');
const sinon = require('sinon');
const hash = require('../../util/hash');
describe('registry', () => {
describe('.register()', () => {
it('should register a node class or factory with given path.', () => {
registry.register({path: 'X'}, base.node.Node);
registry.register({path: 'Y'}, () => new base.node.Node());
assert(registry.registered('X'));
assert(registry.registered('Y'));
});
it('should register a node class or factory with given path and method.', () => {
registry.register({path: 'X', method: 'GET'}, base.node.Node);
registry.register({path: 'Y', method: 'POST'}, () => new base.node.Node());
assert(registry.registered('X'));
assert(registry.registered('Y'));
});
it('should override with subsequent registration.', () => {
class A extends base.node.Node{};
class B extends base.node.Node{};
registry.register({path: 'X'}, A);
assert(registry.instance('X') instanceof A);
registry.register({path: 'X'}, B);
assert(registry.instance('X') instanceof B);
});
it('should override with subsequent registration with method.', () => {
class C extends base.node.Node{};
class D extends base.node.Node{};
const signatureGet = {path: 'X', public: true, method: 'get'};
const sigHash = hash.hashSig(signatureGet);
registry.register(signatureGet, C);
assert(registry.instance('X', sigHash) instanceof C);
registry.register(signatureGet, D);
assert(registry.instance('X', sigHash) instanceof D);
});
it('should override with subsequent registration with key.', () => {
const TEST_KEY = 'test_key';
class C extends base.node.Node{};
class D extends base.node.Node{};
registry.register({path: 'X', key: TEST_KEY}, C);
assert(registry.instance('X', TEST_KEY) instanceof C);
registry.register({path: 'X', key: TEST_KEY}, D);
assert(registry.instance('X', TEST_KEY) instanceof D);
});
it('should not override with subsequent registration with a unique key.', () => {
const TEST_KEY = 'test_key';
const TEST_KEY2 = 'test_key2';
class C extends base.node.Node{};
class D extends base.node.Node{};
registry.register({path: 'X', key: TEST_KEY}, C);
assert(registry.instance('X', TEST_KEY) instanceof C);
registry.register({path: 'X', key: TEST_KEY2}, D);
assert(registry.instance('X', TEST_KEY2) instanceof D);
});
it('should register a node class or factory with the root path.', () => {
registry.register({path: '/'}, base.node.Node);
assert(registry.registered(''));
assert(registry.registered('/'));
});
});
describe('.instance()', () => {
it('should return an instance of a registered class or factory.', () => {
class A extends base.node.Node{};
class B extends base.node.Node{};
registry.register({path: 'X'}, A);
registry.register({path: 'Y'}, () => new B());
assert(registry.instance('X') instanceof A);
assert(registry.instance('Y') instanceof B);
});
it('should return an instance of a registered class on the root endpoint.', () => {
class A extends base.node.Node{};
registry.register({path: '/'}, A);
assert(registry.instance('/') instanceof A);
assert(registry.instance('') instanceof A);
});
it('should throw proper error when given path is not registered.', () => {
assert.throws(() => {
registry.instance('XX/123456');
}, UnregisteredPath);
});
});
describe('.signature()', () => {
it('should return the signature of a registered node class or factory.', ()=> {
registry.register({path: 'X', inputs: ['a']}, base.node.Node);
assert.equal(registry.signature('X').inputs[0], 'a');
});
it('should return the signature of a registered node class or factory with method.', ()=> {
const sig = {path: 'X', inputs: ['a'], public: true, method: 'post'};
registry.register(sig, base.node.Node);
assert.equal(registry.signature('X', hash.hashSig(sig)).inputs[0], 'a');
});
it('should throw proper error when given path is not registered.', () => {
assert.throws(() => {
registry.signature('XX/123456');
}, UnregisteredPath);
});
});
describe('.alias()', () => {
it('should make an alias for a given path.', () => {
class A extends base.node.Node{};
registry.register({path: 'X'}, A);
assert.throws(() => {
registry.instance('X-alias');
}, UnregisteredPath);
registry.alias('X-alias', 'X');
assert(registry.instance('X-alias') instanceof A);
});
it('should be able to resolve chain alaising as well.', () => {
registry.alias('XZZ', 'WZZ');
registry.alias('WZZ', 'ZZZ');
class D extends base.node.Node{};
registry.register({path: 'ZZZ'}, D);
assert(registry.instance('WZZ') instanceof D);
});
});
describe('mocking:', () => {
class Original extends base.node.Node{};
class Mocked extends base.node.Node{};
registry.register({path: '/RTest/mock-test-path'}, Original);
describe('.mock()', () => {
it('should replace a mock object for given path.', () => {
registry.mock('/RTest/mock-test-path', Mocked);
assert(registry.instance('/RTest/mock-test-path') instanceof Mocked);
});
});
describe('.mocked()', () => {
it('should verify that a specific path is mocked.', () => {
assert(!registry.mocked('/RTest/mock-test-path-2'));
assert(registry.mocked('/RTest/mock-test-path'));
});
});
describe('.unmock()', () => {
it('should remove the mock and return to normal behavior.', () => {
registry.unmock('/RTest/mock-test-path');
assert(!registry.mocked('/RTest/mock-test-path'));
assert(registry.instance('/RTest/mock-test-path') instanceof Original);
});
});
});
describe('.registrants', () => {
it('should make an alias for a given path.', () => {
const TEST_KEY1 = 'test_key1';
const TEST_KEY2 = 'test_key2';
const TEST_KEY3 = 'test_key3';
class A extends base.node.Node{};
class B extends base.node.Node{};
class C extends base.node.Node{};
const signatureA = {path: 'Multi', method: 'get', public: true, key: TEST_KEY1 };
const signatureB = {path: 'Multi', method: 'post', public: true, key: TEST_KEY2 };
const signatureC = {path: 'Multi', method: 'get', socket: true, key: TEST_KEY3 };
registry.register(signatureA, A);
registry.register(signatureB, B);
registry.register(signatureC, C);
registry.registrants.should.have.property('Multi');
registry.registrants['Multi'].should.have.property(TEST_KEY1);
registry.registrants['Multi'].should.have.property(TEST_KEY2);
registry.registrants['Multi'].should.have.property(TEST_KEY3);
registry.registrants['Multi'][TEST_KEY1].signature.should.eql(signatureA);
registry.registrants['Multi'][TEST_KEY2].signature.should.eql(signatureB);
registry.registrants['Multi'][TEST_KEY3].signature.should.eql(signatureC);
});
});
describe('.keyIfNotSet()', () => {
let sandbox = null;
const TEST_HASH = 'test_hash';
beforeEach(() => {
sandbox = sinon.createSandbox();
});
afterEach(() => {
sandbox.restore();
});
it('should return the key if it is defined.', () => {
const key = registry.keyIfNotSet('random_key', {});
key.should.equal('random_key');
});
it('should get a new key if not already set.', () => {
const stub = sandbox.stub(hash, 'hashSig').returns(TEST_HASH);
const key = registry.keyIfNotSet(undefined, {
path: '/test'
});
sandbox.assert.calledOnce(hash.hashSig);
key.should.equal(TEST_HASH);
});
});
describe('.reset()', () => {
let sandbox = null;
let stub = null;
beforeEach(() => {
sandbox = sinon.createSandbox();
resetMocksStub = sandbox.stub(registry, 'resetMocks');
resetPathsStub = sandbox.stub(registry, 'resetPaths');
resetAliasesStub = sandbox.stub(registry, 'resetAliases');
});
afterEach(() => {
sandbox.restore();
});
it('should call mocks, paths and aliases reset methods.', () => {
registry.reset();
sandbox.assert.calledOnce(resetMocksStub);
sandbox.assert.calledOnce(resetPathsStub);
sandbox.assert.calledOnce(resetAliasesStub);
});
});
describe('.resetMocks()', () => {
it('should clear mocks.', () => {
class Original extends base.node.Node{};
class Mocked extends base.node.Node{};
registry.register({path: '/RTest/mock-test-path'}, Original);
registry.mock('/RTest/mock-test-path', Mocked);
registry.resetMocks();
registry._mocks.should.eql({});
});
});
describe('.resetPaths()', () => {
it('should clear paths.', () => {
class Original extends base.node.Node{};
registry.register({path: '/test'}, Original);
registry.resetPaths();
registry._paths.should.eql({});
});
});
});