UNPKG

periodicjs

Version:

Periodic is a rapid enterprise application framework for data driven web and mobile applications.

524 lines (522 loc) 17.2 kB
'use strict'; /*jshint expr: true*/ const path = require('path'); const events = require('events'); const chai = require('chai'); const sinon = require('sinon'); const fs = require('fs-extra'); const expect = require('chai').expect; const periodic = require('../../../index'); const periodicClass = require('../../../lib/periodicClass'); const config = require('../../../lib/init/config'); const configSequelizeSchema = require('../../../lib/schemas/config.sequelize'); const testPathDir = path.resolve(__dirname, '../../mock/spec/periodic'); const initTestPathDir = path.join(testPathDir, 'configTest'); const CoreData = require('periodicjs.core.data'); const initTestConfigJsonFile = path.join(initTestPathDir, 'content/config/config.json'); const configTestConfigJson = require('../../mock/config/config_test_config'); const extDoc = require('../../mock/config/ext_doc'); let configPeriodic; chai.use(require('sinon-chai')); chai.use(require('chai-as-promised')); require('mocha-sinon'); describe('Periodic Init Config', function() { this.timeout(10000); before('initialize config test periodic dir', (done) => { fs.ensureDir(initTestPathDir) .then(() => { return fs.ensureDir(path.join(initTestPathDir, 'content/config')); }) .then(() => { return fs.ensureFile(initTestConfigJsonFile); }) .then(() => { return fs.outputJson(initTestConfigJsonFile, configTestConfigJson({ dbpathprefix: initTestPathDir, settingsProp: { logger: { use_winston_logger: false, }, }, })); }) .then(() => { // process.env.ENV = 'test'; configPeriodic = new periodicClass({}); configPeriodic.init({ app_root: initTestPathDir, cli: true, environment: 'test', }) .then(done.bind(done, undefined)) .catch(done); }).catch(done); }); describe('getContentDBModelDir', () => { it('should return the content model directory path', () => { expect(config.getContentDBModelDir.call({ config: { app_root: 'path/to/dir', }, }, 'test')).to.eql('path/to/dir/content/config/databases/test/models'); }); }); describe('getDBModelDir', () => { it('should return the content model directory path', () => { expect(config.getDBModelDir.call({ config: { app_root: 'path/to/dir', }, }, { db_config_type: 'content', periodic_db_name: 'test', })).to.eql('path/to/dir/content/config/databases/test/models'); }); }); describe('assignLowkieModels', () => { it('should resolve as true', () => { const testModelDir = path.join(initTestPathDir, 'content/config/databases/standard/models'); const resolveSpy = sinon.spy(); const createSpy = sinon.spy(); const mockThis = { dbs: new Map(), }; const mockOptions = { resolve: resolveSpy, dboptions: {}, periodic_db_name: 'almTest', db: {}, modelFiles: [], }; config.assignLowkieModels.call(mockThis, mockOptions); expect(resolveSpy.calledWith(true)).to.be.true; }); it('should create lowkie models', () => { const testModelDir = path.join(initTestPathDir, 'content/config/databases/standard/models'); const resolveSpy = sinon.spy(); const createSpy = sinon.spy(); const mockThis = { dbs: new Map(), datas: new Map(), models: new Map(), core: { data: { create: createSpy, }, }, }; const mockOptions = { resolve: resolveSpy, dboptions: {}, periodic_db_name: 'default', db: {}, modelFiles: fs.readdirSync(testModelDir), modelDirPath: testModelDir, }; // console.log(fs.readdirSync(path.join(initTestPathDir,'content/config/databases/standard/models'))) config.assignLowkieModels.call(mockThis, mockOptions); expect(createSpy.called).to.be.true; expect(mockThis.dbs.size).to.be.greaterThan(0); expect(mockThis.datas.size).to.be.greaterThan(0); expect(resolveSpy.calledWith(true)).to.be.true; }); }); describe('assignMongooseModels', () => { it('should resolve as true', () => { const testModelDir = path.join(initTestPathDir, 'content/config/databases/standard/models'); const resolveSpy = sinon.spy(); const createSpy = sinon.spy(); const mockThis = { dbs: new Map(), }; const mockOptions = { resolve: resolveSpy, dboptions: {}, periodic_db_name: 'default', db: {}, modelFiles: [], }; config.assignMongooseModels.call(mockThis, mockOptions); expect(resolveSpy.calledWith(true)).to.be.true; }); it('should create mongoose models', () => { const testModelDir = path.join(initTestPathDir, 'content/config/databases/standard/models'); const resolveSpy = sinon.spy(); const createSpy = sinon.spy(); const mockThis = { dbs: new Map(), datas: new Map(), models: new Map(), core: { data: { create: createSpy, }, }, }; const mockOptions = { resolve: resolveSpy, periodic_db_name: 'default', db: require('mongoose'), dboptions: {}, modelFiles: fs.readdirSync(testModelDir), modelDirPath: testModelDir, }; // console.log(fs.readdirSync(path.join(initTestPathDir,'content/config/databases/standard/models'))) config.assignMongooseModels.call(mockThis, mockOptions); expect(createSpy.called).to.be.true; expect(mockThis.dbs.size).to.be.greaterThan(0); expect(mockThis.datas.size).to.be.greaterThan(0); expect(resolveSpy.calledWith(true)).to.be.true; }); }); describe('assignSequelizeModels', () => { it('should create sequelize models', (done) => { const testModelDir = path.join(initTestPathDir, 'content/config/databases/standard/models'); const Sequelize = require('sequelize'); const dboptions = { database: 'travis_ci_test', username: '', password: '', connection_options: { dialect: 'postgres', port: 5432, host: '127.0.0.1', logging: false, }, }; const sequelizeDB = new Sequelize(dboptions.database, dboptions.username, dboptions.password, dboptions.connection_options); const resolveSpy = sinon.spy(); const createSpy = sinon.spy(); const mockThis = { dbs: new Map(), datas: new Map(), models: new Map(), core: { data: { create: createSpy, }, }, config: { debug:true, }, }; const mockOptions = { resolve: (val) => { resolveSpy(val); expect(createSpy.called).to.be.true; expect(mockThis.dbs.size).to.be.greaterThan(0); expect(mockThis.datas.size).to.be.greaterThan(0); expect(resolveSpy.calledWith(true)).to.be.true; done(); }, reject: done, periodic_db_name: 'default', dboptions: {}, db: sequelizeDB || { sync: () => new Promise((resolve, reject) => { }) }, modelFiles: fs.readdirSync(testModelDir), modelDirPath: testModelDir, }; // console.log(fs.readdirSync(path.join(initTestPathDir,'content/config/databases/standard/models'))) try { config.assignSequelizeModels.call(mockThis, mockOptions); } catch (e) { console.log('Cannot connect to Postgres') done(); } }); }); describe('connectLowkieDB', () => { it('should handle errors', () => { expect(config.connectLowkieDB()).to.eventually.be.rejected; }); it('should connect to loki', () => { const mockOptions = { periodic_db_name: 'default', db_config_type: 'content', options: { dbpath: path.join(initTestPathDir, 'content/config/settings/config_db.json'), }, }; const mockThis = {}; expect(config.connectLowkieDB.call(mockThis, mockOptions)).to.eventually.be.fulfilled; }); }); describe('connectMongooseDB', () => { it('should handle errors', () => { expect(config.connectMongooseDB()).to.eventually.be.rejected; }); it('should connect to mongo', () => { const mockOptions = { periodic_db_name: 'default', db_config_type: 'content', options: { url: 'mongodb://localhost:27017/config_db', connection_options: {}, }, }; const mockThis = { config: { app_root: initTestPathDir, }, }; expect(config.connectMongooseDB.call(mockThis, mockOptions)).to.eventually.be.fulfilled; }); }); describe('connectSequelizeDB', () => { it('should handle errors', () => { expect(config.connectSequelizeDB()).to.eventually.be.rejected; }); it('should connect to sql', () => { const mockOptions = { periodic_db_name: 'default', db_config_type: 'content', options: { database: 'travis_ci_test', username: '', password: '', connection_options: { dialect: 'postgres', port: 5432, host: '127.0.0.1', }, }, }; const mockThis = { config: { app_root: initTestPathDir, }, }; expect(config.connectSequelizeDB.call(mockThis, mockOptions)).to.eventually.be.fulfilled; }); }); describe('connectDB', () => { it('should handle errors', () => { expect(config.connectDB()).to.eventually.be.rejected; }); it('should connect to loki', () => { expect(config.connectDB({ db: 'lowkie', })).to.eventually.be.rejected; }); it('should connect to mongo', () => { expect(config.connectDB({ db: 'mongoose', })).to.eventually.be.rejected; }); it('should connect to sql', () => { expect(config.connectDB({ db: 'sequelize', })).to.eventually.be.rejected; }); it('should resolve to true if no db specified', () => { expect(config.connectDB({ db: 'other', })).to.eventually.eql(true); }); }); describe('loadDatabases', () => { it('should handle errors', () => { expect(config.loadDatabases()).to.eventually.be.rejected; }); it('should return true if no databases to connect', (done) => { config.loadDatabases.call({ resources: { databases: { container: {}, extensions: {}, }, }, settings: { databases: {}, }, }) .then(result => { expect(result).to.be.true; done(); }) .catch(done); }); it('should return connected databases to from settings', (done) => { config.loadDatabases.call({ resources: { databases: { container: {}, extensions: {}, }, }, settings: { databases: { test: { db: 'other', }, test2: { db: 'other', }, }, }, }) .then(results => { expect(results.length).to.eql(2); done(); }) .catch(done); }); }); describe('loadExtensions', () => { const extNotCompatible = extDoc({ 'periodic_compatibility': '11.0.0', }); describe('filterRequiredDependencies', () => { it('should return true if dependency is not optional', () => { expect(config.filterRequiredDependencies({ optional: false, })).to.be.true; }); it('should return false if dependency is optional', () => { expect(config.filterRequiredDependencies({ optional: true, })).to.be.false; }); }); describe('mapForExtensionDependencyName', () => { it('should return extension name', () => { expect(config.mapForExtensionDependencyName({ extname: 'test', })).to.eql('test'); }); }); describe('checkForRequiredExtensions', () => { it('should error if missing required extension', () => { const errors = []; const ext = { name: 'test extension', }; const mockThis = { extensions: new Map(), }; const mockOptions = { errors, reqExt: 'requiredExt', ext, }; config.checkForRequiredExtensions.call(mockThis, mockOptions); expect(errors).to.have.length.greaterThan(0); }); it('should not error if extension map has extension loaded', () => { const errors = []; const ext = { name: 'requiredExt', version: '1.0.0', }; const mockThis = { extensions: new Map( [ [ext.name, ], ext, ] ), }; const mockOptions = { errors, reqExt: 'requiredExt', ext, }; config.checkForRequiredExtensions.call(mockThis, mockOptions); expect(errors.length).to.eql(0); }); }); describe('checkExtensionDependencies', () => { it('should error if extension is incompatible with periodic version', () => { const errors = []; const mockThis = { settings: { application: { version: '10.0.0', }, }, }; const mockOptions = { errors, ext: { periodic_compatibility: '11.0.0', }, }; config.checkExtensionDependencies.call(mockThis, mockOptions); expect(errors).to.have.length.greaterThan(0); }); it('should add valid extension to extensions map', () => { const errors = []; const ext = { name: 'testExtension', periodic_compatibility: '10.0.0', }; const mockThis = { settings: { application: { version: '10.0.0', }, }, extensions: new Map(), }; const mockOptions = { errors, ext, }; config.checkExtensionDependencies.call(mockThis, mockOptions); expect(mockThis.extensions.has(ext.name)).to.be.true; expect(mockThis.extensions.get(ext.name)).to.eql(ext); expect(errors.length).to.eql(0); }); }); describe('loadExtensions functionality', () => { it('should handle errors', () => { expect(config.loadExtensions()).to.eventually.be.rejected; }); it('should return true if there are no extensions', (done) => { const mockThis = { settings: { application: { exit_on_invalid_extensions: false, }, }, crud: { ext: { list: () => { return new Promise((resolve, reject) => { resolve([]); }); }, }, }, }; config.loadExtensions.call(mockThis) .then(result => { expect(result).to.be.true; done(); }) .catch(done); }); it('should return reject on error if settings is set ', (done) => { const errorSpy = sinon.spy(); const mockThis = { settings: { application: { version: '10.0.0', exit_on_invalid_extensions: true, }, }, extensions: new Set(), crud: { ext: { list: () => { return new Promise((resolve, reject) => { resolve([extNotCompatible, ]); }); }, }, }, logger: { error: errorSpy, }, }; config.loadExtensions.call(mockThis) .then(result => { done(new Error('Should reject if invalid extension config')); }) .catch(e => { expect(errorSpy.called).to.be.true; expect(e.message).to.eql('Invalid extension configuration'); done(); }); }); }); }); after('remove config test periodic dir', (done) => { fs.remove(initTestPathDir) .then(() => { done(); }).catch(done); }); });