cuukie 0.1.3 → 0.1.4

Sign up to get free protection for your applications and to get access to all the features.
@@ -2,4 +2,3 @@ rvm:
2
2
  - 1.8.7
3
3
  - 1.9.2
4
4
  - 1.9.3
5
- - rbx-2.0
data/Gemfile CHANGED
@@ -3,6 +3,7 @@ source :rubygems
3
3
  gem 'sinatra'
4
4
  gem 'rest-client'
5
5
  gem 'cucumber'
6
+ gem 'syntax'
6
7
 
7
8
  group :development do
8
9
  gem 'rake'
@@ -16,7 +16,11 @@ Require Cuukie from any file in your _features/support_ directory:
16
16
 
17
17
  require 'cuukie'
18
18
 
19
- Start the Cuukie server from a terminal window and leave it running:
19
+ Add this line to any Ruby file in your _features/support_ directory:
20
+
21
+ require 'cuukie'
22
+
23
+ Start the Cuukie server from a terminal window:
20
24
 
21
25
  cuukie_server
22
26
 
@@ -44,4 +48,4 @@ Right now, Cuukie is not any more useful than Cucumber's own HTML formatter. My
44
48
 
45
49
  ## License
46
50
 
47
- MIT License. Copyright (c) 2011 Paolo "Nusco" Perrotta.
51
+ MIT License. Copyright (c) 2011 Paolo "Nusco" Perrotta. I ripped a few lines of code off Cucumber's HTML formatter.
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.1.3
1
+ 0.1.4
@@ -5,11 +5,11 @@
5
5
 
6
6
  Gem::Specification.new do |s|
7
7
  s.name = "cuukie"
8
- s.version = "0.1.3"
8
+ s.version = "0.1.4"
9
9
 
10
10
  s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
11
  s.authors = ["Paolo \"Nusco\" Perrotta"]
12
- s.date = "2011-12-07"
12
+ s.date = "2011-12-08"
13
13
  s.description = "Shows Cucumber results on a web page as they run."
14
14
  s.email = "paolo.nusco.perrotta@gmail.com"
15
15
  s.executables = ["cuukie_server"]
@@ -30,21 +30,23 @@ Gem::Specification.new do |s|
30
30
  "doc/backlog.txt",
31
31
  "doc/pomodoro.txt",
32
32
  "lib/cuukie.rb",
33
+ "lib/cuukie/cucumber/formatter/code_snippets.rb",
33
34
  "lib/cuukie/cucumber/formatter/cuukie.rb",
34
35
  "lib/cuukie/public/cucumber.css",
35
36
  "lib/cuukie/public/cuukie.js",
36
37
  "lib/cuukie/public/jquery-1.7.min.js",
37
38
  "lib/cuukie/server.rb",
38
39
  "lib/cuukie/views/index.erb",
39
- "lib/test.rb",
40
+ "spec/code_snippets_spec.rb",
40
41
  "spec/commands_spec.rb",
41
42
  "spec/cuukie_spec.rb",
42
43
  "spec/spec_helper.rb",
43
44
  "spec/test_project/features/1_show_scenarios.feature",
44
- "spec/test_project/features/2_multiple_features.feature",
45
+ "spec/test_project/features/2_show_multiline_args.feature",
45
46
  "spec/test_project/features/3_failed_background.feature",
46
- "spec/test_project/features/4_show_multiline_args.feature",
47
- "spec/test_project/features/step_definitions/example_steps.rb",
47
+ "spec/test_project/features/4_exception_with_no_source.feature",
48
+ "spec/test_project/features/step_definitions/exception_steps.rb",
49
+ "spec/test_project/features/step_definitions/main_steps.rb",
48
50
  "spec/test_project/features/support/formatters.rb"
49
51
  ]
50
52
  s.homepage = "http://github.com/nusco/cuukie"
@@ -60,12 +62,14 @@ Gem::Specification.new do |s|
60
62
  s.add_runtime_dependency(%q<sinatra>, [">= 0"])
61
63
  s.add_runtime_dependency(%q<rest-client>, [">= 0"])
62
64
  s.add_runtime_dependency(%q<cucumber>, [">= 0"])
65
+ s.add_runtime_dependency(%q<syntax>, [">= 0"])
63
66
  s.add_development_dependency(%q<rake>, [">= 0"])
64
67
  s.add_development_dependency(%q<jeweler>, [">= 0"])
65
68
  else
66
69
  s.add_dependency(%q<sinatra>, [">= 0"])
67
70
  s.add_dependency(%q<rest-client>, [">= 0"])
68
71
  s.add_dependency(%q<cucumber>, [">= 0"])
72
+ s.add_dependency(%q<syntax>, [">= 0"])
69
73
  s.add_dependency(%q<rake>, [">= 0"])
70
74
  s.add_dependency(%q<jeweler>, [">= 0"])
71
75
  end
@@ -73,6 +77,7 @@ Gem::Specification.new do |s|
73
77
  s.add_dependency(%q<sinatra>, [">= 0"])
74
78
  s.add_dependency(%q<rest-client>, [">= 0"])
75
79
  s.add_dependency(%q<cucumber>, [">= 0"])
80
+ s.add_dependency(%q<syntax>, [">= 0"])
76
81
  s.add_dependency(%q<rake>, [">= 0"])
77
82
  s.add_dependency(%q<jeweler>, [">= 0"])
78
83
  end
@@ -1,15 +1,13 @@
1
- MMF 0.4
2
- - show exceptions
3
- - show code snippets
4
- MMF 0.5
1
+ MMF 0.1.5
5
2
  - show incomplete suite
6
3
  - show undefined Scenarios/suite
7
4
  - show undefined Steps
8
5
  - show incomplete wrap-up for steps/scenarios
9
6
  - show incomplete running time
10
- MMF 0.6
7
+ MMF 0.1.6
11
8
  - deal with Scenario Examples
12
- MMF 1.0
9
+ - open/close steps
10
+ MMF 1.0.0
13
11
  - nice graphics
14
12
  - self-updating Steps
15
13
  - self-updating Scenarios
@@ -24,6 +22,12 @@ Then...
24
22
 
25
23
  - filter by tag
26
24
 
25
+ - instead of showing scenarios that appear one by one,
26
+ show the entire suite ASAP, and then proceed to make
27
+ each scenario red or green (or whatever). this
28
+ gives an immediate feeling of where you are in the
29
+ suite.
30
+
27
31
  - show status for each table row (table rows have an
28
32
  associated status in Cucumber formatters, and the
29
33
  HTML formatter seems to take advantage of this. Why?
@@ -41,4 +45,6 @@ Then...
41
45
  lines for steps than other rubies. I removed the line
42
46
  numbers from tests b/c of this, and b/c they made the
43
47
  tests fragile. Try to put back the line numbers,
44
- and test under rbx)
48
+ and test under rbx)
49
+
50
+ - test against rbx
@@ -1,6 +1,20 @@
1
1
  I use this file to track my own work on the project. Each line is a pomodoro (a 25' slot).
2
2
  Latest pomodoro comes first:
3
3
 
4
+ - show code snippets (and release 0.1.4)
5
+ - show code snippets
6
+ - show code snippets
7
+ - show code snippets
8
+ - show code snippets
9
+ - show code snippets
10
+ - code snippet reader
11
+ - code snippet reader
12
+ - code snippet reader
13
+ - code snippet reader
14
+ - code snippet reader
15
+ - "fix" Travis build (i.e. remove rbx)
16
+ - show exception backtraces
17
+ - show exception messages
4
18
  - run formatter with custom server
5
19
  - run formatter with custom server
6
20
  - run server on custom port
@@ -0,0 +1,23 @@
1
+ module Cuukie
2
+ module CodeSnippets
3
+ NULL_SNIPPET = Hash.new
4
+
5
+ def code_snippet(file, line)
6
+ return NULL_SNIPPET unless File.exist? file
7
+
8
+ all_lines = File.open(file) {|f| f.readlines}
9
+ return NULL_SNIPPET unless line <= all_lines.size
10
+
11
+ first_line = [1, line - 2].max
12
+
13
+ {:first_line => first_line,
14
+ :marked_line => line,
15
+ :raw_lines => all_lines[(first_line - 1)..line].join }
16
+ end
17
+
18
+ def backtrace_to_snippet(backtrace)
19
+ return NULL_SNIPPET unless backtrace[0] =~ /(.*):(\d+)/
20
+ code_snippet $1, $2.to_i
21
+ end
22
+ end
23
+ end
@@ -1,9 +1,12 @@
1
+ require "#{File.dirname(__FILE__)}/code_snippets"
1
2
  require 'rest-client'
2
3
  require 'json'
3
4
 
4
5
  module Cucumber
5
6
  module Formatter
6
7
  class Cuukie
8
+ include ::Cuukie::CodeSnippets
9
+
7
10
  def initialize(step_mother, path_or_io, options)
8
11
  @server = ENV['CUUKIE_SERVER'] || 'http://localhost:4569'
9
12
  ping
@@ -18,25 +21,33 @@ module Cucumber
18
21
  end
19
22
 
20
23
  def before_feature(feature)
21
- # TODO: use symbols as hash keys?
22
- post 'before_feature', { 'short_name' => feature.short_name,
23
- 'description' => feature.description }
24
+ post 'before_feature', { :short_name => feature.short_name,
25
+ :description => feature.description }
24
26
  end
25
27
 
26
28
  def scenario_name(keyword, name, file_colon_line, source_indent)
27
- post 'scenario_name', { 'keyword' => keyword,
28
- 'name' => name,
29
- 'file_colon_line' => file_colon_line }
29
+ post 'scenario_name', { :keyword => keyword,
30
+ :name => name,
31
+ :file_colon_line => file_colon_line }
30
32
  end
31
33
 
32
34
  def before_step_result(keyword, step_match, multiline_arg, status, exception, source_indent, background)
33
- post 'before_step_result', { 'keyword' => keyword,
34
- 'name' => step_match.format_args,
35
- 'file_colon_line' => step_match.file_colon_line }
35
+ post 'before_step_result', { :keyword => keyword,
36
+ :name => step_match.format_args,
37
+ :file_colon_line => step_match.file_colon_line }
36
38
  end
37
39
 
40
+ def exception(exception, status)
41
+ source = backtrace_to_snippet(exception.backtrace)
42
+ post 'exception', { :message => exception.message,
43
+ :backtrace => exception.backtrace.join('\n'),
44
+ :first_line => source[:first_line],
45
+ :marked_line => source[:marked_line],
46
+ :raw_lines => source[:raw_lines] }
47
+ end
48
+
38
49
  def after_step_result(keyword, step_match, multiline_arg, status, exception, source_indent, background)
39
- post 'after_step_result', { 'status' => status }
50
+ post 'after_step_result', { :status => status }
40
51
  end
41
52
 
42
53
  def after_steps(*)
@@ -48,15 +59,15 @@ module Cucumber
48
59
  end
49
60
 
50
61
  def table_cell_value(value, status)
51
- post 'table_cell_value', { 'value' => value }
62
+ post 'table_cell_value', { :value => value }
52
63
  end
53
64
 
54
65
  def doc_string(string)
55
- post 'doc_string', { 'multiline_string' => string }
66
+ post 'doc_string', { :multiline_string => string }
56
67
  end
57
68
 
58
69
  def after_features(features)
59
- post 'after_features', { 'duration' => features.duration }
70
+ post 'after_features', { :duration => features.duration }
60
71
  end
61
72
 
62
73
  private
@@ -1,12 +1,13 @@
1
1
  require 'sinatra/base'
2
2
  require 'json'
3
+ require 'syntax/convertors/html'
3
4
 
4
5
  module Cuukie
5
6
  class Server < Sinatra::Base
6
- set :features, []
7
- set :build_status, nil
8
- set :stats, {:scenarios => '', :steps => ''}
9
- set :duration, '?'
7
+ set :features, []
8
+ set :build_status, nil
9
+ set :duration, '?'
10
+ set :stats, {:scenarios => '', :steps => ''}
10
11
 
11
12
  get '/' do
12
13
  @features = settings.features
@@ -48,6 +49,11 @@ module Cuukie
48
49
  'OK'
49
50
  end
50
51
 
52
+ post '/exception' do
53
+ current_step['exception'] = read_from_request
54
+ 'OK'
55
+ end
56
+
51
57
  post '/after_step_result' do
52
58
  current_step.merge! read_from_request
53
59
  if current_step['status'] == 'failed'
@@ -96,6 +102,22 @@ module Cuukie
96
102
  get('/ping') { 'pong!' }
97
103
  delete('/') { exit! }
98
104
 
105
+ helpers do
106
+ def snippet(exception)
107
+ return '' unless exception['raw_lines']
108
+ result = '<pre class="ruby"><code>'
109
+ linenum = exception['first_line']
110
+ html_lines = htmlize(exception['raw_lines']).split "\n"
111
+ html_lines.each do |html_line|
112
+ line = "<span class=\"linenum\">#{linenum}</span>#{html_line}"
113
+ line = "<span class=\"offending\">#{line}</span>" if linenum == exception['marked_line']
114
+ result << "#{line}<br/>"
115
+ linenum += 1
116
+ end
117
+ result << '</code></pre>'
118
+ end
119
+ end
120
+
99
121
  def current_feature
100
122
  settings.features.last
101
123
  end
@@ -129,7 +151,6 @@ module Cuukie
129
151
  result
130
152
  end
131
153
 
132
- # shamelessly ripped from Cucumber's HTML formatter
133
154
  def counts(elements)
134
155
  counts = ['failed', 'skipped', 'undefined', 'pending', 'passed'].map do |status|
135
156
  selected = elements.find_all {|element| element['status'] == status }
@@ -138,16 +159,23 @@ module Cuukie
138
159
  counts.any? ? " (#{counts.join(', ')})" : ''
139
160
  end
140
161
 
141
- # also shamelessly ripped from Cucumber's HTML formatter
142
- def dump_count(count, what, state=nil)
143
- [count, state, "#{what}#{count == 1 ? '' : 's'}"].compact.join(' ')
162
+ def dump_count(count, what)
163
+ "#{count} #{what}#{count == 1 ? '' : 's'}"
144
164
  end
145
165
 
166
+ def htmlize(ruby)
167
+ convertor = Syntax::Convertors::HTML.for_syntax("ruby")
168
+ convertor.convert(ruby, false)
169
+ end
170
+
146
171
  include Rack::Utils
147
172
 
148
173
  def read_from_request
149
- result = JSON.parse request.body.read
150
- result.each {|k, v| result[k] = escape_html v }
174
+ data = JSON.parse request.body.read
175
+ result = data.clone
176
+ result.each do |k, v|
177
+ result[k] = escape_html(v) if v.class == String && k !~ /^raw_/
178
+ end
151
179
  end
152
180
  end
153
- end
181
+ end
@@ -8,6 +8,7 @@
8
8
  </head>
9
9
 
10
10
  <body>
11
+ <!-- header -->
11
12
  <div class="cucumber"><div id="cucumber-header"><div id="label"><h1>Cucumber Features</h1></div>
12
13
  <div id="summary">
13
14
  <p id="stats"></p>
@@ -15,8 +16,13 @@
15
16
  <div id="expand-collapse"><p id="expander">Expand All</p><p id="collapser">Collapse All</p></div>
16
17
  </div>
17
18
  </div>
18
-
19
19
  <script><%= @build_status %>Colors('cucumber-header')</script>
20
+ <script type="text/javascript">
21
+ document.getElementById('duration').innerHTML = "Finished in <strong><%= @duration %> seconds</strong>";
22
+ </script>
23
+ <script type="text/javascript">
24
+ document.getElementById('stats').innerHTML = "<%= @stats[:scenarios] %><br/><%= @stats[:steps] %>";
25
+ </script>
20
26
 
21
27
  <% @features.each do |feature| %>
22
28
  <div class="feature">
@@ -37,6 +43,11 @@
37
43
  <span class="keyword"><%= step['keyword'] %></span><span class="step val"><%= step['name'] %></span>
38
44
  </div>
39
45
  <div class="step_file"><span><%= step['file_colon_line'] %></span></div>
46
+ <% if step['exception'] %>
47
+ <div class="message"><pre><%= step['exception']['message'] %></pre></div>
48
+ <div class="backtrace"><pre><%= step['exception']['backtrace'].gsub('\n', '<br/>') %></pre></div>
49
+ <%= snippet step['exception'] %>
50
+ <% end %>
40
51
  <% unless step['table'].empty? %>
41
52
  <table>
42
53
  <% step['table'].each_with_index do |rowdata, row| %>
@@ -58,12 +69,6 @@
58
69
  <% end %>
59
70
  </div>
60
71
  <% end %>
61
- <script type="text/javascript">
62
- document.getElementById('duration').innerHTML = "Finished in <strong><%= @duration %> seconds</strong>";
63
- </script>
64
- <script type="text/javascript">
65
- document.getElementById('stats').innerHTML = "<%= @stats[:scenarios] %><br/><%= @stats[:steps] %>";
66
- </script>
67
72
  </div>
68
73
  </body>
69
74
  </html>
@@ -0,0 +1,93 @@
1
+ require 'cuukie/cucumber/formatter/code_snippets'
2
+ require 'tempfile'
3
+
4
+ describe "The code_snippet method" do
5
+ include Cuukie::CodeSnippets
6
+
7
+ before(:all) do
8
+ @source = Tempfile.new('source.rb')
9
+ @source.write <<SOURCE
10
+ # line one
11
+ line_two = 2
12
+ line_three()
13
+ line_four.each do |x|
14
+ x.line_five
15
+ end # line six
16
+ SOURCE
17
+ @source.close
18
+ end
19
+
20
+ after(:all) do
21
+ @source.delete
22
+ end
23
+
24
+ it "has a marked line number" do
25
+ snippet = code_snippet @source.path, 4
26
+ snippet[:marked_line].should == 4
27
+ end
28
+
29
+ it "returns a nil snippet if it cannot find the file" do
30
+ snippet = code_snippet 'no_such_file.txt', 4
31
+ snippet['lines'].should be_nil
32
+ end
33
+
34
+ it "returns nil if the file is not valid" do
35
+ snippet = code_snippet '', 4
36
+ snippet['lines'].should be_nil
37
+ end
38
+
39
+ it "returns nil if it cannot find the line" do
40
+ snippet = code_snippet @source.path, 7
41
+ snippet['lines'].should be_nil
42
+ end
43
+
44
+ it "returns a snippet of the lines around the marked line" do
45
+ snippet = code_snippet @source.path, 5
46
+ snippet[:raw_lines].should == "line_three()\nline_four.each do |x|\n x.line_five\nend # line six\n"
47
+ end
48
+
49
+ it "has a first line number" do
50
+ snippet = code_snippet @source.path, 5
51
+ snippet[:first_line].should == 3
52
+ end
53
+
54
+ it "clips lines at the beginning of the file" do
55
+ snippet = code_snippet @source.path, 2
56
+ snippet[:raw_lines].should == "# line one\nline_two = 2\nline_three()\n"
57
+ snippet[:first_line].should == 1
58
+ end
59
+
60
+ it "clips lines at the end of the file" do
61
+ snippet = code_snippet @source.path, 6
62
+ snippet[:raw_lines].should == "line_four.each do |x|\n x.line_five\nend # line six\n"
63
+ snippet[:first_line].should == 4
64
+ end
65
+ end
66
+
67
+ describe "The backtrace_to_snippet method" do
68
+ include Cuukie::CodeSnippets
69
+
70
+ it "extracts file and line from a backtrace" do
71
+ source = Tempfile.new('source.rb')
72
+ source.write <<SOURCE
73
+ # one
74
+ # two
75
+ 1 / 0
76
+ # four
77
+ SOURCE
78
+ source.close
79
+ begin
80
+ load source.path
81
+ rescue Exception => e
82
+ backtrace_to_snippet(e.backtrace).should == {:first_line => 1,
83
+ :marked_line => 3,
84
+ :raw_lines => "# one\n# two\n1 / 0\n# four\n"}
85
+ ensure
86
+ source.delete
87
+ end
88
+ end
89
+
90
+ it "returns nil if the extraction fails" do
91
+ backtrace_to_snippet(['abcd'])['lines'].should be_nil
92
+ end
93
+ end
@@ -31,7 +31,7 @@ describe "The cuukie formatter" do
31
31
  wait_for_server_on_port 4569
32
32
  cmd = "cd spec/test_project && \
33
33
  cucumber features/1_show_scenarios.feature:9 \
34
- --format cuukie > #{@out.path}"
34
+ --format cuukie > #{@out.path}"
35
35
  system(cmd).should be_true
36
36
  @out.read.should == ''
37
37
  ensure
@@ -45,8 +45,8 @@ describe "The cuukie formatter" do
45
45
  wait_for_server_on_port 4570
46
46
  cmd = "cd spec/test_project && \
47
47
  cucumber features/1_show_scenarios.feature:9 \
48
- CUUKIE_SERVER=http://localhost:4570 \
49
- --format cuukie > #{@out.path}"
48
+ CUUKIE_SERVER=http://localhost:4570 \
49
+ --format cuukie > #{@out.path}"
50
50
  system(cmd).should be_true
51
51
  @out.read.should == ''
52
52
  ensure
@@ -57,8 +57,8 @@ describe "The cuukie formatter" do
57
57
  it "fails gracefully if the server is down" do
58
58
  cmd = "cd spec/test_project && \
59
59
  cucumber features/1_show_scenarios.feature:9 \
60
- CUUKIE_SERVER=http://some.server:4570 \
61
- --format cuukie > #{@out.path}"
60
+ CUUKIE_SERVER=http://some.server:4570 \
61
+ --format cuukie > #{@out.path}"
62
62
  system(cmd).should be_true
63
63
  @out.read.should match 'I cannot find the cuukie_server on http://some.server:4570'
64
64
  end
@@ -4,29 +4,6 @@ describe 'Cuukie' do
4
4
  before(:all) { start_server }
5
5
  after(:all) { stop_server_on_port 4569 }
6
6
 
7
- describe 'shows suite result at the top of the page' do
8
- it "contains essential information" do
9
- run_cucumber
10
- html.should match '<h1>Cucumber Features</h1>'
11
- html.should match '<title>Cuukie</title>'
12
- end
13
-
14
- it "shows green if all scenarios passed" do
15
- run_cucumber '1_show_scenarios.feature:9'
16
- html.should match /passedColors\('cucumber-header'\)/
17
- end
18
-
19
- it "shows red if any scenario failed" do
20
- run_cucumber '1_show_scenarios.feature'
21
- html.should match /failedColors\('cucumber-header'\)/
22
- end
23
-
24
- it "shows yellow if no scenarios failed but some are pending" do
25
- run_cucumber '1_show_scenarios.feature:19'
26
- html.should match /pendingColors\('cucumber-header'\)/
27
- end
28
- end
29
-
30
7
  describe 'in the content area' do
31
8
  before(:all) { run_cucumber }
32
9
 
@@ -37,7 +14,7 @@ describe 'Cuukie' do
37
14
 
38
15
  it "shows the feature names" do
39
16
  html.should match '>Feature: Visualize Scenarios<'
40
- html.should match '>Feature: Multiple Features<'
17
+ html.should match '>Feature: Show Failed Background<'
41
18
  end
42
19
 
43
20
  it "shows the feature narratives" do
@@ -77,14 +54,32 @@ describe 'Cuukie' do
77
54
  end
78
55
 
79
56
  it "shows the step source position" do
80
- html.should match '>features&#x2F;step_definitions&#x2F;example_steps.rb:'
57
+ html.should match '>features&#x2F;step_definitions&#x2F;main_steps.rb:'
81
58
  end
82
59
 
83
60
  it "shows the step status" do
84
61
  html.should match 'class="step passed"'
85
62
  html.should match 'class="step pending"'
86
63
  end
87
-
64
+
65
+ it "shows exception messages" do
66
+ html.should match /main_steps.rb:7<\/span><\/div>[ \n]*<div class="message"><pre>Crash!<\/pre><\/div>/
67
+ end
68
+
69
+ it "shows exception backtraces" do
70
+ html.should match 'backtrace"><pre>.&#x2F;features&#x2F;step_definitions&#x2F;main_steps.rb:8:in `&#x2F;I do'
71
+ html.should match '3_failed_background.feature:7:in `Given I do'
72
+ end
73
+
74
+ it "shows exception source snippets" do
75
+ html.should match '<pre class="ruby"><code><span class="linenum">6<\/span>'
76
+ html.should match '<span class="constant">I</span> <span class="keyword">do</span> <span class="ident">something'
77
+ end
78
+
79
+ it "marks the exception source in snippets" do
80
+ html.should match '<span class="offending"><span class="linenum">8<\/span> <span class=\"keyword\">raise'
81
+ end
82
+
88
83
  it "escapes HTML output" do
89
84
  html.should match 'I pass an &quot;argument&quot;'
90
85
  end
@@ -108,4 +103,27 @@ describe 'Cuukie' do
108
103
  html.should match /11 steps \(1 failed, 2 skipped, 1 pending, 7 passed\)/
109
104
  end
110
105
  end
106
+
107
+ describe 'in the page header' do
108
+ it "contains essential information" do
109
+ run_cucumber
110
+ html.should match '<h1>Cucumber Features</h1>'
111
+ html.should match '<title>Cuukie</title>'
112
+ end
113
+
114
+ it "shows green if all scenarios passed" do
115
+ run_cucumber '1_show_scenarios.feature:9'
116
+ html.should match /passedColors\('cucumber-header'\)/
117
+ end
118
+
119
+ it "shows red if any scenario failed" do
120
+ run_cucumber '1_show_scenarios.feature'
121
+ html.should match /failedColors\('cucumber-header'\)/
122
+ end
123
+
124
+ it "shows yellow if no scenarios failed but some are pending" do
125
+ run_cucumber '1_show_scenarios.feature:19'
126
+ html.should match /pendingColors\('cucumber-header'\)/
127
+ end
128
+ end
111
129
  end
@@ -18,6 +18,10 @@ require 'rest-client'
18
18
  end
19
19
  end
20
20
 
21
+ def html
22
+ GET('/').body
23
+ end
24
+
21
25
  def start_server
22
26
  start_process "ruby bin/cuukie_server >/dev/null 2>&1"
23
27
  wait_for_server_on_port 4569
@@ -37,7 +41,3 @@ def stop_server_on_port(port)
37
41
  RestClient.delete "http://localhost:#{port}/"
38
42
  rescue
39
43
  end
40
-
41
- def html
42
- GET('/').body
43
- end
@@ -0,0 +1,16 @@
1
+ Feature: Exception with no source
2
+ As a Cuker
3
+ I want to visualize exceptions even if I cannot retrieve the code
4
+ So that I can still use Cuukie when the source is on another machine
5
+
6
+ Scenario: Exception with unknown file
7
+ When I get an exception referencing a file that doesn't exist
8
+ Then Cuukie should be OK with it
9
+
10
+ Scenario: Exception with wrong line
11
+ When I get an exception referencing a line that doesn't exist
12
+ Then Cuukie should be OK with it
13
+
14
+ Scenario: Exception with mangled backtrace
15
+ When I get an exception and I cannot even tell which file and line it's from
16
+ Then Cuukie should be OK with it
@@ -0,0 +1,26 @@
1
+ When /^I get an exception referencing a file that doesn't exist$/ do
2
+ begin
3
+ 1 / 0
4
+ rescue Exception => e
5
+ e.backtrace[0].gsub! File.dirname(__FILE__), 'no_such_directory'
6
+ raise e
7
+ end
8
+ end
9
+
10
+ When /^I get an exception referencing a line that doesn't exist$/ do
11
+ begin
12
+ 1 / 0
13
+ rescue Exception => e
14
+ e.backtrace[0].gsub! /:[\d]+:/, ':10000:'
15
+ raise e
16
+ end
17
+ end
18
+
19
+ When /^I get an exception and I cannot even tell which file and line it's from$/ do
20
+ begin
21
+ 1 / 0
22
+ rescue Exception => e
23
+ e.backtrace[0].gsub! /:(.*):/, 'mangle mangle'
24
+ raise e
25
+ end
26
+ end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: cuukie
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.3
4
+ version: 0.1.4
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,11 +9,11 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2011-12-07 00:00:00.000000000 Z
12
+ date: 2011-12-08 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: sinatra
16
- requirement: &70255289550100 !ruby/object:Gem::Requirement
16
+ requirement: &70339163759300 !ruby/object:Gem::Requirement
17
17
  none: false
18
18
  requirements:
19
19
  - - ! '>='
@@ -21,10 +21,10 @@ dependencies:
21
21
  version: '0'
22
22
  type: :runtime
23
23
  prerelease: false
24
- version_requirements: *70255289550100
24
+ version_requirements: *70339163759300
25
25
  - !ruby/object:Gem::Dependency
26
26
  name: rest-client
27
- requirement: &70255289549480 !ruby/object:Gem::Requirement
27
+ requirement: &70339163757860 !ruby/object:Gem::Requirement
28
28
  none: false
29
29
  requirements:
30
30
  - - ! '>='
@@ -32,10 +32,10 @@ dependencies:
32
32
  version: '0'
33
33
  type: :runtime
34
34
  prerelease: false
35
- version_requirements: *70255289549480
35
+ version_requirements: *70339163757860
36
36
  - !ruby/object:Gem::Dependency
37
37
  name: cucumber
38
- requirement: &70255289548840 !ruby/object:Gem::Requirement
38
+ requirement: &70339163755420 !ruby/object:Gem::Requirement
39
39
  none: false
40
40
  requirements:
41
41
  - - ! '>='
@@ -43,10 +43,21 @@ dependencies:
43
43
  version: '0'
44
44
  type: :runtime
45
45
  prerelease: false
46
- version_requirements: *70255289548840
46
+ version_requirements: *70339163755420
47
+ - !ruby/object:Gem::Dependency
48
+ name: syntax
49
+ requirement: &70339163753560 !ruby/object:Gem::Requirement
50
+ none: false
51
+ requirements:
52
+ - - ! '>='
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
55
+ type: :runtime
56
+ prerelease: false
57
+ version_requirements: *70339163753560
47
58
  - !ruby/object:Gem::Dependency
48
59
  name: rake
49
- requirement: &70255289548080 !ruby/object:Gem::Requirement
60
+ requirement: &70339163760240 !ruby/object:Gem::Requirement
50
61
  none: false
51
62
  requirements:
52
63
  - - ! '>='
@@ -54,10 +65,10 @@ dependencies:
54
65
  version: '0'
55
66
  type: :development
56
67
  prerelease: false
57
- version_requirements: *70255289548080
68
+ version_requirements: *70339163760240
58
69
  - !ruby/object:Gem::Dependency
59
70
  name: jeweler
60
- requirement: &70255289547420 !ruby/object:Gem::Requirement
71
+ requirement: &70339163758480 !ruby/object:Gem::Requirement
61
72
  none: false
62
73
  requirements:
63
74
  - - ! '>='
@@ -65,7 +76,7 @@ dependencies:
65
76
  version: '0'
66
77
  type: :development
67
78
  prerelease: false
68
- version_requirements: *70255289547420
79
+ version_requirements: *70339163758480
69
80
  description: Shows Cucumber results on a web page as they run.
70
81
  email: paolo.nusco.perrotta@gmail.com
71
82
  executables:
@@ -87,21 +98,23 @@ files:
87
98
  - doc/backlog.txt
88
99
  - doc/pomodoro.txt
89
100
  - lib/cuukie.rb
101
+ - lib/cuukie/cucumber/formatter/code_snippets.rb
90
102
  - lib/cuukie/cucumber/formatter/cuukie.rb
91
103
  - lib/cuukie/public/cucumber.css
92
104
  - lib/cuukie/public/cuukie.js
93
105
  - lib/cuukie/public/jquery-1.7.min.js
94
106
  - lib/cuukie/server.rb
95
107
  - lib/cuukie/views/index.erb
96
- - lib/test.rb
108
+ - spec/code_snippets_spec.rb
97
109
  - spec/commands_spec.rb
98
110
  - spec/cuukie_spec.rb
99
111
  - spec/spec_helper.rb
100
112
  - spec/test_project/features/1_show_scenarios.feature
101
- - spec/test_project/features/2_multiple_features.feature
113
+ - spec/test_project/features/2_show_multiline_args.feature
102
114
  - spec/test_project/features/3_failed_background.feature
103
- - spec/test_project/features/4_show_multiline_args.feature
104
- - spec/test_project/features/step_definitions/example_steps.rb
115
+ - spec/test_project/features/4_exception_with_no_source.feature
116
+ - spec/test_project/features/step_definitions/exception_steps.rb
117
+ - spec/test_project/features/step_definitions/main_steps.rb
105
118
  - spec/test_project/features/support/formatters.rb
106
119
  homepage: http://github.com/nusco/cuukie
107
120
  licenses:
@@ -118,7 +131,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
118
131
  version: '0'
119
132
  segments:
120
133
  - 0
121
- hash: -2321068096290706559
134
+ hash: -2459400379263552476
122
135
  required_rubygems_version: !ruby/object:Gem::Requirement
123
136
  none: false
124
137
  requirements:
File without changes
@@ -1,8 +0,0 @@
1
- Feature: Multiple Features
2
- As a Cuker
3
- I want to see multiple Features
4
- So that I can check my entire suite
5
-
6
- Scenario: One Simple Step
7
- Given I do something
8
- Then I should see stuff