Major updates for testing and grunt, jenkins tests are now powered by the jenkins.sh script in the scripts directory.
This commit is contained in:
1
.gitignore
vendored
1
.gitignore
vendored
@ -8,6 +8,7 @@ test/integration/yaml_suite/log
|
||||
|
||||
## generated files
|
||||
scripts/last_rest_spec_update.sha
|
||||
test/integration/yaml_suite/yaml_tests.json
|
||||
test/browser_integration/yaml_tests.js
|
||||
test-output-*.xml
|
||||
coverage.html
|
||||
|
||||
3
.gitmodules
vendored
Normal file
3
.gitmodules
vendored
Normal file
@ -0,0 +1,3 @@
|
||||
[submodule "src/rest-api-spec"]
|
||||
path = src/rest-api-spec
|
||||
url = git@github.com:elasticsearch/elasticsearch-rest-api-spec.git
|
||||
18
README.md
18
README.md
@ -66,3 +66,21 @@ bower install elasticsearch-jquery
|
||||
- [Extending Core Components](http://spenceralger.github.io/elasticsearch-js/index.html#extending)
|
||||
- [Logging](http://spenceralger.github.io/elasticsearch-js/index.html#logging)
|
||||
- [Contributing](http://spenceralger.github.io/elasticsearch-js/index.html#contributing)
|
||||
|
||||
## License
|
||||
|
||||
This software is licensed under the Apache 2 license, quoted below.
|
||||
|
||||
Copyright (c) 2013 Elasticsearch <http://www.elasticsearch.org>
|
||||
|
||||
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.
|
||||
@ -1,5 +1,5 @@
|
||||
module.exports = function (grunt) {
|
||||
grunt.registerTask('build', [
|
||||
grunt.registerTask('browser_clients_build', [
|
||||
'clean:dist',
|
||||
'browserify',
|
||||
'uglify:dist',
|
||||
30
grunt/browser_clients_export.js
Normal file
30
grunt/browser_clients_export.js
Normal file
@ -0,0 +1,30 @@
|
||||
module.exports = function (grunt) {
|
||||
grunt.registerTask('export_client', function (build, outDir) {
|
||||
var path = require('path');
|
||||
|
||||
grunt.config.set('copy.export_client', {
|
||||
expand: true,
|
||||
cwd: './dist/',
|
||||
src: 'elasticsearch' + (build ? '.' + build : '') + '{.min,}.js',
|
||||
dest: outDir,
|
||||
rename: function (dest, src) {
|
||||
return path.join(dest, 'elasticsearch' + (~src.indexOf('.min') ? '.min' : '') + '.js');
|
||||
}
|
||||
});
|
||||
|
||||
this.requires('build');
|
||||
|
||||
grunt.task.run([
|
||||
'copy:export_client'
|
||||
]);
|
||||
});
|
||||
|
||||
grunt.registerTask('export_all_clients', function () {
|
||||
grunt.task.run([
|
||||
'build',
|
||||
'export_client:angular:../bower-elasticsearch-angular',
|
||||
'export_client::../bower-elasticsearch-browser',
|
||||
'export_client:jquery:../bower-elasticsearch-jquery'
|
||||
]);
|
||||
});
|
||||
};
|
||||
10
grunt/browser_clients_publish.js
Normal file
10
grunt/browser_clients_publish.js
Normal file
@ -0,0 +1,10 @@
|
||||
module.exports = function (grunt) {
|
||||
|
||||
grunt.registerTask('browser_clients_publish', [
|
||||
'build_browser_clients',
|
||||
'compress:dist_zip',
|
||||
'compress:dist_tarball',
|
||||
's3:latest'
|
||||
]);
|
||||
|
||||
};
|
||||
10
grunt/browser_clients_release.js
Normal file
10
grunt/browser_clients_release.js
Normal file
@ -0,0 +1,10 @@
|
||||
module.exports = function (grunt) {
|
||||
|
||||
grunt.registerTask('browser_clients_release', [
|
||||
'build_browser_clients',
|
||||
'compress:dist_zip',
|
||||
'compress:dist_tarball',
|
||||
's3:release'
|
||||
]);
|
||||
|
||||
};
|
||||
@ -1,4 +1,18 @@
|
||||
module.exports = {
|
||||
yaml_suite: {
|
||||
options: {
|
||||
external: [
|
||||
'optimist'
|
||||
],
|
||||
ignore: [
|
||||
'test/integration/yaml_suite/reporter',
|
||||
'src/elasticsearch.js'
|
||||
]
|
||||
},
|
||||
files: {
|
||||
'test/integration/browser_yaml_suite/yaml_tests.js': 'test/integration/yaml_suite/index.js'
|
||||
}
|
||||
},
|
||||
browser_client: {
|
||||
files: {
|
||||
'<%= distDir %>/elasticsearch.js': 'src/elasticsearch.js'
|
||||
|
||||
14
grunt/config/compress.js
Normal file
14
grunt/config/compress.js
Normal file
@ -0,0 +1,14 @@
|
||||
module.exports = {
|
||||
dist_zip: {
|
||||
src: '<%= distDir %>/*.js',
|
||||
options: {
|
||||
archive: '<%= distDir %>/archives/elasticsearch-js.zip'
|
||||
}
|
||||
},
|
||||
dist_tarball: {
|
||||
src: '<%= distDir %>/*.js',
|
||||
options: {
|
||||
archive: '<%= distDir %>/archives/elasticsearch-js.tar.gz'
|
||||
}
|
||||
}
|
||||
};
|
||||
@ -4,6 +4,7 @@ module.exports = {
|
||||
'src/**/*.js',
|
||||
'scripts/**/*.js',
|
||||
'test/**/*.js -test/browser_integration/yaml_tests.js',
|
||||
'grunt/**/*.js',
|
||||
'Gruntfile.js'
|
||||
],
|
||||
options: {
|
||||
|
||||
8
grunt/config/mocha.js
Normal file
8
grunt/config/mocha.js
Normal file
@ -0,0 +1,8 @@
|
||||
module.exports = {
|
||||
unit: {
|
||||
src: ['test/unit/test_*.js'],
|
||||
reporter: 'XUnit',
|
||||
dest: './test-output-phantom-unit.xml',
|
||||
run: true
|
||||
}
|
||||
};
|
||||
43
grunt/config/run.js
Normal file
43
grunt/config/run.js
Normal file
@ -0,0 +1,43 @@
|
||||
module.exports = {
|
||||
generate: {
|
||||
exec: 'node scripts/generate'
|
||||
},
|
||||
unit_tests: {
|
||||
exec: 'node scripts/run_tests --unit --no-browsers',
|
||||
options: {
|
||||
passArgs: [
|
||||
'port',
|
||||
'host'
|
||||
]
|
||||
}
|
||||
},
|
||||
integration_tests: {
|
||||
exec: 'node scripts/run_tests --integration --no-browsers',
|
||||
options: {
|
||||
passArgs: [
|
||||
'port',
|
||||
'host'
|
||||
]
|
||||
}
|
||||
},
|
||||
browser_unit_tests: {
|
||||
exec: 'node scripts/run_tests --unit --no-server',
|
||||
options: {
|
||||
cwd: '.',
|
||||
passArgs: [
|
||||
'port',
|
||||
'host'
|
||||
]
|
||||
}
|
||||
},
|
||||
browser_integration_tests: {
|
||||
exec: 'node scripts/run_tests --integration --no-server',
|
||||
options: {
|
||||
cwd: '.',
|
||||
passArgs: [
|
||||
'port',
|
||||
'host'
|
||||
]
|
||||
}
|
||||
}
|
||||
};
|
||||
@ -1,17 +1,26 @@
|
||||
var config = require('../../.aws-config.json');
|
||||
var config = {};
|
||||
try {
|
||||
config = require('../../.aws-config.json');
|
||||
} catch (e) {}
|
||||
|
||||
|
||||
module.exports = {
|
||||
options: {
|
||||
key: config.key,
|
||||
secret: config.secret,
|
||||
bucket: 'download.elasticsearch.org',
|
||||
access: 'public-read'
|
||||
access: 'public-read',
|
||||
headers: {
|
||||
'Content-Type': 'text/plain',
|
||||
'X-Content-Type-Options': 'nosniff',
|
||||
'Content-Disposition': 'attachment'
|
||||
}
|
||||
},
|
||||
|
||||
latest: {
|
||||
upload: [
|
||||
{
|
||||
src: '<%= distDir %>/*.js',
|
||||
src: '<%= distDir %>/archives/*',
|
||||
dest: 'elasticsearch/elasticsearch-js/latest'
|
||||
}
|
||||
]
|
||||
@ -20,7 +29,7 @@ module.exports = {
|
||||
release: {
|
||||
upload: [
|
||||
{
|
||||
src: '<%= distDir %>/*.js',
|
||||
src: '<%= distDir %>/archives/*',
|
||||
dest: 'elasticsearch/elasticsearch-js/<%= package.version %>'
|
||||
}
|
||||
]
|
||||
|
||||
@ -2,7 +2,8 @@ module.exports = function (grunt) {
|
||||
|
||||
// Default task runs the build process.
|
||||
grunt.registerTask('default', [
|
||||
'build'
|
||||
'run:generate',
|
||||
'test'
|
||||
]);
|
||||
|
||||
};
|
||||
5
grunt/generate.js
Normal file
5
grunt/generate.js
Normal file
@ -0,0 +1,5 @@
|
||||
module.exports = function (grunt) {
|
||||
grunt.registerTask('generate', [
|
||||
'run:generate'
|
||||
]);
|
||||
};
|
||||
@ -1,8 +0,0 @@
|
||||
module.exports = function (grunt) {
|
||||
|
||||
grunt.registerTask('publish', [
|
||||
'build',
|
||||
's3:latest'
|
||||
]);
|
||||
|
||||
};
|
||||
@ -1,8 +0,0 @@
|
||||
module.exports = function (grunt) {
|
||||
|
||||
grunt.registerTask('release', [
|
||||
'build',
|
||||
's3:release'
|
||||
]);
|
||||
|
||||
};
|
||||
15
grunt/test.js
Normal file
15
grunt/test.js
Normal file
@ -0,0 +1,15 @@
|
||||
module.exports = function (grunt) {
|
||||
|
||||
grunt.registerTask('test', [
|
||||
'jshint',
|
||||
'run:unit_tests',
|
||||
'run:integration_tests'
|
||||
]);
|
||||
|
||||
grunt.registerTask('browser_clients_test', [
|
||||
'build',
|
||||
'run:browser_unit_tests',
|
||||
'run:browser_integration_tests'
|
||||
]);
|
||||
|
||||
};
|
||||
22
package.json
22
package.json
@ -9,7 +9,8 @@
|
||||
"version": "0.0.1",
|
||||
"browser": {
|
||||
"./src/lib/connectors/index.js": "./src/lib/connectors/browser_index.js",
|
||||
"./src/lib/loggers/index.js": "./src/lib/loggers/browser_index.js"
|
||||
"./src/lib/loggers/index.js": "./src/lib/loggers/browser_index.js",
|
||||
"./test/mocks/server.js": "./test/mocks/browser_server.js"
|
||||
},
|
||||
"devDependencies": {
|
||||
"tar": "~0.1.18",
|
||||
@ -36,12 +37,17 @@
|
||||
"mocha-lcov-reporter": "0.0.1",
|
||||
"blanket": "~1.1.5",
|
||||
"sinon": "~1.7.3",
|
||||
"nock": "~0.23.0",
|
||||
"nock": "git://github.com/spenceralger/nock.git#c5b07103eb3058035b99118d343ee0dfca666107",
|
||||
"open": "0.0.4",
|
||||
"testling": "git://github.com/spenceralger/testling.git",
|
||||
"load-grunt-tasks": "~0.2.0",
|
||||
"load-grunt-config": "~0.7.0",
|
||||
"grunt-s3": "~0.2.0-alpha.3"
|
||||
"grunt-s3": "~0.2.0-alpha.3",
|
||||
"grunt-run": "~0.1.5",
|
||||
"relative-fs": "0.0.1",
|
||||
"grunt-contrib-compress": "~0.5.3",
|
||||
"grunt-contrib-copy": "~0.4.1",
|
||||
"grunt-mocha": "~0.4.7"
|
||||
},
|
||||
"license": "Apache 2.0",
|
||||
"dependencies": {
|
||||
@ -51,14 +57,12 @@
|
||||
"chalk": "~0.3.0"
|
||||
},
|
||||
"repository": {
|
||||
"type" : "git",
|
||||
"url" : "http://github.com/elasticsearch/elasticsearch-js.git"
|
||||
"type": "git",
|
||||
"url": "http://github.com/elasticsearch/elasticsearch-js.git"
|
||||
},
|
||||
"scripts": {
|
||||
"test": "node scripts/run_tests.js --integration --unit --browsers=chrome,safari,firefox,opera",
|
||||
"coverage": "mocha test/unit/test_*.js --require blanket -R html-cov > coverage.html && open -a \"Google Chrome\" ./coverage.html",
|
||||
"build_clients": "grunt",
|
||||
"generate": "node scripts/generate/js_api && node scripts/generate/yaml_tests",
|
||||
"test": "grunt test",
|
||||
"coverage": "mocha test/unit/test_*.js --require blanket -R html-cov > coverage.html && open -a \"Google Chrome\"./coverage.html",
|
||||
"blanket": {
|
||||
"pattern": "src"
|
||||
}
|
||||
|
||||
@ -1,33 +0,0 @@
|
||||
var path = require('path');
|
||||
var fs = require('fs');
|
||||
|
||||
var argv = require('optimist')
|
||||
.default({
|
||||
verbose: false
|
||||
})
|
||||
.alias({
|
||||
v: 'verbose'
|
||||
})
|
||||
.argv;
|
||||
|
||||
var steps = [];
|
||||
|
||||
['browser', 'jquery', 'angular'].forEach(function (build) {
|
||||
|
||||
if (!fs.existsSync('../bower-elasticsearch-' + build) ||
|
||||
!fs.existsSync('../bower-elasticsearch-' + build + '/.git')
|
||||
) {
|
||||
throw new Error('Ensure that all of the bower repos are checked out next to this repo');
|
||||
}
|
||||
|
||||
steps.push([
|
||||
'run', {
|
||||
cwd: '../bower-elasticsearch-' + build + '/',
|
||||
cmd: 'npm',
|
||||
args: ['run', 'generate']
|
||||
}
|
||||
]);
|
||||
|
||||
});
|
||||
|
||||
require('./_steps')(argv, steps);
|
||||
@ -1,49 +0,0 @@
|
||||
var path = require('path');
|
||||
|
||||
var argv = require('optimist')
|
||||
.default({
|
||||
buildName: '',
|
||||
outputDir: '.',
|
||||
verbose: false
|
||||
})
|
||||
.alias({
|
||||
b: 'buildName',
|
||||
o: 'outputDir',
|
||||
v: 'verbose'
|
||||
})
|
||||
.argv;
|
||||
|
||||
switch (argv.buildName) {
|
||||
case 'jquery':
|
||||
var buildFile = './dist/elasticsearch.jquery.js';
|
||||
var minifiedBuildFile = './dist/elasticsearch.jquery.min.js';
|
||||
break;
|
||||
case 'angular':
|
||||
var buildFile = './dist/elasticsearch.angular.js';
|
||||
var minifiedBuildFile = './dist/elasticsearch.angular.min.js';
|
||||
break;
|
||||
default:
|
||||
var buildFile = './dist/elasticsearch.js';
|
||||
var minifiedBuildFile = './dist/elasticsearch.min.js';
|
||||
break;
|
||||
}
|
||||
|
||||
var outputFile = path.join(argv.outputDir, 'elasticsearch.js');
|
||||
var minifiedOutputFile = path.join(argv.outputDir, 'elasticsearch.min.js');
|
||||
|
||||
require('./_steps')(argv, [
|
||||
['run', {
|
||||
cmd: 'npm',
|
||||
args: ['run', 'build_clients']
|
||||
}],
|
||||
['copy', {
|
||||
from: buildFile,
|
||||
to: outputFile
|
||||
}],
|
||||
['copy', {
|
||||
from: minifiedBuildFile,
|
||||
to: minifiedOutputFile
|
||||
}]
|
||||
]);
|
||||
|
||||
|
||||
@ -14,7 +14,7 @@ var argv = require('optimist')
|
||||
require('./_steps')(argv, [
|
||||
['runInModule', {
|
||||
cmd: 'node',
|
||||
args: [path.join(__dirname, './generate/js_api'), '--force']
|
||||
args: [path.join(__dirname, './generate'), '--force']
|
||||
}],
|
||||
['copy', {
|
||||
from: path.join(__dirname, '../docs/_methods.jade'),
|
||||
|
||||
@ -1,24 +0,0 @@
|
||||
var force = process.env.FORCE || process.env.FORCE_GEN;
|
||||
|
||||
if (!force) {
|
||||
var argv = require('optimist')
|
||||
.options({
|
||||
force: {
|
||||
alias: 'f',
|
||||
default: false,
|
||||
boolean: true
|
||||
}
|
||||
});
|
||||
|
||||
if (process.env.npm_config_argv) {
|
||||
// when called by NPM
|
||||
argv = argv.parse(JSON.parse(process.env.npm_config_argv).original);
|
||||
} else {
|
||||
// when called directly
|
||||
argv = argv.argv;
|
||||
}
|
||||
|
||||
force = argv.force;
|
||||
}
|
||||
|
||||
module.exports = force;
|
||||
71
scripts/generate/index.js
Normal file
71
scripts/generate/index.js
Normal file
@ -0,0 +1,71 @@
|
||||
var cp = require('child_process');
|
||||
var async = require('async');
|
||||
var argv = require('optimist')
|
||||
.options({
|
||||
force: {
|
||||
alias: 'f',
|
||||
default: false,
|
||||
boolean: true
|
||||
},
|
||||
verbose: {
|
||||
alias: 'v',
|
||||
default: false,
|
||||
boolean: true
|
||||
},
|
||||
api: {
|
||||
default: true,
|
||||
boolean: true
|
||||
},
|
||||
tests: {
|
||||
default: true,
|
||||
boolean: true
|
||||
}
|
||||
});
|
||||
|
||||
if (process.env.npm_config_argv) {
|
||||
// when called by NPM
|
||||
argv = argv.parse(JSON.parse(process.env.npm_config_argv).original);
|
||||
} else {
|
||||
// when called directly
|
||||
argv = argv.argv;
|
||||
}
|
||||
|
||||
if (!argv.force && process.env.FORCE || process.env.FORCE_GEN) {
|
||||
argv.force = argv.f = process.env.FORCE || process.env.FORCE_GEN;
|
||||
}
|
||||
|
||||
function updateSubmodules(done) {
|
||||
cp.exec('git submodule update --init --recursive', function (err, stdout, stderr) {
|
||||
stdout = stdout.trim();
|
||||
stderr = stderr.trim();
|
||||
|
||||
if (err) {
|
||||
done(new Error('Unable to update submodules: ' + err.message));
|
||||
return;
|
||||
} else if (argv.verbose && stdout) {
|
||||
console.log(stdout);
|
||||
}
|
||||
|
||||
if (stderr) {
|
||||
console.error(stderr);
|
||||
}
|
||||
done();
|
||||
});
|
||||
}
|
||||
|
||||
updateSubmodules(function (err) {
|
||||
if (err) {
|
||||
throw err;
|
||||
}
|
||||
|
||||
var tasks = [];
|
||||
|
||||
if (argv.api) {
|
||||
tasks.push(require('./js_api'));
|
||||
}
|
||||
if (argv.tests) {
|
||||
tasks.push(require('./yaml_tests'));
|
||||
}
|
||||
|
||||
async.parallel(tasks, function () {});
|
||||
});
|
||||
344
scripts/generate/js_api.js
Normal file
344
scripts/generate/js_api.js
Normal file
@ -0,0 +1,344 @@
|
||||
var aliases; // defined at the bottom of this file.
|
||||
|
||||
module.exports = function (done) {
|
||||
/**
|
||||
* Read the API actions form the rest-api-spec repo.
|
||||
* @type {[type]}
|
||||
*/
|
||||
var _ = require('../../src/lib/utils');
|
||||
var fs = require('relative-fs').relativeTo(__dirname);
|
||||
var async = require('async');
|
||||
var templates = require('./templates');
|
||||
var castExistsRE = /exists/;
|
||||
var usesBulkBodyRE = /^(bulk|msearch)$/;
|
||||
var urlParamRE = /\{(\w+)\}/g;
|
||||
|
||||
var files; // populated in readSpecFiles
|
||||
var apiSpec; // populated by parseSpecFiles
|
||||
|
||||
// generate the API
|
||||
async.series([
|
||||
readSpecFiles,
|
||||
parseSpecFiles,
|
||||
writeApiFile,
|
||||
ensureDocsDir,
|
||||
writeMethodList,
|
||||
writeMethodDocs
|
||||
], done);
|
||||
|
||||
function readSpecFiles(done) {
|
||||
var apiDir = '../../src/rest-api-spec/api/';
|
||||
files = fs.readdirSync(apiDir).map(function (filename) {
|
||||
return require(apiDir + filename);
|
||||
});
|
||||
done();
|
||||
}
|
||||
|
||||
function parseSpecFiles(done) {
|
||||
var actions = [];
|
||||
|
||||
files.forEach(function (spec) {
|
||||
__puke__transformSpec(spec).forEach(function (action) {
|
||||
actions.push(action);
|
||||
});
|
||||
});
|
||||
|
||||
// collect the namespaces from the action locations
|
||||
var namespaces = _.filter(_.map(actions, function (action) {
|
||||
if (~action.location.indexOf('.')) {
|
||||
var path = action.location.split('.').slice(0, -1);
|
||||
_.pull(path, 'prototype');
|
||||
return path.join('.');
|
||||
}
|
||||
}));
|
||||
|
||||
// seperate the proxy actions
|
||||
var groups = _.groupBy(actions, function (action) {
|
||||
return action.proxy ? 'proxies' : 'normal';
|
||||
});
|
||||
|
||||
apiSpec = {
|
||||
actions: groups.normal,
|
||||
proxies: groups.proxies,
|
||||
namespaces: _.unique(namespaces.sort(), true)
|
||||
};
|
||||
|
||||
done();
|
||||
}
|
||||
|
||||
function writeApiFile(done) {
|
||||
var outputPath = require('path').join(__dirname, '../../src/lib/api.js');
|
||||
console.log('writing', apiSpec.actions.length, 'api actions to', outputPath);
|
||||
fs.writeFile(outputPath, templates.apiFile(apiSpec), done);
|
||||
}
|
||||
|
||||
function ensureDocsDir(done) {
|
||||
fs.stat('../../docs', function (err, stat) {
|
||||
if (err) {
|
||||
if (err.message.match(/enoent/i)) {
|
||||
fs.mkdir('../../docs', done);
|
||||
} else {
|
||||
done(err);
|
||||
}
|
||||
} else if (stat.isDirectory()) {
|
||||
done();
|
||||
} else {
|
||||
done(new Error('../../docs exists, but it is not a directory'));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function writeMethodList(done) {
|
||||
fs.writeFile(
|
||||
'../../docs/_method_list.jade',
|
||||
templates.apiMethodList(apiSpec),
|
||||
done
|
||||
);
|
||||
}
|
||||
|
||||
function writeMethodDocs(done) {
|
||||
fs.writeFile(
|
||||
'../../docs/_methods.jade',
|
||||
templates.apiMethods(apiSpec),
|
||||
done
|
||||
);
|
||||
}
|
||||
|
||||
function __puke__transformSpec(spec) {
|
||||
var actions = [];
|
||||
|
||||
// itterate all of the specs within the file, should only be one
|
||||
_.each(spec, function (def, name) {
|
||||
//camelcase the name
|
||||
name = _.map(name.split('.'), _.camelCase).join('.');
|
||||
|
||||
var steps = name.split('.');
|
||||
|
||||
function transformParamKeys(note, param, key) {
|
||||
var cmlKey = _.camelCase(key);
|
||||
if (cmlKey !== key) {
|
||||
param.name = key;
|
||||
}
|
||||
note[cmlKey] = param;
|
||||
}
|
||||
|
||||
def.url.params = _.transform(def.url.params, transformParamKeys, {});
|
||||
def.url.parts = _.transform(def.url.parts, transformParamKeys, {});
|
||||
|
||||
var allParams = _.extend({}, def.url.params, def.url.parts);
|
||||
var spec = {
|
||||
name: name,
|
||||
methods: _.map(def.methods, function (m) { return m.toUpperCase(); }),
|
||||
params: def.url.params,
|
||||
body: def.body || null,
|
||||
path2lib: _.repeat('../', steps.length + 1) + 'lib/'
|
||||
};
|
||||
|
||||
if (def.body && def.body.requires) {
|
||||
spec.needBody = true;
|
||||
}
|
||||
|
||||
if (usesBulkBodyRE.test(name)) {
|
||||
spec.bulkBody = true;
|
||||
}
|
||||
|
||||
if (castExistsRE.test(name)) {
|
||||
spec.castExists = true;
|
||||
}
|
||||
|
||||
var urls = _.difference(def.url.paths, aliases[name]);
|
||||
urls = _.map(urls, function (url) {
|
||||
var optionalVars = {};
|
||||
var requiredVars = {};
|
||||
var param;
|
||||
var name;
|
||||
var target;
|
||||
var match;
|
||||
|
||||
if (url.charAt(0) !== '/') {
|
||||
url = '/' + url;
|
||||
}
|
||||
|
||||
while (match = urlParamRE.exec(url)) {
|
||||
name = _.camelCase(match[1]);
|
||||
param = def.url.parts[name] || {};
|
||||
target = (param.required || !param.default) ? requiredVars : optionalVars;
|
||||
target[name] = _.omit(param, 'required', 'description', 'name');
|
||||
}
|
||||
|
||||
return _.omit({
|
||||
fmt: url.replace(urlParamRE, function (full, match) {
|
||||
return '<%=' + _.camelCase(match) + '%>';
|
||||
}),
|
||||
opt: _.size(optionalVars) ? optionalVars : null,
|
||||
req: _.size(requiredVars) ? requiredVars : null,
|
||||
sortOrder: _.size(requiredVars) * -1
|
||||
}, function (v) {
|
||||
return !v;
|
||||
});
|
||||
});
|
||||
|
||||
if (urls.length > 1) {
|
||||
spec.urls = _.map(_.sortBy(urls, 'sortOrder'), function (url) {
|
||||
return _.omit(url, 'sortOrder');
|
||||
});
|
||||
} else {
|
||||
spec.url = urls[0];
|
||||
}
|
||||
|
||||
spec.params = _.transform(spec.params, function (note, param, name) {
|
||||
// param.name = name;
|
||||
note[name] = _.pick(param, [
|
||||
'type', 'default', 'options', 'required', 'name'
|
||||
]);
|
||||
}, {});
|
||||
|
||||
if (_.size(spec.params) === 0) {
|
||||
delete spec.params;
|
||||
}
|
||||
|
||||
// escape method names with "special" keywords
|
||||
var location = spec.name.split('.').join('.prototype.')
|
||||
.replace(/(^|\.)(delete|default)(\.|$)/g, '[\'$2\']');
|
||||
|
||||
var action = {
|
||||
_methods: spec.methods,
|
||||
spec: _.pick(spec, [
|
||||
'params',
|
||||
'url',
|
||||
'urls',
|
||||
'needBody',
|
||||
'bulkBody',
|
||||
'castExists',
|
||||
'castNotFound'
|
||||
]),
|
||||
location: location,
|
||||
docUrl: def.documentation,
|
||||
name: spec.name,
|
||||
allParams: allParams
|
||||
};
|
||||
|
||||
function hasMethod(/* ...methods */) {
|
||||
for (var i = 0; i < arguments.length; i++) {
|
||||
if (~action._methods.indexOf(arguments[i])) {
|
||||
continue;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
function methodsAre(/* ...methods */) {
|
||||
return hasMethod.apply(null, arguments) && arguments.length === action._methods.length;
|
||||
}
|
||||
|
||||
var method;
|
||||
|
||||
if (action._methods.length === 1) {
|
||||
method = action._methods[0];
|
||||
} else {
|
||||
// we need to define what the default method(s) will be
|
||||
if (hasMethod('DELETE', 'POST')) {
|
||||
method = 'POST';
|
||||
}
|
||||
else if (methodsAre('DELETE')) {
|
||||
method = 'DELETE';
|
||||
}
|
||||
else if (methodsAre('POST', 'PUT')) {
|
||||
method = action.name.match(/put/i) ? 'PUT' : 'POST';
|
||||
}
|
||||
else if (methodsAre('GET', 'POST')) {
|
||||
method = 'POST';
|
||||
}
|
||||
else if (methodsAre('GET', 'HEAD')) {
|
||||
if (action.spec.castExists) {
|
||||
method = 'HEAD';
|
||||
} else {
|
||||
method = 'GET';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (method) {
|
||||
if (method !== 'GET') {
|
||||
action.spec.method = method;
|
||||
}
|
||||
} else {
|
||||
throw new Error('unable to pick a method for ' + JSON.stringify(action, null, ' '));
|
||||
}
|
||||
|
||||
if (action.name === 'create') {
|
||||
action.proxy = 'index';
|
||||
action.transformBody = 'params.op_type = \'create\';';
|
||||
}
|
||||
|
||||
actions.push(action);
|
||||
});
|
||||
|
||||
return actions;
|
||||
}
|
||||
};
|
||||
|
||||
aliases = {
|
||||
'cluster.nodeHotThreads': [
|
||||
'/_cluster/nodes/hotthreads',
|
||||
'/_cluster/nodes/hot_threads',
|
||||
'/_nodes/hot_threads',
|
||||
'/_cluster/nodes/{node_id}/hotthreads',
|
||||
'/_cluster/nodes/{node_id}/hot_threads',
|
||||
'/_nodes/{node_id}/hot_threads'
|
||||
],
|
||||
'cluster.nodeInfo': [
|
||||
'/_cluster/nodes',
|
||||
'/_nodes/settings',
|
||||
'/_nodes/os',
|
||||
'/_nodes/process',
|
||||
'/_nodes/jvm',
|
||||
'/_nodes/thread_pool',
|
||||
'/_nodes/network',
|
||||
'/_nodes/transport',
|
||||
'/_nodes/http',
|
||||
'/_nodes/plugin',
|
||||
'/_cluster/nodes/{node_id}',
|
||||
'/_nodes/{node_id}/settings',
|
||||
'/_nodes/{node_id}/os',
|
||||
'/_nodes/{node_id}/process',
|
||||
'/_nodes/{node_id}/jvm',
|
||||
'/_nodes/{node_id}/thread_pool',
|
||||
'/_nodes/{node_id}/network',
|
||||
'/_nodes/{node_id}/transport',
|
||||
'/_nodes/{node_id}/http',
|
||||
'/_nodes/{node_id}/plugin'
|
||||
],
|
||||
'cluster.nodeShutdown': [
|
||||
'/_cluster/nodes/_shutdown'
|
||||
],
|
||||
'cluster.nodeStats': [
|
||||
'/_cluster/nodes/stats',
|
||||
'/_nodes/stats/{metric_family}',
|
||||
'/_nodes/stats/indices/{metric}/{fields}',
|
||||
'/_cluster/nodes/{node_id}/stats',
|
||||
'/_nodes/{node_id}/stats/{metric_family}',
|
||||
'/_nodes/{node_id}/stats/indices/{metric}/{fields}'
|
||||
],
|
||||
'get': [
|
||||
'/{index}/{type}/{id}/_source'
|
||||
],
|
||||
'indices.deleteMapping': [
|
||||
'/{index}/{type}/_mapping'
|
||||
],
|
||||
'indices.stats': [
|
||||
'_stats/{metric_family}',
|
||||
'/_stats/indexing',
|
||||
'/_stats/indexing/{indexing_types}',
|
||||
'/_stats/search/{search_groups}',
|
||||
'/_stats/fielddata/{fields}',
|
||||
'/{index}/_stats/{metric_family}',
|
||||
'/{index}/_stats/indexing',
|
||||
'/{index}/_stats/search/{search_groups}',
|
||||
'/{index}/_stats/fielddata/{fields}'
|
||||
],
|
||||
'search': [
|
||||
'/_search'
|
||||
]
|
||||
};
|
||||
@ -1,3 +0,0 @@
|
||||
Generate the API using the es [REST api spec](https://github.com/elasticsearch/elasticsearch-rest-api-spec).
|
||||
|
||||
run by calling `npm run generate`. Force it to update, even if their has not been a new commit, but calling with `--force` or `-f`
|
||||
@ -1,240 +0,0 @@
|
||||
var _ = require('../../../src/lib/utils');
|
||||
|
||||
var EventEmitter = require('events').EventEmitter;
|
||||
var aliases = require('./aliases');
|
||||
|
||||
var castExistsRE = /exists/;
|
||||
var usesBulkBodyRE = /^(bulk|msearch)$/;
|
||||
var urlParamRE = /\{(\w+)\}/g;
|
||||
|
||||
var specCount = 0;
|
||||
var actions = [];
|
||||
var doneParsing = false;
|
||||
|
||||
require('../../get_spec')
|
||||
.get('api/*.json')
|
||||
.on('entry', transformFile)
|
||||
.on('end', function () {
|
||||
doneParsing = true;
|
||||
if (actions.length === specCount) {
|
||||
module.exports.emit('ready', actions);
|
||||
}
|
||||
});
|
||||
|
||||
function transformFile(entry) {
|
||||
specCount++;
|
||||
|
||||
// itterate all of the specs within the file, should only be one
|
||||
_.each(JSON.parse(entry.data), function (def, name) {
|
||||
//camelcase the name
|
||||
name = _.map(name.split('.'), _.camelCase).join('.');
|
||||
|
||||
var steps = name.split('.');
|
||||
|
||||
function transformParamKeys(note, param, key) {
|
||||
var cmlKey = _.camelCase(key);
|
||||
if (cmlKey !== key) {
|
||||
param.name = key;
|
||||
}
|
||||
note[cmlKey] = param;
|
||||
}
|
||||
|
||||
def.url.params = _.transform(def.url.params, transformParamKeys, {});
|
||||
def.url.parts = _.transform(def.url.parts, transformParamKeys, {});
|
||||
|
||||
var allParams = _.extend({}, def.url.params, def.url.parts);
|
||||
var spec = {
|
||||
name: name,
|
||||
methods: _.map(def.methods, function (m) { return m.toUpperCase(); }),
|
||||
params: def.url.params,
|
||||
body: def.body || null,
|
||||
path2lib: _.repeat('../', steps.length + 1) + 'lib/'
|
||||
};
|
||||
|
||||
if (def.body && def.body.requires) {
|
||||
spec.needBody = true;
|
||||
}
|
||||
|
||||
if (usesBulkBodyRE.test(name)) {
|
||||
spec.bulkBody = true;
|
||||
}
|
||||
|
||||
if (castExistsRE.test(name)) {
|
||||
spec.castExists = true;
|
||||
}
|
||||
|
||||
var urls = _.difference(def.url.paths, aliases[name]);
|
||||
urls = _.map(urls, function (url) {
|
||||
var optionalVars = {};
|
||||
var requiredVars = {};
|
||||
var param;
|
||||
var name;
|
||||
var target;
|
||||
var match;
|
||||
|
||||
if (url.charAt(0) !== '/') {
|
||||
url = '/' + url;
|
||||
}
|
||||
|
||||
while (match = urlParamRE.exec(url)) {
|
||||
name = _.camelCase(match[1]);
|
||||
param = def.url.parts[name] || {};
|
||||
target = (param.required || !param.default) ? requiredVars : optionalVars;
|
||||
target[name] = _.omit(param, 'required', 'description', 'name');
|
||||
}
|
||||
|
||||
return _.omit({
|
||||
fmt: url.replace(urlParamRE, function (full, match) {
|
||||
return '<%=' + _.camelCase(match) + '%>';
|
||||
}),
|
||||
opt: _.size(optionalVars) ? optionalVars : null,
|
||||
req: _.size(requiredVars) ? requiredVars : null,
|
||||
sortOrder: _.size(requiredVars) * -1
|
||||
}, function (v) {
|
||||
return !v;
|
||||
});
|
||||
});
|
||||
|
||||
if (urls.length > 1) {
|
||||
spec.urls = _.map(_.sortBy(urls, 'sortOrder'), function (url) {
|
||||
return _.omit(url, 'sortOrder');
|
||||
});
|
||||
} else {
|
||||
spec.url = urls[0];
|
||||
}
|
||||
|
||||
spec.params = _.transform(spec.params, function (note, param, name) {
|
||||
// param.name = name;
|
||||
note[name] = _.pick(param, [
|
||||
'type', 'default', 'options', 'required', 'name'
|
||||
]);
|
||||
}, {});
|
||||
|
||||
if (_.size(spec.params) === 0) {
|
||||
delete spec.params;
|
||||
}
|
||||
|
||||
// escape method names with "special" keywords
|
||||
var location = spec.name.split('.').join('.prototype.')
|
||||
.replace(/(^|\.)(delete|default)(\.|$)/g, '[\'$2\']');
|
||||
|
||||
var action = {
|
||||
_methods: spec.methods,
|
||||
spec: _.pick(spec, [
|
||||
'params',
|
||||
'url',
|
||||
'urls',
|
||||
'needBody',
|
||||
'bulkBody',
|
||||
'castExists',
|
||||
'castNotFound'
|
||||
]),
|
||||
location: location,
|
||||
docUrl: def.documentation,
|
||||
name: spec.name,
|
||||
allParams: allParams
|
||||
};
|
||||
|
||||
function hasMethod(/* ...methods */) {
|
||||
for (var i = 0; i < arguments.length; i++) {
|
||||
if (~action._methods.indexOf(arguments[i])) {
|
||||
continue;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
function methodsAre(/* ...methods */) {
|
||||
return hasMethod.apply(null, arguments) && arguments.length === action._methods.length;
|
||||
}
|
||||
|
||||
var method;
|
||||
|
||||
if (action._methods.length === 1) {
|
||||
method = action._methods[0];
|
||||
} else {
|
||||
// we need to define what the default method(s) will be
|
||||
if (hasMethod('DELETE', 'POST')) {
|
||||
method = 'POST';
|
||||
}
|
||||
else if (methodsAre('DELETE')) {
|
||||
method = 'DELETE';
|
||||
}
|
||||
else if (methodsAre('POST', 'PUT')) {
|
||||
method = action.name.match(/put/i) ? 'PUT' : 'POST';
|
||||
}
|
||||
else if (methodsAre('GET', 'POST')) {
|
||||
method = 'POST';
|
||||
}
|
||||
else if (methodsAre('GET', 'HEAD')) {
|
||||
if (action.spec.castExists) {
|
||||
method = 'HEAD';
|
||||
} else {
|
||||
method = 'GET';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (method) {
|
||||
if (method !== 'GET') {
|
||||
action.spec.method = method;
|
||||
}
|
||||
} else {
|
||||
throw new Error('unable to pick a method for ' + JSON.stringify(action, null, ' '));
|
||||
}
|
||||
|
||||
if (action.name === 'create') {
|
||||
action.proxy = 'index';
|
||||
action.transformBody = 'params.op_type = \'create\';';
|
||||
}
|
||||
|
||||
if (actions.push(action) === specCount && doneParsing) {
|
||||
module.exports.emit('ready', actions);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* un-comment to print out the default method for any action that has multiple options
|
||||
*/
|
||||
module.exports = new EventEmitter();
|
||||
// module.exports.on('ready', function (actions) {
|
||||
// var longestName = 0;
|
||||
// var reports = {
|
||||
// multi_methods: [],
|
||||
// get_with_body: []
|
||||
// };
|
||||
// actions.forEach(function (action) {
|
||||
// var name;
|
||||
|
||||
// // console.log(action);
|
||||
// if (action._methods.length > 1) {
|
||||
// name = action.name + ' (' + action._methods.join('/') + ')';
|
||||
// longestName = Math.max(name.length, longestName);
|
||||
// reports.multi_methods.push([name, action.spec.method || 'GET', action.docUrl]);
|
||||
// }
|
||||
|
||||
// if (action._methods.length === 1 && action._methods[0] === 'GET' && action.body) {
|
||||
// name = action.name + ' (' + action._methods.join('/') + ')';
|
||||
// longestName = Math.max(name.length, longestName);
|
||||
// reports.get_with_body.push([name, action.spec.method || 'GET', action.docUrl]);
|
||||
// }
|
||||
// });
|
||||
|
||||
// Object.keys(reports).forEach(function (key) {
|
||||
// console.log('\n' + key);
|
||||
// if (reports[key].length) {
|
||||
// reports[key].forEach(function (line) {
|
||||
// var name = line[0];
|
||||
// var def = line[1];
|
||||
// var docUrl = line[2];
|
||||
// var spacing = (new Array(longestName - name.length + 1)).join(' ');
|
||||
// console.log(name + spacing + ' [' + def + (def.length === 3 ? ' ' : '') + '] -> ' + docUrl);
|
||||
// });
|
||||
// } else {
|
||||
// console.log('--nada--');
|
||||
// }
|
||||
// console.log('\n');
|
||||
// });
|
||||
// });
|
||||
@ -1,63 +0,0 @@
|
||||
module.exports = {
|
||||
'cluster.nodeHotThreads': [
|
||||
'/_cluster/nodes/hotthreads',
|
||||
'/_cluster/nodes/hot_threads',
|
||||
'/_nodes/hot_threads',
|
||||
'/_cluster/nodes/{node_id}/hotthreads',
|
||||
'/_cluster/nodes/{node_id}/hot_threads',
|
||||
'/_nodes/{node_id}/hot_threads'
|
||||
],
|
||||
'cluster.nodeInfo': [
|
||||
'/_cluster/nodes',
|
||||
'/_nodes/settings',
|
||||
'/_nodes/os',
|
||||
'/_nodes/process',
|
||||
'/_nodes/jvm',
|
||||
'/_nodes/thread_pool',
|
||||
'/_nodes/network',
|
||||
'/_nodes/transport',
|
||||
'/_nodes/http',
|
||||
'/_nodes/plugin',
|
||||
'/_cluster/nodes/{node_id}',
|
||||
'/_nodes/{node_id}/settings',
|
||||
'/_nodes/{node_id}/os',
|
||||
'/_nodes/{node_id}/process',
|
||||
'/_nodes/{node_id}/jvm',
|
||||
'/_nodes/{node_id}/thread_pool',
|
||||
'/_nodes/{node_id}/network',
|
||||
'/_nodes/{node_id}/transport',
|
||||
'/_nodes/{node_id}/http',
|
||||
'/_nodes/{node_id}/plugin'
|
||||
],
|
||||
'cluster.nodeShutdown': [
|
||||
'/_cluster/nodes/_shutdown'
|
||||
],
|
||||
'cluster.nodeStats': [
|
||||
'/_cluster/nodes/stats',
|
||||
'/_nodes/stats/{metric_family}',
|
||||
'/_nodes/stats/indices/{metric}/{fields}',
|
||||
'/_cluster/nodes/{node_id}/stats',
|
||||
'/_nodes/{node_id}/stats/{metric_family}',
|
||||
'/_nodes/{node_id}/stats/indices/{metric}/{fields}'
|
||||
],
|
||||
'get': [
|
||||
'/{index}/{type}/{id}/_source'
|
||||
],
|
||||
'indices.deleteMapping': [
|
||||
'/{index}/{type}/_mapping'
|
||||
],
|
||||
'indices.stats': [
|
||||
'_stats/{metric_family}',
|
||||
'/_stats/indexing',
|
||||
'/_stats/indexing/{indexing_types}',
|
||||
'/_stats/search/{search_groups}',
|
||||
'/_stats/fielddata/{fields}',
|
||||
'/{index}/_stats/{metric_family}',
|
||||
'/{index}/_stats/indexing',
|
||||
'/{index}/_stats/search/{search_groups}',
|
||||
'/{index}/_stats/fielddata/{fields}'
|
||||
],
|
||||
'search': [
|
||||
'/_search'
|
||||
]
|
||||
};
|
||||
@ -1,59 +0,0 @@
|
||||
module.exports = function (force) {
|
||||
var _ = require('../../../src/lib/utils');
|
||||
var fs = require('fs');
|
||||
var templates = require('./templates');
|
||||
var restSpecUpdated = require('../../rest_spec_updated');
|
||||
|
||||
var outputPath = _.joinPath(__dirname, '../../../src/lib/api.js');
|
||||
var docOutputDir = _.joinPath(__dirname, '../../../docs/');
|
||||
|
||||
function download() {
|
||||
require('./actions').on('ready', function (actions) {
|
||||
var namespaces = _.filter(_.map(actions, function (action) {
|
||||
if (~action.location.indexOf('.')) {
|
||||
var path = action.location.split('.').slice(0, -1);
|
||||
_.pull(path, 'prototype');
|
||||
return path.join('.');
|
||||
}
|
||||
}));
|
||||
|
||||
// seperate the proxy actions
|
||||
var groups = _.groupBy(actions, function (action) {
|
||||
return action.proxy ? 'proxies' : 'normal';
|
||||
});
|
||||
|
||||
fs.unlink(outputPath, function () {
|
||||
console.log('writing', actions.length, 'api actions to', outputPath);
|
||||
|
||||
fs.writeFileSync(outputPath, templates.apiFile({
|
||||
actions: groups.normal,
|
||||
proxies: groups.proxies,
|
||||
namespaces: _.unique(namespaces.sort(), true)
|
||||
}));
|
||||
|
||||
if (!fs.existsSync(docOutputDir)) {
|
||||
fs.mkdirSync(docOutputDir);
|
||||
}
|
||||
|
||||
fs.writeFileSync(docOutputDir + '_method_list.jade', templates.apiMethodList({
|
||||
actions: actions
|
||||
}));
|
||||
|
||||
fs.writeFileSync(docOutputDir + '_methods.jade', templates.apiMethods({
|
||||
actions: actions
|
||||
}));
|
||||
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
if (force) {
|
||||
download();
|
||||
} else {
|
||||
restSpecUpdated(function (err, updated) {
|
||||
if (err || updated) {
|
||||
download();
|
||||
}
|
||||
});
|
||||
}
|
||||
};
|
||||
@ -1 +0,0 @@
|
||||
require('./generate')(require('../_force'));
|
||||
@ -19,9 +19,6 @@ var argv = require('optimist')
|
||||
})
|
||||
.argv;
|
||||
|
||||
// Error.stackTraceLimit = Infinity;
|
||||
// process.exit();
|
||||
|
||||
var es = require('../../../src/elasticsearch');
|
||||
var _ = require('../../../src/lib/utils');
|
||||
var async = require('async');
|
||||
|
||||
@ -22,6 +22,7 @@ api.<%= namespace %> = function <%= className %>(transport) {
|
||||
});
|
||||
|
||||
_.each(proxies, function (action) {%>
|
||||
|
||||
<%= partials.client_action_proxy(action) %><%
|
||||
});
|
||||
%>
|
||||
%>
|
||||
@ -9,4 +9,4 @@ _.each(allParams, function(param, paramName) { %>
|
||||
}
|
||||
%><% }) %>
|
||||
*/
|
||||
api<%= (location[0] === '[' ? '' : '.') + location %> = ca(<%= stringify(spec, true) %>);
|
||||
api<%= (location[0] === '[' ? '' : '.') + location %> = ca(<%= stringify(spec, true) %>);
|
||||
@ -16,4 +16,4 @@ if (typeof transformBody === 'string') { %>, {
|
||||
}
|
||||
}<%
|
||||
}
|
||||
%>);
|
||||
%>);
|
||||
@ -1,5 +1,5 @@
|
||||
|
||||
var _ = require('../../../../src/lib/utils');
|
||||
var _ = require('../../../src/lib/utils');
|
||||
var fs = require('fs');
|
||||
var path = require('path');
|
||||
|
||||
46
scripts/generate/yaml_tests.js
Normal file
46
scripts/generate/yaml_tests.js
Normal file
@ -0,0 +1,46 @@
|
||||
module.exports = function (done) {
|
||||
|
||||
/**
|
||||
* Creates a JSON version of the YAML test suite that can be simply bundled for use in the browser.
|
||||
*/
|
||||
var jsYaml = require('js-yaml');
|
||||
var fs = require('relative-fs').relativeTo(__dirname);
|
||||
var async = require('async');
|
||||
var path = require('path');
|
||||
var tests = {}; // populated in readYamlTests
|
||||
|
||||
// generate the yaml tests
|
||||
async.series([
|
||||
readYamlTests,
|
||||
writeYamlTests
|
||||
], done);
|
||||
|
||||
function readYamlTests(done) {
|
||||
var testDir = path.join(__dirname, '../../src/rest-api-spec/test/');
|
||||
|
||||
function readDirectories(dir) {
|
||||
fs.readdirSync(dir).forEach(function (filename) {
|
||||
var filePath = path.join(dir, filename);
|
||||
var stat = fs.statSync(filePath);
|
||||
if (stat.isDirectory()) {
|
||||
readDirectories(filePath);
|
||||
} else if (filename.match(/\.yaml$/)) {
|
||||
var file = tests[path.relative(testDir, filePath)] = [];
|
||||
jsYaml.loadAll(fs.readFileSync(filePath, 'utf8'), function (doc) {
|
||||
file.push(doc);
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
readDirectories(testDir);
|
||||
done();
|
||||
}
|
||||
|
||||
function writeYamlTests(done) {
|
||||
var testFile = require('path').resolve(__dirname, '../../test/integration/yaml_suite/yaml_tests.json');
|
||||
fs.writeFileSync(testFile, JSON.stringify(tests, null, ' '), 'utf8');
|
||||
console.log('wrote YAML tests as JSON to', testFile);
|
||||
done();
|
||||
}
|
||||
};
|
||||
@ -1,3 +0,0 @@
|
||||
Download the yaml suite's test specs, runs before each run of the suite to ensure they are up to date.
|
||||
|
||||
run by calling `npm run generate`. Force it to update, even if their has not been a new commit, but calling with `--force` or `-f`
|
||||
@ -1,44 +0,0 @@
|
||||
module.exports = function (force) {
|
||||
/**
|
||||
* Check that the test directory exists, and is less than a day old, otherwise wipe it out
|
||||
* and rebuild
|
||||
*/
|
||||
var fs = require('fs');
|
||||
var path = require('path');
|
||||
var jsYaml = require('js-yaml');
|
||||
var spec = require('../../get_spec');
|
||||
var restSpecUpdated = require('../../rest_spec_updated');
|
||||
|
||||
var testFile = path.resolve(__dirname, '../../../test/integration/yaml_suite/yaml_tests.json');
|
||||
|
||||
function download() {
|
||||
|
||||
var tests = {};
|
||||
|
||||
fs.unlink(testFile, function () {
|
||||
spec.get('test/**/*.yaml')
|
||||
.on('entry', function (entry) {
|
||||
var filename = path.relative('test', entry.path);
|
||||
var file = tests[filename] = [];
|
||||
jsYaml.loadAll(entry.data, function (doc) {
|
||||
file.push(doc);
|
||||
});
|
||||
})
|
||||
.on('end', function () {
|
||||
fs.writeFileSync(testFile, JSON.stringify(tests, null, ' '), 'utf8');
|
||||
console.log('download yaml tests to', testFile);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
if (force) {
|
||||
download();
|
||||
} else {
|
||||
restSpecUpdated(function (err, updated) {
|
||||
if (err || updated) {
|
||||
download();
|
||||
}
|
||||
});
|
||||
}
|
||||
};
|
||||
@ -1 +0,0 @@
|
||||
require('./generate')(require('../_force'));
|
||||
19
scripts/jenkins.sh
Executable file
19
scripts/jenkins.sh
Executable file
@ -0,0 +1,19 @@
|
||||
#!/bin/sh
|
||||
|
||||
echo "generate the latest version of the yaml-tests"
|
||||
node scripts/generate/ --no-api 2>&1 > /dev/null
|
||||
|
||||
echo "\n--- unit ---"
|
||||
./node_modules/.bin/mocha test/unit/test_*.js \
|
||||
--require should \
|
||||
--reporter ../../../test/utils/jenkins-reporter.js \
|
||||
2> test-output-node-unit.xml
|
||||
|
||||
echo "\n--- integration ---"
|
||||
# run the integration tests
|
||||
./node_modules/.bin/mocha test/integration/yaml_suite/index.js \
|
||||
--require should \
|
||||
--host localhost \
|
||||
--port $es_port \
|
||||
--reporter ../../../test/utils/jenkins-reporter.js \
|
||||
2> test-output-node-integration.xml
|
||||
@ -1,16 +1,9 @@
|
||||
var server = require('./server');
|
||||
var child_process = require('child_process');
|
||||
var _ = require('lodash');
|
||||
var open = require('open');
|
||||
var fs = require('fs');
|
||||
var path = require('path');
|
||||
var async = require('async');
|
||||
var chalk = require('chalk');
|
||||
|
||||
var yamlTestSourceFile = path.join(__dirname, '../../test/integration/yaml_suite/index.js');
|
||||
var yamlTestBundleFile = path.join(__dirname, '../../test/integration/browser_yaml_suite/yaml_tests.js');
|
||||
var clientEntryFile = path.join(__dirname, '../../src/elasticsearch.js');
|
||||
|
||||
var browserAppNames = _.transform({
|
||||
safari: {
|
||||
darwin: 'Safari'
|
||||
@ -79,102 +72,45 @@ if (badKeys.length) {
|
||||
console.log('opening browser suite in', server.browsers);
|
||||
}
|
||||
|
||||
server.on('tests done', function (report) {
|
||||
var reports = [];
|
||||
var success = true;
|
||||
_.each(report, function (testSucceeded, browser) {
|
||||
var msg = browser + ':' + (success ? '✔︎' : '⚑');
|
||||
if (testSucceeded) {
|
||||
msg = chalk.green(msg);
|
||||
} else {
|
||||
msg = chalk.red(msg);
|
||||
success = false;
|
||||
}
|
||||
reports.push(' - ' + msg);
|
||||
});
|
||||
console.log('test completed!\n', reports.join('\n'));
|
||||
process.exit(success ? 0 : 1);
|
||||
});
|
||||
|
||||
async.series([
|
||||
function (done) {
|
||||
fs.exists('dist', function (yes) {
|
||||
if (!argv.forceGen && yes) {
|
||||
done();
|
||||
return;
|
||||
}
|
||||
|
||||
console.log('generating client with "grunt build"');
|
||||
child_process.spawn('npm', ['run', 'build_clients'], {
|
||||
stdio: 'inherit'
|
||||
}).on('close', function (status) {
|
||||
done(status && 'grunt closed with a status code of ' + status + '. aborting.');
|
||||
});
|
||||
server.listen(0, function () {
|
||||
server.port = server.address().port;
|
||||
console.log('server listening on port', server.port);
|
||||
done();
|
||||
});
|
||||
},
|
||||
function (done) {
|
||||
fs.exists(yamlTestBundleFile, function (yes) {
|
||||
if (!argv.forceGen && yes) {
|
||||
done();
|
||||
return;
|
||||
}
|
||||
async.eachSeries(_.clone(server.browsers), function (browser, browserDone) {
|
||||
open('http://localhost:' + server.port +
|
||||
'?es_hostname=' + encodeURIComponent(argv.host) +
|
||||
'&es_port=' + encodeURIComponent(argv.port) +
|
||||
'&browser=' + encodeURIComponent(browser), browserAppNames[browser]);
|
||||
|
||||
console.log('generating browser\'s yaml_tests.js bundle');
|
||||
var b = require('browserify')();
|
||||
|
||||
b.add(yamlTestSourceFile);
|
||||
var bundle = b.bundle({
|
||||
external: [
|
||||
'optimist'
|
||||
],
|
||||
ignore: [
|
||||
'test/integration/yaml_suite/reporter',
|
||||
clientEntryFile
|
||||
]
|
||||
});
|
||||
var file = fs.createWriteStream(yamlTestBundleFile, {
|
||||
flags: 'w',
|
||||
encoding: 'utf8',
|
||||
mode: 0666
|
||||
});
|
||||
|
||||
bundle.pipe(file);
|
||||
|
||||
file.once('error', function (err) {
|
||||
done(err);
|
||||
});
|
||||
|
||||
bundle.once('error', function (err) {
|
||||
done(err);
|
||||
});
|
||||
|
||||
bundle.once('end', function () {
|
||||
done();
|
||||
});
|
||||
|
||||
});
|
||||
server.once('browser complete', _.bind(browserDone, null, null));
|
||||
}, done);
|
||||
}
|
||||
], function (err) {
|
||||
if (err) {
|
||||
console.error(err);
|
||||
process.exit(1);
|
||||
} else {
|
||||
server.listen(0, function () {
|
||||
var port = server.address().port;
|
||||
console.log('server listening on port', port);
|
||||
|
||||
async.eachSeries(_.clone(server.browsers), function (browser, done) {
|
||||
open('http://localhost:' + port +
|
||||
'?es_hostname=' + encodeURIComponent(argv.host) +
|
||||
'&es_port=' + encodeURIComponent(argv.port) +
|
||||
'&browser=' + encodeURIComponent(browser), browserAppNames[browser]);
|
||||
|
||||
server.once('browser complete', function () {
|
||||
done();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
server.on('tests done', function (report) {
|
||||
var reports = [];
|
||||
var success = true;
|
||||
_.each(report, function (testSucceeded, browser) {
|
||||
var msg = browser + ':' + (success ? '✔︎' : '⚑');
|
||||
if (testSucceeded) {
|
||||
msg = chalk.green(msg);
|
||||
} else {
|
||||
msg = chalk.red(msg);
|
||||
success = false;
|
||||
}
|
||||
reports.push(' - ' + msg);
|
||||
});
|
||||
console.log('test completed!\n', reports.join('\n'));
|
||||
process.exit(success ? 0 : 1);
|
||||
});
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
|
||||
@ -4,7 +4,7 @@ var path = require('path');
|
||||
var fs = require('fs');
|
||||
var _ = require('lodash');
|
||||
var chalk = require('chalk');
|
||||
var makeJUnitXml = require('../make_j_unit_xml');
|
||||
var makeJUnitXml = require('../../test/utils/make_j_unit_xml');
|
||||
var docRoot = path.join(__dirname, '../../test/integration/browser_yaml_suite');
|
||||
chalk.enabled = true;
|
||||
|
||||
@ -21,8 +21,14 @@ var server = http.createServer(function (req, resp) {
|
||||
req.filename = path.join(docRoot, req.uri);
|
||||
|
||||
var end = resp.end;
|
||||
resp.end = function () {
|
||||
console.log(chalk[this.statusCode < 300 ? 'green' : 'red'](this.statusCode), req.uri);
|
||||
resp.end = function (data) {
|
||||
console.log(
|
||||
chalk[this.statusCode < 300 ? 'green' : 'red'](this.statusCode),
|
||||
req.uri,
|
||||
'-',
|
||||
Buffer.byteLength(data || ''),
|
||||
'bytes'
|
||||
);
|
||||
end.apply(resp, arguments);
|
||||
};
|
||||
|
||||
|
||||
@ -1,7 +1,6 @@
|
||||
var async = require('async');
|
||||
var cp = require('child_process');
|
||||
var chalk = require('chalk');
|
||||
var path = require('path');
|
||||
var argv = require('optimist')
|
||||
.usage([
|
||||
'Runner for the Elasticsearch.js unit and integration tests in both node and the browser.',
|
||||
@ -25,7 +24,7 @@ var argv = require('optimist')
|
||||
alias: 's'
|
||||
},
|
||||
unit: {
|
||||
default: true,
|
||||
default: false,
|
||||
alias: 'u'
|
||||
},
|
||||
integration: {
|
||||
@ -44,10 +43,6 @@ var argv = require('optimist')
|
||||
default: '*',
|
||||
alias: 'b'
|
||||
},
|
||||
'xml-output': {
|
||||
default: true,
|
||||
alias: 'x'
|
||||
},
|
||||
'check-upstream': {
|
||||
default: false,
|
||||
description: 'check for remote updates to the yaml test suite'
|
||||
@ -61,22 +56,17 @@ if (process.argv.indexOf('help') + process.argv.indexOf('--help') + process.argv
|
||||
|
||||
if (process.env.npm_config_argv) {
|
||||
// when called by NPM
|
||||
argv = argv.parse(JSON.parse(process.env.npm_config_argv).original);
|
||||
argv = argv.parse([].concat(process.argv).concat(JSON.parse(process.env.npm_config_argv).original));
|
||||
} else {
|
||||
// when called by NPM - via `npm test`
|
||||
// when called directly
|
||||
argv = argv.argv;
|
||||
}
|
||||
|
||||
var commands = [];
|
||||
var command;
|
||||
|
||||
if (argv['just-browser']) {
|
||||
argv.server = false;
|
||||
argv.browsers = '*';
|
||||
}
|
||||
|
||||
if (argv['check-upstream']) {
|
||||
command = ['node', 'scripts/generate/yaml_tests/index.js'];
|
||||
command = ['node', 'scripts/generate'];
|
||||
if (argv.force) {
|
||||
command.push('--force');
|
||||
}
|
||||
@ -85,21 +75,20 @@ if (argv['check-upstream']) {
|
||||
|
||||
if (argv.unit) {
|
||||
if (argv.server) {
|
||||
commands.push(['mocha', 'test/unit/test_*.js', '--require should']);
|
||||
commands.push(['./node_modules/.bin/mocha', 'test/unit/test_*.js', '--require should']);
|
||||
}
|
||||
if (argv.browsers) {
|
||||
commands.push(['testling', '.']);
|
||||
commands.push(['./node_modules/.bin/testling', '.']);
|
||||
}
|
||||
}
|
||||
|
||||
if (argv.integration) {
|
||||
if (argv.server) {
|
||||
commands.push([
|
||||
'mocha',
|
||||
'./node_modules/.bin/mocha',
|
||||
'test/integration/yaml_suite/index.js',
|
||||
'-b',
|
||||
// '-b',
|
||||
'--require', 'should',
|
||||
argv.x ? '--reporter' : '', argv.x ? path.join(__dirname, '../test/integration/yaml_suite/reporter.js') : '',
|
||||
'--host', argv.host,
|
||||
'--port', argv.port
|
||||
].filter(Boolean));
|
||||
@ -125,6 +114,7 @@ if (commands.length) {
|
||||
async.forEachSeries(commands, function (args, done) {
|
||||
var command = args.shift();
|
||||
console.log(chalk.gray.bold('\n\n' + '# ' + command + ' ' + args.join(' ')));
|
||||
|
||||
proc = cp.spawn(command, args, {
|
||||
stdio: 'inherit'
|
||||
});
|
||||
|
||||
@ -29,4 +29,5 @@ angular.module('elasticsearch.client', [])
|
||||
factory.ConnectionPool = require('./lib/connection_pool');
|
||||
factory.Transport = require('./lib/transport');
|
||||
|
||||
return factory;
|
||||
}]);
|
||||
|
||||
@ -72,7 +72,6 @@ api.bulk = ca({
|
||||
method: 'POST'
|
||||
});
|
||||
|
||||
|
||||
/**
|
||||
* Perform a [clearScroll](http://www.elasticsearch.org/guide/reference/api/search/scroll/) request
|
||||
*
|
||||
@ -92,7 +91,6 @@ api.clearScroll = ca({
|
||||
method: 'DELETE'
|
||||
});
|
||||
|
||||
|
||||
api.cluster = function ClusterNS(transport) {
|
||||
this.transport = transport;
|
||||
};
|
||||
@ -108,7 +106,6 @@ api.cluster.prototype.getSettings = ca({
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
/**
|
||||
* Perform a [cluster.health](http://elasticsearch.org/guide/reference/api/admin-cluster-health/) request
|
||||
*
|
||||
@ -182,7 +179,6 @@ api.cluster.prototype.health = ca({
|
||||
]
|
||||
});
|
||||
|
||||
|
||||
/**
|
||||
* Perform a [cluster.nodeHotThreads](http://www.elasticsearch.org/guide/reference/api/admin-cluster-nodes-hot-threads/) request
|
||||
*
|
||||
@ -228,7 +224,6 @@ api.cluster.prototype.nodeHotThreads = ca({
|
||||
]
|
||||
});
|
||||
|
||||
|
||||
/**
|
||||
* Perform a [cluster.nodeInfo](http://elasticsearch.org/guide/reference/api/admin-cluster-nodes-info/) request
|
||||
*
|
||||
@ -302,7 +297,6 @@ api.cluster.prototype.nodeInfo = ca({
|
||||
]
|
||||
});
|
||||
|
||||
|
||||
/**
|
||||
* Perform a [cluster.nodeShutdown](http://elasticsearch.org/guide/reference/api/admin-cluster-nodes-shutdown/) request
|
||||
*
|
||||
@ -336,7 +330,6 @@ api.cluster.prototype.nodeShutdown = ca({
|
||||
method: 'POST'
|
||||
});
|
||||
|
||||
|
||||
/**
|
||||
* Perform a [cluster.nodeStats](http://elasticsearch.org/guide/reference/api/admin-cluster-nodes-stats/) request
|
||||
*
|
||||
@ -412,7 +405,6 @@ api.cluster.prototype.nodeStats = ca({
|
||||
]
|
||||
});
|
||||
|
||||
|
||||
/**
|
||||
* Perform a [cluster.putSettings](http://elasticsearch.org/guide/reference/api/admin-cluster-update-settings/) request
|
||||
*
|
||||
@ -425,7 +417,6 @@ api.cluster.prototype.putSettings = ca({
|
||||
method: 'PUT'
|
||||
});
|
||||
|
||||
|
||||
/**
|
||||
* Perform a [cluster.reroute](http://elasticsearch.org/guide/reference/api/admin-cluster-reroute/) request
|
||||
*
|
||||
@ -450,7 +441,6 @@ api.cluster.prototype.reroute = ca({
|
||||
method: 'POST'
|
||||
});
|
||||
|
||||
|
||||
/**
|
||||
* Perform a [cluster.state](http://elasticsearch.org/guide/reference/api/admin-cluster-state/) request
|
||||
*
|
||||
@ -503,7 +493,6 @@ api.cluster.prototype.state = ca({
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
/**
|
||||
* Perform a [count](http://elasticsearch.org/guide/reference/api/count/) request
|
||||
*
|
||||
@ -568,7 +557,6 @@ api.count = ca({
|
||||
method: 'POST'
|
||||
});
|
||||
|
||||
|
||||
/**
|
||||
* Perform a [delete](http://elasticsearch.org/guide/reference/api/delete/) request
|
||||
*
|
||||
@ -645,7 +633,6 @@ api['delete'] = ca({
|
||||
method: 'DELETE'
|
||||
});
|
||||
|
||||
|
||||
/**
|
||||
* Perform a [deleteByQuery](http://www.elasticsearch.org/guide/reference/api/delete-by-query/) request
|
||||
*
|
||||
@ -742,7 +729,6 @@ api.deleteByQuery = ca({
|
||||
method: 'DELETE'
|
||||
});
|
||||
|
||||
|
||||
/**
|
||||
* Perform a [exists](http://elasticsearch.org/guide/reference/api/get/) request
|
||||
*
|
||||
@ -796,7 +782,6 @@ api.exists = ca({
|
||||
method: 'HEAD'
|
||||
});
|
||||
|
||||
|
||||
/**
|
||||
* Perform a [explain](http://elasticsearch.org/guide/reference/api/explain/) request
|
||||
*
|
||||
@ -896,7 +881,6 @@ api.explain = ca({
|
||||
method: 'POST'
|
||||
});
|
||||
|
||||
|
||||
/**
|
||||
* Perform a [get](http://elasticsearch.org/guide/reference/api/get/) request
|
||||
*
|
||||
@ -966,7 +950,6 @@ api.get = ca({
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
/**
|
||||
* Perform a [getSource](http://elasticsearch.org/guide/reference/api/get/) request
|
||||
*
|
||||
@ -1026,7 +1009,6 @@ api.getSource = ca({
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
/**
|
||||
* Perform a [index](http://elasticsearch.org/guide/reference/api/index_/) request
|
||||
*
|
||||
@ -1137,7 +1119,6 @@ api.index = ca({
|
||||
method: 'POST'
|
||||
});
|
||||
|
||||
|
||||
api.indices = function IndicesNS(transport) {
|
||||
this.transport = transport;
|
||||
};
|
||||
@ -1204,7 +1185,6 @@ api.indices.prototype.analyze = ca({
|
||||
method: 'POST'
|
||||
});
|
||||
|
||||
|
||||
/**
|
||||
* Perform a [indices.clearCache](http://www.elasticsearch.org/guide/reference/api/admin-indices-clearcache/) request
|
||||
*
|
||||
@ -1283,7 +1263,6 @@ api.indices.prototype.clearCache = ca({
|
||||
method: 'POST'
|
||||
});
|
||||
|
||||
|
||||
/**
|
||||
* Perform a [indices.close](http://www.elasticsearch.org/guide/reference/api/admin-indices-open-close/) request
|
||||
*
|
||||
@ -1314,7 +1293,6 @@ api.indices.prototype.close = ca({
|
||||
method: 'POST'
|
||||
});
|
||||
|
||||
|
||||
/**
|
||||
* Perform a [indices.create](http://www.elasticsearch.org/guide/reference/api/admin-indices-create-index/) request
|
||||
*
|
||||
@ -1345,7 +1323,6 @@ api.indices.prototype.create = ca({
|
||||
method: 'POST'
|
||||
});
|
||||
|
||||
|
||||
/**
|
||||
* Perform a [indices.delete](http://www.elasticsearch.org/guide/reference/api/admin-indices-delete-index/) request
|
||||
*
|
||||
@ -1380,7 +1357,6 @@ api.indices.prototype['delete'] = ca({
|
||||
method: 'DELETE'
|
||||
});
|
||||
|
||||
|
||||
/**
|
||||
* Perform a [indices.deleteAlias](http://www.elasticsearch.org/guide/reference/api/admin-indices-aliases/) request
|
||||
*
|
||||
@ -1415,7 +1391,6 @@ api.indices.prototype.deleteAlias = ca({
|
||||
method: 'DELETE'
|
||||
});
|
||||
|
||||
|
||||
/**
|
||||
* Perform a [indices.deleteMapping](http://www.elasticsearch.org/guide/reference/api/admin-indices-delete-mapping/) request
|
||||
*
|
||||
@ -1446,7 +1421,6 @@ api.indices.prototype.deleteMapping = ca({
|
||||
method: 'DELETE'
|
||||
});
|
||||
|
||||
|
||||
/**
|
||||
* Perform a [indices.deleteTemplate](http://www.elasticsearch.org/guide/reference/api/admin-indices-templates/) request
|
||||
*
|
||||
@ -1477,7 +1451,6 @@ api.indices.prototype.deleteTemplate = ca({
|
||||
method: 'DELETE'
|
||||
});
|
||||
|
||||
|
||||
/**
|
||||
* Perform a [indices.deleteWarmer](http://www.elasticsearch.org/guide/reference/api/admin-indices-warmers/) request
|
||||
*
|
||||
@ -1532,7 +1505,6 @@ api.indices.prototype.deleteWarmer = ca({
|
||||
method: 'DELETE'
|
||||
});
|
||||
|
||||
|
||||
/**
|
||||
* Perform a [indices.exists](http://www.elasticsearch.org/guide/reference/api/admin-indices-indices-exists/) request
|
||||
*
|
||||
@ -1553,7 +1525,6 @@ api.indices.prototype.exists = ca({
|
||||
method: 'HEAD'
|
||||
});
|
||||
|
||||
|
||||
/**
|
||||
* Perform a [indices.existsAlias](http://www.elasticsearch.org/guide/reference/api/admin-indices-aliases/) request
|
||||
*
|
||||
@ -1599,7 +1570,6 @@ api.indices.prototype.existsAlias = ca({
|
||||
method: 'HEAD'
|
||||
});
|
||||
|
||||
|
||||
/**
|
||||
* Perform a [indices.existsType](http://www.elasticsearch.org/guide/reference/api/admin-indices-types-exists/) request
|
||||
*
|
||||
@ -1636,7 +1606,6 @@ api.indices.prototype.existsType = ca({
|
||||
method: 'HEAD'
|
||||
});
|
||||
|
||||
|
||||
/**
|
||||
* Perform a [indices.flush](http://www.elasticsearch.org/guide/reference/api/admin-indices-flush/) request
|
||||
*
|
||||
@ -1684,7 +1653,6 @@ api.indices.prototype.flush = ca({
|
||||
method: 'POST'
|
||||
});
|
||||
|
||||
|
||||
/**
|
||||
* Perform a [indices.getAlias](http://www.elasticsearch.org/guide/reference/api/admin-indices-aliases/) request
|
||||
*
|
||||
@ -1728,7 +1696,6 @@ api.indices.prototype.getAlias = ca({
|
||||
]
|
||||
});
|
||||
|
||||
|
||||
/**
|
||||
* Perform a [indices.getAliases](http://www.elasticsearch.org/guide/reference/api/admin-indices-aliases/) request
|
||||
*
|
||||
@ -1757,7 +1724,6 @@ api.indices.prototype.getAliases = ca({
|
||||
]
|
||||
});
|
||||
|
||||
|
||||
/**
|
||||
* Perform a [indices.getFieldMapping](http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/indices-get-field-mapping.html) request
|
||||
*
|
||||
@ -1811,7 +1777,6 @@ api.indices.prototype.getFieldMapping = ca({
|
||||
]
|
||||
});
|
||||
|
||||
|
||||
/**
|
||||
* Perform a [indices.getMapping](http://www.elasticsearch.org/guide/reference/api/admin-indices-get-mapping/) request
|
||||
*
|
||||
@ -1846,7 +1811,6 @@ api.indices.prototype.getMapping = ca({
|
||||
]
|
||||
});
|
||||
|
||||
|
||||
/**
|
||||
* Perform a [indices.getSettings](http://www.elasticsearch.org/guide/reference/api/admin-indices-get-settings/) request
|
||||
*
|
||||
@ -1869,7 +1833,6 @@ api.indices.prototype.getSettings = ca({
|
||||
]
|
||||
});
|
||||
|
||||
|
||||
/**
|
||||
* Perform a [indices.getTemplate](http://www.elasticsearch.org/guide/reference/api/admin-indices-templates/) request
|
||||
*
|
||||
@ -1892,7 +1855,6 @@ api.indices.prototype.getTemplate = ca({
|
||||
]
|
||||
});
|
||||
|
||||
|
||||
/**
|
||||
* Perform a [indices.getWarmer](http://www.elasticsearch.org/guide/reference/api/admin-indices-warmers/) request
|
||||
*
|
||||
@ -1939,7 +1901,6 @@ api.indices.prototype.getWarmer = ca({
|
||||
]
|
||||
});
|
||||
|
||||
|
||||
/**
|
||||
* Perform a [indices.open](http://www.elasticsearch.org/guide/reference/api/admin-indices-open-close/) request
|
||||
*
|
||||
@ -1970,7 +1931,6 @@ api.indices.prototype.open = ca({
|
||||
method: 'POST'
|
||||
});
|
||||
|
||||
|
||||
/**
|
||||
* Perform a [indices.optimize](http://www.elasticsearch.org/guide/reference/api/admin-indices-optimize/) request
|
||||
*
|
||||
@ -2033,7 +1993,6 @@ api.indices.prototype.optimize = ca({
|
||||
method: 'POST'
|
||||
});
|
||||
|
||||
|
||||
/**
|
||||
* Perform a [indices.putAlias](http://www.elasticsearch.org/guide/reference/api/admin-indices-aliases/) request
|
||||
*
|
||||
@ -2088,7 +2047,6 @@ api.indices.prototype.putAlias = ca({
|
||||
method: 'PUT'
|
||||
});
|
||||
|
||||
|
||||
/**
|
||||
* Perform a [indices.putMapping](http://www.elasticsearch.org/guide/reference/api/admin-indices-put-mapping/) request
|
||||
*
|
||||
@ -2128,7 +2086,6 @@ api.indices.prototype.putMapping = ca({
|
||||
method: 'PUT'
|
||||
});
|
||||
|
||||
|
||||
/**
|
||||
* Perform a [indices.putSettings](http://www.elasticsearch.org/guide/reference/api/admin-indices-update-settings/) request
|
||||
*
|
||||
@ -2159,7 +2116,6 @@ api.indices.prototype.putSettings = ca({
|
||||
method: 'PUT'
|
||||
});
|
||||
|
||||
|
||||
/**
|
||||
* Perform a [indices.putTemplate](http://www.elasticsearch.org/guide/reference/api/admin-indices-templates/) request
|
||||
*
|
||||
@ -2194,7 +2150,6 @@ api.indices.prototype.putTemplate = ca({
|
||||
method: 'PUT'
|
||||
});
|
||||
|
||||
|
||||
/**
|
||||
* Perform a [indices.putWarmer](http://www.elasticsearch.org/guide/reference/api/admin-indices-warmers/) request
|
||||
*
|
||||
@ -2241,7 +2196,6 @@ api.indices.prototype.putWarmer = ca({
|
||||
method: 'PUT'
|
||||
});
|
||||
|
||||
|
||||
/**
|
||||
* Perform a [indices.refresh](http://www.elasticsearch.org/guide/reference/api/admin-indices-refresh/) request
|
||||
*
|
||||
@ -2281,7 +2235,6 @@ api.indices.prototype.refresh = ca({
|
||||
method: 'POST'
|
||||
});
|
||||
|
||||
|
||||
/**
|
||||
* Perform a [indices.segments](http://elasticsearch.org/guide/reference/api/admin-indices-segments/) request
|
||||
*
|
||||
@ -2320,7 +2273,6 @@ api.indices.prototype.segments = ca({
|
||||
]
|
||||
});
|
||||
|
||||
|
||||
/**
|
||||
* Perform a [indices.snapshotIndex](http://www.elasticsearch.org/guide/reference/api/admin-indices-gateway-snapshot/) request
|
||||
*
|
||||
@ -2356,7 +2308,6 @@ api.indices.prototype.snapshotIndex = ca({
|
||||
method: 'POST'
|
||||
});
|
||||
|
||||
|
||||
/**
|
||||
* Perform a [indices.stats](http://elasticsearch.org/guide/reference/api/admin-indices-stats/) request
|
||||
*
|
||||
@ -2474,7 +2425,6 @@ api.indices.prototype.stats = ca({
|
||||
]
|
||||
});
|
||||
|
||||
|
||||
/**
|
||||
* Perform a [indices.status](http://elasticsearch.org/guide/reference/api/admin-indices-status/) request
|
||||
*
|
||||
@ -2521,7 +2471,6 @@ api.indices.prototype.status = ca({
|
||||
]
|
||||
});
|
||||
|
||||
|
||||
/**
|
||||
* Perform a [indices.updateAliases](http://www.elasticsearch.org/guide/reference/api/admin-indices-aliases/) request
|
||||
*
|
||||
@ -2546,7 +2495,6 @@ api.indices.prototype.updateAliases = ca({
|
||||
method: 'POST'
|
||||
});
|
||||
|
||||
|
||||
/**
|
||||
* Perform a [indices.validateQuery](http://www.elasticsearch.org/guide/reference/api/validate/) request
|
||||
*
|
||||
@ -2610,7 +2558,6 @@ api.indices.prototype.validateQuery = ca({
|
||||
method: 'POST'
|
||||
});
|
||||
|
||||
|
||||
/**
|
||||
* Perform a [info](http://elasticsearch.org/guide/) request
|
||||
*
|
||||
@ -2622,7 +2569,6 @@ api.info = ca({
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
/**
|
||||
* Perform a [mget](http://elasticsearch.org/guide/reference/api/multi-get/) request
|
||||
*
|
||||
@ -2690,7 +2636,6 @@ api.mget = ca({
|
||||
method: 'POST'
|
||||
});
|
||||
|
||||
|
||||
/**
|
||||
* Perform a [mlt](http://elasticsearch.org/guide/reference/api/more-like-this/) request
|
||||
*
|
||||
@ -2814,7 +2759,6 @@ api.mlt = ca({
|
||||
method: 'POST'
|
||||
});
|
||||
|
||||
|
||||
/**
|
||||
* Perform a [msearch](http://www.elasticsearch.org/guide/reference/api/multi-search/) request
|
||||
*
|
||||
@ -2866,7 +2810,6 @@ api.msearch = ca({
|
||||
method: 'POST'
|
||||
});
|
||||
|
||||
|
||||
/**
|
||||
* Perform a [percolate](http://elasticsearch.org/guide/reference/api/percolate/) request
|
||||
*
|
||||
@ -2897,7 +2840,6 @@ api.percolate = ca({
|
||||
method: 'POST'
|
||||
});
|
||||
|
||||
|
||||
/**
|
||||
* Perform a [scroll](http://www.elasticsearch.org/guide/reference/api/search/scroll/) request
|
||||
*
|
||||
@ -2931,7 +2873,6 @@ api.scroll = ca({
|
||||
method: 'POST'
|
||||
});
|
||||
|
||||
|
||||
/**
|
||||
* Perform a [search](http://www.elasticsearch.org/guide/reference/api/search/) request
|
||||
*
|
||||
@ -3122,7 +3063,6 @@ api.search = ca({
|
||||
method: 'POST'
|
||||
});
|
||||
|
||||
|
||||
/**
|
||||
* Perform a [suggest](http://elasticsearch.org/guide/reference/api/search/suggest/) request
|
||||
*
|
||||
@ -3170,7 +3110,6 @@ api.suggest = ca({
|
||||
method: 'POST'
|
||||
});
|
||||
|
||||
|
||||
/**
|
||||
* Perform a [update](http://elasticsearch.org/guide/reference/api/update/) request
|
||||
*
|
||||
@ -3297,5 +3236,4 @@ api.create = ca.proxy(api.index, {
|
||||
transform: function (params) {
|
||||
params.op_type = 'create';
|
||||
}
|
||||
});
|
||||
|
||||
});
|
||||
2
src/lib/connectors/angular.js
vendored
2
src/lib/connectors/angular.js
vendored
@ -24,7 +24,7 @@ AngularConnector.prototype.request = function (params, cb) {
|
||||
cache: false,
|
||||
timeout: abort.promise
|
||||
}).then(function (response) {
|
||||
cb(null, response.data, response.status);
|
||||
cb(null, response.data, response.status, response.headers);
|
||||
}, function (err) {
|
||||
cb(new ConnectionFault(err.message));
|
||||
});
|
||||
|
||||
@ -68,6 +68,10 @@ HttpConnector.prototype.makeReqParams = function (params) {
|
||||
agent: this.agent
|
||||
};
|
||||
|
||||
if (!reqParams.path) {
|
||||
reqParams.path = '/';
|
||||
}
|
||||
|
||||
var query = this.host.query ? _.clone(this.host.query) : {};
|
||||
|
||||
if (params.query) {
|
||||
@ -87,6 +91,7 @@ HttpConnector.prototype.request = function (params, cb) {
|
||||
var request;
|
||||
var response;
|
||||
var status = 0;
|
||||
var headers;
|
||||
var log = this.log;
|
||||
|
||||
var reqParams = this.makeReqParams(params);
|
||||
@ -116,6 +121,7 @@ HttpConnector.prototype.request = function (params, cb) {
|
||||
request = this.hand.request(reqParams, function (_incoming) {
|
||||
incoming = _incoming;
|
||||
status = incoming.statusCode;
|
||||
headers = incoming.headers;
|
||||
incoming.setEncoding('utf8');
|
||||
response = '';
|
||||
|
||||
|
||||
@ -55,9 +55,9 @@ XhrConnector.prototype.request = function (params, cb) {
|
||||
var async = params.async === false ? false : asyncDefault;
|
||||
|
||||
if (params.auth) {
|
||||
xhr.open(params.method, url, async, params.auth.user, params.auth.pass);
|
||||
xhr.open(params.method || 'GET', url, async, params.auth.user, params.auth.pass);
|
||||
} else {
|
||||
xhr.open(params.method, url, async);
|
||||
xhr.open(params.method || 'GET', url, async);
|
||||
}
|
||||
|
||||
xhr.onreadystatechange = function () {
|
||||
|
||||
@ -305,6 +305,7 @@ Log.prototype.trace = function (method, requestUrl, body, responseBody, response
|
||||
|
||||
function prettyJSON(body) {
|
||||
try {
|
||||
// TESTME
|
||||
return JSON.stringify(JSON.parse(body), null, ' ').replace(/'/g, '\\\'');
|
||||
} catch (e) {
|
||||
return body || '';
|
||||
|
||||
@ -35,7 +35,7 @@ function Transport(config) {
|
||||
this.maxRetries = config.hasOwnProperty('maxRetries') ? config.maxRetries : 3;
|
||||
|
||||
// setup requestTimeout default
|
||||
this.requestTimeout = config.hasOwnProperty('requestTimeout') ? config.requestTimeout : 10000;
|
||||
this.requestTimeout = config.hasOwnProperty('requestTimeout') ? config.requestTimeout : 30000;
|
||||
|
||||
// randomizeHosts option
|
||||
var randomizeHosts = config.hasOwnProperty('randomizeHosts') ? !!config.randomizeHosts : true;
|
||||
@ -98,7 +98,7 @@ Transport.prototype.request = function (params, cb) {
|
||||
var remainingRetries = this.maxRetries;
|
||||
var connection; // set in sendReqWithConnection
|
||||
var aborted = false; // several connector will respond with an error when the request is aborted
|
||||
var requestAbort; // an abort function, returned by connection#request()
|
||||
var requestAborter; // an abort function, returned by connection#request()
|
||||
var requestTimeout; // the general timeout for the total request (inculding all retries)
|
||||
var requestTimeoutId; // the id of the ^timeout
|
||||
var request; // the object returned to the user, might be a promise
|
||||
@ -118,7 +118,7 @@ Transport.prototype.request = function (params, cb) {
|
||||
|
||||
params.req = {
|
||||
method: params.method,
|
||||
path: params.path,
|
||||
path: params.path || '/',
|
||||
query: params.query,
|
||||
body: params.body,
|
||||
};
|
||||
@ -132,18 +132,20 @@ Transport.prototype.request = function (params, cb) {
|
||||
respond(err);
|
||||
} else if (_connection) {
|
||||
connection = _connection;
|
||||
requestAbort = connection.request(params.req, checkRespForFailure);
|
||||
requestAborter = connection.request(params.req, checkRespForFailure);
|
||||
} else {
|
||||
self.log.warning('No living connections');
|
||||
respond(new errors.NoConnections());
|
||||
}
|
||||
}
|
||||
|
||||
function checkRespForFailure(err, body, status) {
|
||||
function checkRespForFailure(err, body, status, headers) {
|
||||
if (aborted) {
|
||||
return;
|
||||
}
|
||||
|
||||
requestAborter = void 0;
|
||||
|
||||
if (err) {
|
||||
connection.setStatus('dead');
|
||||
if (remainingRetries) {
|
||||
@ -156,21 +158,26 @@ Transport.prototype.request = function (params, cb) {
|
||||
}
|
||||
} else {
|
||||
self.log.info('Request complete');
|
||||
respond(void 0, body, status);
|
||||
respond(void 0, body, status, headers);
|
||||
}
|
||||
}
|
||||
|
||||
function respond(err, body, status) {
|
||||
function respond(err, body, status, headers) {
|
||||
if (aborted) {
|
||||
return;
|
||||
}
|
||||
|
||||
clearTimeout(requestTimeoutId);
|
||||
var parsedBody;
|
||||
|
||||
if (!err && body) {
|
||||
parsedBody = self.serializer.deserialize(body);
|
||||
if (parsedBody == null) {
|
||||
err = new errors.Serialization();
|
||||
if (!headers || headers['content-type'] === 'application/json') {
|
||||
parsedBody = self.serializer.deserialize(body);
|
||||
if (parsedBody == null) {
|
||||
err = new errors.Serialization();
|
||||
}
|
||||
} else {
|
||||
parsedBody = body;
|
||||
}
|
||||
}
|
||||
|
||||
@ -222,8 +229,8 @@ Transport.prototype.request = function (params, cb) {
|
||||
aborted = true;
|
||||
remainingRetries = 0;
|
||||
clearTimeout(requestTimeoutId);
|
||||
if (typeof requestAbort === 'function') {
|
||||
requestAbort();
|
||||
if (typeof requestAborter === 'function') {
|
||||
requestAborter();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
1
src/rest-api-spec
Submodule
1
src/rest-api-spec
Submodule
Submodule src/rest-api-spec added at bd7f4e3c5d
File diff suppressed because it is too large
Load Diff
@ -11,23 +11,27 @@ var argv = require('./argv');
|
||||
var testDir = path.resolve(__dirname, './tests');
|
||||
var doPattern = new Minimatch(argv.match);
|
||||
|
||||
// before running any tests...
|
||||
before(function (done) {
|
||||
// start our personal ES Server
|
||||
this.timeout(null);
|
||||
clientManager.create(done);
|
||||
});
|
||||
describe('yaml -', function () {
|
||||
|
||||
before(function (done) {
|
||||
// make sure ES is empty
|
||||
clientManager.get().indices.delete({
|
||||
index: '*',
|
||||
ignore: 404
|
||||
}, done);
|
||||
});
|
||||
// before running any tests...
|
||||
before(function (done) {
|
||||
// start our personal ES Server
|
||||
this.timeout(null);
|
||||
clientManager.create(done);
|
||||
});
|
||||
|
||||
var files = _.map(require('./yaml_tests.json'), function (docs, filename) {
|
||||
if (doPattern.match(filename)) {
|
||||
return new YamlFile(filename, docs);
|
||||
}
|
||||
});
|
||||
before(function (done) {
|
||||
// make sure ES is empty
|
||||
clientManager.get().indices.delete({
|
||||
index: '*',
|
||||
ignore: 404
|
||||
}, done);
|
||||
});
|
||||
|
||||
var files = _.map(require('./yaml_tests.json'), function (docs, filename) {
|
||||
if (doPattern.match(filename)) {
|
||||
return new YamlFile(filename, docs);
|
||||
}
|
||||
});
|
||||
|
||||
});
|
||||
484
test/mocks/browser_http.js
Normal file
484
test/mocks/browser_http.js
Normal file
@ -0,0 +1,484 @@
|
||||
/* jshint browser:true */
|
||||
/* global ActiveXObject */
|
||||
|
||||
//////////////
|
||||
/// Extended version of:
|
||||
/// https://github.com/philikon/MockHttpRequest/
|
||||
//////////////
|
||||
/*
|
||||
* Mock XMLHttpRequest (see http://www.w3.org/TR/XMLHttpRequest)
|
||||
*
|
||||
* Written by Philipp von Weitershausen <philipp@weitershausen.de>
|
||||
* Released under the MIT license.
|
||||
* http://www.opensource.org/licenses/mit-license.php
|
||||
*
|
||||
* For test interaction it exposes the following attributes:
|
||||
*
|
||||
* - method, url, urlParts, async, user, password
|
||||
* - requestText
|
||||
*
|
||||
* as well as the following methods:
|
||||
*
|
||||
* - getRequestHeader(header)
|
||||
* - setResponseHeader(header, value)
|
||||
* - receive(status, data)
|
||||
* - err(exception)
|
||||
* - authenticate(user, password)
|
||||
*
|
||||
*/
|
||||
|
||||
module.exports = MockHttpRequest;
|
||||
|
||||
var _ = require('lodash');
|
||||
|
||||
function MockHttpRequest() {
|
||||
// These are internal flags and data structures
|
||||
this.error = false;
|
||||
this.sent = false;
|
||||
this.requestHeaders = {};
|
||||
this.responseHeaders = {};
|
||||
}
|
||||
|
||||
MockHttpRequest.prototype = {
|
||||
|
||||
statusReasons: {
|
||||
100: 'Continue',
|
||||
101: 'Switching Protocols',
|
||||
102: 'Processing',
|
||||
200: 'OK',
|
||||
201: 'Created',
|
||||
202: 'Accepted',
|
||||
203: 'Non-Authoritative Information',
|
||||
204: 'No Content',
|
||||
205: 'Reset Content',
|
||||
206: 'Partial Content',
|
||||
207: 'Multi-Status',
|
||||
300: 'Multiple Choices',
|
||||
301: 'Moved Permanently',
|
||||
302: 'Moved Temporarily',
|
||||
303: 'See Other',
|
||||
304: 'Not Modified',
|
||||
305: 'Use Proxy',
|
||||
307: 'Temporary Redirect',
|
||||
400: 'Bad Request',
|
||||
401: 'Unauthorized',
|
||||
402: 'Payment Required',
|
||||
403: 'Forbidden',
|
||||
404: 'Not Found',
|
||||
405: 'Method Not Allowed',
|
||||
406: 'Not Acceptable',
|
||||
407: 'Proxy Authentication Required',
|
||||
408: 'Request Time-out',
|
||||
409: 'Conflict',
|
||||
410: 'Gone',
|
||||
411: 'Length Required',
|
||||
412: 'Precondition Failed',
|
||||
413: 'Request Entity Too Large',
|
||||
414: 'Request-URI Too Large',
|
||||
415: 'Unsupported Media Type',
|
||||
416: 'Requested range not satisfiable',
|
||||
417: 'Expectation Failed',
|
||||
422: 'Unprocessable Entity',
|
||||
423: 'Locked',
|
||||
424: 'Failed Dependency',
|
||||
500: 'Internal Server Error',
|
||||
501: 'Not Implemented',
|
||||
502: 'Bad Gateway',
|
||||
503: 'Service Unavailable',
|
||||
504: 'Gateway Time-out',
|
||||
505: 'HTTP Version not supported',
|
||||
507: 'Insufficient Storage'
|
||||
},
|
||||
|
||||
/*** State ***/
|
||||
|
||||
UNSENT: 0,
|
||||
OPENED: 1,
|
||||
HEADERS_RECEIVED: 2,
|
||||
LOADING: 3,
|
||||
DONE: 4,
|
||||
readyState: 0,
|
||||
|
||||
/*** Request ***/
|
||||
|
||||
open: function (method, url, async, user, password) {
|
||||
if (typeof method !== 'string') {
|
||||
throw 'INVALID_METHOD';
|
||||
}
|
||||
switch (method.toUpperCase()) {
|
||||
case 'CONNECT':
|
||||
case 'TRACE':
|
||||
case 'TRACK':
|
||||
throw 'SECURITY_ERR';
|
||||
|
||||
case 'DELETE':
|
||||
case 'GET':
|
||||
case 'HEAD':
|
||||
case 'OPTIONS':
|
||||
case 'POST':
|
||||
case 'PUT':
|
||||
method = method.toUpperCase();
|
||||
}
|
||||
this.method = method;
|
||||
|
||||
if (typeof url !== 'string') {
|
||||
throw 'INVALID_URL';
|
||||
}
|
||||
this.url = url;
|
||||
this.urlParts = this.parseUri(url);
|
||||
|
||||
if (async === undefined) {
|
||||
async = true;
|
||||
}
|
||||
this.async = async;
|
||||
this.user = user;
|
||||
this.password = password;
|
||||
|
||||
this.readyState = this.OPENED;
|
||||
this.onreadystatechange();
|
||||
},
|
||||
|
||||
setRequestHeader: function (header, value) {
|
||||
header = header.toLowerCase();
|
||||
|
||||
switch (header) {
|
||||
case 'accept-charset':
|
||||
case 'accept-encoding':
|
||||
case 'connection':
|
||||
case 'content-length':
|
||||
case 'cookie':
|
||||
case 'cookie2':
|
||||
case 'content-transfer-encoding':
|
||||
case 'date':
|
||||
case 'expect':
|
||||
case 'host':
|
||||
case 'keep-alive':
|
||||
case 'referer':
|
||||
case 'te':
|
||||
case 'trailer':
|
||||
case 'transfer-encoding':
|
||||
case 'upgrade':
|
||||
case 'user-agent':
|
||||
case 'via':
|
||||
return;
|
||||
}
|
||||
if ((header.substr(0, 6) === 'proxy-') || (header.substr(0, 4) === 'sec-')) {
|
||||
return;
|
||||
}
|
||||
|
||||
// it's the first call on this header field
|
||||
if (this.requestHeaders[header] === undefined) {
|
||||
this.requestHeaders[header] = value;
|
||||
}
|
||||
else {
|
||||
var prev = this.requestHeaders[header];
|
||||
this.requestHeaders[header] = prev + ', ' + value;
|
||||
}
|
||||
|
||||
},
|
||||
|
||||
send: function (data) {
|
||||
if ((this.readyState !== this.OPENED) || this.sent) {
|
||||
throw 'INVALID_STATE_ERR';
|
||||
}
|
||||
if ((this.method === 'GET') || (this.method === 'HEAD')) {
|
||||
data = null;
|
||||
}
|
||||
|
||||
//TODO set Content-Type header?
|
||||
this.error = false;
|
||||
this.sent = true;
|
||||
this.onreadystatechange();
|
||||
|
||||
// fake send
|
||||
this.requestText = data;
|
||||
this.onsend();
|
||||
},
|
||||
|
||||
abort: function () {
|
||||
this.responseText = null;
|
||||
this.error = true;
|
||||
for (var header in this.requestHeaders) {
|
||||
if (this.requestHeaders.hasOwnProperty(header)) {
|
||||
delete this.requestHeaders[header];
|
||||
}
|
||||
}
|
||||
delete this.requestText;
|
||||
this.onreadystatechange();
|
||||
this.onabort();
|
||||
this.readyState = this.UNSENT;
|
||||
},
|
||||
|
||||
/*** Response ***/
|
||||
|
||||
status: 0,
|
||||
statusText: '',
|
||||
|
||||
getResponseHeader: function (header) {
|
||||
if ((this.readyState === this.UNSENT) || (this.readyState === this.OPENED) || this.error) {
|
||||
return null;
|
||||
}
|
||||
return this.responseHeaders[header.toLowerCase()];
|
||||
},
|
||||
|
||||
getAllResponseHeaders: function () {
|
||||
var r = '';
|
||||
_.each(this.responseHeaders, function (header) {
|
||||
if ((header === 'set-cookie') || (header === 'set-cookie2')) {
|
||||
return;
|
||||
}
|
||||
//TODO title case header
|
||||
r += header + ': ' + this.responseHeaders[header] + '\r\n';
|
||||
}, this);
|
||||
return r;
|
||||
},
|
||||
|
||||
responseText: '',
|
||||
responseXML: undefined, //TODO
|
||||
|
||||
/*** See http://www.w3.org/TR/progress-events/ ***/
|
||||
|
||||
onload: function () {
|
||||
// Instances should override this.
|
||||
},
|
||||
|
||||
onprogress: function () {
|
||||
// Instances should override this.
|
||||
},
|
||||
|
||||
onerror: function () {
|
||||
// Instances should override this.
|
||||
},
|
||||
|
||||
onabort: function () {
|
||||
// Instances should override this.
|
||||
},
|
||||
|
||||
onreadystatechange: function () {
|
||||
// Instances should override this.
|
||||
},
|
||||
|
||||
/*** Properties and methods for test interaction ***/
|
||||
|
||||
onsend: function () {
|
||||
// Instances should override this.
|
||||
},
|
||||
|
||||
getRequestHeader: function (header) {
|
||||
return this.requestHeaders[header.toLowerCase()];
|
||||
},
|
||||
|
||||
setResponseHeader: function (header, value) {
|
||||
this.responseHeaders[header.toLowerCase()] = value;
|
||||
},
|
||||
|
||||
makeXMLResponse: function (data) {
|
||||
var xmlDoc;
|
||||
// according to specs from point 3.7.5:
|
||||
// '1. If the response entity body is null terminate these steps
|
||||
// and return null.
|
||||
// 2. If final MIME type is not null, text/xml, application/xml,
|
||||
// and does not end in +xml terminate these steps and return null.
|
||||
var mimetype = this.getResponseHeader('Content-Type');
|
||||
mimetype = mimetype && mimetype.split(';', 1)[0];
|
||||
if ((mimetype == null) || (mimetype === 'text/xml') ||
|
||||
(mimetype === 'application/xml') ||
|
||||
(mimetype && mimetype.substring(mimetype.length - 4) === '+xml')) {
|
||||
// Attempt to produce an xml response
|
||||
// and it will fail if not a good xml
|
||||
try {
|
||||
if (window.DOMParser) {
|
||||
var parser = new DOMParser();
|
||||
xmlDoc = parser.parseFromString(data, 'text/xml');
|
||||
} else { // Internet Explorer
|
||||
xmlDoc = new ActiveXObject('Microsoft.XMLDOM');
|
||||
xmlDoc.async = 'false';
|
||||
xmlDoc.loadXML(data);
|
||||
}
|
||||
} catch (e) {
|
||||
// according to specs from point 3.7.5:
|
||||
// '3. Let document be a cookie-free Document object that
|
||||
// represents the result of parsing the response entity body
|
||||
// into a document tree following the rules from the XML
|
||||
// specifications. If this fails (unsupported character
|
||||
// encoding, namespace well-formedness error etc.), terminate
|
||||
// these steps return null.'
|
||||
xmlDoc = null;
|
||||
}
|
||||
// parse errors also yield a null.
|
||||
if ((xmlDoc && xmlDoc.parseError && xmlDoc.parseError.errorCode !== 0) || (xmlDoc && xmlDoc.documentElement &&
|
||||
xmlDoc.documentElement.nodeName !== 'parsererror') || (xmlDoc && xmlDoc.documentElement && xmlDoc.documentElement
|
||||
.nodeName !== 'html' && xmlDoc.documentElement.firstChild && xmlDoc.documentElement.firstChild.nodeName ===
|
||||
'body' && xmlDoc.documentElement.firstChild.firstChild && xmlDoc.documentElement.firstChild.firstChild.nodeName
|
||||
=== 'parsererror')) {
|
||||
xmlDoc = null;
|
||||
}
|
||||
} else {
|
||||
// mimetype is specified, but not xml-ish
|
||||
xmlDoc = null;
|
||||
}
|
||||
return xmlDoc;
|
||||
},
|
||||
|
||||
// Call this to simulate a server response
|
||||
receive: function (status, data) {
|
||||
if ((this.readyState !== this.OPENED) || (!this.sent)) {
|
||||
// Can't respond to unopened request.
|
||||
throw 'INVALID_STATE_ERR';
|
||||
}
|
||||
|
||||
this.status = status;
|
||||
this.statusText = status + ' ' + this.statusReasons[status];
|
||||
this.readyState = this.HEADERS_RECEIVED;
|
||||
this.onprogress();
|
||||
this.onreadystatechange();
|
||||
|
||||
this.responseText = data;
|
||||
this.responseXML = this.makeXMLResponse(data);
|
||||
|
||||
this.readyState = this.LOADING;
|
||||
this.onprogress();
|
||||
this.onreadystatechange();
|
||||
|
||||
this.readyState = this.DONE;
|
||||
this.onreadystatechange();
|
||||
this.onprogress();
|
||||
this.onload();
|
||||
},
|
||||
|
||||
// Call this to simulate a request error (e.g. NETWORK_ERR)
|
||||
err: function (exception) {
|
||||
if ((this.readyState !== this.OPENED) || (!this.sent)) {
|
||||
// Can't respond to unopened request.
|
||||
throw 'INVALID_STATE_ERR';
|
||||
}
|
||||
|
||||
this.responseText = null;
|
||||
this.error = true;
|
||||
_.each(this.requestHeaders, function (header) {
|
||||
delete this.requestHeaders[header];
|
||||
}, this);
|
||||
|
||||
this.readyState = this.DONE;
|
||||
if (!this.async) {
|
||||
throw exception;
|
||||
}
|
||||
this.onreadystatechange();
|
||||
this.onerror();
|
||||
},
|
||||
|
||||
// Convenience method to verify HTTP credentials
|
||||
authenticate: function (user, password) {
|
||||
if (this.user) {
|
||||
return (user === this.user) && (password === this.password);
|
||||
}
|
||||
|
||||
if (this.urlParts.user) {
|
||||
return ((user === this.urlParts.user) && (password === this.urlParts.password));
|
||||
}
|
||||
|
||||
// Basic auth. Requires existence of the 'atob' function.
|
||||
var auth = this.getRequestHeader('Authorization');
|
||||
if (auth === undefined) {
|
||||
return false;
|
||||
}
|
||||
if (auth.substr(0, 6) !== 'Basic ') {
|
||||
return false;
|
||||
}
|
||||
if (typeof atob !== 'function') {
|
||||
return false;
|
||||
}
|
||||
auth = atob(auth.substr(6));
|
||||
var pieces = auth.split(':');
|
||||
var requser = pieces.shift();
|
||||
var reqpass = pieces.join(':');
|
||||
return (user === requser) && (password === reqpass);
|
||||
},
|
||||
|
||||
// Parse RFC 3986 compliant URIs.
|
||||
// Based on parseUri by Steven Levithan <stevenlevithan.com>
|
||||
// See http://blog.stevenlevithan.com/archives/parseuri
|
||||
parseUri: function (str) {
|
||||
/* jshint maxlen:false */
|
||||
var pattern =
|
||||
/^(?:([^:\/?#]+):)?(?:\/\/((?:(([^:@]*)(?::([^:@]*))?)?@)?([^:\/?#]*)(?::(\d*))?))?((((?:[^?#\/]*\/)*)([^?#]*))(?:\?([^#]*))?(?:#(.*))?)/;
|
||||
var key = ['source', 'protocol', 'authority', 'userInfo', 'user',
|
||||
'password', 'host', 'port', 'relative', 'path',
|
||||
'directory', 'file', 'query', 'anchor'
|
||||
];
|
||||
var querypattern = /(?:^|&)([^&=]*)=?([^&]*)/g;
|
||||
|
||||
var match = pattern.exec(str);
|
||||
var uri = {};
|
||||
var i = 14;
|
||||
while (i--) {
|
||||
uri[key[i]] = match[i] || '';
|
||||
}
|
||||
|
||||
uri.queryKey = {};
|
||||
uri[key[12]].replace(querypattern, function ($0, $1, $2) {
|
||||
if ($1) {
|
||||
uri.queryKey[$1] = $2;
|
||||
}
|
||||
});
|
||||
|
||||
return uri;
|
||||
}
|
||||
};
|
||||
|
||||
/*
|
||||
* A small mock 'server' that intercepts XMLHttpRequest calls and
|
||||
* diverts them to your handler.
|
||||
*
|
||||
* Usage:
|
||||
*
|
||||
* 1. Initialize with either
|
||||
* var server = new MockHttpServer(your_request_handler);
|
||||
* or
|
||||
* var server = new MockHttpServer();
|
||||
* server.handle = function (request) { ... };
|
||||
*
|
||||
* 2. Call server.start() to start intercepting all XMLHttpRequests.
|
||||
*
|
||||
* 3. Do your tests.
|
||||
*
|
||||
* 4. Call server.stop() to tear down.
|
||||
*
|
||||
* 5. Profit!
|
||||
*/
|
||||
function MockHttpServer(handler) {
|
||||
if (handler) {
|
||||
this.handle = handler;
|
||||
}
|
||||
}
|
||||
MockHttpRequest.MockHttpServer = MockHttpServer;
|
||||
|
||||
MockHttpServer.prototype = {
|
||||
|
||||
start: function () {
|
||||
var self = this;
|
||||
|
||||
function Request() {
|
||||
var req = this;
|
||||
req.onsend = function () {
|
||||
req.sendStack = (new Error()).stack;
|
||||
process.nextTick(function () {
|
||||
self.handle(req);
|
||||
});
|
||||
};
|
||||
MockHttpRequest.apply(this, arguments);
|
||||
}
|
||||
Request.prototype = MockHttpRequest.prototype;
|
||||
|
||||
window.OriginalHttpRequest = window.XMLHttpRequest;
|
||||
window.XMLHttpRequest = Request;
|
||||
},
|
||||
|
||||
stop: function () {
|
||||
window.XMLHttpRequest = window.OriginalHttpRequest;
|
||||
},
|
||||
|
||||
handle: function (request) {
|
||||
// Instances should override this.
|
||||
}
|
||||
};
|
||||
83
test/mocks/browser_server.js
Normal file
83
test/mocks/browser_server.js
Normal file
@ -0,0 +1,83 @@
|
||||
var interceptors = [];
|
||||
var complete = [];
|
||||
var MockHttpRequest = require('./browser_http');
|
||||
var XhrServer = MockHttpRequest.MockHttpServer;
|
||||
var parseUrl = MockHttpRequest.prototype.parseUri;
|
||||
var _ = require('lodash');
|
||||
|
||||
var server = new XhrServer(function (request) {
|
||||
var reqDetails = {
|
||||
method: request.method,
|
||||
host: request.urlParts.host,
|
||||
path: request.urlParts.relative
|
||||
};
|
||||
var response = _.find(interceptors, reqDetails);
|
||||
|
||||
if (response) {
|
||||
// remove of tick down the times
|
||||
if (response.times === 1) {
|
||||
var i = interceptors.indexOf(response);
|
||||
complete.push(interceptors.splice(i, 1));
|
||||
} else {
|
||||
response.times--;
|
||||
}
|
||||
|
||||
request.receive(response.status, response.body || void 0);
|
||||
} else {
|
||||
throw new Error('No known match for request: ' + JSON.stringify(reqDetails));
|
||||
}
|
||||
});
|
||||
|
||||
server.start();
|
||||
|
||||
var mockNock = module.exports = function (url) {
|
||||
var parsedUrl = parseUrl(url);
|
||||
var req = {
|
||||
method: 'GET',
|
||||
host: parsedUrl.host,
|
||||
times: 1
|
||||
};
|
||||
|
||||
var modifyReq = {
|
||||
get: function (path) {
|
||||
req.path = path;
|
||||
req.method = 'GET';
|
||||
return modifyReq;
|
||||
},
|
||||
port: function (path) {
|
||||
req.path = path;
|
||||
req.method = 'POST';
|
||||
return modifyReq;
|
||||
},
|
||||
times: function (times) {
|
||||
req.times = times;
|
||||
return modifyReq;
|
||||
},
|
||||
reply: function (status, body) {
|
||||
req.status = status;
|
||||
req.body = body;
|
||||
switch (typeof req.body) {
|
||||
case 'string':
|
||||
case 'number':
|
||||
break;
|
||||
default:
|
||||
try {
|
||||
req.body = req.body && JSON.stringify(req.body);
|
||||
} catch (e) {
|
||||
req.body = req.body;
|
||||
}
|
||||
}
|
||||
interceptors.push(req);
|
||||
return mockNock(url);
|
||||
},
|
||||
done: mockNock.done
|
||||
};
|
||||
|
||||
return modifyReq;
|
||||
};
|
||||
|
||||
mockNock.done = function () {
|
||||
if (interceptors.length) {
|
||||
throw new Error('Some interceptors were not called: ' + JSON.stringify(interceptors));
|
||||
}
|
||||
};
|
||||
3
test/mocks/server.js
Normal file
3
test/mocks/server.js
Normal file
@ -0,0 +1,3 @@
|
||||
var nock = require('nock');
|
||||
nock.disableNetConnect();
|
||||
module.exports = nock;
|
||||
@ -14,9 +14,7 @@ exports.make = function () {
|
||||
};
|
||||
|
||||
stubber.autoRelease = function (item) {
|
||||
if (item.restore && !~log.indexOf(item)) {
|
||||
log.push(item);
|
||||
}
|
||||
log.push(item);
|
||||
};
|
||||
|
||||
return stubber;
|
||||
|
||||
@ -96,34 +96,31 @@ describe('Connection Abstract', function () {
|
||||
var conn = new ConnectionAbstract(host);
|
||||
|
||||
conn.setStatus('alive');
|
||||
conn.ping = function () {
|
||||
stub(conn, 'ping', function () {
|
||||
throw new Error('ping should not have been called');
|
||||
};
|
||||
});
|
||||
|
||||
conn.resuscitate();
|
||||
});
|
||||
|
||||
it('should ping the connection after the deadTimeout, and set the status to "alive" on pong', function (done) {
|
||||
var conn = new ConnectionAbstract(host);
|
||||
var clock = sinon.useFakeTimers('setTimeout', 'clearTimeout');
|
||||
stub.autoRelease(clock);
|
||||
var clock;
|
||||
stub.autoRelease(clock = sinon.useFakeTimers('setTimeout', 'clearTimeout'));
|
||||
|
||||
// schedules the resuscitate
|
||||
conn.setStatus('dead');
|
||||
|
||||
// override the ping method to just callback without an error
|
||||
conn.ping = function (cb) {
|
||||
process.nextTick(function () {
|
||||
cb();
|
||||
});
|
||||
};
|
||||
stub(conn, 'ping', function (cb) {
|
||||
cb();
|
||||
});
|
||||
|
||||
// will be called after the ping calls back
|
||||
conn.setStatus = function (status) {
|
||||
stub(conn, 'setStatus', function (status) {
|
||||
status.should.eql('alive');
|
||||
clock.restore();
|
||||
done();
|
||||
};
|
||||
});
|
||||
|
||||
// fast forward the clock
|
||||
clock.tick(conn.deadTimeout);
|
||||
@ -131,24 +128,22 @@ describe('Connection Abstract', function () {
|
||||
|
||||
it('should ping the connection after the deadTimeout, and set the status to "dead" on error', function (done) {
|
||||
var conn = new ConnectionAbstract(host);
|
||||
var clock = sinon.useFakeTimers('setTimeout', 'clearTimeout');
|
||||
stub.autoRelease(clock);
|
||||
var clock;
|
||||
stub.autoRelease(clock = sinon.useFakeTimers('setTimeout', 'clearTimeout'));
|
||||
|
||||
// schedules the resuscitate
|
||||
conn.setStatus('dead');
|
||||
|
||||
// override the ping method to just callback without an error
|
||||
conn.ping = function (cb) {
|
||||
process.nextTick(function () {
|
||||
cb(new Error('server still down'));
|
||||
});
|
||||
};
|
||||
stub(conn, 'ping', function (cb) {
|
||||
cb(new Error('server still down'));
|
||||
});
|
||||
|
||||
// will be called after the ping calls back
|
||||
conn.setStatus = function (status) {
|
||||
stub(conn, 'setStatus', function (status) {
|
||||
status.should.eql('dead');
|
||||
done();
|
||||
};
|
||||
});
|
||||
|
||||
// fast forward the clock
|
||||
clock.tick(conn.deadTimeout);
|
||||
|
||||
@ -151,12 +151,13 @@ describe('Connection Pool', function () {
|
||||
};
|
||||
|
||||
pool.select(function (err, selection) {
|
||||
should(err).Error;
|
||||
should(err).be.an.instanceOf(Error);
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('should automatically select the first dead connection when there no living connections', function (done) {
|
||||
pool.setHosts([]);
|
||||
pool._conns.alive = [];
|
||||
pool._conns.dead = [1, 2, 3];
|
||||
|
||||
@ -188,6 +189,10 @@ describe('Connection Pool', function () {
|
||||
pool._conns.dead.should.have.length(0);
|
||||
});
|
||||
|
||||
afterEach(function () {
|
||||
pool.close();
|
||||
});
|
||||
|
||||
it('moves an alive connection to dead', function () {
|
||||
connection.setStatus('dead');
|
||||
|
||||
@ -207,7 +212,7 @@ describe('Connection Pool', function () {
|
||||
pool._conns.dead[0].should.be.exactly(connection2);
|
||||
});
|
||||
|
||||
it('moves a does nothing when a connection is re-alive', function () {
|
||||
it('does nothing when a connection is re-alive', function () {
|
||||
var last = pool._conns.alive[pool._conns.alive.length - 1];
|
||||
var first = pool._conns.alive[0];
|
||||
|
||||
|
||||
@ -28,7 +28,7 @@ describe('Console Logger', function () {
|
||||
it('checks before using unique logging functions, falls back to #log()', function () {
|
||||
var _warning = console.warn;
|
||||
console.warn = null;
|
||||
stub(console, 'log');
|
||||
sinon.stub(console, 'log');
|
||||
|
||||
var logger = makeLogger();
|
||||
|
||||
@ -36,6 +36,7 @@ describe('Console Logger', function () {
|
||||
console.log.callCount.should.eql(1);
|
||||
|
||||
console.warn = _warning;
|
||||
console.log.restore();
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
@ -116,7 +116,7 @@ describe('Http Connector', function () {
|
||||
});
|
||||
|
||||
reqParams.should.include({
|
||||
path: '?user_id=123&jvm=yes'
|
||||
path: '/?user_id=123&jvm=yes'
|
||||
});
|
||||
});
|
||||
|
||||
@ -353,7 +353,7 @@ describe('Http Connector', function () {
|
||||
it('uses TCP no delay', function (done) {
|
||||
var con = new HttpConnection(new Host('localhost'));
|
||||
stub(http.ClientRequest.prototype, 'setNoDelay');
|
||||
var server = nock('http://localhost').get('').reply(200);
|
||||
var server = nock('http://localhost').get('/').reply(200);
|
||||
|
||||
con.request({}, function (err, resp, status) {
|
||||
http.ClientRequest.prototype.setNoDelay.callCount.should.eql(1);
|
||||
@ -366,7 +366,7 @@ describe('Http Connector', function () {
|
||||
it('sets the Content-Length header properly', function (done) {
|
||||
var con = new HttpConnection(new Host('localhost'));
|
||||
stub(http.ClientRequest.prototype, 'setHeader');
|
||||
var server = nock('http://localhost').get('').reply(200);
|
||||
var server = nock('http://localhost').get('/').reply(200);
|
||||
|
||||
var body = 'pasta and 𝄞';
|
||||
body.length.should.eql(12); // nope
|
||||
|
||||
@ -3,7 +3,6 @@ var StreamLogger = require('../../src/lib/loggers/stream');
|
||||
var MockWritableStream = require('../mocks/writable_stream');
|
||||
var MockOldWritableStream = require('../mocks/old_writable_stream');
|
||||
var once = require('events').EventEmitter.prototype.once;
|
||||
var sinon = require('sinon');
|
||||
var stream = new MockWritableStream();
|
||||
var _ = require('lodash');
|
||||
var util = require('util');
|
||||
|
||||
@ -4,14 +4,12 @@ var errors = require('../../src/lib/errors');
|
||||
var when = require('when');
|
||||
|
||||
var sinon = require('sinon');
|
||||
var nock = require('nock');
|
||||
var nock = require('../mocks/server.js');
|
||||
var should = require('should');
|
||||
var _ = require('lodash');
|
||||
var nodeList = require('../fixtures/short_node_list.json');
|
||||
var stub = require('./auto_release_stub').make();
|
||||
|
||||
nock.disableNetConnect();
|
||||
|
||||
/**
|
||||
* Allows the tests call #request() without it doing anything past trying to select
|
||||
* a connection.
|
||||
@ -19,10 +17,7 @@ nock.disableNetConnect();
|
||||
*/
|
||||
function shortCircuitRequest(tran, delay) {
|
||||
stub(tran.connectionPool, 'select', function (cb) {
|
||||
setTimeout(function () {
|
||||
// call back with no error, and no connection === "NoConnections"
|
||||
cb();
|
||||
}, delay);
|
||||
setTimeout(cb, delay);
|
||||
});
|
||||
}
|
||||
|
||||
@ -315,14 +310,13 @@ describe('Transport Class', function () {
|
||||
done();
|
||||
});
|
||||
});
|
||||
it('logs when it begins', function (done) {
|
||||
it('rejects get requests with bodies', function (done) {
|
||||
var trans = new Transport();
|
||||
stub(trans.log, 'debug');
|
||||
stub(trans.connectionPool, 'select', function (cb) {
|
||||
// simulate "no connections"
|
||||
process.nextTick(cb);
|
||||
});
|
||||
|
||||
trans.request({
|
||||
body: 'JSON!!',
|
||||
method: 'GET'
|
||||
@ -754,71 +748,90 @@ describe('Transport Class', function () {
|
||||
});
|
||||
|
||||
describe('timeout', function () {
|
||||
it('uses 10 seconds for the default', function (done) {
|
||||
this.timeout(5);
|
||||
var clock;
|
||||
stub.autoRelease(clock = sinon.useFakeTimers('setTimeout'));
|
||||
|
||||
it('uses 30 seconds for the default', function () {
|
||||
var clock = sinon.useFakeTimers();
|
||||
var tran = new Transport({});
|
||||
var err;
|
||||
|
||||
stub(tran.connectionPool, 'select', function (cb) {
|
||||
setTimeout(cb, 11000);
|
||||
tran.request({});
|
||||
|
||||
_.size(clock.timeouts).should.eql(1);
|
||||
_.each(clock.timeouts, function (timer, id) {
|
||||
timer.callAt.should.eql(30000);
|
||||
clearTimeout(id);
|
||||
});
|
||||
|
||||
tran.request({}, function (err) {
|
||||
err.should.be.an.instanceOf(errors.RequestTimeout);
|
||||
done();
|
||||
});
|
||||
|
||||
clock.tick(10010);
|
||||
clock.restore();
|
||||
});
|
||||
it('inherits the requestTimeout from the transport', function (done) {
|
||||
this.timeout(5);
|
||||
var clock;
|
||||
stub.autoRelease(clock = sinon.useFakeTimers('setTimeout'));
|
||||
|
||||
it('inherits the requestTimeout from the transport', function () {
|
||||
var clock = sinon.useFakeTimers();
|
||||
var tran = new Transport({
|
||||
requestTimeout: 5000
|
||||
});
|
||||
var err;
|
||||
|
||||
stub(tran.connectionPool, 'select', function (cb) {
|
||||
setTimeout(cb, 11000);
|
||||
tran.request({});
|
||||
|
||||
_.size(clock.timeouts).should.eql(1);
|
||||
_.each(clock.timeouts, function (timer, id) {
|
||||
timer.callAt.should.eql(5000);
|
||||
clearTimeout(id);
|
||||
});
|
||||
clock.restore();
|
||||
});
|
||||
it('clears the timeout when the request is complete', function () {
|
||||
var clock = sinon.useFakeTimers('setTimeout', 'clearTimeout');
|
||||
var tran = new Transport({
|
||||
host: 'http://localhost:9200'
|
||||
});
|
||||
|
||||
tran.request({}, function (err) {
|
||||
var server = nock('http://localhost:9200')
|
||||
.get('/')
|
||||
.reply(200, {
|
||||
i: 'am here'
|
||||
});
|
||||
|
||||
tran.request({}, function (err, resp, status) {
|
||||
should.not.exist(err);
|
||||
resp.should.eql({ i: 'am here' });
|
||||
status.should.eql(200);
|
||||
Object.keys(clock.timeouts).should.have.length(0);
|
||||
clock.restore();
|
||||
});
|
||||
});
|
||||
it('timeout responds with a requestTimeout error', function (done) {
|
||||
// var clock = sinon.useFakeTimers('setTimeout', 'clearTimeout');
|
||||
var tran = new Transport({
|
||||
host: 'http://localhost:9200'
|
||||
});
|
||||
|
||||
var server = nock('http://localhost:9200')
|
||||
.get('/')
|
||||
.delay(1000)
|
||||
.reply(200, {
|
||||
i: 'am here'
|
||||
});
|
||||
|
||||
tran.request({
|
||||
requestTimeout: 25
|
||||
}, function (err, resp, status) {
|
||||
err.should.be.an.instanceOf(errors.RequestTimeout);
|
||||
// Object.keys(clock.timeouts).should.have.length(0);
|
||||
// clock.restore();
|
||||
done();
|
||||
});
|
||||
|
||||
clock.tick(6000);
|
||||
});
|
||||
[false, 0, null].forEach(function (falsy) {
|
||||
it('skips the timeout when it is ' + falsy, function (done) {
|
||||
this.timeout(5);
|
||||
var clock;
|
||||
stub.autoRelease(clock = sinon.useFakeTimers('setTimeout'));
|
||||
|
||||
var tran = new Transport({
|
||||
requestTimeout: 5000
|
||||
});
|
||||
|
||||
stub(tran.connectionPool, 'select', function (cb) {
|
||||
setTimeout(function () {
|
||||
cb(new Error('it works'));
|
||||
}, 10000);
|
||||
});
|
||||
it('skips the timeout when it is ' + falsy, function () {
|
||||
var clock = sinon.useFakeTimers();
|
||||
var tran = new Transport({});
|
||||
stub(tran.connectionPool, 'select', function () {});
|
||||
|
||||
tran.request({
|
||||
requestTimeout: falsy
|
||||
}, function (err) {
|
||||
err.message.should.eql('it works');
|
||||
done();
|
||||
});
|
||||
}, function (_err) {});
|
||||
|
||||
clock.tick(6000);
|
||||
process.nextTick(function () {
|
||||
clock.tick(6000);
|
||||
});
|
||||
_.size(clock.timeouts).should.eql(0);
|
||||
clock.restore();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@ -4,20 +4,33 @@
|
||||
* @param {Runner} runner
|
||||
* @api public
|
||||
*/
|
||||
module.exports = EsjsReporter;
|
||||
module.exports = JenkinsReporter;
|
||||
|
||||
var Base = require('mocha/lib/reporters/base');
|
||||
var _ = require('lodash');
|
||||
var chalk = require('chalk');
|
||||
var clientManager = require('./client_manager');
|
||||
var makeJUnitXml = require('../../../scripts/make_j_unit_xml');
|
||||
var makeJUnitXml = require('./make_j_unit_xml');
|
||||
var fs = require('fs');
|
||||
var path = require('path');
|
||||
var inspect = require('util').inspect;
|
||||
|
||||
function EsjsReporter(runner) {
|
||||
var log = (function () {
|
||||
var locked = _.bind(process.stdout.write, process.stdout);
|
||||
return function (str) {
|
||||
if (typeof str !== 'string') {
|
||||
str = inspect(str);
|
||||
}
|
||||
locked(str);
|
||||
};
|
||||
})();
|
||||
|
||||
function JenkinsReporter(runner) {
|
||||
Base.call(this, runner);
|
||||
clientManager.reporter = this;
|
||||
|
||||
var stats = this.stats;
|
||||
var pass = 0;
|
||||
var pending = 0;
|
||||
var fail = 0;
|
||||
var rootSuite = {
|
||||
results: [],
|
||||
suites: []
|
||||
@ -36,7 +49,7 @@ function EsjsReporter(runner) {
|
||||
|
||||
// suite
|
||||
suite = {
|
||||
name: suite.title,
|
||||
name: suite.fullTitle(),
|
||||
results: [],
|
||||
start: Date.now(),
|
||||
stdout: '',
|
||||
@ -68,9 +81,17 @@ function EsjsReporter(runner) {
|
||||
});
|
||||
|
||||
runner.on('test end', function (test) {
|
||||
// test
|
||||
var color = chalk[test.state === 'passed' ? 'green' : 'red'];
|
||||
log(color('.'));
|
||||
if (test.state === 'passed') {
|
||||
pass++;
|
||||
log(chalk.green('.'));
|
||||
} else if (test.pending) {
|
||||
pending++;
|
||||
log(chalk.grey('.'));
|
||||
return;
|
||||
} else {
|
||||
fail++;
|
||||
log(chalk.red('x'));
|
||||
}
|
||||
|
||||
var errMsg = void 0;
|
||||
|
||||
@ -98,22 +119,19 @@ function EsjsReporter(runner) {
|
||||
}).join('\n'));
|
||||
}
|
||||
|
||||
if (!test.pending) {
|
||||
if (stack[0]) {
|
||||
stack[0].results.push({
|
||||
name: test.title,
|
||||
time: test.duration,
|
||||
pass: test.state === 'passed',
|
||||
test: test
|
||||
});
|
||||
}
|
||||
if (stack[0]) {
|
||||
stack[0].results.push({
|
||||
name: test.title,
|
||||
time: test.duration,
|
||||
pass: test.state === 'passed',
|
||||
test: test
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
runner.on('end', function () {
|
||||
restoreStdio();
|
||||
var outputFilename = path.join(__dirname, '../../../test-output-node-yaml.xml');
|
||||
var xml = makeJUnitXml('node ' + process.version + ' yaml tests', {
|
||||
var xml = makeJUnitXml('node ' + process.version, {
|
||||
stats: stats,
|
||||
suites: _.map(rootSuite.suites, function removeElements(suite) {
|
||||
var s = {
|
||||
@ -131,16 +149,15 @@ function EsjsReporter(runner) {
|
||||
return s;
|
||||
})
|
||||
});
|
||||
fs.writeFileSync(outputFilename, xml);
|
||||
console.log('\nwrote log to', outputFilename);
|
||||
});
|
||||
console.error(xml);
|
||||
|
||||
var log = (function () {
|
||||
var locked = _.bind(process.stdout.write, process.stdout);
|
||||
return function (str) {
|
||||
locked(str);
|
||||
};
|
||||
})();
|
||||
console.log('\n' + [
|
||||
'tests complete in ' + (Math.round(stats.duration / 10) / 100) + ' seconds',
|
||||
' fail: ' + chalk.red(stats.failures),
|
||||
' pass: ' + chalk.green(stats.passes),
|
||||
' pending: ' + chalk.grey(stats.pending)
|
||||
].join('\n'));
|
||||
});
|
||||
|
||||
// overload the write methods on stdout and stderr
|
||||
['stdout', 'stderr'].forEach(function (name) {
|
||||
@ -32,8 +32,9 @@ var _ = require('lodash');
|
||||
|
||||
function makeJUnitXml(runnerName, testDetails) {
|
||||
_.each(testDetails.suites, function serializeSuite(suiteInfo) {
|
||||
|
||||
var suite = suites.ele('testsuite', {
|
||||
package: 'elasticsearch-js:yaml_tests',
|
||||
package: 'elasticsearch-js',
|
||||
id: suiteCount++,
|
||||
name: suiteInfo.name,
|
||||
timestamp: moment(suiteInfo.start).toJSON(),
|
||||
@ -45,13 +46,16 @@ function makeJUnitXml(runnerName, testDetails) {
|
||||
});
|
||||
|
||||
_.each(suiteInfo.results, function (testInfo) {
|
||||
var section;
|
||||
|
||||
var parts = suiteInfo.name.replace(/\.yaml$/, '').replace(/\./g, '_').split(/\//);
|
||||
var section = parts.shift();
|
||||
var behavior = parts.join('/');
|
||||
if (suiteInfo.name.match(/\/.*\.yaml$/)) {
|
||||
section = suiteInfo.name.split('/').slice(0, -1).join('/');
|
||||
} else {
|
||||
section = suiteInfo.name;
|
||||
}
|
||||
|
||||
var testcase = suite.ele('testcase', {
|
||||
name: behavior + ' - ' + testInfo.name,
|
||||
name: testInfo.name,
|
||||
time: (testInfo.time || 0) / 1000,
|
||||
classname: runnerName + '.' + section
|
||||
});
|
||||
@ -73,8 +77,12 @@ function makeJUnitXml(runnerName, testDetails) {
|
||||
_.each(suiteInfo.suites, serializeSuite);
|
||||
}
|
||||
|
||||
suite.ele('system-out', {}).cdata(suiteInfo.stdout);
|
||||
suite.ele('system-err', {}).cdata(suiteInfo.stderr);
|
||||
// if (suiteInfo.stdout.trim()) {
|
||||
// suite.ele('system-out', {}).cdata(suiteInfo.stdout);
|
||||
// }
|
||||
// if (suiteInfo.stderr.trim()) {
|
||||
// suite.ele('system-err', {}).cdata(suiteInfo.stderr);
|
||||
// }
|
||||
});
|
||||
|
||||
return suites.toString({ pretty: true});
|
||||
Reference in New Issue
Block a user