more tests, added contributing.md and license.md
This commit is contained in:
@ -0,0 +1,47 @@
|
|||||||
|
If you have a bugfix or new feature that you would like to contribute to elasticsearch.js please feel free to submit a pull request, or open an issue for discussion. If your change is adding new functionality, you should open an issue ***before*** writing any code.
|
||||||
|
|
||||||
|
The process for contributing to any of the Elasticsearch repositories is similar.
|
||||||
|
|
||||||
|
1. Lint your codes
|
||||||
|
|
||||||
|
While developing, be sure to run JSHint on the files you modify. This is simple with most IDE's and the project has .jshintrc files in the proper places, make sure jshint is using them.
|
||||||
|
|
||||||
|
We use the `"white": true` jshint config option to enforce style, but the
|
||||||
|
|
||||||
|
2. Write tests
|
||||||
|
|
||||||
|
Please write test cases to exercise your changes.
|
||||||
|
|
||||||
|
2. When you're ready to run the tests
|
||||||
|
|
||||||
|
Call `npm test` which executes `scripts/run_tests.js`.
|
||||||
|
|
||||||
|
```sh
|
||||||
|
$ node scripts/run_tests.js --help
|
||||||
|
|
||||||
|
Runner for the Elasticsearch.js Unit and Integration tests in both node and the browser.
|
||||||
|
Specify --no-{{flag}} to negate it.
|
||||||
|
|
||||||
|
Options:
|
||||||
|
--server [true]
|
||||||
|
--browser [true]
|
||||||
|
--unit [true]
|
||||||
|
--integration [false]
|
||||||
|
--port [9200]
|
||||||
|
--host ["localhost"] hostname for elasticsearch instance used in integration tests
|
||||||
|
--check-upstream [false] check for remote updates to the yaml test suite
|
||||||
|
```
|
||||||
|
|
||||||
|
3. Submit a pull request
|
||||||
|
|
||||||
|
Push your local changes to your forked copy of the repository and submit a pull request. In the pull request, describe what your changes do and be sure to link to any conversations regarding this implementation, eg "Closes #123".
|
||||||
|
|
||||||
|
4. Sign the CLA
|
||||||
|
|
||||||
|
Please make sure you have signed the [Contributor License Agreement](http://www.elasticsearch.org/contributor-agreement/). We are not asking you to assign copyright to us, but to give us the right to distribute your code without restriction. We ask this of all contributors in order to assure our users of the origin and continuing existence of the code. You only need to sign the CLA once.
|
||||||
|
|
||||||
|
5. Grab a beer
|
||||||
|
|
||||||
|
There will probably be discussion about the pull request and we will work with you if any changes are needed.
|
||||||
|
|
||||||
|
6. Know that we greatly apreciate your help!! :D
|
||||||
|
|||||||
13
LICENSE.md
13
LICENSE.md
@ -0,0 +1,13 @@
|
|||||||
|
Copyright 2012-2013 Elasticsearch BV
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License"); you
|
||||||
|
may not use this file except in compliance with the License. You may
|
||||||
|
obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||||
|
implied. See the License for the specific language governing
|
||||||
|
permissions and limitations under the License.
|
||||||
|
|||||||
@ -49,6 +49,7 @@
|
|||||||
},
|
},
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"test": "node scripts/run_tests.js",
|
"test": "node scripts/run_tests.js",
|
||||||
|
"coverage": "mocha test/unit/test_*.js --require blanket -R html-cov > coverage.html && open -a \"Google Chrome\" ./coverage.html",
|
||||||
"build": "grunt",
|
"build": "grunt",
|
||||||
"generate": "node scripts/generate/js_api && node scripts/generate/yaml_tests",
|
"generate": "node scripts/generate/js_api && node scripts/generate/yaml_tests",
|
||||||
"export_client": "node scripts/export_client.js",
|
"export_client": "node scripts/export_client.js",
|
||||||
|
|||||||
@ -2,59 +2,91 @@ var async = require('async');
|
|||||||
var cp = require('child_process');
|
var cp = require('child_process');
|
||||||
var chalk = require('chalk');
|
var chalk = require('chalk');
|
||||||
var argv = require('optimist')
|
var argv = require('optimist')
|
||||||
|
.usage([
|
||||||
|
'Runner for the Elasticsearch.js unit and integration tests in both node and the browser.',
|
||||||
|
'Specify --no-{{flag}} to negate it.'
|
||||||
|
].join('\n'))
|
||||||
.default({
|
.default({
|
||||||
'check-upstream': false,
|
server: true,
|
||||||
'in-node': true,
|
browser: true,
|
||||||
'in-browser': true,
|
unit: true,
|
||||||
'not-in-node': false,
|
integration: false,
|
||||||
'not-in-browser': false,
|
host: 'localhost',
|
||||||
'unit': true,
|
port: 9200,
|
||||||
'integration': true
|
'check-upstream': false
|
||||||
|
})
|
||||||
|
.describe({
|
||||||
|
host: 'hostname for elasticsearch instance used in integration tests',
|
||||||
|
'check-upstream': 'check for remote updates to the yaml test suite'
|
||||||
})
|
})
|
||||||
.alias({
|
.alias({
|
||||||
u: 'unit',
|
u: 'unit',
|
||||||
i: 'integration',
|
i: 'integration',
|
||||||
b: 'in-browser',
|
b: 'browser',
|
||||||
n: 'in-node',
|
s: 'server',
|
||||||
})
|
});
|
||||||
.parse(JSON.parse(process.env.npm_config_argv).original);
|
|
||||||
|
|
||||||
if (argv['not-in-browser']) {
|
if (process.argv.indexOf('help') + process.argv.indexOf('--help') + process.argv.indexOf('-h') !== -3) {
|
||||||
argv.b = argv['in-browser'] = false;
|
argv.showHelp();
|
||||||
|
process.exit(1);
|
||||||
}
|
}
|
||||||
if (argv['not-in-node']) {
|
|
||||||
argv.n = argv['in-node'] = false;
|
if (process.env.npm_config_argv) {
|
||||||
|
// when called by NPM
|
||||||
|
argv = argv.parse(JSON.parse(process.env.npm_config_argv).original);
|
||||||
|
} else {
|
||||||
|
// when called by NPM - via `npm test`
|
||||||
|
argv = argv.argv;
|
||||||
}
|
}
|
||||||
|
|
||||||
var commands = [];
|
var commands = [];
|
||||||
|
|
||||||
|
if (argv['just-browser']) {
|
||||||
|
argv.server = false;
|
||||||
|
argv.browser = true;
|
||||||
|
}
|
||||||
|
|
||||||
if (argv['check-upstream']) {
|
if (argv['check-upstream']) {
|
||||||
commands.push(['node', 'scripts/generate/yaml_tests/index.js']);
|
commands.push(['node', 'scripts/generate/yaml_tests/index.js']);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (argv.unit) {
|
if (argv.unit) {
|
||||||
if (argv['in-node']) {
|
if (argv.server) {
|
||||||
commands.push(['mocha', 'test/unit/test_*.js', '--require=should']);
|
commands.push(['mocha', 'test/unit/test_*.js', '--require=should']);
|
||||||
}
|
}
|
||||||
if (argv['in-browser']) {
|
if (argv.browser) {
|
||||||
commands.push(['testling', '.']);
|
commands.push(['testling', '.']);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (argv.integration) {
|
if (argv.integration) {
|
||||||
if (argv['in-node']) {
|
if (argv.server) {
|
||||||
commands.push(['mocha', 'test/integration/yaml_suite/index.js', '-b', '--require=should']);
|
commands.push([
|
||||||
|
'mocha',
|
||||||
|
'test/integration/yaml_suite/index.js',
|
||||||
|
'-b',
|
||||||
|
'--require=should',
|
||||||
|
'--host=' + argv.host,
|
||||||
|
'--port=' + argv.port
|
||||||
|
]);
|
||||||
}
|
}
|
||||||
if (argv['in-browser']) {
|
if (argv.browser) {
|
||||||
commands.push(['node', 'scripts/run_browser_integration_suite/index.js']);
|
commands.push(['node', 'scripts/run_browser_integration_suite/index.js']);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var proc = null;
|
||||||
|
process.on('exit', function () {
|
||||||
|
if (proc && proc.kill) {
|
||||||
|
proc.kill();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
if (commands.length) {
|
if (commands.length) {
|
||||||
async.forEachSeries(commands, function (args, done) {
|
async.forEachSeries(commands, function (args, done) {
|
||||||
var command = args.shift();
|
var command = args.shift();
|
||||||
console.log(chalk.gray('\n\n' + '# ' + command + ' ' + args.join(' ')));
|
console.log(chalk.gray.bold('\n\n' + '# ' + command + ' ' + args.join(' ')));
|
||||||
var proc = cp.spawn(command, args, {
|
proc = cp.spawn(command, args, {
|
||||||
stdio: 'inherit'
|
stdio: 'inherit'
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -69,9 +101,11 @@ if (commands.length) {
|
|||||||
});
|
});
|
||||||
}, function (err) {
|
}, function (err) {
|
||||||
if (err) {
|
if (err) {
|
||||||
|
console.log(chalk.red('\n\n⚑⚑⚑︎ Error! ⚑⚑⚑'));
|
||||||
console.error(err.message);
|
console.error(err.message);
|
||||||
process.exit(1);
|
process.exit(1);
|
||||||
} else {
|
} else {
|
||||||
|
console.log(chalk.green('\n\n✔︎ looks good\n\n'));
|
||||||
process.exit(0);
|
process.exit(0);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|||||||
@ -31,6 +31,13 @@ var ca = require('./client_action');
|
|||||||
var Transport = require('./transport');
|
var Transport = require('./transport');
|
||||||
|
|
||||||
function Client(config) {
|
function Client(config) {
|
||||||
|
config = config || {};
|
||||||
|
|
||||||
|
// our client will log minimally by default
|
||||||
|
if (!config.hasOwnProperty('log')) {
|
||||||
|
config.log = 'warning';
|
||||||
|
}
|
||||||
|
|
||||||
this.transport = new Transport(config);
|
this.transport = new Transport(config);
|
||||||
|
|
||||||
// instantiate the api's namespaces
|
// instantiate the api's namespaces
|
||||||
|
|||||||
@ -45,7 +45,11 @@ var castType = {
|
|||||||
return param.options[i];
|
return param.options[i];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
throw new TypeError('Invalid ' + name + ': expected one of ' + param.options.join(','));
|
throw new TypeError('Invalid ' + name + ': expected ' + (
|
||||||
|
param.options.length > 1
|
||||||
|
? 'one of ' + param.options.join(',')
|
||||||
|
: param.options[0]
|
||||||
|
));
|
||||||
},
|
},
|
||||||
duration: function (param, val, name) {
|
duration: function (param, val, name) {
|
||||||
if (_.isNumeric(val) || _.isInterval(val)) {
|
if (_.isNumeric(val) || _.isInterval(val)) {
|
||||||
|
|||||||
@ -7,25 +7,12 @@ module.exports = Transport;
|
|||||||
var _ = require('./utils');
|
var _ = require('./utils');
|
||||||
var errors = require('./errors');
|
var errors = require('./errors');
|
||||||
var Host = require('./host');
|
var Host = require('./host');
|
||||||
var Log = require('./log');
|
|
||||||
var when = require('when');
|
var when = require('when');
|
||||||
|
|
||||||
function Transport(config) {
|
function Transport(config) {
|
||||||
config = config || {};
|
config = config || {};
|
||||||
|
|
||||||
var LogClass;
|
var LogClass = _.funcEnum(config, 'logClass', Transport.logs, 'main');
|
||||||
// setup the log
|
|
||||||
switch (typeof config.log) {
|
|
||||||
case 'function':
|
|
||||||
LogClass = config.log;
|
|
||||||
break;
|
|
||||||
case 'undefined':
|
|
||||||
config.log = 'warning';
|
|
||||||
/* fall through */
|
|
||||||
default:
|
|
||||||
LogClass = Log;
|
|
||||||
}
|
|
||||||
|
|
||||||
config.log = this.log = new LogClass(config);
|
config.log = this.log = new LogClass(config);
|
||||||
|
|
||||||
// overwrite the createDefer method if a new implementation is provided
|
// overwrite the createDefer method if a new implementation is provided
|
||||||
@ -37,25 +24,31 @@ function Transport(config) {
|
|||||||
var ConnectionPool = _.funcEnum(config, 'connectionPool', Transport.connectionPools, 'main');
|
var ConnectionPool = _.funcEnum(config, 'connectionPool', Transport.connectionPools, 'main');
|
||||||
this.connectionPool = new ConnectionPool(config);
|
this.connectionPool = new ConnectionPool(config);
|
||||||
|
|
||||||
|
// setup the serializer
|
||||||
|
var Serializer = _.funcEnum(config, 'serializer', Transport.serializers, 'json');
|
||||||
|
this.serializer = new Serializer(config);
|
||||||
|
|
||||||
if (config.hosts) {
|
if (config.hosts) {
|
||||||
var hosts = _.createArray(config.hosts, function (val) {
|
var hostsConfig = _.createArray(config.hosts, function (val) {
|
||||||
if (_.isPlainObject(val) || _.isString(val)) {
|
if (_.isPlainObject(val) || _.isString(val)) {
|
||||||
return val;
|
return val;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
if (!hosts) {
|
if (!hostsConfig) {
|
||||||
throw new Error('Invalid hosts config. Expected a URL, an array of urls, a host config object, or an array of ' +
|
throw new Error('Invalid hosts config. Expected a URL, an array of urls, a host config object, or an array of ' +
|
||||||
'host config objects.');
|
'host config objects.');
|
||||||
}
|
}
|
||||||
|
|
||||||
this.connectionPool.setHosts(_.map(hosts, function (conf) {
|
var hosts = _.map(hostsConfig, function (conf) {
|
||||||
return new Host(conf);
|
return new Host(conf);
|
||||||
}));
|
});
|
||||||
}
|
|
||||||
|
|
||||||
// setup the serializer
|
if (config.randomizeHosts) {
|
||||||
var Serializer = _.funcEnum(config, 'serializer', Transport.serializers, 'json');
|
hosts = _.shuffle(hosts);
|
||||||
this.serializer = new Serializer(config);
|
}
|
||||||
|
|
||||||
|
this.connectionPool.setHosts(hosts);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Transport.connectionPools = {
|
Transport.connectionPools = {
|
||||||
@ -66,6 +59,10 @@ Transport.serializers = {
|
|||||||
json: require('./serializers/json')
|
json: require('./serializers/json')
|
||||||
};
|
};
|
||||||
|
|
||||||
|
Transport.logs = {
|
||||||
|
main: require('./log')
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Perform a request with the client's transport
|
* Perform a request with the client's transport
|
||||||
*
|
*
|
||||||
|
|||||||
@ -399,13 +399,23 @@ _.funcEnum = function (config, name, opts, def) {
|
|||||||
case 'function':
|
case 'function':
|
||||||
return val;
|
return val;
|
||||||
case 'string':
|
case 'string':
|
||||||
if (opts[val]) {
|
if (opts.hasOwnProperty(val)) {
|
||||||
return opts[val];
|
return opts[val];
|
||||||
}
|
}
|
||||||
/* falls through */
|
/* falls through */
|
||||||
default:
|
default:
|
||||||
throw new TypeError('Invalid ' + name + ' "' + val + '", expected a function or one of ' +
|
var err = 'Invalid ' + name + ' "' + val + '", expected a function';
|
||||||
_.keys(opts).join(', '));
|
switch (_.size(opts)) {
|
||||||
|
case 0:
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
err += 'or ' + _.keys(opts)[0];
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
err += 'or one of ' + _.keys(opts).join(', ');
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
throw new TypeError(err);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
79
test/unit/test_transport.js
Normal file
79
test/unit/test_transport.js
Normal file
@ -0,0 +1,79 @@
|
|||||||
|
var Transport = require('../../src/lib/transport');
|
||||||
|
|
||||||
|
describe('Transport Class', function () {
|
||||||
|
|
||||||
|
describe('Constructor', function () {
|
||||||
|
|
||||||
|
it('Accepts a log class and intanciates it at this.log', function () {
|
||||||
|
function CustomLogClass() {}
|
||||||
|
var trans = new Transport({
|
||||||
|
logClass: CustomLogClass
|
||||||
|
});
|
||||||
|
|
||||||
|
trans.log.should.be.an.instanceOf(CustomLogClass);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('Accepts the name of a log class that is defined on Transport.logs', function () {
|
||||||
|
Transport.logs.custom = function () {
|
||||||
|
// custom logger class!
|
||||||
|
};
|
||||||
|
|
||||||
|
var trans = new Transport({
|
||||||
|
logClass: 'custom'
|
||||||
|
});
|
||||||
|
|
||||||
|
trans.log.should.be.an.instanceOf(Transport.logs.custom);
|
||||||
|
delete Transport.logs.custom;
|
||||||
|
});
|
||||||
|
|
||||||
|
it('Accepts a "createDefer" function, which can be used to tie into other promise libs.', function () {
|
||||||
|
function CustomPromise() {
|
||||||
|
this.then = function () {};
|
||||||
|
}
|
||||||
|
|
||||||
|
var trans = new Transport({
|
||||||
|
createDefer: function () {
|
||||||
|
return new CustomPromise();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
trans.createDefer().should.be.an.instanceOf(CustomPromise);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('Accepts a connection pool class and intanciates it at this.connectionPool', function () {
|
||||||
|
function CustomConnectionPool() {}
|
||||||
|
var trans = new Transport({
|
||||||
|
connectionPool: CustomConnectionPool
|
||||||
|
});
|
||||||
|
|
||||||
|
trans.connectionPool.should.be.an.instanceOf(CustomConnectionPool);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('Accepts the name of a connectionPool class that is defined on Transport.connectionPools', function () {
|
||||||
|
Transport.connectionPools.custom = function () {};
|
||||||
|
|
||||||
|
var trans = new Transport({
|
||||||
|
connectionPool: 'custom'
|
||||||
|
});
|
||||||
|
|
||||||
|
trans.connectionPool.should.be.an.instanceOf(Transport.connectionPools.custom);
|
||||||
|
delete Transport.connectionPools.custom;
|
||||||
|
});
|
||||||
|
|
||||||
|
it('Throws an error when the logClass or connectionPool configs are set wrong', function () {
|
||||||
|
(function () {
|
||||||
|
var trans = new Transport({
|
||||||
|
connectionPool: 'pasta'
|
||||||
|
});
|
||||||
|
}).should.throw(/invalid connectionpool/i);
|
||||||
|
|
||||||
|
(function () {
|
||||||
|
var trans = new Transport({
|
||||||
|
logClass: 'pasta'
|
||||||
|
});
|
||||||
|
}).should.throw(/invalid logclass/i);
|
||||||
|
});
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
});
|
||||||
@ -291,4 +291,39 @@ describe('Utils', function () {
|
|||||||
}).should.be.exactly(false);
|
}).should.be.exactly(false);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
describe('#funcEnum', function () {
|
||||||
|
/*
|
||||||
|
* _.funcEnum(object, key, opts, default);
|
||||||
|
*/
|
||||||
|
it('tests if the value at key in object is a function, returns it if so', function () {
|
||||||
|
var config = {
|
||||||
|
func: function () {}
|
||||||
|
};
|
||||||
|
_.funcEnum(config, 'func', {}, 'toString')
|
||||||
|
.should.be.exactly(config.func);
|
||||||
|
});
|
||||||
|
it('tests if the value at key in object is undefined, returns the option at key default if so', function () {
|
||||||
|
var config = {
|
||||||
|
func: undefined
|
||||||
|
};
|
||||||
|
_.funcEnum(config, 'func', {}, 'toString')
|
||||||
|
.should.be.exactly(Object.prototype.toString);
|
||||||
|
});
|
||||||
|
it('tests if the value at key in object is a string, returns the option at that key if so', function () {
|
||||||
|
var config = {
|
||||||
|
'config key name': 'toString'
|
||||||
|
};
|
||||||
|
_.funcEnum(config, 'config key name', { toString: 'pizza' }, 'toJSON')
|
||||||
|
.should.be.exactly('pizza');
|
||||||
|
});
|
||||||
|
it('throws an error if the selection if invalid', function () {
|
||||||
|
var config = {
|
||||||
|
'config': 'val'
|
||||||
|
};
|
||||||
|
(function () {
|
||||||
|
_.funcEnum(config, 'config', { main: 'default' }, 'main');
|
||||||
|
}).should.throw(/invalid config/i);
|
||||||
|
});
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
Reference in New Issue
Block a user