added filterPath support to master api and enhanced yaml testing

This commit is contained in:
Spencer Alger
2015-06-02 11:11:30 -07:00
parent 7d14e7d24e
commit 5e1da82688
9 changed files with 139 additions and 68 deletions

View File

@ -17,6 +17,10 @@ NOTE: the https://github.com/fullscale/elastic.js[elastic.js] library can be use
+ +
`Number, Number[]` -- HTTP status codes which should not be considered errors for this request. `Number, Number[]` -- HTTP status codes which should not be considered errors for this request.
`filterPath`::
+
`String|String[]` -- Starting in **elasticsearch 2.0** the `filterPath` parameter can be passed to any API to filter it's reponse values. See the https://www.elastic.co/guide/en/elasticsearch/reference/master/common-options.html#_response_filtering[elasticsearch response filtering docs] for more information.
=== Config values you can override per request === Config values you can override per request
* `requestTimeout` -- <<config-request-timeout, more info>> * `requestTimeout` -- <<config-request-timeout, more info>>
* `maxRetries` -- <<config-max-retries, more info>> * `maxRetries` -- <<config-max-retries, more info>>

View File

@ -38,7 +38,10 @@ var config = {
}, },
integration: { integration: {
src: null src: null,
options: {
reporter: 'spec'
}
}, },
jenkins_integration: { jenkins_integration: {

View File

@ -64,7 +64,7 @@
"js-yaml": "~2.1.3", "js-yaml": "~2.1.3",
"load-grunt-config": "~0.7.0", "load-grunt-config": "~0.7.0",
"load-grunt-tasks": "~0.2.0", "load-grunt-tasks": "~0.2.0",
"mocha": "~1.21.4", "mocha": "^2.2.5",
"mocha-lcov-reporter": "0.0.1", "mocha-lcov-reporter": "0.0.1",
"mocha-screencast-reporter": "~0.1.4", "mocha-screencast-reporter": "~0.1.4",
"moment": "~2.4.0", "moment": "~2.4.0",
@ -98,4 +98,4 @@
"node": ">=0.8 <=0.12", "node": ">=0.8 <=0.12",
"iojs": ">=1.5" "iojs": ">=1.5"
} }
} }

View File

@ -29,7 +29,7 @@ module.exports = function (branch, done) {
var m; var m;
// master === the highest version number // master === the highest version number
if (branch === 'master') return '999.999.999'; if (branch === 'master') return '2.0.0';
// n.m -> n.m.0 // n.m -> n.m.0
if (m = branch.match(/^\d+\.\d+$/)) return branch + '.0'; if (m = branch.match(/^\d+\.\d+$/)) return branch + '.0';
// n.x -> n.(maxVersion + 1).0 // n.x -> n.(maxVersion + 1).0
@ -48,7 +48,8 @@ module.exports = function (branch, done) {
return _.merge(overrides, _.omit(rule, 'version')); return _.merge(overrides, _.omit(rule, 'version'));
}, { }, {
aliases: {}, aliases: {},
paramAsBody: {} paramAsBody: {},
clientActionModifier: false
}); });
var steps = [ var steps = [
@ -106,7 +107,8 @@ module.exports = function (branch, done) {
apiSpec = { apiSpec = {
actions: groups.normal || [], actions: groups.normal || [],
proxies: groups.proxies || [], proxies: groups.proxies || [],
namespaces: _.unique(namespaces.sort(), true) namespaces: _.unique(namespaces.sort(), true),
clientActionModifier: overrides.clientActionModifier
}; };
var create = _.assign({}, _.find(apiSpec.actions, { name: 'index' }), { var create = _.assign({}, _.find(apiSpec.actions, { name: 'index' }), {

View File

@ -177,5 +177,26 @@ module.exports = [
'/{index}/_aliases/{name}' '/{index}/_aliases/{name}'
] ]
} }
},
{
version: '>=2.0.0',
/* jshint ignore:start */
// strange indentation makes pretty api files
clientActionModifier:
function (spec) {
return require('../utils').merge(spec, {
params: {
filterPath: {
type: 'list',
name: 'filter_path'
}
}
});
}
/* jshint ignore:end */
} }
]; ];

View File

@ -1,7 +1,11 @@
/* jshint maxlen: false */ /* jshint maxlen: false */
var ca = require('../client_action').factory; var ca = require('../client_action').<%
var proxy = require('../client_action').proxyFactory;
if (!clientActionModifier) print('factory');
else print('makeFactoryWithModifier(' + clientActionModifier.toString() + ')');
%>;
var namespace = require('../client_action').namespaceFactory; var namespace = require('../client_action').namespaceFactory;
var api = module.exports = {}; var api = module.exports = {};

View File

@ -9,7 +9,7 @@ _.each(allParams, function(param, paramName) { %>
} }
%><% }) %> %><% }) %>
*/ */
api<%= (location[0] === '[' ? '' : '.') + location %> = proxy(<%= 'api' + (proxy[0] === '[' ? '' : '.') + proxy %><% api<%= (location[0] === '[' ? '' : '.') + location %> = ca.proxy(<%= 'api' + (proxy[0] === '[' ? '' : '.') + proxy %><%
if (typeof transformBody === 'string') { %>, { if (typeof transformBody === 'string') { %>, {
transform: function (params) { transform: function (params) {
<%= indent(transformBody, 4) %> <%= indent(transformBody, 4) %>

View File

@ -1,15 +1,23 @@
var _ = require('./utils');
/**
* Constructs a client action factory that uses specific defaults
* @type {Function}
*/
exports.makeFactoryWithModifier = makeFactoryWithModifier;
/** /**
* Constructs a function that can be called to make a request to ES * Constructs a function that can be called to make a request to ES
* @type {Function} * @type {Function}
*/ */
exports.factory = factory; exports.factory = makeFactoryWithModifier();
/** /**
* Constructs a proxy to another api method * Constructs a proxy to another api method
* @type {Function} * @type {Function}
*/ */
exports.proxyFactory = proxyFactory; exports.proxyFactory = exports.factory.proxy;
// export so that we can test this // export so that we can test this
exports._resolveUrl = resolveUrl; exports._resolveUrl = resolveUrl;
@ -25,60 +33,66 @@ exports.namespaceFactory = function () {
return ClientNamespace; return ClientNamespace;
}; };
var _ = require('./utils'); function makeFactoryWithModifier(modifier) {
modifier = modifier || _.identity;
function factory(spec) { var factory = function (spec) {
if (!_.isPlainObject(spec.params)) { spec = modifier(spec);
spec.params = {};
}
if (!spec.method) { if (!_.isPlainObject(spec.params)) {
spec.method = 'GET'; spec.params = {};
}
function action(params, cb) {
if (typeof params === 'function') {
cb = params;
params = {};
} else {
params = params || {};
cb = typeof cb === 'function' ? cb : null;
} }
try { if (!spec.method) {
return exec(this.transport, spec, _.clone(params), cb); spec.method = 'GET';
} catch (e) { }
if (typeof cb === 'function') {
_.nextTick(cb, e); function action(params, cb) {
if (typeof params === 'function') {
cb = params;
params = {};
} else { } else {
var def = this.transport.defer(); params = params || {};
def.reject(e); cb = typeof cb === 'function' ? cb : null;
return def.promise; }
try {
return exec(this.transport, spec, _.clone(params), cb);
} catch (e) {
if (typeof cb === 'function') {
_.nextTick(cb, e);
} else {
var def = this.transport.defer();
def.reject(e);
return def.promise;
}
} }
} }
}
action.spec = spec; action.spec = spec;
return action; return action;
}
function proxyFactory(fn, spec) {
return function (params, cb) {
if (typeof params === 'function') {
cb = params;
params = {};
} else {
params = params || {};
cb = typeof cb === 'function' ? cb : null;
}
if (spec.transform) {
spec.transform(params);
}
return fn.call(this, params, cb);
}; };
factory.proxy = function (fn, spec) {
return function (params, cb) {
if (typeof params === 'function') {
cb = params;
params = {};
} else {
params = params || {};
cb = typeof cb === 'function' ? cb : null;
}
if (spec.transform) {
spec.transform(params);
}
return fn.call(this, params, cb);
};
};
return factory;
} }
var castType = { var castType = {
@ -288,9 +302,7 @@ function exec(transport, spec, params, cb) {
}, []); }, []);
} }
var key, paramSpec; for (var key in params) {
for (key in params) {
if (params.hasOwnProperty(key) && params[key] != null) { if (params.hasOwnProperty(key) && params[key] != null) {
switch (key) { switch (key) {
case 'body': case 'body':
@ -305,7 +317,7 @@ function exec(transport, spec, params, cb) {
request.method = _.toUpperString(params[key]); request.method = _.toUpperString(params[key]);
break; break;
default: default:
paramSpec = spec.params[key]; var paramSpec = spec.params[key];
if (paramSpec) { if (paramSpec) {
// param keys don't always match the param name, in those cases it's stored in the param def as "name" // param keys don't always match the param name, in those cases it's stored in the param def as "name"
paramSpec.name = paramSpec.name || key; paramSpec.name = paramSpec.name || key;

View File

@ -12,7 +12,7 @@ var expect = require('expect.js');
var clientManager = require('./client_manager'); var clientManager = require('./client_manager');
var inspect = require('util').inspect; var inspect = require('util').inspect;
var implementedFeatures = ['gtelte', 'regex', 'benchmark']; var implementedFeatures = ['gtelte', 'regex', 'benchmark', 'stash_in_path'];
/** /**
* The version that ES is running, in comparable string form XXX-XXX-XXX, fetched when needed * The version that ES is running, in comparable string form XXX-XXX-XXX, fetched when needed
@ -239,21 +239,25 @@ YamlDoc.prototype = {
* @return {*} - The value requested, or undefined if it was not found * @return {*} - The value requested, or undefined if it was not found
*/ */
get: function (path, from) { get: function (path, from) {
var self = this;
var log = process.env.LOG_GETS && !from ? console.log.bind(console) : function () {}; var log = process.env.LOG_GETS && !from ? console.log.bind(console) : function () {};
var i; var i;
if (path === '$body') { if (path === '$body') {
// shortcut, the test just wants the whole body // shortcut, the test just wants the whole body
return this._last_requests_response; return self._last_requests_response;
} else if (path) {
path = path.replace(/\.\$([a-zA-Z0-9_]+)/g, function (m, name) {
return '.' + self._stash[name];
});
} }
if (!from) { if (!from) {
if (path[0] === '$') { if (path[0] === '$') {
from = this._stash; from = self._stash;
path = path.substring(1); path = path.substring(1);
} else { } else {
from = this._last_requests_response; from = self._last_requests_response;
} }
} }
@ -331,6 +335,15 @@ YamlDoc.prototype = {
do_do: function (args, done) { do_do: function (args, done) {
var catcher; var catcher;
if (process.env.LOG_DO) {
var __done = done;
done = function (err, resp) {
console.log('doing', clientActionName, 'with', params);
console.log('got', resp);
__done(err, resp);
};
}
// resolve the catch arg to a value used for matching once the request is complete // resolve the catch arg to a value used for matching once the request is complete
switch (args.catch) { switch (args.catch) {
case void 0: case void 0:
@ -475,7 +488,12 @@ YamlDoc.prototype = {
* @return {undefined} * @return {undefined}
*/ */
do_is_true: function (path) { do_is_true: function (path) {
expect(Boolean(this.get(path))).to.be(true, 'path: ' + path); var val = this.get(path);
try {
expect(Boolean(val)).to.be(true, 'path: ' + path);
} catch (e) {
throw new Error('expected path "' + path + '" to be true but got ' + val);
}
}, },
/** /**
@ -486,7 +504,12 @@ YamlDoc.prototype = {
* @return {undefined} * @return {undefined}
*/ */
do_is_false: function (path) { do_is_false: function (path) {
expect(Boolean(this.get(path))).to.be(false, 'path: ' + path); var val = this.get(path);
try {
expect(Boolean(val)).to.be(false, 'path: ' + path);
} catch (e) {
throw new Error('expected path "' + path + '" to be false but got ' + val);
}
}, },
/** /**
@ -529,8 +552,10 @@ YamlDoc.prototype = {
return _.each(val, recurse); return _.each(val, recurse);
} }
if (_.isString(val) && val[0] === '$') { if (_.isString(val)) {
lvl[key] = self.get(val); lvl[key] = val.replace(/\$[a-zA-Z0-9_]+/g, function (name) {
return self.get(name);
});
} }
}); });