Web applications are using more JavaScript than ever before. The following image (thanks to Gineer) shows the shift in the architecture types of web applications from simple thin clients to thicker clients driven by rich presentations and client logic.

Since most of the newer web applications include business logic embedded into the client using JavaScript, we must put assurances to make sure the quality of the application is not compromised over time.
In most cases, the JavaScript side of the applications goes untested or is not automated which is a bad idea.
I have selected the following tools to be able to provide Continuous Integration to Rich Internet Applications:
Jasmine is a testing framework for JavaScript. It is usually used as a red-green tool for developing applications with either TDD or BDD. Jasmin runs on the browser for convenience to check the TDD red-green method but this makes it a bit harder to automate.
Team City is a Continuos Integration server that is extremely popular due to its flexibility to work with a wide variety of projects, it is easy to configure and it works in most environments.
Jasmine Team City Reporter is a reporter type for Jasmine. Jasmine uses a plugin based architecture where it allows different types of reporters to consume and prepare the data. The Jasmine Team City Reporter module allows Jasmine to output the data to the web page console window of the browser that runs Jasmine.
PhantomJS is a headless web-kit browser that allows execution and rendering of web content. We will use it to simulate as if we would be running Jasmine with the Team City Reporter on a website, this way we can automate the whole process.
I built a simple PhatomJS script that consumes the Jasmine Team City Reporter example, it worked great!
JavaScript file to control PhantomJS
console.log('Loading a web page');
var page = new WebPage();
//This was tricky, this is the way to open LOCAL files
var url = "file://localhost/Users/danmerino/test/teamcity_reporter.html";
phantom.viewportSize = {width: 800, height: 600};
//This is required because PhantomJS sandboxes the website and it does not show up the console messages form that page by default
page.onConsoleMessage = function (msg) { console.log(msg); };
//Open the website
page.open(url, function (status) {
//Page is loaded!
if (status !== 'success') {
console.log('Unable to load the address!');
} else {
//Using a delay to make sure the JavaScript is executed in the browser
window.setTimeout(function () {
page.render("output.png");
phantom.exit();
}, 200);
}
});
JavaScript tests
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<title>Console Reporter Spec</title>
<link rel="stylesheet" href="../ext/jasmine.css" type="text/css" />
<script type="text/javascript" src="../ext/jasmine.js"></script>
<script type="text/javascript" src="../ext/jasmine-html.js"></script>
<script type="text/javascript" src="../src/jasmine.teamcity_reporter.js"></script>
</head>
<body>
<script type="text/javascript">
describe("Basic Suite", function() {
it("Should pass a basic truthiness test.", function() {
expect(true).toEqual(true);
});
it("Should fail when it hits an inequal statement.", function() {
expect(1+1).toEqual(3);
});
});
describe("Another Suite", function() {
it("Should pass this test as well.", function() {
expect(0).toEqual(0);
});
});
jasmine.getEnv().addReporter(new jasmine.TeamcityReporter());
jasmine.getEnv().addReporter(new jasmine.TrivialReporter());
jasmine.getEnv().execute();
</script>
</body>
</html>
Team City Configuration

Team City Test Results
