periodicjs
Version:
Periodic is a rapid enterprise application framework for data driven web and mobile applications.
427 lines (426 loc) • 16 kB
JavaScript
;
/*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 CRUD_ext = require('../../../lib/crud/ext');
const testPathDir = path.resolve(__dirname, '../../mock/spec/periodic');
const initTestPathDir = path.join(testPathDir, 'crudEXTTest');
const initTestConfigJsonFile = path.join(initTestPathDir, 'content/config/config.json');
const configTestConfigJson = require('../../mock/config/config_test_config');
let configPeriodic;
chai.use(require('sinon-chai'));
chai.use(require('chai-as-promised'));
require('mocha-sinon');
let TEXT_ext;
describe('Periodic Crud Ext', 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.copy(path.resolve(__dirname, '../../mock/extensions'), path.join(initTestPathDir, 'node_modules'));
})
.then(() => {
return fs.outputJson(initTestConfigJsonFile, configTestConfigJson({
dbpathprefix: initTestPathDir,
settingsProp: {
logger: {
use_winston_logger: false,
},
},
}));
})
.then(() => {
console.log('custom setting file')
// process.env.ENV = 'test';
configPeriodic = new periodicClass({});
// console.log('configPeriodic.init', configPeriodic.init)
configPeriodic.init({
app_root: initTestPathDir,
cli: true,
environment: 'test',
})
.then(result => {
console.log({ result });
done();
// done.bind(done, undefined);
})
.catch(done);
}).catch(done);
});
describe('getExtensionPaths', () => {
it('should throw an error if invalid extension type', () => {
try {
CRUD_ext.getExtensionPaths();
} catch (e) {
expect(e).to.be.an('error');
}
try {
CRUD_ext.getExtensionPaths({ source: 'local' });
} catch (e) {
expect(e).to.be.an('error');
}
});
it('should return extension paths to module folder and periodic extension settings', () => {
const mockThis = {
config: {
app_root: initTestPathDir
},
};
const mockOptions = {
source: 'npm',
name: 'testextension',
};
const extensionPaths = CRUD_ext.getExtensionPaths.call(mockThis, mockOptions);
expect(extensionPaths).to.be.an('object');
expect(extensionPaths.package).to.eql(path.join(mockThis.config.app_root, 'node_modules', mockOptions.name, 'package.json'));
expect(extensionPaths.ext).to.eql(path.join(mockThis.config.app_root, 'node_modules', mockOptions.name, 'periodicjs.ext.json'));
});
});
describe('getExtensionDoc', () => {
it('should throw an error if invalid extension properties', () => {
try {
CRUD_ext.getExtensionDoc();
} catch (e) {
expect(e).to.be.an('error');
}
try {
CRUD_ext.getExtensionDoc({ source: 'local' });
} catch (e) {
expect(e).to.be.an('error');
}
});
it('should require an extension name', () => {
try {
const ext_package_json = {};
const ext_config_json = {};
const ext_source = {};
CRUD_ext.getExtensionDoc({ ext_package_json, ext_config_json, ext_source, });
} catch (e) {
expect(e.message).to.eql('Extension package.json is missing a name');
}
});
it('should require an extension version', () => {
try {
const ext_package_json = {
name: 'test',
};
const ext_config_json = {};
const ext_source = {};
CRUD_ext.getExtensionDoc({ ext_package_json, ext_config_json, ext_source, });
} catch (e) {
expect(e.message).to.eql('Extension package.json is missing a version');
}
});
it('should require an extension periodic_type', () => {
try {
const ext_package_json = {
name: 'test',
version: '10.0.1',
};
const ext_config_json = {};
const ext_source = {};
CRUD_ext.getExtensionDoc({ ext_package_json, ext_config_json, ext_source, });
} catch (e) {
expect(e.message).to.eql('Extension periodicjs.ext.json is missing a periodic_type classification (0-core, 1-communication, 2-auth, 3-uac, 4-api, 5-admin,6-data,7-ui)');
}
});
it('should require an extension periodic_priority', () => {
try {
const ext_package_json = {
name: 'test',
version: '10.0.1',
};
const ext_config_json = {
periodic_type: 0,
};
const ext_source = {};
CRUD_ext.getExtensionDoc({ ext_package_json, ext_config_json, ext_source, });
} catch (e) {
expect(e.message).to.eql('Extension periodicjs.ext.json is missing a periodic_priority');
}
});
it('should require an extension periodic_compatibility', () => {
try {
const ext_package_json = {
name: 'test',
version: '10.0.1',
};
const ext_config_json = {
periodic_type: 0,
periodic_priority: 0,
};
const ext_source = {};
CRUD_ext.getExtensionDoc({ ext_package_json, ext_config_json, ext_source, });
} catch (e) {
expect(e.message).to.eql('Extension periodicjs.ext.json is missing a periodic_compatibility');
}
});
it('should require an extension periodic_config', () => {
try {
const ext_package_json = {
name: 'test',
version: '10.0.1',
};
const ext_config_json = {
periodic_type: 0,
periodic_priority: 0,
periodic_compatibility: '10.0.0',
};
const ext_source = {};
CRUD_ext.getExtensionDoc({ ext_package_json, ext_config_json, ext_source, });
} catch (e) {
expect(e.message).to.eql('Extension periodicjs.ext.json is missing a periodic_config');
}
});
it('should return a formatted extension', () => {
const ext_package_json = {
name: 'test',
version: '10.0.1',
};
const ext_config_json = {
periodic_type: 0,
periodic_priority: 0,
periodic_compatibility: '10.0.0',
periodic_config: {},
};
const ext_source = {};
const validExt = CRUD_ext.getExtensionDoc({ ext_package_json, ext_config_json, ext_source, });
expect(validExt).to.have.property('name');
expect(validExt).to.have.property('version');
expect(validExt).to.have.property('author');
expect(validExt).to.have.property('periodic_type');
expect(validExt).to.have.property('periodic_priority');
expect(validExt).to.have.property('periodic_compatibility');
expect(validExt).to.have.property('periodic_config');
expect(validExt).to.have.property('contributors');
expect(validExt).to.have.property('description');
expect(validExt).to.have.property('source');
expect(validExt).to.have.property('enabled');
expect(validExt).to.have.property('createdat');
expect(validExt).to.have.property('updatedat');
});
});
describe('create', () => {
it('should handle errors', () => {
expect(CRUD_ext.create()).to.eventually.be.rejected;
});
it('should add extension to extension db', (done) => {
CRUD_ext.create.call(configPeriodic, 'periodicjs.ext.cloudupload')
.then(createdExtension => {
TEXT_ext = createdExtension;
// console.log({ createdExtension });
expect(createdExtension).to.be.ok;
expect(createdExtension.name).to.eql('periodicjs.ext.cloudupload');
expect(createdExtension.source).to.eql('npm');
expect(createdExtension.enabled).to.eql(true);
expect(createdExtension._id).to.be.ok;
// expect
return configPeriodic.datas.get('extension').load({ query: createdExtension._id, });
})
.then(loadedExtension => {
expect(loadedExtension._id).to.eql(TEXT_ext._id);
done();
})
.catch(done);
// expect().to.eventually.eql(true);
});
});
describe('update', () => {
it('should handle errors', () => {
expect(CRUD_ext.update()).to.eventually.be.rejected;
});
it('should update extension in extension db', (done) => {
const updatedExt = Object.assign({}, TEXT_ext, {
enabled: false,
description: 'updated cloud upload extension',
});
// console.log({ updatedExt });
CRUD_ext.update.call(configPeriodic, {
ext: updatedExt,
isPatch: true,
})
.then(updatedExtensionStatus => {
expect(updatedExtensionStatus.status).to.eql('ok');
return configPeriodic.datas.get('extension').load({ docid: 'name', query: TEXT_ext.name, });
})
.then(updatedExtension => {
// console.log({ updatedExtension });
expect(updatedExtension._id).to.eql(TEXT_ext._id);
expect(updatedExtension).to.be.ok;
expect(updatedExtension.name).to.eql('periodicjs.ext.cloudupload');
expect(updatedExtension.source).to.eql('npm');
expect(updatedExtension.enabled).to.eql(false);
expect(updatedExtension.description).to.eql('updated cloud upload extension');
expect(updatedExtension._id).to.be.ok;
done();
})
.catch(done);
});
});
describe('remove', () => {
it('should handle errors', () => {
expect(CRUD_ext.remove()).to.eventually.be.rejected;
});
it('should remove extension from extension db', (done) => {
Promise.all([
CRUD_ext.create.call(configPeriodic, 'periodicjs.ext.admin'),
CRUD_ext.create.call(configPeriodic, 'periodicjs.ext.login'),
CRUD_ext.create.call(configPeriodic, 'periodicjs.ext.login_mfa'),
])
.then(() => {
return configPeriodic.datas.get('extension').query();
})
.then(exts => {
expect(exts.length).to.eql(4);
return CRUD_ext.remove.call(configPeriodic, 'periodicjs.ext.cloudupload');
})
.then(removedExt => {
if (Array.isArray(removedExt)) {
expect(removedExt[0].name).to.eql('periodicjs.ext.cloudupload');
} else {
expect(removedExt.name).to.eql('periodicjs.ext.cloudupload');
}
return configPeriodic.datas.get('extension').query();
})
.then(exts => {
// console.log({exts});
expect(exts.length).to.eql(3);
})
.then(() => {
return CRUD_ext.remove.call(configPeriodic, { name: 'periodicjs.ext.admin' });
})
.then(() => {
return configPeriodic.datas.get('extension').query();
})
.then(extensions => {
expect(extensions.length).to.eql(2);
// console.log({extensions});
return CRUD_ext.remove.call(configPeriodic, { _id: extensions[0]._id, });
})
.then(removedExt => {
// console.log({removedExt});
// expect(removedExt).to.be.ok;
done();
})
.catch(done);
});
});
describe('list', () => {
it('should handle errors', () => {
expect(CRUD_ext.list()).to.eventually.be.rejected;
});
it('should return sorted extensions', (done) => {
Promise.all([
CRUD_ext.create.call(configPeriodic, 'periodicjs.ext.mailer'),
CRUD_ext.create.call(configPeriodic, 'periodicjs.ext.oauth2client'),
CRUD_ext.create.call(configPeriodic, 'periodicjs.ext.oauth2server'),
CRUD_ext.create.call(configPeriodic, 'periodicjs.ext.test'),
CRUD_ext.create.call(configPeriodic, 'periodicjs.ext.uac'),
])
.then(() => {
return CRUD_ext.list.call(configPeriodic, {});
})
.then(exts => {
const periodic_types = exts.map(ext => ext.periodic_type || 0);
// const periodic_priorities = exts.map(ext => ext.periodic_priority || 0);
/* https://gist.github.com/yorkie/7959685
* check the array is sorted
* return: if positive -> 1
* if negative -> -1
* not sorted -> 0
*/
const isSorted = function() {
return (function(direction) {
return this.reduce(function(prev, next, i, arr) {
if (direction === undefined)
return (direction = prev <= next ? 1 : -1) || true;
else
return (direction + 1 ?
(arr[i - 1] <= next) :
(arr[i - 1] > next));
}) ? Number(direction) : false;
}).call(this);
};
expect(isSorted.call(periodic_types)).to.eql(1);
done();
})
.catch(done);
});
});
describe('init', () => {
it('should handle errors', () => {
expect(CRUD_ext.init()).to.eventually.be.rejected;
});
it('should create the structure for a new extension', (done) => {
const extname = 'testNewExtension';
CRUD_ext.init.call(configPeriodic, false, extname)
.then(result => {
return fs.readdir(path.join(initTestPathDir, 'node_modules', extname));
})
.then(newextfiles => {
expect(newextfiles).to.contain.members([
'.coveralls.yml',
'.eslintrc.json',
'.travis.yml',
'Gruntfile.js',
'LICENSE',
'README.md',
'commands',
'config',
'controllers',
'doc',
'index.js',
'jsdoc.json',
'package.json',
'periodicjs.ext.json',
'resources',
'routers',
'test',
'transforms',
'utilities',
'views'
]);
return fs.readJson(path.join(initTestPathDir, 'node_modules', extname, 'package.json'));
})
.then(newextPackageJson => {
expect(newextPackageJson.name).to.eql(extname);
return fs.readFile(path.join(initTestPathDir, 'node_modules', extname, 'README.md'));
})
.then(readmeMarkDown => {
expect(readmeMarkDown.toString().indexOf(extname) === -1).to.be.false;
done();
})
.catch(done);
});
});
describe('generateREADME', () => {
it('should return a structured readme', (done) => {
expect(CRUD_ext.generateREADME({ extensionName: 'newtestext' })).to.be.a('string');
done();
// fs.readFile(path.resolve(__dirname,'./newtestext.md'))
// .then(testMD => {
// expect(CRUD_ext.generateREADME({ extensionName: 'newtestext' })).to.eql(testMD.toString());
// done();
// })
// .catch(done);
});
});
after('remove config test periodic dir', (done) => {
fs.remove(initTestPathDir)
.then(() => {
done();
}).catch(done);
});
});