Thursday, September 22, 2011

Integrating jasmine-maven-plugin With Your Legacy Enterprisey App

Let's say you're working on enhancing an old legacy app with javascript. Doesn't really matter what sort of app, just legacy, with an old source tree and an old deployment style. How can you integrate jasmine within that app and have it also integrate with your new fangled CI environment? What if you've also been asked to use maven since it's "The way forward" for your organization? How can you accomplish this?

Well, there's the jasmine-maven-plugin, which is all sorts of awesome, but because you have a legacy file structure there's no clear way on how to hook it into your legacy app. But when there's a will there's a way.

There are several problems that need to be tackled here. Let's go over them bit by bit.

First, how do we get jasmine-maven-plugin to see our legacy app?

Let's hope that you can create your project somewhere "near" the legacy app in the SCM system. In this example, I'm going to assume that we have a tree structure that looks like this:

Pretty simple, we'll put our specs inside jasmine-tests\src\test\javascript. We'll put any jasmine required javascript inside jasmine-tests\src\test\javascript\lib. We just need to figure out how to tell jasmine-maven-plugin to look at our legacy app for our scripts. Fortunately, it's configurable. Let's look at a snippet of the pom.xml that shows how you would configure the plugin.

In this configuration, we're telling the jasmine-maven-plugin to look outside of our project structure for our javascript files. It even preloads our new fangled jquery thing that we've introduced into our legacy application from our legacy.js.src property. The key to this is that we've kept the configuration of the plugin outside of our execution configuration. When jasmine-maven-plugin runs, maven will actually fork a process to generate the manual runner. It will not receive the configuration settings if you're using an older maven like 2.0.11. I do not know if 2.2.1 or 3.x change this. By placing the configuration at the top level of the plugin, we fix that concern.

At this point, we actually have a plugin that can execute on our system if we've checked out our entire source tree. It should also execute in your CI environment.

However, some teams, like to check things out in different directory structures than what's in the SCM tree due to their tools (like Eclipse). Although your team is excited, they've also noticed that the ManualTestRunner is deprecated. When they try to run jasmine:bdd, they find that nothing gets picked up from the legacy app because the jetty runs from the root of your jasmine-tests directory. It can't see things underneath it. Normally you'd create a symbolic link,'re on Windows. Windows XP. Remember, I said Enterprisey app, not just legacy.

How can you fix the process so you can run jasmine:bdd like good sensible developers? Glad you asked. Maven profiles to the rescue. And, a neat plugin that lets you build symbolic links on crazy things like Windows XP.

Let's look at the profile:

The maven-junction-plugin actually builds symbolic links in both unix and windows. We redefine the location of our legacy.js.src to be a temporary directory inside the jasmine-tests project. The checkedout.legacy.js.src points to where our application has been checked out locally. The plugin is executed in the initialize phase so it occurs before jasmine. And initialize is supposed to setup directory structures, and the like, so it makes sense.

Since we've redefined the legacy.js.src, jasmine:bdd will simply see our files as if they are inside the project, and the jetty will be able to serve them properly.

Our final pom looks like this:

Hopefully this is helpful for you.