<?xml version="1.0" encoding="UTF-8"?>
<commit>
  <added type="array">
    <added>
      <filename>lib/autotest/result.rb</filename>
    </added>
  </added>
  <modified type="array">
    <modified>
      <diff>@@ -1,3 +1,13 @@
+== 0.1.3 2009-07-23
+
+* 2 major improvements
+  * Better result analysis and more readable notifications
+  * Support for Growl on Windows
+* 3 minor improvement
+  * Move Cucumber notification to :ran_features hook
+  * Add one_notification_per_run configuration option
+  * Notification for undefined Cucumber scenarios/steps
+
 == 0.1.2 2009-06-08
 
 * 3 major improvements</diff>
      <filename>History.txt</filename>
    </modified>
    <modified>
      <diff>@@ -12,6 +12,7 @@ img/passed.png
 img/pending.png
 lib/autotest-growl.rb
 lib/autotest/growl.rb
+lib/autotest/result.rb
 script/console
 script/destroy
 script/generate</diff>
      <filename>Manifest.txt</filename>
    </modified>
    <modified>
      <diff>@@ -16,7 +16,7 @@ priorities:
 
 * 2 for error or failed
 * 0 for info
-* -1 for pending or unknown
+* -1 for pending, undefined or unknown
 * -2 for passed
 
 Furthermore the terminal running autotest is cleared on every cycle (unless
@@ -32,8 +32,8 @@ might take a while though as autotest itself is currently misbehaving on Ruby
 
 == REQUIREMENTS:
 
-* Growl &gt;= 1.1.4
-* ZenTest &gt;= 4.1.0
+* Growl &gt;= 1.1.5
+* ZenTest &gt;= 4.1.3
 
 == INSTALL:
 
@@ -71,6 +71,13 @@ All tests have passed&quot;, add the following to your ~/.autotest:
 
   Autotest::Growl::hide_label = true
 
+=== One Notifications per Run
+
+Allow only one test and one feature notification per run by adding the
+following to your ~/.autotest:
+
+  Autotest::Growl::one_notification_per_run = true
+
 === Show Modified Files
 
 Add the following to your ~/.autotest if you would like to receive a Growl
@@ -95,12 +102,6 @@ Or remove all outdated versions of all installed gems:
 
   sudo gem cleanup
 
-=== Missing Cucumber Notifications
-
-If you are using autotest-fsevent as well, the require statements are not
-ordered correctly. The require for autotest-fsevent must come after all
-other requires in your ~/.autotest.
-
 === Unreliable Growl Notifications
 
 Under some circumstances, Growl notifications seem to be swallowed randomly.</diff>
      <filename>README.rdoc</filename>
    </modified>
    <modified>
      <diff>@@ -17,7 +17,7 @@ $hoe = Hoe.spec 'autotest-growl' do
   self.post_install_message = &quot;\n\e[1;32m&quot; + File.read('PostInstall.txt') + &quot;\e[0;30m\n&quot;
   self.rubyforge_name       = self.name
   self.extra_deps           = [
-                                ['ZenTest','&gt;= 4.1.0'],
+                                ['ZenTest','&gt;= 4.1.3'],
                               ]
 end
 </diff>
      <filename>Rakefile</filename>
    </modified>
    <modified>
      <diff></diff>
      <filename>growl/growlnotify</filename>
    </modified>
    <modified>
      <diff>@@ -5,6 +5,6 @@ require File.dirname(__FILE__) + '/autotest/growl'
 
 module AutotestGrowl
 
-  VERSION  = '0.1.1'
+  VERSION  = '0.1.3'
 
 end</diff>
      <filename>lib/autotest-growl.rb</filename>
    </modified>
    <modified>
      <diff>@@ -1,5 +1,6 @@
 require 'rubygems'
 require 'autotest'
+require File.dirname(__FILE__) + '/result.rb'
 
 ##
 # Autotest::Growl
@@ -19,6 +20,7 @@ module Autotest::Growl
   @modified_files = []
 
   @@remote_notification = false
+  @@one_notification_per_run = false
   @@clear_terminal = true
   @@hide_label = false
   @@show_modified_files = false
@@ -30,6 +32,12 @@ module Autotest::Growl
   end
 
   ##
+  # Whether to limit the number of notifications per run to one or not (default).
+  def self.one_notification_per_run=(boolean)
+    @@one_notification_per_run = boolean
+  end
+
+  ##
   # Whether to clear the terminal before running tests (default) or not.
   def self.clear_terminal=(boolean)
     @@clear_terminal = boolean
@@ -61,28 +69,9 @@ module Autotest::Growl
   end
 
   ##
-  # Analyze test results and return the numbers in a hash or nil.
-  def self.analyze(results)
-    results.map! {|s| s.gsub(/(\e.*?m|\n)/, '') }   # remove escape sequences
-    results.reject! {|line| !line.match(/\d+\s+(example|test|scenario|step)s?/) }   # isolate result numbers
-    unless results.empty?
-      results = results.join(' ').gsub(/\W+/, ' ').split(' ')   # clean brackets, commas and such
-      results = results.map do |r| 
-        r.sub(/s$/, '')   # singularize
-        r.sub(/failure/, 'failed')   # homogenize
-      end
-      results = Hash[*results.reverse]   # create numbers hash
-      results.reject {|k, v| v.to_i == 0 }   # remove zero numbers
-    end
-  end
-
-  def pretty(*args)
-    'not yet done'
-  end
-
-  ##
   # Display the modified files.
   Autotest.add_hook :updated do |autotest, modified|
+    @ran_tests = @ran_features = false
     if @@show_modified_files
       if modified != @last_modified
         growl @label + 'Modifications detected.', modified.collect {|m| m[0]}.join(', '), 'info', 0
@@ -96,7 +85,6 @@ module Autotest::Growl
   # Set the label and clear the terminal.
   Autotest.add_hook :run_command do
     @label = File.basename(Dir.pwd).upcase + ': ' if !@@hide_label
-    @run_scenarios = false   # WORKAROUND
     print &quot;\n&quot;*2 + '-'*80 + &quot;\n&quot;*2
     print &quot;\e[2J\e[f&quot; if @@clear_terminal
     false
@@ -105,57 +93,66 @@ module Autotest::Growl
   ##
   # Parse the RSpec and Test::Unit results and send them to Growl.
   Autotest.add_hook :ran_command do |autotest|
-    results = analyze(autotest.results)
-    if results
-      case autotest.testlib
-      when 'rspec'
-        if results['failed']
-          growl @label + 'Some RSpec examples have failed.', pretty('example', 'failed', 'pending'), 'failed', 2
-        elsif numbers['pending']
-          growl @label + 'Some RSpec examples are pending.', pretty('example', 'pending'), 'pending', -1
-        else
-          growl @label + 'All RSpec examples have passed.', pretty('example'), 'passed', -2
-          @run_scenarios = true   # WORKAROUND
+    unless @@one_notification_per_run &amp;&amp; @ran_tests
+      result = Result.new(autotest)
+      if result.exists?
+        case result.framework
+        when 'test-unit'        
+          if result.has?('test-error')
+            growl @label + 'Cannot run some unit tests.', &quot;#{result.get('test-error')} in #{result.get('test')}&quot;, 'error', 2
+          elsif result.has?('test-failed')
+            growl @label + 'Some unit tests failed.', &quot;#{result['test-failed']} of #{result.get('test-assertion')} in #{result.get('test')} failed&quot;, 'failed', 2
+          else
+            growl @label + 'All unit tests passed.', &quot;#{result.get('test-assertion')} in #{result.get('test')}&quot;, 'passed', -2
+          end
+        when 'rspec'
+          if result.has?('example-failed')
+            growl @label + 'Some RSpec examples failed.', &quot;#{result['example-failed']} of #{result.get('example')} failed&quot;, 'failed', 2
+          elsif result.has?('example-pending')
+            growl @label + 'Some RSpec examples are pending.', &quot;#{result['example-pending']} of #{result.get('example')} pending&quot;, 'pending', -1
+          else
+            growl @label + 'All RSpec examples passed.', &quot;#{result.get('example')}&quot;, 'passed', -2
+          end
         end
-      when 'test/unit'
-        if results['error']
-          growl @label + 'Cannot run some unit tests.', pretty(['assertion', 'in', 'test'], 'error'), 'error', 2
-        elsif results['failed']
-          growl @label + 'Some unit tests have failed.', pretty(['assertion', 'in', 'test'], 'failed'), 'failed', 2
-        else
-          growl @label + 'All unit tests have passed.', pretty(['assertion', 'in', 'test']), 'passed', -2
-          @run_scenarios = true   # WORKAROUND
-        end
-      when 'cucumber'
-        growl 'HOOK FIRED', 'cool', 'passed'
-        # WORKARDOUND: Hooked to :waiting until properly integrated in ZenTest.
+      else
+        growl @label + 'Could not run tests.', '', 'error', 2
       end
-    else
-      growl @label + 'Cannot run tests.', '', 'error', 2
+      @ran_test = true
     end
     false
   end
 
-=begin
   ##
-  # WORKAROUND: Parse the Cucumber results and send them to Growl.
-  Autotest.add_hook :waiting do |autotest|
-    if @run_scenarios &amp;&amp; !autotest.results.grep(/^\d+ scenario/).empty?
-      gist = autotest.results.map {|s| s.gsub(/(\e.*?m|\n)/, '') }.grep(/\d+\s+(scenario|step)s?/).join(&quot;, &quot;)
-      if gist == ''
-        growl @label + 'Cannot run Cucumber scenarios.', '', 'error', 2
-      else
-        if gist =~ /failed/
-          growl @label + 'Some Cucumber scenarios have failed.', gist, 'failed', 2
-        elsif gist =~ /undefined/
-          growl @label + 'Some Cucumber scenarios are undefined.', gist, 'pending', -1
-        else
-          growl @label + 'All Cucumber scenarios have passed.', gist, 'passed', -2
+  # Parse the Cucumber results and sent them to Growl.
+  Autotest.add_hook :ran_features do |autotest|
+    unless @@one_notification_per_run &amp;&amp; @ran_features
+      result = Result.new(autotest)
+      if result.exists?
+        case result.framework
+        when 'cucumber'
+          explanation = []
+          if result.has?('scenario-undefined') || result.has?('step-undefined')
+            explanation &lt;&lt; &quot;#{result['scenario-undefined']} of #{result.get('scenario')} not defined&quot; if result['scenario-undefined']
+            explanation &lt;&lt; &quot;#{result['step-undefined']} of #{result.get('step')} not defined&quot; if result['step-undefined']
+            growl @label + 'Some Cucumber scenarios are not defined.', &quot;#{explanation.join(&quot;\n&quot;)}&quot;, 'pending', -1          
+          elsif result.has?('scenario-failed') || result.has?('step-failed')
+            explanation &lt;&lt; &quot;#{result['scenario-failed']} of #{result.get('scenario')} failed&quot; if result['scenario-failed']
+            explanation &lt;&lt; &quot;#{result['step-failed']} of #{result.get('step')} failed&quot; if result['step-failed']
+            growl @label + 'Some Cucumber scenarios failed.', &quot;#{explanation.join(&quot;\n&quot;)}&quot;, 'failed', 2
+          elsif result.has?('scenario-pending') || result.has?('step-pending')
+            explanation &lt;&lt; &quot;#{result['scenario-pending']} of #{result.get('scenario')} pending&quot; if result['scenario-pending']
+            explanation &lt;&lt; &quot;#{result['step-pending']} of #{result.get('step')} pending&quot; if result['step-pending']
+            growl @label + 'Some Cucumber scenarios are pending.', &quot;#{explanation.join(&quot;\n&quot;)}&quot;, 'pending', -1          
+          else
+            growl @label + 'All Cucumber features passed.', '', 'passed', -2
+          end      
         end
+      else
+        growl @label + 'Could not run features.', '', 'error', 2
       end
+      @ran_features = true
     end
     false
   end
-=end
 
 end</diff>
      <filename>lib/autotest/growl.rb</filename>
    </modified>
    <modified>
      <diff>@@ -3,6 +3,7 @@ require File.dirname(__FILE__) + '/spec_helper.rb'
 describe &quot;handling results&quot; do
   before do
     @autotest = Autotest.new
+    @autotest.hook(:updated)
   end
 
   describe &quot;for RSpec&quot; do
@@ -55,25 +56,25 @@ describe &quot;handling results&quot; do
     it &quot;should show a 'passed' notification&quot; do
       Autotest::Growl.should_receive(:growl).and_return('passed')
       @autotest.results = [&quot;1 scenario (1 passed)&quot;, &quot;1 step (1 passed)&quot;]
-      @autotest.hook(:ran_command)
+      @autotest.hook(:ran_features)
     end
 
     it &quot;should show a 'failed' notification&quot; do
       Autotest::Growl.should_receive(:growl).and_return('failed')
       @autotest.results = [&quot;2 scenarios (1 failed, 1 passed)&quot;, &quot;2 steps (1 failed, 1 passed)&quot;]
-      @autotest.hook(:ran_command)
+      @autotest.hook(:ran_features)
     end
 
     it &quot;should show a 'pending' notification&quot; do
       Autotest::Growl.should_receive(:growl).and_return('pending')
       @autotest.results = [&quot;2 scenarios (1 undefined, 1 passed)&quot;, &quot;2 steps (1 undefined, 1 passed)&quot;]
-      @autotest.hook(:ran_command)
+      @autotest.hook(:ran_features)
     end
 
     it &quot;should show an 'error' notification&quot; do
       Autotest::Growl.should_receive(:growl).and_return('error')
       @autotest.results = []
-      @autotest.hook(:ran_command)
+      @autotest.hook(:ran_features)
     end
   end
 end</diff>
      <filename>spec/autotest-growl_spec.rb</filename>
    </modified>
  </modified>
  <removed type="array"/>
  <parents type="array">
    <parent>
      <id>fccc79e101766ff122f09466304fc7e0b3467ced</id>
    </parent>
  </parents>
  <author>
    <name>Sven Schwyn</name>
    <email>schwyn@bitcetera.com</email>
  </author>
  <url>http://github.com/svoop/autotest-growl/commit/78d0e6bbce1dc3d1ff89f2133da92de2cb701632</url>
  <id>78d0e6bbce1dc3d1ff89f2133da92de2cb701632</id>
  <committed-date>2009-07-23T06:41:20-07:00</committed-date>
  <authored-date>2009-07-23T06:41:20-07:00</authored-date>
  <message>Better notificatios, fix Cucumber, add one_notification_per_run, small things.</message>
  <tree>0f3da90747ec54f88114abac0940afebe75f4b32</tree>
  <committer>
    <name>Sven Schwyn</name>
    <email>schwyn@bitcetera.com</email>
  </committer>
</commit>
