added test runner for jenkins
This commit is contained in:
0
test/browser_integration/console.shim.js
Normal file
0
test/browser_integration/console.shim.js
Normal file
14
test/browser_integration/esjs_reporter.css
Normal file
14
test/browser_integration/esjs_reporter.css
Normal file
@ -0,0 +1,14 @@
|
||||
#mocha h1 {
|
||||
font-size: .7em;
|
||||
}
|
||||
|
||||
.test {
|
||||
font-size: .8em;
|
||||
color: yellow;
|
||||
}
|
||||
.test.passed {
|
||||
color: green;
|
||||
}
|
||||
.test.failed {
|
||||
color: red;
|
||||
}
|
||||
213
test/browser_integration/esjs_reporter.js
Normal file
213
test/browser_integration/esjs_reporter.js
Normal file
@ -0,0 +1,213 @@
|
||||
(function (global) {
|
||||
/* jshint browser:true */
|
||||
/* global alert */
|
||||
|
||||
/**
|
||||
* Save timer references to avoid Sinon interfering (see GH-237).
|
||||
*/
|
||||
|
||||
var Date = global.Date;
|
||||
var setTimeout = global.setTimeout;
|
||||
var setInterval = global.setInterval;
|
||||
var clearTimeout = global.clearTimeout;
|
||||
var clearInterval = global.clearInterval;
|
||||
var mocha = global.mocha;
|
||||
var Base = mocha.reporter('base')._reporter;
|
||||
var $ = global.jQuery;
|
||||
|
||||
/**
|
||||
* Expose `HTML`.
|
||||
*/
|
||||
|
||||
global.EsjsReporter = EsjsReporter;
|
||||
|
||||
/**
|
||||
* Initialize a new `HTML` reporter.
|
||||
*
|
||||
* @param {Runner} runner
|
||||
* @api public
|
||||
*/
|
||||
|
||||
function EsjsReporter(runner, root) {
|
||||
Base.call(this, runner);
|
||||
|
||||
var stats = this.stats;
|
||||
var rootSuite = {
|
||||
$el: $('<ul id="mocha-report"></ul>'),
|
||||
results: []
|
||||
};
|
||||
|
||||
|
||||
var stack = [rootSuite];
|
||||
rootSuite.$el.appendTo(root || '#mocha');
|
||||
|
||||
runner.on('suite', function (suite) {
|
||||
if (suite.root) {
|
||||
return;
|
||||
}
|
||||
|
||||
// suite
|
||||
suite = {
|
||||
name: suite.title,
|
||||
results: [],
|
||||
start: Date.now(),
|
||||
stdout: '',
|
||||
stderr: '',
|
||||
$el: $('<li class="suite">').append($('<h1>').text(suite.title)),
|
||||
$results: $('<ul>')
|
||||
};
|
||||
|
||||
// append the list of results to the main element
|
||||
suite.$results.appendTo(suite.$el);
|
||||
|
||||
// append to the previous stack leader
|
||||
stack[0].$el.append(suite.$el);
|
||||
if (!stack[0].suites) {
|
||||
stack[0].suites = [];
|
||||
}
|
||||
stack[0].suites.push(suite);
|
||||
|
||||
// push the suite onto the top of the stack
|
||||
stack.unshift(suite);
|
||||
});
|
||||
|
||||
runner.on('suite end', function (suite) {
|
||||
if (suite.root) {
|
||||
return;
|
||||
}
|
||||
stack[0].time = Date.now() - stack[0].start;
|
||||
stack.shift();
|
||||
});
|
||||
|
||||
runner.on('fail', function (test, err) {
|
||||
if ('hook' === test.type) {
|
||||
runner.emit('test end', test);
|
||||
}
|
||||
});
|
||||
|
||||
runner.on('test end', function (test) {
|
||||
// test
|
||||
var $test = $('<li>')
|
||||
.addClass('test')
|
||||
.addClass(test.state)
|
||||
.text(test.title + ' (' + test.duration + 'ms)');
|
||||
|
||||
var errMsg = void 0;
|
||||
|
||||
if ('passed' !== test.state && !test.pending) {
|
||||
errMsg = test.err.stack || test.err.toString();
|
||||
|
||||
// FF / Opera do not add the message
|
||||
if (!~errMsg.indexOf(test.err.message)) {
|
||||
errMsg = test.err.message + '\n' + errMsg;
|
||||
}
|
||||
|
||||
// <=IE7 stringifies to [Object Error]. Since it can be overloaded, we
|
||||
// check for the result of the stringifying.
|
||||
if ('[object Error]' === errMsg) {
|
||||
errMsg = test.err.message;
|
||||
}
|
||||
|
||||
// Safari doesn't give you a stack. Let's at least provide a source line.
|
||||
if (!test.err.stack && test.err.sourceURL && test.err.line !== undefined) {
|
||||
errMsg += '\n(' + test.err.sourceURL + ':' + test.err.line + ')';
|
||||
}
|
||||
|
||||
|
||||
$test.append($('<pre class="error">').text(errMsg));
|
||||
}
|
||||
|
||||
if (!test.pending) {
|
||||
if (stack[0]) {
|
||||
stack[0].results.push({
|
||||
name: test.title,
|
||||
time: test.duration,
|
||||
pass: test.state === 'passed',
|
||||
errMsg: errMsg
|
||||
});
|
||||
$test.appendTo(stack[0].$results);
|
||||
}
|
||||
if (test.type === 'hook' || stats.tests === this.total) {
|
||||
allTestsDone();
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
function allTestsDone() {
|
||||
window.testResults = {
|
||||
stats: stats,
|
||||
suites: $.map(rootSuite.suites, function removeElements(suite) {
|
||||
var s = {
|
||||
name: suite.name,
|
||||
start: suite.start,
|
||||
time: suite.time,
|
||||
results: suite.results,
|
||||
stdout: suite.stdout,
|
||||
stderr: suite.stderr
|
||||
};
|
||||
|
||||
if (suite.suites) {
|
||||
s.suites = $.map(suite.suites, removeElements);
|
||||
}
|
||||
return s;
|
||||
})
|
||||
};
|
||||
$.post('/tests-complete', JSON.stringify(window.testResults), function () {
|
||||
// alert('test complete');
|
||||
window.close();
|
||||
});
|
||||
}
|
||||
|
||||
/** override console to force all output to go to log and err, then we have all the output **/
|
||||
global.console = (function () {
|
||||
function flattenArgs(_arguments) {
|
||||
var args = [];
|
||||
for (var i = 0; i < _arguments.length; i++) {
|
||||
args.push(_arguments[i]);
|
||||
}
|
||||
return args;
|
||||
}
|
||||
|
||||
function argsToString(args) {
|
||||
return $.map(flattenArgs(args), function (arg) {
|
||||
return String(arg);
|
||||
}).join('\n');
|
||||
}
|
||||
|
||||
var origLog = $.noop;
|
||||
var origErr = $.noop;
|
||||
if (global.console) {
|
||||
if (global.console.log) {
|
||||
origLog = $.proxy(global.console, 'log');
|
||||
}
|
||||
if (global.console.error) {
|
||||
origErr = $.proxy(global.console, 'error');
|
||||
} else {
|
||||
origErr = origLog;
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
log: function () {
|
||||
if (stack[0]) {
|
||||
stack[0].stdout += argsToString(arguments) + '\n';
|
||||
} else {
|
||||
origLog(argsToString(arguments));
|
||||
}
|
||||
},
|
||||
error: function () {
|
||||
if (stack[0]) {
|
||||
stack[0].stderr += argsToString(arguments) + '\n';
|
||||
} else {
|
||||
origErr(argsToString(arguments));
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
}());
|
||||
|
||||
}
|
||||
|
||||
mocha.reporter(EsjsReporter);
|
||||
|
||||
}(this));
|
||||
@ -1,3 +1,4 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
@ -6,11 +7,28 @@
|
||||
</head>
|
||||
<body>
|
||||
<div id="mocha"></div>
|
||||
<script src="expect.js?_c={{ts}}"></script>
|
||||
<script src="mocha.js?_c={{ts}}"></script>
|
||||
|
||||
<!-- libs -->
|
||||
<script type="text/javascript" src="expect.js?_c=<%= ts %>"></script>
|
||||
<script type="text/javascript" src="mocha.js?_c=<%= ts %>"></script>
|
||||
<script type="text/javascript" src="jquery.js?_c=<%= ts %>"></script>
|
||||
|
||||
<!-- ESJS Reporter - sets itself as the reporter -->
|
||||
<link rel="stylesheet" href="esjs_reporter.css?_c=<%= ts %>"/>
|
||||
<script type="text/javascript" src="esjs_reporter.js?_c=<%= ts %>"></script>
|
||||
|
||||
<!-- global vars -->
|
||||
<script>
|
||||
var ES_HOSTNAME = '<%- es_hostname %>';
|
||||
var ES_PORT = <%= es_port %>;
|
||||
</script>
|
||||
|
||||
<!-- test -->
|
||||
<script>mocha.setup('bdd')</script>
|
||||
<script src="client.js?_c={{ts}}"></script>
|
||||
<script src="yaml_tests.js?_c={{ts}}"></script>
|
||||
<script type="text/javascript" src="client.js?_c=<%= ts %>"></script>
|
||||
<script type="text/javascript" src="yaml_tests.js?_c=<%= ts %>"></script>
|
||||
|
||||
<!-- begin -->
|
||||
<script>
|
||||
mocha.checkLeaks();
|
||||
mocha.slow(1000);
|
||||
|
||||
6
test/browser_integration/jquery.js
vendored
Normal file
6
test/browser_integration/jquery.js
vendored
Normal file
File diff suppressed because one or more lines are too long
@ -2,6 +2,13 @@ var http = require('http');
|
||||
var url = require('url');
|
||||
var path = require('path');
|
||||
var fs = require('fs');
|
||||
var crypto = require('crypto');
|
||||
var _ = require('lodash');
|
||||
var util = require('util');
|
||||
var chalk = require('chalk');
|
||||
var moment = require('moment');
|
||||
chalk.enabled = true;
|
||||
|
||||
var browserify = require('browserify');
|
||||
var port = process.argv[2] || 8888;
|
||||
|
||||
@ -9,6 +16,15 @@ var middleware = [];
|
||||
|
||||
Error.stackTraceLimit = Infinity;
|
||||
|
||||
var chars = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';
|
||||
function rand(length) {
|
||||
var str = '';
|
||||
while (str.length < length) {
|
||||
str += chars.charAt(Math.floor(Math.random() * chars.length));
|
||||
}
|
||||
return str;
|
||||
}
|
||||
|
||||
function sendBundle(req, resp, files, opts, extend) {
|
||||
resp.setHeader('Content-Type', 'application/javascript');
|
||||
resp.writeHead(200);
|
||||
@ -30,14 +46,126 @@ function sendBundle(req, resp, files, opts, extend) {
|
||||
});
|
||||
}
|
||||
|
||||
function collectTestResults(req, resp) {
|
||||
var body = '';
|
||||
|
||||
req.on('data', function (chunk) {
|
||||
body += chunk;
|
||||
});
|
||||
|
||||
req.on('error', function (err) {
|
||||
resp.writeHead(500);
|
||||
resp.end(err.message || 'failed to receive request completely');
|
||||
});
|
||||
|
||||
req.on('end', function () {
|
||||
var testDetails;
|
||||
try {
|
||||
testDetails = JSON.parse(body);
|
||||
} catch (e) {
|
||||
resp.writeHead(500);
|
||||
resp.end('encoding failure');
|
||||
return;
|
||||
}
|
||||
|
||||
resp.writeHead(200);
|
||||
resp.end('good work');
|
||||
|
||||
/**
|
||||
* The JUnit xml output desired by Jenkins essentially looks like this:
|
||||
*
|
||||
* testsuites:
|
||||
* - testsuite: (name, timestamp, hostname, tests, failures, errors, time)
|
||||
* - testcase: (error or failure, name, classname, time)
|
||||
*
|
||||
* Full XSD avaliable [here](http://windyroad.com.au/dl/Open%20Source/JUnit.xsd)
|
||||
*
|
||||
* from
|
||||
*
|
||||
* {
|
||||
* stats: {
|
||||
*
|
||||
* }
|
||||
* suite: [
|
||||
* {
|
||||
* name:
|
||||
* results: []
|
||||
* suites: [] // optional
|
||||
* }
|
||||
* ]
|
||||
* }
|
||||
*/
|
||||
|
||||
var testXml = require('xmlbuilder');
|
||||
var suites = testXml.create('testsuites');
|
||||
var suiteCount = 0;
|
||||
|
||||
_.each(testDetails.suites, function serializeSuite(suiteInfo) {
|
||||
|
||||
var suite = suites.ele('testsuite', {
|
||||
package: 'elasticsearch-js:yaml_tests',
|
||||
id: suiteCount++,
|
||||
name: suiteInfo.name,
|
||||
timestamp: moment(suiteInfo.start).toJSON(),
|
||||
hostname: 'localhost',
|
||||
tests: (suiteInfo.results && suiteInfo.results.length) || 0,
|
||||
failures: _.where(suiteInfo.results, {pass: false}).length,
|
||||
errors: 0,
|
||||
time: suiteInfo.time / 1000
|
||||
});
|
||||
|
||||
_.each(suiteInfo.results, function (testInfo) {
|
||||
var testcase = suite.ele('testcase', {
|
||||
name: testInfo.name,
|
||||
time: (testInfo.time || 0) / 1000,
|
||||
classname: suiteInfo.name
|
||||
});
|
||||
|
||||
if (testInfo.errMsg) {
|
||||
testcase.ele('failure', {
|
||||
message: testInfo.errMsg,
|
||||
type: 'AssertError'
|
||||
});
|
||||
} else if (!testInfo.pass) {
|
||||
testcase.ele('error', {
|
||||
message: 'Unknown Error',
|
||||
type: 'TestError'
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
if (suiteInfo.suites) {
|
||||
_.each(suiteInfo.suites, serializeSuite);
|
||||
}
|
||||
|
||||
suite.ele('system-out', {}, suiteInfo.stdout);
|
||||
suite.ele('system-err', {}, suiteInfo.stderr);
|
||||
});
|
||||
|
||||
var filename = path.join(__dirname, 'test-output.xml');
|
||||
fs.writeFile(filename, suites.toString({ pretty: true}), function (err) {
|
||||
if (err) {
|
||||
console.log('unable to save test-output', err.message);
|
||||
console.trace();
|
||||
process.exit(1);
|
||||
} else {
|
||||
console.log('test output written to ', filename);
|
||||
process.exit(testDetails.stats.failures ? 1 : 0);
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
var server = http.createServer(function (req, resp) {
|
||||
req.uri = url.parse(req.url).pathname;
|
||||
var parsedUrl = url.parse(req.url, true);
|
||||
req.uri = parsedUrl.pathname;
|
||||
req.query = parsedUrl.query;
|
||||
req.filename = path.join(__dirname, req.uri);
|
||||
|
||||
resp._end = resp.end;
|
||||
var end = resp.end;
|
||||
resp.end = function () {
|
||||
console.log(this.statusCode, req.uri);
|
||||
resp._end.apply(resp, arguments);
|
||||
console.log(chalk[this.statusCode < 300 ? 'green' : 'red'](this.statusCode), req.uri);
|
||||
end.apply(resp, arguments);
|
||||
};
|
||||
|
||||
var middleIndex = -1;
|
||||
@ -57,6 +185,8 @@ var server = http.createServer(function (req, resp) {
|
||||
middleware.push(function (req, resp, next) {
|
||||
// resolve filenames
|
||||
switch (req.uri) {
|
||||
case '/tests-complete':
|
||||
return collectTestResults(req, resp);
|
||||
case '/expect.js':
|
||||
req.filename = path.join(__dirname, '../../node_modules/expect.js/expect.js');
|
||||
break;
|
||||
@ -131,13 +261,17 @@ middleware.push(function (req, resp, next) {
|
||||
break;
|
||||
}
|
||||
|
||||
resp.setHeader('Content-Type', contentType);
|
||||
resp.writeHead(200);
|
||||
resp.end(
|
||||
data
|
||||
.replace(/\{\{ts\}\}/g, Date.now())
|
||||
.replace(/\{\{phantom\}\}/g, req.filename === '/phantom.html' ? '-phantom' : '')
|
||||
);
|
||||
if (contentType === 'text/html') {
|
||||
resp.end(_.template(data, _.defaults(req.query, {
|
||||
es_hostname: 'localhost',
|
||||
es_port: 9200,
|
||||
ts: rand(5)
|
||||
})));
|
||||
} else {
|
||||
resp.end(data);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
12676
test/browser_integration/test-output.xml
Normal file
12676
test/browser_integration/test-output.xml
Normal file
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@ -11,6 +11,15 @@ var defaults = {
|
||||
};
|
||||
|
||||
if (process.browser) {
|
||||
/* jshint browser:true */
|
||||
if (window.ES_HOST) {
|
||||
defaults.host = window.ES_HOST;
|
||||
}
|
||||
|
||||
if (window.ES_PORT) {
|
||||
defaults.port = window.ES_PORT;
|
||||
}
|
||||
|
||||
module.exports = defaults;
|
||||
} else {
|
||||
module.exports = require('optimist')
|
||||
|
||||
@ -8393,7 +8393,7 @@
|
||||
"do": {
|
||||
"index": {
|
||||
"index": "test_index",
|
||||
"type": "_percolator",
|
||||
"type": ".percolator",
|
||||
"id": "test_percolator",
|
||||
"body": {
|
||||
"query": {
|
||||
@ -8919,7 +8919,7 @@
|
||||
],
|
||||
"suggest/10_basic.yaml": [
|
||||
{
|
||||
"Basic tests for suggest API": [
|
||||
"setup": [
|
||||
{
|
||||
"skip": {
|
||||
"version": "0 - 0.90.2",
|
||||
@ -8942,6 +8942,16 @@
|
||||
"do": {
|
||||
"indices.refresh": {}
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"Basic tests for suggest API - pre v1": [
|
||||
{
|
||||
"skip": {
|
||||
"version": "1 - 99",
|
||||
"reason": "Standard analyzer uses stopwords"
|
||||
}
|
||||
},
|
||||
{
|
||||
"do": {
|
||||
@ -8968,6 +8978,40 @@
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"Basic tests for suggest API - post v1": [
|
||||
{
|
||||
"skip": {
|
||||
"version": "0 - 0.90.9",
|
||||
"reason": "Standard analyzer ignores stopwords"
|
||||
}
|
||||
},
|
||||
{
|
||||
"do": {
|
||||
"suggest": {
|
||||
"body": {
|
||||
"test_suggestion": {
|
||||
"text": "The Amsterdma meetpu",
|
||||
"term": {
|
||||
"field": "body"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"match": {
|
||||
"test_suggestion.1.options.0.text": "amsterdam"
|
||||
}
|
||||
},
|
||||
{
|
||||
"match": {
|
||||
"test_suggestion.2.options.0.text": "meetup"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"update/10_doc.yaml": [
|
||||
|
||||
Reference in New Issue
Block a user