Nov 24
Again, simple hack to run JsTestDriver tests as part of my SBT build.
I created it as a mixin trait. Server is started with run-js-test-driver task, that is automatically performed first time the run-js-test is run. I had to put the project into sbt package, as I wanted to use ExitHooks to shut the server down automatically on exit, and ExitHooks methods visibility did not allow me otherwise.
trait JsTestDriver { self: DefaultWebProject =>
val jsTestDriverPort = 9876
val jsTestDriverPath = "lib/JsTestDriver-1.2.2.jar"
val javacmd = "java"
val jsTestDriverCmd = "%s -jar %s".format(javacmd, jsTestDriverPath)
protected var jsTestDriver: Option[Process] = None
protected def destroyJsTestDriver = {
jsTestDriver.foreach { _.destroy }
jsTestDriver = None
}
protected def startJsTestDriver = jsTestDriver match {
case None => {
jsTestDriver = Some("%s --port %d --browser open".format(jsTestDriverCmd, jsTestDriverPort) run log)
ExitHooks.register(new ExitHook {
val name = "Shutdown JsTestDriver"
def runBeforeExiting() {
destroyJsTestDriver
}
})
Thread.sleep(2000L)
}
case _ =>
}
lazy val runJsTestDriver = self.task {
startJsTestDriver
None
}
lazy val stopJsTestDriver = self.task {
destroyJsTestDriver
None
}
lazy val testJs = self.task {
startJsTestDriver
"%s --tests all".format(jsTestDriverCmd) ! log match {
case 0 => None
case x => Some("There were test failures")
}
}
}
The only thing left is to extend the web project with this trait and add
override def testAction = super.testAction dependsOn (testCompile, copyResources, copyTestResources, testJs)
to run the JS tests as part of test action.
Nov 16
LESS is a system that "extends CSS with variables, mixins, operations and nested rules". As that is something that CSS desperately needs, here's how to integrate it to your Scala Lift based web project using SBT.
The following code:
- Keeps *.less files together with *.css files in src/main/webapp/css.
- Recompiles .less to .css on prepare-webapp automatically, if changed.
- Leaves out *.less files from the resulting war.
- Creates "lessc" task to call the compiler.
Just add it to your web project class.
def lessPaths = (webappPath / "css" * "*.less")
def less2CSS(x: String) = x.replaceAll("\\.less$", ".css")
def dependentCssPaths = Path.lazyPathFinder(lessPaths.get.map(l => less2CSS(l.toString)).map(Path.fromFile _))
override def watchPaths = super.watchPaths --- dependentCssPaths
override def webappResources = super.webappResources --- lessPaths
val lessCompiler = "lessc"
lazy val lessc = task{
val toCompile = lessPaths.get.filter(l => l.lastModified > Path.fromFile(less2CSS(l.toString)).lastModified).toList
log.info("Compiling with lessc: %d file(s).".format(toCompile.length))
def process(paths: List[Path]):Option[String] = paths match {
case Nil => None
case x :: xs => {
log.debug("Compiling less file %s".format(x))
("%s %s".format(lessCompiler, x) ! log) match {
case 0 => process(xs)
case _ => Some("Error while compiling file: %s".format(x))
}
}
}
process(toCompile)
}
override def prepareWebappAction = super.prepareWebappAction dependsOn (compile, lessc, copyResources)
Nov 4
Well, as I don't seem to be able to blog regularly, nor make myself to find a way how to make
Squarespace multi-lingual without paying more, I just decided to move my blog to
Posterous, and create another free site for my czech posts.
I really like it, so far. No tools necesarry, just email client. What a great idea. Working on a blog post? Just create a draft. What a concept :-D
And it even has auto posting to other services like Twitter, Facebook etc.
Not, that it would make me blog more, but you never know ;-)