Commit 974c7bf8 by James Cropcho

Merge pull request #114 from todvora/master

ES6 and ES7 features in tests (import, export, async & await)
parents bf42b642 6a908273
{ {
"presets": ["es2015" ] "presets": ["es2015", "stage-0"]
} }
module.exports = { module.exports = {
"parser": "babel-eslint",
"env": { "env": {
"mongo": true, "mongo": true,
"node": true, "node": true,
......
...@@ -9,7 +9,7 @@ ...@@ -9,7 +9,7 @@
"scripts": { "scripts": {
"lint": "node_modules/.bin/eslint variety.js spec", "lint": "node_modules/.bin/eslint variety.js spec",
"lint:fix": "node_modules/.bin/eslint variety.js spec --fix", "lint:fix": "node_modules/.bin/eslint variety.js spec --fix",
"test": "node_modules/.bin/mocha --compilers js:babel-core/register --recursive --reporter spec --timeout 15000 spec", "test": "node_modules/.bin/mocha --compilers js:babel-core/register --require babel-polyfill --recursive --reporter spec --timeout 15000 spec",
"test:docker": "./test.sh", "test:docker": "./test.sh",
"travis-ci": "npm run lint && npm run test:docker" "travis-ci": "npm run lint && npm run test:docker"
}, },
...@@ -30,11 +30,13 @@ ...@@ -30,11 +30,13 @@
"homepage": "https://github.com/variety/variety#readme", "homepage": "https://github.com/variety/variety#readme",
"devDependencies": { "devDependencies": {
"babel-core": "^6.7.2", "babel-core": "^6.7.2",
"babel-eslint": "^6.0.2",
"babel-polyfill": "^6.7.4",
"babel-preset-es2015": "^6.6.0", "babel-preset-es2015": "^6.6.0",
"babel-preset-stage-0": "^6.5.0",
"child-process-promise": "^1.1.0", "child-process-promise": "^1.1.0",
"eslint": "^2.4.0", "eslint": "^2.4.0",
"mocha": "^2.4.5", "mocha": "^2.4.5",
"mongodb": "^2.1.7", "mongodb": "^2.1.7"
"q": "^1.4.1"
} }
} }
const assert = require('assert'); import assert from 'assert';
const Tester = require('./utils/Tester.js'); import Tester from './utils/Tester.js';
const test = new Tester('test', 'users'); const test = new Tester('test', 'users');
const sampleData = require('./assets/SampleData'); import sampleData from './assets/SampleData';
const expectedAscii = require('./assets/ExpectedAscii'); import expectedAscii from './assets/ExpectedAscii';
describe('Basic Analysis', () => { describe('Basic Analysis', () => {
beforeEach(() => test.init(sampleData)); beforeEach(() => test.init(sampleData));
afterEach(() => test.cleanUp()); afterEach(() => test.cleanUp());
it('should return ASCII results', () => { it('should return ASCII results', async () => {
return test.runAnalysis({collection:'users'}, true).then(output => { const output = await test.runAnalysis({collection:'users'}, true);
assert.equal(output, expectedAscii); assert.equal(output, expectedAscii);
});
}); });
it('should return JSON results', () => { it('should return JSON results', async () => {
return test.runJsonAnalysis({collection:'users'}, true) const results = await test.runJsonAnalysis({collection:'users'}, true);
.then(results => { results.validateResultsCount(7);
results.validate('_id', 5, 100.0, {ObjectId: 5});
results.validateResultsCount(7); results.validate('name', 5, 100.0, {String: 5});
results.validate('bio', 3, 60.0, {String: 3});
results.validate('_id', 5, 100.0, {ObjectId: 5}); results.validate('birthday', 2, 40.0, {Date: 2});
results.validate('name', 5, 100.0, {String: 5}); results.validate('pets', 2, 40.0, {String: 1, Array: 1});
results.validate('bio', 3, 60.0, {String: 3}); results.validate('someBinData', 1, 20.0, {'BinData-generic': 1});
results.validate('birthday', 2, 40.0, {Date: 2}); results.validate('someWeirdLegacyKey', 1, 20.0, {String: 1});
results.validate('pets', 2, 40.0, {String: 1, Array: 1});
results.validate('someBinData', 1, 20.0, {'BinData-generic': 1});
results.validate('someWeirdLegacyKey', 1, 20.0, {String: 1});
});
}); });
}); });
const assert = require('assert'); import assert from 'assert';
const Tester = require('./utils/Tester.js'); import Tester from './utils/Tester.js';
const test = new Tester('test', 'users'); import sampleData from './assets/SampleData';
const sampleData = require('./assets/SampleData'); const test = new Tester('test', 'users');
const pattern = /^Found new key type "(.{1,})" type "(.{1,})"$/g; const pattern = /^Found new key type "(.{1,})" type "(.{1,})"$/g;
const expectedLines = [ const expectedLines = [
...@@ -19,21 +19,20 @@ const expectedLines = [ ...@@ -19,21 +19,20 @@ const expectedLines = [
describe('Continuous logging', () => { describe('Continuous logging', async () => {
beforeEach(() => test.init(sampleData)); beforeEach(() => test.init(sampleData));
afterEach(() => test.cleanUp()); afterEach(() => test.cleanUp());
it('should log every new key', () => { it('should log every new key', async () => {
return test.runAnalysis({collection:'users', logKeysContinuously:true}).then(output => { const output = await test.runAnalysis({collection:'users', logKeysContinuously:true});
var filteredOutput = output var filteredOutput = output
.split('\n') .split('\n')
.filter(line => line.match(pattern)); .filter(line => line.match(pattern));
assert.equal(filteredOutput.length, expectedLines.length); assert.equal(filteredOutput.length, expectedLines.length);
expectedLines.forEach(expectedLine => { expectedLines.forEach(expectedLine => {
const found = filteredOutput.indexOf(expectedLine) > -1; const found = filteredOutput.indexOf(expectedLine) > -1;
assert.ok(found, `Expected line '${expectedLine}' not found in Variety output`); assert.ok(found, `Expected line '${expectedLine}' not found in Variety output`);
});
}); });
}); });
}); });
const Binary = require('mongodb').Binary; import { Binary } from 'mongodb';
const Tester = require('./utils/Tester.js'); import Tester from './utils/Tester.js';
const test = new Tester('test', 'users'); const test = new Tester('test', 'users');
const crazyObject = { const crazyObject = {
...@@ -18,17 +18,15 @@ describe('Data type recognition', () => { ...@@ -18,17 +18,15 @@ describe('Data type recognition', () => {
beforeEach(() => test.init([crazyObject])); beforeEach(() => test.init([crazyObject]));
afterEach(() => test.cleanUp()); afterEach(() => test.cleanUp());
it('should recognize all supported data types', () => { it('should recognize all supported data types', async () => {
return test.runJsonAnalysis({collection:'users'}, true) const results = await test.runJsonAnalysis({collection:'users'}, true);
.then(results => { results.validate('_id', 1, 100.0, {ObjectId: 1});
results.validate('_id', 1, 100.0, {ObjectId: 1}); results.validate('key_string', 1, 100.0, {String: 1});
results.validate('key_string', 1, 100.0, {String: 1}); results.validate('key_number', 1, 100.0, {Number: 1});
results.validate('key_number', 1, 100.0, {Number: 1}); results.validate('key_date', 1, 100.0, {Date: 1});
results.validate('key_date', 1, 100.0, {Date: 1}); results.validate('key_binData-generic', 1, 100.0, {'BinData-generic': 1});
results.validate('key_binData-generic', 1, 100.0, {'BinData-generic': 1}); results.validate('key_array', 1, 100.0, {Array: 1});
results.validate('key_array', 1, 100.0, {Array: 1}); results.validate('key_object', 1, 100.0, {Object: 1});
results.validate('key_object', 1, 100.0, {Object: 1}); results.validate('key_null', 1, 100.0, {null: 1}); // TODO: why has 'null' first letter lowercase, unlike all other types?
results.validate('key_null', 1, 100.0, {null: 1}); // TODO: why has 'null' first letter lowercase, unlike all other types?
});
}); });
}); });
const Tester = require('./utils/Tester.js'); import Tester from './utils/Tester.js';
import sampleData from './assets/SampleData';
const test = new Tester('test', 'users'); const test = new Tester('test', 'users');
const sampleData = require('./assets/SampleData');
describe('Limited results count analysis', () => { describe('Limited results count analysis', () => {
beforeEach(() => test.init(sampleData)); beforeEach(() => test.init(sampleData));
afterEach(() => test.cleanUp()); afterEach(() => test.cleanUp());
it('should analyze only first item', () => { it('should analyze only first item', async () => {
// limit=1 without other params selects the last inserted document (see sampleData) // limit=1 without other params selects the last inserted document (see sampleData)
// it should equals {name: "Jim", someBinData: new BinData(2,"1234")} // it should equals {name: "Jim", someBinData: new BinData(2,"1234")}
return test.runJsonAnalysis({collection:'users', limit:1}).then(results => { const results = await test.runJsonAnalysis({collection:'users', limit:1});
results.validate('_id', 1, 100.0, {ObjectId:1}); results.validate('_id', 1, 100.0, {ObjectId:1});
results.validate('name', 1, 100.0, {String:1}); results.validate('name', 1, 100.0, {String:1});
results.validate('someBinData', 1, 100.0, {'BinData-generic':1}); results.validate('someBinData', 1, 100.0, {'BinData-generic':1});
});
}); });
it('should analyze all and compute real percentages', () => { it('should analyze all and compute real percentages', async () => {
return test.runJsonAnalysis({collection:'users', limit:10}).then(results => { const results = await test.runJsonAnalysis({collection:'users', limit:10});
// limit is set to higher number, that the actual number of documents in collection // limit is set to higher number, that the actual number of documents in collection
// analysis should compute percentages based on the real number of documents, not on the // analysis should compute percentages based on the real number of documents, not on the
// number provided in the limit var. // number provided in the limit var.
results.validateResultsCount(7); results.validateResultsCount(7);
results.validate('_id', 5, 100.0, {ObjectId: 5}); results.validate('_id', 5, 100.0, {ObjectId: 5});
results.validate('name', 5, 100.0, {String: 5}); results.validate('name', 5, 100.0, {String: 5});
results.validate('bio', 3, 60.0, {String: 3}); results.validate('bio', 3, 60.0, {String: 3});
results.validate('birthday', 2, 40.0, {Date: 2}); results.validate('birthday', 2, 40.0, {Date: 2});
results.validate('pets', 2, 40.0, {String: 1, Array: 1}); results.validate('pets', 2, 40.0, {String: 1, Array: 1});
results.validate('someBinData', 1, 20.0, {'BinData-generic': 1}); results.validate('someBinData', 1, 20.0, {'BinData-generic': 1});
results.validate('someWeirdLegacyKey', 1, 20.0, {String: 1}); results.validate('someWeirdLegacyKey', 1, 20.0, {String: 1});
});
}); });
}); });
const Tester = require('./utils/Tester.js'); import Tester from './utils/Tester.js';
const test = new Tester('test', 'users'); const test = new Tester('test', 'users');
describe('Max-depth-limited analysis', () => { describe('Max-depth-limited analysis', () => {
...@@ -6,32 +6,30 @@ describe('Max-depth-limited analysis', () => { ...@@ -6,32 +6,30 @@ describe('Max-depth-limited analysis', () => {
beforeEach(() => test.init([{name:'Walter', someNestedObject:{a:{b:{c:{d:{e:1}}}}}}])); beforeEach(() => test.init([{name:'Walter', someNestedObject:{a:{b:{c:{d:{e:1}}}}}}]));
afterEach(() => test.cleanUp()); afterEach(() => test.cleanUp());
it('should return all keys', () => { it('should return all keys', async () => {
return test.runJsonAnalysis({collection:'users'}).then(results => { const results = await test.runJsonAnalysis({collection:'users'});
results.validateResultsCount(8); results.validateResultsCount(8);
results.validate('_id', 1, 100.0, {ObjectId:1}); results.validate('_id', 1, 100.0, {ObjectId:1});
results.validate('name', 1, 100.0, {String:1}); results.validate('name', 1, 100.0, {String:1});
results.validate('someNestedObject', 1, 100.0, {Object:1}); results.validate('someNestedObject', 1, 100.0, {Object:1});
results.validate('someNestedObject.a', 1, 100.0, {Object:1}); results.validate('someNestedObject.a', 1, 100.0, {Object:1});
results.validate('someNestedObject.a.b', 1, 100.0, {Object:1}); results.validate('someNestedObject.a.b', 1, 100.0, {Object:1});
results.validate('someNestedObject.a.b.c', 1, 100.0, {Object:1}); results.validate('someNestedObject.a.b.c', 1, 100.0, {Object:1});
results.validate('someNestedObject.a.b.c.d', 1, 100.0, {Object:1}); results.validate('someNestedObject.a.b.c.d', 1, 100.0, {Object:1});
results.validate('someNestedObject.a.b.c.d.e', 1, 100.0, {Number:1}); results.validate('someNestedObject.a.b.c.d.e', 1, 100.0, {Number:1});
});
}); });
it('should return only first 3 levels', () => { it('should return only first 3 levels', async () => {
return test.runJsonAnalysis({collection:'users', maxDepth:3}).then(results => { const results = await test.runJsonAnalysis({collection:'users', maxDepth:3});
results.validateResultsCount(5); results.validateResultsCount(5);
results.validate('_id', 1, 100.0, {ObjectId:1}); results.validate('_id', 1, 100.0, {ObjectId:1});
results.validate('name', 1, 100.0, {String:1}); results.validate('name', 1, 100.0, {String:1});
results.validate('someNestedObject', 1, 100.0, {Object:1}); results.validate('someNestedObject', 1, 100.0, {Object:1});
results.validate('someNestedObject.a', 1, 100.0, {Object:1}); results.validate('someNestedObject.a', 1, 100.0, {Object:1});
results.validate('someNestedObject.a.b', 1, 100.0, {Object:1}); results.validate('someNestedObject.a.b', 1, 100.0, {Object:1});
});
}); });
}); });
const assert = require('assert'); import assert from 'assert';
const Tester = require('./utils/Tester.js'); import Tester from './utils/Tester.js';
import sampleData from './assets/SampleData';
const test = new Tester('test', 'users'); const test = new Tester('test', 'users');
const sampleData = require('./assets/SampleData');
const parseParams = (output) => { const parseParams = (output) => {
return output return output
...@@ -16,26 +17,24 @@ describe('Parameters parsing', () => { ...@@ -16,26 +17,24 @@ describe('Parameters parsing', () => {
beforeEach(() => test.init(sampleData)); beforeEach(() => test.init(sampleData));
afterEach(() => test.cleanUp()); afterEach(() => test.cleanUp());
it('should parse default params', () => { it('should parse default params', async () => {
return test.runAnalysis({collection:'users'}) const results = await test.runAnalysis({collection:'users'});
.then(parseParams) const params = parseParams(results);
.then(params => { assert.equal(params.collection, 'users');
assert.equal(params.collection, 'users'); assert.deepEqual(params.query, {});
assert.deepEqual(params.query, {}); assert.equal(params.limit, 5);
assert.equal(params.limit, 5); assert.equal(params.maxDepth, 99);
assert.equal(params.maxDepth, 99); assert.deepEqual(params.sort, {'_id':-1});
assert.deepEqual(params.sort, {'_id':-1}); assert.equal(params.outputFormat, 'ascii');
assert.equal(params.outputFormat, 'ascii'); assert.equal(params.persistResults, false);
assert.equal(params.persistResults, false); assert.equal(params.resultsDatabase, 'varietyResults');
assert.equal(params.resultsDatabase, 'varietyResults'); assert.equal(params.resultsCollection, 'usersKeys');
assert.equal(params.resultsCollection, 'usersKeys'); assert.equal(params.resultsUser, null);
assert.equal(params.resultsUser, null); assert.equal(params.resultsPass, null);
assert.equal(params.resultsPass, null); assert.deepEqual(params.plugins, []);
assert.deepEqual(params.plugins, []);
});
}); });
it('should parse restricted results', () => { it('should parse restricted results', async () => {
const criteria = { const criteria = {
collection:'users', collection:'users',
...@@ -45,23 +44,22 @@ describe('Parameters parsing', () => { ...@@ -45,23 +44,22 @@ describe('Parameters parsing', () => {
limit: 2 limit: 2
}; };
return test.runAnalysis(criteria) const results = await test.runAnalysis(criteria);
.then(parseParams) const params = parseParams(results);
.then(params => { assert.equal(params.limit, 2);
assert.equal(params.limit, 2); assert.equal(params.maxDepth, 5);
assert.equal(params.maxDepth, 5); assert.deepEqual(params.sort, {name:1});
assert.deepEqual(params.sort, {name:1}); assert.deepEqual(params.query, {name:'Harry'});
assert.deepEqual(params.query, {name:'Harry'});
});
}); });
it('should recognize unknown collection', () => { it('should recognize unknown collection', async () => {
return test.runAnalysis({collection:'--unknown--'}) try {
.then(() => {throw new Error('Should fail and be handled in catch branch');}) await test.runAnalysis({collection:'--unknown--'});
.catch(err => { throw new Error('Should fail and be handled in catch branch');
assert.ok(err.code > 0); } catch(err) {
assert.ok(err.stdout.indexOf('The collection specified (--unknown--) in the database specified (test) does not exist or is empty.') > -1); assert.ok(err.code > 0);
}); assert.ok(err.stdout.indexOf('The collection specified (--unknown--) in the database specified (test) does not exist or is empty.') > -1);
}
}); });
}); });
const assert = require('assert'); import assert from 'assert';
const Tester = require('./utils/Tester.js'); import Tester from './utils/Tester.js';
import sampleData from './assets/SampleData';
const test = new Tester('test', 'users'); const test = new Tester('test', 'users');
const sampleData = require('./assets/SampleData');
describe('Persistence of results', () => { describe('Persistence of results', () => {
beforeEach(() => test.init(sampleData)); beforeEach(() => test.init(sampleData));
afterEach(() => test.cleanUp()); afterEach(() => test.cleanUp());
it('should persist results into varietyResults DB', () => { it('should persist results into varietyResults DB', async () => {
return test.runAnalysis({collection:'users', persistResults: true}, true) await test.runAnalysis({collection:'users', persistResults: true}, true);
.then(() => test.getDb('varietyResults')) const db = await test.getDb('varietyResults');
.then((db) => db.collection('usersKeys').find().toArray()) const arr = await db.collection('usersKeys').find().toArray();
.then((arr) => { assert.equal(arr.length, 7);
assert.equal(arr.length, 7); const keys = arr.map(it => it._id.key);
let keys = arr.map(it => it._id.key); assert.deepEqual(keys, ['_id', 'name', 'bio', 'birthday', 'pets', 'someBinData', 'someWeirdLegacyKey']);
assert.deepEqual(keys, ['_id', 'name', 'bio', 'birthday', 'pets', 'someBinData', 'someWeirdLegacyKey']);
});
}); });
}); });
const assert = require('assert'); import assert from 'assert';
const Tester = require('./utils/Tester.js'); import Tester from './utils/Tester.js';
const path = require('path'); import { resolve, join } from 'path';
const test = new Tester('test', 'users'); import sampleData from './assets/SampleData';
const sampleData = require('./assets/SampleData'); const test = new Tester('test', 'users');
const expectedOutput = ` const expectedOutput = `
key|types|occurrences|percents key|types|occurrences|percents
...@@ -16,24 +16,22 @@ someBinData|BinData-generic|1|20 ...@@ -16,24 +16,22 @@ someBinData|BinData-generic|1|20
someWeirdLegacyKey|String|1|20 someWeirdLegacyKey|String|1|20
`.trim(); `.trim();
const getPluginPath = () => path.resolve(path.join(__dirname , 'assets', 'csvplugin.js')); const getPluginPath = () => resolve(join(__dirname , 'assets', 'csvplugin.js'));
describe('Plugins', () => { describe('Plugins', () => {
beforeEach(() => test.init(sampleData)); beforeEach(() => test.init(sampleData));
afterEach(() => test.cleanUp()); afterEach(() => test.cleanUp());
it('should load plugin and modify output', () => { it('should load plugin and modify output', async () => {
return test.runAnalysis({collection:'users', plugins: getPluginPath()}, true).then(output => { const output = await test.runAnalysis({collection:'users', plugins: getPluginPath()}, true);
assert.equal(output, expectedOutput); assert.equal(output, expectedOutput);
});
}); });
it('should read additional plugin params', () => { it('should read additional plugin params', async () => {
return test.runAnalysis({collection:'users', plugins: getPluginPath() + '|delimiter=;'}, true).then(output => { const output = await test.runAnalysis({collection:'users', plugins: getPluginPath() + '|delimiter=;'}, true);
const expectedWithSeparator = expectedOutput.replace(/\|/g, ';'); const expectedWithSeparator = expectedOutput.replace(/\|/g, ';');
assert.equal(output, expectedWithSeparator); assert.equal(output, expectedWithSeparator);
});
}); });
}); });
const Tester = require('./utils/Tester.js'); import Tester from './utils/Tester.js';
import sampleData from './assets/SampleData';
const test = new Tester('test', 'users'); const test = new Tester('test', 'users');
const sampleData = require('./assets/SampleData');
describe('Query-limited analysis', () => { describe('Query-limited analysis', () => {
beforeEach(() => test.init(sampleData)); beforeEach(() => test.init(sampleData));
afterEach(() => test.cleanUp()); afterEach(() => test.cleanUp());
it('should return only filtered values', () => { it('should return only filtered values', async () => {
return test.runJsonAnalysis({collection:'users', query:{birthday:{$exists: true}}}).then(results => { const results = await test.runJsonAnalysis({collection:'users', query:{birthday:{$exists: true}}});
results.validateResultsCount(5); results.validateResultsCount(5);
results.validate('_id', 2, 100.0, {ObjectId: 2}); results.validate('_id', 2, 100.0, {ObjectId: 2});
results.validate('birthday', 2, 100.0, {Date: 2}); results.validate('birthday', 2, 100.0, {Date: 2});
results.validate('name', 2, 100.0, {String: 2}); results.validate('name', 2, 100.0, {String: 2});
results.validate('bio', 1, 50.0, {String: 1}); results.validate('bio', 1, 50.0, {String: 1});
results.validate('pets', 1, 50.0, {String: 1}); results.validate('pets', 1, 50.0, {String: 1});
});
}); });
}); });
const Tester = require('./utils/Tester.js'); import Tester from './utils/Tester.js';
const test = new Tester('test', 'users'); import sampleData from './assets/SampleData';
const sampleData = require('./assets/SampleData'); const test = new Tester('test', 'users');
describe('Sorted-data analysis', () => { describe('Sorted-data analysis', () => {
beforeEach(() => test.init(sampleData)); beforeEach(() => test.init(sampleData));
afterEach(() => test.cleanUp()); afterEach(() => test.cleanUp());
it('should not exclude any results', () => { it('should not exclude any results', async () => {
return test.runJsonAnalysis({collection:'users', sort:{name:-1}}).then(results => { const results = await test.runJsonAnalysis({collection:'users', sort:{name:-1}});
results.validateResultsCount(7); results.validateResultsCount(7);
results.validate('_id', 5, 100.0, {ObjectId: 5}); results.validate('_id', 5, 100.0, {ObjectId: 5});
results.validate('name', 5, 100.0, {String: 5}); results.validate('name', 5, 100.0, {String: 5});
results.validate('bio', 3, 60.0, {String: 3}); results.validate('bio', 3, 60.0, {String: 3});
results.validate('birthday', 2, 40.0, {Date: 2}); results.validate('birthday', 2, 40.0, {Date: 2});
results.validate('pets', 2, 40.0, {String: 1, Array: 1}); results.validate('pets', 2, 40.0, {String: 1, Array: 1});
results.validate('someBinData', 1, 20.0, {'BinData-generic': 1}); results.validate('someBinData', 1, 20.0, {'BinData-generic': 1});
results.validate('someWeirdLegacyKey', 1, 20.0, {String: 1}); results.validate('someWeirdLegacyKey', 1, 20.0, {String: 1});
});
}); });
it('should sort and apply limit', () => { it('should sort and apply limit', async () => {
const criteria = { const criteria = {
collection:'users', collection:'users',
sort:{name:-1}, sort:{name:-1},
...@@ -32,13 +31,12 @@ describe('Sorted-data analysis', () => { ...@@ -32,13 +31,12 @@ describe('Sorted-data analysis', () => {
// Together with applying limit 1, Tom is the only result in analysis. That gives us chance to assume keys and verify // Together with applying limit 1, Tom is the only result in analysis. That gives us chance to assume keys and verify
// that ordering is correct. // that ordering is correct.
// {name: "Tom", bio: "A nice guy.", pets: ["monkey", "fish"], someWeirdLegacyKey: "I like Ike!"} // {name: "Tom", bio: "A nice guy.", pets: ["monkey", "fish"], someWeirdLegacyKey: "I like Ike!"}
return test.runJsonAnalysis(criteria).then(results => { const results = await test.runJsonAnalysis(criteria);
results.validateResultsCount(5); results.validateResultsCount(5);
results.validate('_id', 1, 100.0, {ObjectId: 1}); results.validate('_id', 1, 100.0, {ObjectId: 1});
results.validate('name', 1, 100.0, {String: 1}); results.validate('name', 1, 100.0, {String: 1});
results.validate('bio', 1, 100.0, {String: 1}); results.validate('bio', 1, 100.0, {String: 1});
results.validate('pets', 1, 100.0, {Array: 1}); results.validate('pets', 1, 100.0, {Array: 1});
results.validate('someWeirdLegacyKey', 1, 100.0, {String: 1}); results.validate('someWeirdLegacyKey', 1, 100.0, {String: 1});
});
}); });
}); });
const Tester = require('./utils/Tester.js'); import Tester from './utils/Tester.js';
const test = new Tester('test', 'users'); const test = new Tester('test', 'users');
const sampleData = [ const sampleData = [
...@@ -14,18 +14,17 @@ describe('Unnamed object analysis', () => { ...@@ -14,18 +14,17 @@ describe('Unnamed object analysis', () => {
beforeEach(() => test.init(sampleData)); beforeEach(() => test.init(sampleData));
afterEach(() => test.cleanUp()); afterEach(() => test.cleanUp());
it('should handle keys of unnamed object', () => { it('should handle keys of unnamed object', async () => {
return test.runJsonAnalysis({collection:'users'}, true) const results = await test.runJsonAnalysis({collection:'users'}, true);
.then(results => {
results.validateResultsCount(6);
results.validate('_id', 2, 100.0, {ObjectId: 2});
results.validate('title', 2, 100.0, {String: 2});
results.validate('comments', 2, 100.0, {Array: 2});
// unnamed objects are prefixed with .XX key results.validateResultsCount(6);
results.validate('comments.XX.author', 2, 100.0, {String: 2}); results.validate('_id', 2, 100.0, {ObjectId: 2});
results.validate('comments.XX.body', 2, 100.0, {String: 2, Number:1}); results.validate('title', 2, 100.0, {String: 2});
results.validate('comments.XX.visible', 1, 50.0, {Boolean: 1}); results.validate('comments', 2, 100.0, {Array: 2});
});
// unnamed objects are prefixed with .XX key
results.validate('comments.XX.author', 2, 100.0, {String: 2});
results.validate('comments.XX.body', 2, 100.0, {String: 2, Number:1});
results.validate('comments.XX.visible', 1, 50.0, {Boolean: 1});
}); });
}); });
module.exports =` export default `
+--------------------------------------------------------------------+ +--------------------------------------------------------------------+
| key | types | occurrences | percents | | key | types | occurrences | percents |
......
var Binary = require('mongodb').Binary; import { Binary } from 'mongodb';
module.exports = [{ export default [{
'name': 'Tom', 'name': 'Tom',
'bio': 'A nice guy.', 'bio': 'A nice guy.',
'pets': ['monkey', 'fish'], 'pets': ['monkey', 'fish'],
......
'use strict'; 'use strict';
const assert = require('assert'); import { equal, deepEqual } from 'assert';
class JsonValidator { export default class JsonValidator {
constructor(results) { constructor(results) {
this.results = results; this.results = results;
} }
validate(key, totalOccurrences, percentContaining, types) { validate(key, totalOccurrences, percentContaining, types) {
let row = this.results.filter(item => item._id.key === key)[0]; const row = this.results.filter(item => item._id.key === key)[0];
if(typeof row === 'undefined') { if(typeof row === 'undefined') {
throw new Error(`Key '${key}' is not present in results`); throw new Error(`Key '${key}' is not present in results`);
} }
assert.equal(row.totalOccurrences, totalOccurrences, `TotalOccurrences of key ${key} does not match`); equal(row.totalOccurrences, totalOccurrences, `TotalOccurrences of key ${key} does not match`);
assert.equal(row.percentContaining, percentContaining, `PercentContaining of key ${key} does not match`); equal(row.percentContaining, percentContaining, `PercentContaining of key ${key} does not match`);
assert.deepEqual(row.value.types, types, `Types of key ${key} do not match`); deepEqual(row.value.types, types, `Types of key ${key} do not match`);
} }
validateResultsCount(count) { validateResultsCount(count) {
assert.equal(this.results.length, count, 'Total count of results does not match expected count.'); equal(this.results.length, count, 'Total count of results does not match expected count.');
} }
} }
module.exports = JsonValidator;
'use strict'; 'use strict';
const exec = require('child-process-promise').exec; import { exec } from 'child-process-promise';
const execute = (database, credentials, args, script, quiet, port) => { export default async (database, credentials, args, script, quiet, port) => {
let commands = ['mongo']; const commands = ['mongo'];
commands.push('--port'); commands.push('--port');
commands.push(port); commands.push(port);
...@@ -33,10 +33,6 @@ const execute = (database, credentials, args, script, quiet, port) => { ...@@ -33,10 +33,6 @@ const execute = (database, credentials, args, script, quiet, port) => {
commands.push(script); commands.push(script);
} }
return exec(commands.join(' ')) const result = await exec(commands.join(' '));
.then(result => result.stdout.trim()); return result.stdout.trim();
};
module.exports = {
execute:execute
}; };
'use strict'; 'use strict';
const path = require('path'); import { resolve, join } from 'path';
const Q = require('q'); import { MongoClient } from 'mongodb';
const MongoClient = require('mongodb').MongoClient; import execute from './MongoShell';
const shell = require('./MongoShell'); import JsonValidator from './JsonValidator';
const JsonValidator = require('./JsonValidator');
const mongodb_port = process.env.MONGODB_PORT || 27017; const mongodb_port = process.env.MONGODB_PORT || 27017;
const default_url = `mongodb://localhost:${mongodb_port}/test?autoReconnect=true`; const default_url = `mongodb://localhost:${mongodb_port}/test?autoReconnect=true`;
class Tester { export default class Tester {
constructor(databaseName, collectionName) { constructor(databaseName, collectionName) {
this.databaseName = databaseName; this.databaseName = databaseName;
this.collectionName = collectionName; this.collectionName = collectionName;
} }
connect() { async connect() {
return Q.nfcall(MongoClient.connect, default_url) const connection = await MongoClient.connect(default_url);
.then((connection) => { this.connection = connection;
this.connection = connection; this.coll = connection.db(this.databaseName).collection(this.collectionName);
this.coll = connection.db(this.databaseName).collection(this.collectionName); return connection;
return connection;
});
} }
init(initialData) { async init(initialData) {
return this.connect() var connection = await this.connect();
.then(() => this.coll.deleteMany()) await this.coll.deleteMany();
.then(() => this.coll.insertMany(initialData)) await this.coll.insertMany(initialData);
.then(() => this.connection); return connection;
} }
cleanUp() { async cleanUp() {
return this.coll.deleteMany() await this.coll.deleteMany();
.then(() => this.connection.close()); await this.connection.close();
} }
getDb(dbName) { getDb(dbName) {
return Q(this.connection.db(dbName)); return this.connection.db(dbName);
} }
getVarietyPath() { getVarietyPath() {
return path.resolve(path.join(__dirname , '..', '..', 'variety.js')); return resolve(join(__dirname , '..', '..', 'variety.js'));
} }
runJsonAnalysis(options) { async runJsonAnalysis(options) {
options.outputFormat = 'json'; options.outputFormat = 'json';
return this.runAnalysis(options, true) const result = await this.runAnalysis(options, true);
.then(JSON.parse) return new JsonValidator(JSON.parse(result));
.then(data => new JsonValidator(data));
} }
...@@ -60,8 +56,6 @@ class Tester { ...@@ -60,8 +56,6 @@ class Tester {
str.push(`var ${key}=${value}`); str.push(`var ${key}=${value}`);
} }
} }
return shell.execute(this.database, null, '"' + str.join(';') + '"', this.getVarietyPath(), quiet, mongodb_port); return execute(this.database, null, '"' + str.join(';') + '"', this.getVarietyPath(), quiet, mongodb_port);
} }
} }
module.exports = Tester;
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment