OSX Leopard, RSpec Autotest Growl/growlnotify Workaround
Posted by mhagedorn on October 31st, 2007 filed in RspecUpon loading up the new release of OSX 10.5 (Leopard), I was very frustrated to find that Growl notifications no longer work when using
Autotest. Apparently growlnotify, the command line app which makes the magic happen, isn’t compatible. Read on to see how I got this work
It turns out that there is another way to get notifications into Growl other than the the (broken) growlnotify. That technique is to use Applescript.
Applescript allows you to do all sorts of neat things to applications in OSX but it is an arcane and hard to understand beast (at least in my
opinion – feel free to flame me
). Based on a sample from the Growl website I was able to cobble together a working solution which
restores all the growlnotify goodness we have come to expect from Autotest. The first thing is to write the Applescript which talks to Growl.
Here is what I came up with (as modified from the Growl website)
— growlNotify.applescript
–
— Created by Mike Hagedorn on 2007-10-31.
— Copyright (c) 2007 Silverchair Solutions. All rights reserved. http://www.silverchairsolutions.com
— based on script from the growl website
— works around the fact that growlnotify doesnt work on leopard
— pass in like osascript growlNotify.applescript
on run argv
set rspectitle to item 1 of argv
set rspecmessage to item 2 of argv
set rspecimage to item 3 of argv
tell application “GrowlHelperApp”
— Make a list of all the notification types
— that this script will ever send:
set the allNotificationsList to ¬
{”RSpec Notification” }
— Make a list of the notifications
— that will be enabled by default.
— Those not enabled by default can be enabled later
— in the ‘Applications’ tab of the growl prefpane.
set the enabledNotificationsList to ¬
{”RSpec Notification”}
— Register our script with growl.
— You can optionally (as here) set a default icon
— for this script’s notifications.
register as application “Growl-RSpec AppleScript Notifications” ¬
all notifications allNotificationsList ¬
default notifications enabledNotificationsList ¬
icon of application “Script Editor”
— Send a Notification…
notify with name “RSpec Notification” ¬
title rspec
description rspecmessage ¬
application name “Growl-RSpec AppleScript Notifications” ¬
image from location rspecimage
end tell
end run
Put this file somewhere where you can find it (I used ~/Library/Scripts/growlNotify.applescript) then modify the .autotest file you have in your home directory
to not call growlnotify, but the new method you just crafted (i.e. the applescript). Here is what mine looks like
#
# .autotest
# Autotest Growl Notifications for Rspec and Test::Unit
#
# Created by Rein Henrichs on 2007-09-12.
# Modified by Mike Hagedorn (www.silverchairsolutions.com) to use osascript to work around Leopard issues
#
# Copyright 2007 Rein Henrichs.
# http://pastie.caboo.se/96573/download
#
require ‘logger’
logfile = File.join(File.dirname(FILE), ‘.autotest.log’)
$logger = Logger.new(logfile)
module Autotest::Growl
Autotest.addhook :rancommand do |at|
input = Input.new( at.results )
Growler.displaynotification( input )
end
end
class String
def removecolorcodes!
self.gsub!(/\e[\d+m/,”)
self.strip!
end
end
class Growler
class << self
def displaynotification( input )
growler = RspecGrowler if input.fromrspec?
growler = TestUnitGrowler if input.fromtestunit?
growler.displaynotification( input.resultline )
rescue => e
$logger.fatal e
notifysystemerror( “Unexpected Error”, “Please check your ~/.autotest.log and report anything strange to reinh@reinh.com” )
end
def notify(title, msg, img, pri=0, stick=”" )
#system “growlnotify -n autotest –image #{img} -p #{pri} -m #{msg.inspect} #{title} #{stick}”
system “osascript ~/Library/Scripts/growlNotify.applescript ‘#{title}’ ‘#{msg.inspect}’ ‘#{img}’”
end
def notifysystemerror( title = “System Error”, err = “”)
Growler.notify( title, err, ‘~/Library/autotest/railsfail.png’)
end
end
end
class Input
def initialize(input)
@input = input
end
def empty?; @input.empty?; end
# TODO: Make these work
def failing?; end
def passing?; end
def error?; end
def fromrspec?; !!rspecresultline || empty?; end
def fromtestunit?; !!testunitresultline; end
def rspecresultline; @input.grep( /\d+\sexample/ ).first; end
def testunitresultline; @input.grep( /\d+\sassertion/ ).first; end
def resultline
@line ||= case
when fromrspec? then rspecresultline
when fromtestunit? then testunitresultline
else nil
end
@line.removecolorcodes! if @line
end
end
class AutoGrowler < Growler
class << self
def notifyfailure(input)
notify( “Tests Failed”, input, ‘~/Library/autotest/railsfail.png’, 2 )
end
def notifysuccess(input)
notify( “Tests Passed”, input, ‘~/Library/autotest/railsok.png’, 0 )
end
end
end
class RspecGrowler < AutoGrowler
class << self
def notifypending(input)
notify( “Tests Pending”, input, ‘~/Library/autotest/pending.png’, 1 )
end
def notifyerror
notify( “Syntax Error”, “It looks like there was a syntax error. Check your autotest results.”, ‘~/Library/autotest/railsfail.png’)
end
def displaynotification(input)
notifyerror and return unless input
# TODO: replace with some object oriented goodness. elsif FTL!
examples, failures, pending = input.split(”, “)
if failures.toi > 0
notifyfailure input
elsif pending.toi > 0
notifypending input
else
notifysuccess input
end
end
end
end
class TestUnitGrowler < AutoGrowler
class << self
def notifyerror(input)
notify( “Tests Errored”, input, ‘~/Library/autotest/railsfail.png’, 2 )
end
def displaynotification( input )
# TODO: replace with some object oriented goodness. elsif FTL!
tests, assertions, failures, errors = input.split(”, “)
if errors.toi > 0
notifyerror input
elsif failures.toi > 0
notifyfailure input
else
notifysuccess input
end
end
end
end
Notice that the change here is a small one, only on line 44, reference the commented out growlnotify. This is working great for me. Hope this helps
you!
6 Responses to “OSX Leopard, RSpec Autotest Growl/growlnotify Workaround”
Leave a Comment
You must be logged in to post a comment.
October 31st, 2007 at 5:34 pm
Hey, the html mangled both of the scripts, and I never really used such a complex .autotest script, but the applescript works flawlessly after some character replacement. I put it in pasties:
growlnotify.scpt – http://pastie.caboo.se/112911 .autotest I use – http://pastie.caboo.se/112912
October 31st, 2007 at 7:24 pm
Thanks for the tip, Mike? I wanted to ask if you did a clean install or an upgrade to 10.5? Growlnotify did not work for me after my upgrade but I quickly found out that the upgrade had dropped my /usr/local/bin path out of my $PATH…
November 1st, 2007 at 5:58 am
yeah I upgraded. the growl guys confirmed it as a bug.
November 27th, 2007 at 8:08 am
This solved my Growl problems on Leopard. Thanks guys.
December 6th, 2007 at 3:50 pm
Hi, I came up with another solution, a 1 line wrapper, no applescript… please tell me if it does not cover your needs, I may be missing your point here, or some aspects of it
In the growl prefs pane, network tab, activate incoming connections
rename /usr/local/bin/growlnotify to /usr/local/bin/growlnotify.wrapped
create /usr/local/bin/growlnotify as a shell script containing “exec /usr/local/bin/growlnotify.wrapped -H localhost ${1+$@}”
This forces growlnotify to use the network to communicate with growl. (The script could also check that it is not already invoked with the “-H” option, I just did not need to care, maybe you would.)
Cheers
February 16th, 2008 at 7:14 pm
[...] it work.My solution is a mashup of ideas from these sites, growl docs and autotest docs:UnixmonkeySilver Chair Solutions Neither of the above worked out of the box for me. (Not sure why) My solution [...]