Skip to content

Instantly share code, notes, and snippets.

@barahilia
Forked from dlidstrom/run-jasmine.js
Last active March 24, 2022 11:38
Show Gist options
  • Save barahilia/9663804 to your computer and use it in GitHub Desktop.
Save barahilia/9663804 to your computer and use it in GitHub Desktop.
Runs Jasmine tests using PhantomJS. Adapted for use within TeamCity..Compatible with Jasmine 2.0.
var system = require('system'),
env = system.env;
/**
* Wait until the test condition is true or a timeout occurs. Useful for waiting
* on a server response or for a ui change (fadeIn, etc.) to occur.
*
* @param testFx javascript condition that evaluates to a boolean,
* it can be passed in as a string (e.g.: "1 == 1" or "$('#bar').is(':visible')" or
* as a callback function.
* @param onReady what to do when testFx condition is fulfilled,
* it can be passed in as a string (e.g.: "1 == 1" or "$('#bar').is(':visible')" or
* as a callback function.
* @param timeOutMillis the max amount of time to wait. If not specified, 3 sec is used.
*/
function waitFor(testFx, onReady, timeOutMillis) {
var maxtimeOutMillis = timeOutMillis ? timeOutMillis : 3001, //< Default Max Timeout is 3s
start = new Date().getTime(),
condition = false,
interval = setInterval(function () {
if ((new Date().getTime() - start < maxtimeOutMillis) && !condition) {
// If not time-out yet and condition not yet fulfilled
condition = (typeof (testFx) === "string" ? eval(testFx) : testFx()); //< defensive code
} else {
if (!condition) {
// If condition still not fulfilled (timeout but condition is 'false')
console.log("'waitFor()' timeout");
phantom.exit(1);
} else {
// Condition fulfilled (timeout and/or condition is 'true')
console.log("'waitFor()' finished in " + (new Date().getTime() - start) + "ms.");
typeof (onReady) === "string" ? eval(onReady) : onReady(); //< Do what it's supposed to do once the condition is fulfilled
clearInterval(interval); //< Stop this interval
}
}
}, 100); //< repeat check every 100ms
};
if (system.args.length !== 2) {
console.log('Usage: run-jasmine.js URL');
phantom.exit(1);
}
var page = require('webpage').create();
/**
*
##teamcity[testSuiteStarted name='suite.name']
##teamcity[testSuiteStarted name='nested.suite']
##teamcity[testStarted name='package_or_namespace.ClassName.TestName']
##teamcity[testFailed name='package_or_namespace.ClassName.TestName' message='The number should be 20000' details='expected:<20000> but was:<10000>']
##teamcity[testFinished name='package_or_namespace.ClassName.TestName']
##teamcity[testSuiteFinished name='nested.suite']
##teamcity[testSuiteFinished name='suite.name']
*/
// Route "console.log()" calls from within the Page context to the main Phantom context (i.e. current "this")
page.onConsoleMessage = function (msg) {
var teamCityMessage = msg.indexOf('TEAMCITY_') === 0;
if (teamCityMessage) {
if (!env.hasOwnProperty('TEAMCITY_PROJECT_NAME')) return;
var separatorIndex = msg.indexOf(':');
var command = msg.substring(0, separatorIndex);
var data = JSON.parse(msg.substring(separatorIndex + 1));
switch (command) {
case 'TEAMCITY_TESTSTARTED': {
console.log("##teamcity[testStarted name='" + escape(data.name) + "']");
break;
}
case 'TEAMCITY_TESTFINISHED': {
console.log("##teamcity[testFinished name='" + escape(data.name) + "']");
break;
}
case 'TEAMCITY_SUITESTARTED': {
console.log("##teamcity[testSuiteStarted name='" + escape(data.suite) + "']");
break;
}
case 'TEAMCITY_SUITEFINISHED': {
console.log("##teamcity[testSuiteFinished name='" + escape(data.suite) + "']");
break;
}
case 'TEAMCITY_TESTFAILED': {
console.log("##teamcity[testFailed name='" + escape(data.name) + "' message='" + escape(data.message) + "']");
break;
}
}
}
else {
if (env.hasOwnProperty('TEAMCITY_PROJECT_NAME')) return;
console.log(msg);
}
function escape(message) {
while (message.indexOf("'") >= 0) message = message.replace("'", '"');
return message;
}
};
page.open(system.args[1], function (status) {
if (status !== "success") {
console.log("Unable to access network");
phantom.exit();
} else {
waitFor(function () {
return page.evaluate(function () {
return document.body.querySelector('.symbolSummary .pending') === null
});
}, function () {
var exitCode = page.evaluate(function () {
var currentSuite;
var successList = document.body.querySelectorAll('.results > .summary .specs > .passed');
var suites = {};
if (successList && successList.length > 0) {
for (var i = 0; i < successList.length; ++i) {
var el = successList[i],
name = el.children[0].innerText,
suite = el.parentElement.parentElement.querySelector('.suite-detail').innerText;
suites[suite] = suites[suite] || [];
suites[suite].push({ status: 'success', name: name });
}
}
var failedList = document.body.querySelectorAll('.results > .failures > .spec-detail.failed');
if (failedList && failedList.length > 0) {
console.log('');
console.log(failedList.length + ' test(s) FAILED:');
for (var i = 0; i < failedList.length; ++i) {
var el = failedList[i],
name = el.querySelector('.description').innerText,
msg = el.querySelector('.result-message').innerText,
suite = name.substring(0, name.indexOf(' '));
// remove trailing period
name = name.substring(0, name.length - 1);
suites[suite] = suites[suite] || [];
suites[suite].push({ suite: suite, status: 'failed', name: name, message: name + ': ' + msg });
}
}
for (var suite in suites) {
var tests = suites[suite];
console.log('TEAMCITY_SUITESTARTED:' + JSON.stringify({ suite: suite }));
for (var i in tests) {
var test = tests[i];
console.log('TEAMCITY_TESTSTARTED:' + JSON.stringify({ name: test.name }));
if (test.status === 'success') {
}
else if (test.status === 'failed') {
console.log('TEAMCITY_TESTFAILED:' + JSON.stringify({ name: test.name, message: test.message }));
console.log('');
console.log(test.suite);
console.log(test.message);
}
console.log('TEAMCITY_TESTFINISHED:' + JSON.stringify({ name: test.name }));
}
console.log('TEAMCITY_SUITEFINISHED:' + JSON.stringify({ suite: suite }));
}
if (failedList && failedList.length > 0) {
return 1;
} else {
console.log(document.body.querySelector('.alert > .bar.passed').innerText);
return 0;
}
});
phantom.exit(exitCode);
});
}
});
@leviwilson
Copy link

Nice, @daniel-chambers...thanks for the patch!

@jiimaho
Copy link

jiimaho commented May 19, 2015

Does this work with Jasmine 2.2?

Update: Yes it seems to be working for 2.2. However I get the same error as Purush0th above.
Update2: After trying with daniel-chambers script, I instead get "'waitFor()' timeout". Any ideas?

@marti1125
Copy link

nice! 👍

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment