cuukie 0.1.3 → 0.1.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -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