spektacular 0.0.2 → 0.1.3
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.
- data/README.md +2 -2
- data/VERSION +1 -1
- data/lib/spektacular/html_formatter.rb +410 -0
- data/lib/spektacular.rb +331 -345
- data/spektacular.gemspec +3 -2
- metadata +5 -4
data/README.md
CHANGED
@@ -6,7 +6,7 @@ In order to install this gem:
|
|
6
6
|
|
7
7
|
Make sure to add the gem to the Gemfile file located in your project directory:
|
8
8
|
|
9
|
-
gem 'spektacular'
|
9
|
+
gem 'spektacular', '0.1.3'
|
10
10
|
|
11
11
|
## Usage ##
|
12
12
|
|
@@ -32,4 +32,4 @@ This will create a new _index.html_ file in the root of your project directory.
|
|
32
32
|
|
33
33
|
## Copyright ##
|
34
34
|
|
35
|
-
Copyright (c) 2010
|
35
|
+
Copyright (c) 2010 Daniel Salmerón Amselem. See LICENSE for details.
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.
|
1
|
+
0.1.3
|
@@ -0,0 +1,410 @@
|
|
1
|
+
require 'erb'
|
2
|
+
require 'rspec/core/formatters/base_text_formatter'
|
3
|
+
|
4
|
+
module RSpec
|
5
|
+
module Core
|
6
|
+
module Formatters
|
7
|
+
class HtmlFormatter < BaseTextFormatter
|
8
|
+
include ERB::Util # for the #h method
|
9
|
+
|
10
|
+
def initialize(output)
|
11
|
+
super(output)
|
12
|
+
@group_level = 0
|
13
|
+
end
|
14
|
+
|
15
|
+
def start(example_count)
|
16
|
+
super(example_count)
|
17
|
+
output.puts html_header
|
18
|
+
output.puts report_header
|
19
|
+
end
|
20
|
+
|
21
|
+
def current_indentation
|
22
|
+
' ' * @group_level
|
23
|
+
end
|
24
|
+
|
25
|
+
def example_group_started(example_group)
|
26
|
+
super(example_group)
|
27
|
+
|
28
|
+
output.puts if @group_level == 0
|
29
|
+
output.puts "#{current_indentation}<div class='group_#{@group_level}'>"
|
30
|
+
output.puts "#{current_indentation}<div class='description'>#{example_group.description}</div>"
|
31
|
+
|
32
|
+
@group_level += 1
|
33
|
+
end
|
34
|
+
|
35
|
+
def example_group_finished(example_group)
|
36
|
+
@group_level -= 1
|
37
|
+
output.puts "#{current_indentation}</div>"
|
38
|
+
end
|
39
|
+
|
40
|
+
def example_passed(example)
|
41
|
+
super(example)
|
42
|
+
output.puts "#{current_indentation}<div class='passed level_#{@group_level}'>#{example.description}</div>"
|
43
|
+
end
|
44
|
+
|
45
|
+
def example_failed(example)
|
46
|
+
super(example)
|
47
|
+
output.puts "#{current_indentation}<div class='failed level_#{@group_level}'>#{example.description} (FAILED - #{next_failure_index})</div>"
|
48
|
+
end
|
49
|
+
|
50
|
+
def example_pending(example)
|
51
|
+
super(example)
|
52
|
+
output.puts "#{current_indentation}<div class='pending level_#{@group_level}'>#{example.description} (PENDING - #{example.execution_result[:pending_message]})</div>"
|
53
|
+
end
|
54
|
+
|
55
|
+
def next_failure_index
|
56
|
+
@next_failure_index ||= 0
|
57
|
+
@next_failure_index += 1
|
58
|
+
end
|
59
|
+
|
60
|
+
def example_group_chain
|
61
|
+
example_group.ancestors.reverse
|
62
|
+
end
|
63
|
+
|
64
|
+
def dump_pending
|
65
|
+
|
66
|
+
end
|
67
|
+
|
68
|
+
def dump_failures
|
69
|
+
|
70
|
+
end
|
71
|
+
|
72
|
+
def dump_summary(duration, example_count, failure_count, pending_count)
|
73
|
+
output.puts "</body>"
|
74
|
+
output.puts "</html>"
|
75
|
+
end
|
76
|
+
|
77
|
+
def html_header
|
78
|
+
<<-EOF
|
79
|
+
<?xml version="1.0" encoding="UTF-8"?>
|
80
|
+
<!DOCTYPE html
|
81
|
+
PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
|
82
|
+
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
|
83
|
+
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
|
84
|
+
<head>
|
85
|
+
<title>RSpec results</title>
|
86
|
+
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
|
87
|
+
<meta http-equiv="Expires" content="-1" />
|
88
|
+
<meta http-equiv="Pragma" content="no-cache" />
|
89
|
+
<link rel="stylesheet" href="style.css">
|
90
|
+
|
91
|
+
<script type="text/javascript">
|
92
|
+
// <![CDATA[
|
93
|
+
#{global_scripts}
|
94
|
+
// ]]>
|
95
|
+
</script>
|
96
|
+
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.4.2/jquery.min.js"></script>
|
97
|
+
<script type="text/javascript">
|
98
|
+
// <![CDATA[
|
99
|
+
#{jquery_scripts}
|
100
|
+
// ]]>
|
101
|
+
</script>
|
102
|
+
<style type="text/css">
|
103
|
+
#{global_styles}
|
104
|
+
</style>
|
105
|
+
</head>
|
106
|
+
<body>
|
107
|
+
EOF
|
108
|
+
end
|
109
|
+
|
110
|
+
def report_header
|
111
|
+
<<-EOF
|
112
|
+
<div class="rspec-report">
|
113
|
+
|
114
|
+
<div id="rspec-header">
|
115
|
+
<div id="label">
|
116
|
+
<h1>RSpec Code Examples</h1>
|
117
|
+
</div>
|
118
|
+
|
119
|
+
<div id="summary">
|
120
|
+
<p id="totals"> </p>
|
121
|
+
<p id="duration"> </p>
|
122
|
+
</div>
|
123
|
+
</div>
|
124
|
+
|
125
|
+
<div class="results">
|
126
|
+
<a id="toogle" href="#">Collapse</a>
|
127
|
+
EOF
|
128
|
+
end
|
129
|
+
|
130
|
+
def jquery_scripts
|
131
|
+
<<-EOF
|
132
|
+
function findLastId(){
|
133
|
+
var i = $("dt[id*='example_group']").last().attr("id").split("_")[2];
|
134
|
+
return i;
|
135
|
+
}
|
136
|
+
|
137
|
+
$(document).ready(function(){
|
138
|
+
$("div[class*='group_']").toggle(
|
139
|
+
function () {
|
140
|
+
$(this).children("div[class!='description']").hide();
|
141
|
+
},
|
142
|
+
function () {
|
143
|
+
$(this).children("div[class!='description']").show();
|
144
|
+
}
|
145
|
+
);
|
146
|
+
|
147
|
+
$("#toogle").toggle(
|
148
|
+
function(e){
|
149
|
+
e.preventDefault();
|
150
|
+
$(this).html("Expand");
|
151
|
+
$("div[class*='group_']").children("div[class!='description']").hide();
|
152
|
+
},
|
153
|
+
function(e){
|
154
|
+
e.preventDefault();
|
155
|
+
$(this).html("Collapse");
|
156
|
+
$("div[class*='group_']").children("div[class!='description']").show();
|
157
|
+
}
|
158
|
+
);
|
159
|
+
})
|
160
|
+
EOF
|
161
|
+
end
|
162
|
+
|
163
|
+
def global_scripts
|
164
|
+
<<-EOF
|
165
|
+
function moveProgressBar(percentDone) {
|
166
|
+
document.getElementById("rspec-header").style.width = percentDone +"%";
|
167
|
+
}
|
168
|
+
function makeRed(element_id) {
|
169
|
+
document.getElementById(element_id).style.background = '#C40D0D';
|
170
|
+
document.getElementById(element_id).style.color = '#FFFFFF';
|
171
|
+
}
|
172
|
+
|
173
|
+
function makeYellow(element_id) {
|
174
|
+
if (element_id == "rspec-header" && document.getElementById(element_id).style.background != '#C40D0D')
|
175
|
+
{
|
176
|
+
document.getElementById(element_id).style.background = '#FAF834';
|
177
|
+
document.getElementById(element_id).style.color = '#000000';
|
178
|
+
}
|
179
|
+
else
|
180
|
+
{
|
181
|
+
document.getElementById(element_id).style.background = '#FAF834';
|
182
|
+
document.getElementById(element_id).style.color = '#000000';
|
183
|
+
}
|
184
|
+
}
|
185
|
+
EOF
|
186
|
+
end
|
187
|
+
|
188
|
+
def global_styles
|
189
|
+
<<-EOF
|
190
|
+
#rspec-header {
|
191
|
+
background: #65C400; color: #fff; height: 4em;
|
192
|
+
}
|
193
|
+
|
194
|
+
div.group_0 {
|
195
|
+
margin: 10px 15px 30px 5px;
|
196
|
+
}
|
197
|
+
|
198
|
+
div.group_1 {
|
199
|
+
margin-left: 15px;
|
200
|
+
margin-bottom: 10px;
|
201
|
+
margin-top: 10px;
|
202
|
+
}
|
203
|
+
|
204
|
+
a {
|
205
|
+
color: #445767;
|
206
|
+
}
|
207
|
+
|
208
|
+
#toogle {
|
209
|
+
margin-left: 5px;
|
210
|
+
color: #424242;
|
211
|
+
font-weight: bold;
|
212
|
+
text-transform: uppercase;
|
213
|
+
}
|
214
|
+
|
215
|
+
div.group_2 {
|
216
|
+
margin-left: 15px;
|
217
|
+
margin-bottom: 10px;
|
218
|
+
margin-top: 10px;
|
219
|
+
}
|
220
|
+
|
221
|
+
div.group_3 {
|
222
|
+
margin-left: 15px;
|
223
|
+
margin-bottom: 10px;
|
224
|
+
margin-top: 10px;
|
225
|
+
}
|
226
|
+
|
227
|
+
div.description {
|
228
|
+
font-weight: bold;
|
229
|
+
border-left: 5px solid #00000a;
|
230
|
+
border-bottom: 1px solid #000;
|
231
|
+
color: #000; background: #d5d5d5;
|
232
|
+
padding-left: 5px;
|
233
|
+
}
|
234
|
+
|
235
|
+
div.passed {
|
236
|
+
margin-top: 5px;
|
237
|
+
margin-bottom: 5px;
|
238
|
+
padding-left: 5px;
|
239
|
+
border-left: 5px solid #65C400;
|
240
|
+
border-bottom: 1px solid #65C400;
|
241
|
+
background: #DBFFB4; color: #3D7700;
|
242
|
+
}
|
243
|
+
|
244
|
+
div.failed {
|
245
|
+
margin-top: 5px;
|
246
|
+
margin-bottom: 5px;
|
247
|
+
padding-left: 5px;
|
248
|
+
border-left: 5px solid #C20000;
|
249
|
+
border-bottom: 1px solid #C20000;
|
250
|
+
color: #830705; background: #fa7b7a;
|
251
|
+
}
|
252
|
+
|
253
|
+
div#rspec-header {
|
254
|
+
background-color: #65c400;
|
255
|
+
}
|
256
|
+
|
257
|
+
div.pending {
|
258
|
+
margin-top: 5px;
|
259
|
+
margin-bottom: 5px;
|
260
|
+
padding-left: 5px;
|
261
|
+
border-left: 5px solid #eeef33;
|
262
|
+
border-bottom: 1px solid #FAF834;
|
263
|
+
background: #faffcc; color: #131313;
|
264
|
+
}
|
265
|
+
|
266
|
+
body {
|
267
|
+
font-family: "Lucida Grande", Lucida, Verdana, sans-serif;
|
268
|
+
}
|
269
|
+
|
270
|
+
.level_1 {
|
271
|
+
margin-left: 15px;
|
272
|
+
}
|
273
|
+
|
274
|
+
.level_2 {
|
275
|
+
margin-left: 15px;
|
276
|
+
}
|
277
|
+
|
278
|
+
.level_3 {
|
279
|
+
margin-left: 15px;
|
280
|
+
}
|
281
|
+
|
282
|
+
.level_4 {
|
283
|
+
margin-left: 15px;
|
284
|
+
}
|
285
|
+
|
286
|
+
.rspec-report h1 {
|
287
|
+
margin: 0px 10px 0px 10px;
|
288
|
+
padding: 10px;
|
289
|
+
font-family: "Lucida Grande", Helvetica, sans-serif;
|
290
|
+
font-size: 1.8em;
|
291
|
+
position: absolute;
|
292
|
+
}
|
293
|
+
|
294
|
+
#summary {
|
295
|
+
margin: 0; padding: 5px 10px;
|
296
|
+
font-family: "Lucida Grande", Helvetica, sans-serif;
|
297
|
+
text-align: right;
|
298
|
+
top: 0px;
|
299
|
+
right: 0px;
|
300
|
+
float:right;
|
301
|
+
}
|
302
|
+
|
303
|
+
#summary p {
|
304
|
+
margin: 0 0 0 2px;
|
305
|
+
}
|
306
|
+
|
307
|
+
#summary #totals {
|
308
|
+
font-size: 1.2em;
|
309
|
+
}
|
310
|
+
|
311
|
+
.example_group {
|
312
|
+
margin: 0 10px 5px;
|
313
|
+
background: #fff;
|
314
|
+
}
|
315
|
+
|
316
|
+
dl {
|
317
|
+
margin: 0; padding: 0 0 5px;
|
318
|
+
font: normal 11px "Lucida Grande", Helvetica, sans-serif;
|
319
|
+
}
|
320
|
+
|
321
|
+
dt {
|
322
|
+
padding: 3px;
|
323
|
+
background: #65C400;
|
324
|
+
color: #fff;
|
325
|
+
font-weight: bold;
|
326
|
+
}
|
327
|
+
|
328
|
+
dt.last {
|
329
|
+
margin-left: 10px;
|
330
|
+
}
|
331
|
+
|
332
|
+
dd {
|
333
|
+
margin: 5px 0 5px 25px;
|
334
|
+
padding: 3px 3px 3px 18px;
|
335
|
+
}
|
336
|
+
|
337
|
+
dd.spec.passed {
|
338
|
+
border-left: 5px solid #65C400;
|
339
|
+
border-bottom: 1px solid #65C400;
|
340
|
+
background: #DBFFB4; color: #3D7700;
|
341
|
+
}
|
342
|
+
|
343
|
+
dd.spec.failed {
|
344
|
+
border-left: 5px solid #C20000;
|
345
|
+
border-bottom: 1px solid #C20000;
|
346
|
+
color: #C20000; background: #FFFBD3;
|
347
|
+
}
|
348
|
+
|
349
|
+
dd.spec.not_implemented {
|
350
|
+
border-left: 5px solid #FAF834;
|
351
|
+
border-bottom: 1px solid #FAF834;
|
352
|
+
background: #FCFB98; color: #131313;
|
353
|
+
}
|
354
|
+
|
355
|
+
dd.spec.pending_fixed {
|
356
|
+
border-left: 5px solid #0000C2;
|
357
|
+
border-bottom: 1px solid #0000C2;
|
358
|
+
color: #0000C2; background: #D3FBFF;
|
359
|
+
}
|
360
|
+
|
361
|
+
.backtrace {
|
362
|
+
color: #000;
|
363
|
+
font-size: 12px;
|
364
|
+
}
|
365
|
+
|
366
|
+
a {
|
367
|
+
color: #BE5C00;
|
368
|
+
}
|
369
|
+
|
370
|
+
/* Ruby code, style similar to vibrant ink */
|
371
|
+
.ruby {
|
372
|
+
font-size: 12px;
|
373
|
+
font-family: monospace;
|
374
|
+
color: white;
|
375
|
+
background-color: black;
|
376
|
+
padding: 0.1em 0 0.2em 0;
|
377
|
+
}
|
378
|
+
|
379
|
+
.ruby .keyword { color: #FF6600; }
|
380
|
+
.ruby .constant { color: #339999; }
|
381
|
+
.ruby .attribute { color: white; }
|
382
|
+
.ruby .global { color: white; }
|
383
|
+
.ruby .module { color: white; }
|
384
|
+
.ruby .class { color: white; }
|
385
|
+
.ruby .string { color: #66FF00; }
|
386
|
+
.ruby .ident { color: white; }
|
387
|
+
.ruby .method { color: #FFCC00; }
|
388
|
+
.ruby .number { color: white; }
|
389
|
+
.ruby .char { color: white; }
|
390
|
+
.ruby .comment { color: #9933CC; }
|
391
|
+
.ruby .symbol { color: white; }
|
392
|
+
.ruby .regex { color: #44B4CC; }
|
393
|
+
.ruby .punct { color: white; }
|
394
|
+
.ruby .escape { color: white; }
|
395
|
+
.ruby .interp { color: white; }
|
396
|
+
.ruby .expr { color: white; }
|
397
|
+
|
398
|
+
.ruby .offending { background-color: gray; }
|
399
|
+
.ruby .linenum {
|
400
|
+
width: 75px;
|
401
|
+
padding: 0.1em 1em 0.2em 0;
|
402
|
+
color: #000000;
|
403
|
+
background-color: #FFFBD3;
|
404
|
+
}
|
405
|
+
EOF
|
406
|
+
end
|
407
|
+
end
|
408
|
+
end
|
409
|
+
end
|
410
|
+
end
|
data/lib/spektacular.rb
CHANGED
@@ -7,420 +7,406 @@ module RSpec
|
|
7
7
|
class HtmlFormatter < BaseTextFormatter
|
8
8
|
include ERB::Util # for the #h method
|
9
9
|
|
10
|
-
def method_missing(m, *a, &b)
|
11
|
-
# no-op
|
12
|
-
end
|
13
|
-
|
14
|
-
def message(message)
|
15
|
-
end
|
16
|
-
|
17
10
|
def initialize(output)
|
18
11
|
super(output)
|
19
|
-
@
|
20
|
-
@example_number = 0
|
21
|
-
@header_red = nil
|
22
|
-
end
|
23
|
-
|
24
|
-
# The number of the currently running example_group
|
25
|
-
def example_group_number
|
26
|
-
@example_group_number
|
27
|
-
end
|
28
|
-
|
29
|
-
# The number of the currently running example (a global counter)
|
30
|
-
def example_number
|
31
|
-
@example_number
|
12
|
+
@group_level = 0
|
32
13
|
end
|
33
|
-
|
14
|
+
|
34
15
|
def start(example_count)
|
35
16
|
super(example_count)
|
36
|
-
|
37
|
-
|
38
|
-
|
17
|
+
output.puts html_header
|
18
|
+
output.puts report_header
|
19
|
+
end
|
20
|
+
|
21
|
+
def current_indentation
|
22
|
+
' ' * @group_level
|
39
23
|
end
|
40
24
|
|
41
25
|
def example_group_started(example_group)
|
42
26
|
super(example_group)
|
43
|
-
|
44
|
-
@
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
@output.puts "<div class=\"example_group\">"
|
50
|
-
@output.puts " <dl>"
|
51
|
-
@output.puts " <dt id=\"example_group_#{example_group_number}\">#{h(example_group.description)}</dt>"
|
52
|
-
@output.flush
|
27
|
+
|
28
|
+
output.puts if @group_level == 0
|
29
|
+
output.puts "#{current_indentation}<div class='group_#{@group_level}'>"
|
30
|
+
output.puts "#{current_indentation}<div class='description'>#{example_group.description}</div>"
|
31
|
+
|
32
|
+
@group_level += 1
|
53
33
|
end
|
54
|
-
|
55
|
-
def
|
56
|
-
@
|
57
|
-
|
58
|
-
@output.flush
|
59
|
-
end
|
60
|
-
|
61
|
-
def example_started(example)
|
62
|
-
super(example)
|
63
|
-
@example_number += 1
|
34
|
+
|
35
|
+
def example_group_finished(example_group)
|
36
|
+
@group_level -= 1
|
37
|
+
output.puts "#{current_indentation}</div>"
|
64
38
|
end
|
65
39
|
|
66
40
|
def example_passed(example)
|
67
|
-
|
68
|
-
|
69
|
-
@output.puts " <dd class=\"spec passed\"><span class=\"passed_spec_name\">#{h(example.description)}</span></dd>"
|
70
|
-
@output.flush
|
41
|
+
super(example)
|
42
|
+
output.puts "#{current_indentation}<div class='passed level_#{@group_level}'>#{example.description}</div>"
|
71
43
|
end
|
72
44
|
|
73
45
|
def example_failed(example)
|
74
|
-
|
75
|
-
|
76
|
-
extra = extra_failure_content(exception)
|
77
|
-
failure_style = 'failed'
|
78
|
-
failure_style = RSpec::Core::PendingExampleFixedError === exception ? 'pending_fixed' : 'failed'
|
79
|
-
@output.puts " <script type=\"text/javascript\">makeRed('rspec-header');</script>" unless @header_red
|
80
|
-
@header_red = true
|
81
|
-
@output.puts " <script type=\"text/javascript\">changeClass('example_group_#{example_group_number}');</script>"
|
82
|
-
@output.puts " <script type=\"text/javascript\">makeRed('example_group_#{example_group_number}');</script>" unless @example_group_red
|
83
|
-
@example_group_red = true
|
84
|
-
move_progress
|
85
|
-
@output.puts " <dd class=\"spec #{failure_style}\">"
|
86
|
-
@output.puts " <span class=\"failed_spec_name\">#{h(example.description)}</span>"
|
87
|
-
@output.puts " <div class=\"failure\" id=\"failure_#{counter}\">"
|
88
|
-
@output.puts " <div class=\"message\"><pre>#{h(exception.message)}</pre></div>" unless exception.nil?
|
89
|
-
@output.puts " <div class=\"backtrace\"><pre>#{format_backtrace(exception.backtrace, example).join("\n")}</pre></div>" if exception
|
90
|
-
@output.puts extra unless extra == ""
|
91
|
-
@output.puts " </div>"
|
92
|
-
@output.puts " </dd>"
|
93
|
-
@output.flush
|
46
|
+
super(example)
|
47
|
+
output.puts "#{current_indentation}<div class='failed level_#{@group_level}'>#{example.description} (FAILED - #{next_failure_index})</div>"
|
94
48
|
end
|
95
49
|
|
96
50
|
def example_pending(example)
|
97
|
-
|
98
|
-
|
99
|
-
@output.puts " <script type=\"text/javascript\">makeYellow('rspec-header');</script>" unless @header_red
|
100
|
-
@output.puts " <script type=\"text/javascript\">makeYellow('example_group_#{example_group_number}');</script>" unless @example_group_red
|
101
|
-
move_progress
|
102
|
-
@output.puts " <dd class=\"spec not_implemented\"><span class=\"not_implemented_spec_name\">#{h(example.description)} (PENDING: #{h(message)})</span></dd>"
|
103
|
-
@output.flush
|
51
|
+
super(example)
|
52
|
+
output.puts "#{current_indentation}<div class='pending level_#{@group_level}'>#{example.description} (PENDING - #{example.execution_result[:pending_message]})</div>"
|
104
53
|
end
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
def extra_failure_content(exception)
|
110
|
-
require 'rspec/core/formatters/snippet_extractor'
|
111
|
-
@snippet_extractor ||= SnippetExtractor.new
|
112
|
-
" <pre class=\"ruby\"><code>#{@snippet_extractor.snippet(exception)}</code></pre>"
|
54
|
+
|
55
|
+
def next_failure_index
|
56
|
+
@next_failure_index ||= 0
|
57
|
+
@next_failure_index += 1
|
113
58
|
end
|
114
59
|
|
115
|
-
def
|
116
|
-
|
117
|
-
@output.flush
|
60
|
+
def example_group_chain
|
61
|
+
example_group.ancestors.reverse
|
118
62
|
end
|
119
|
-
|
120
|
-
def
|
121
|
-
|
122
|
-
if @example_count > 0
|
123
|
-
result = ((example_number).to_f / @example_count.to_f * 1000).to_i / 10.0
|
124
|
-
end
|
125
|
-
result
|
63
|
+
|
64
|
+
def dump_pending
|
65
|
+
|
126
66
|
end
|
127
|
-
|
128
|
-
def
|
67
|
+
|
68
|
+
def example_started(example)
|
69
|
+
|
129
70
|
end
|
130
|
-
|
131
|
-
def
|
71
|
+
|
72
|
+
def dump_failures
|
73
|
+
|
132
74
|
end
|
133
|
-
|
75
|
+
|
134
76
|
def dump_summary(duration, example_count, failure_count, pending_count)
|
135
|
-
|
136
|
-
|
137
|
-
totals = "This was a dry-run"
|
138
|
-
else
|
139
|
-
totals = "#{example_count} example#{'s' unless example_count == 1}, #{failure_count} failure#{'s' unless failure_count == 1}"
|
140
|
-
totals << ", #{pending_count} pending" if pending_count > 0
|
141
|
-
end
|
142
|
-
@output.puts "<script type=\"text/javascript\">document.getElementById('duration').innerHTML = \"Finished in <strong>#{duration} seconds</strong>\";</script>"
|
143
|
-
@output.puts "<script type=\"text/javascript\">document.getElementById('totals').innerHTML = \"#{totals}\";</script>"
|
144
|
-
@output.puts "</div>"
|
145
|
-
@output.puts "</div>"
|
146
|
-
@output.puts "</body>"
|
147
|
-
@output.puts "</html>"
|
148
|
-
@output.flush
|
77
|
+
output.puts "</body>"
|
78
|
+
output.puts "</html>"
|
149
79
|
end
|
150
|
-
|
80
|
+
|
151
81
|
def html_header
|
152
82
|
<<-EOF
|
153
|
-
<?xml version="1.0" encoding="UTF-8"?>
|
154
|
-
<!DOCTYPE html
|
155
|
-
|
156
|
-
|
157
|
-
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
|
158
|
-
<head>
|
159
|
-
|
160
|
-
|
161
|
-
|
162
|
-
|
163
|
-
|
164
|
-
|
165
|
-
|
166
|
-
|
167
|
-
|
168
|
-
|
169
|
-
|
170
|
-
|
171
|
-
|
172
|
-
|
173
|
-
#{
|
174
|
-
|
175
|
-
|
176
|
-
|
177
|
-
|
178
|
-
|
179
|
-
|
180
|
-
|
181
|
-
|
182
|
-
<style type="text/css">
|
183
|
-
#{global_styles}
|
184
|
-
</style>
|
185
|
-
</head>
|
186
|
-
<body>
|
187
|
-
EOF
|
83
|
+
<?xml version="1.0" encoding="UTF-8"?>
|
84
|
+
<!DOCTYPE html
|
85
|
+
PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
|
86
|
+
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
|
87
|
+
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
|
88
|
+
<head>
|
89
|
+
<title>RSpec results</title>
|
90
|
+
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
|
91
|
+
<meta http-equiv="Expires" content="-1" />
|
92
|
+
<meta http-equiv="Pragma" content="no-cache" />
|
93
|
+
<link rel="stylesheet" href="style.css">
|
94
|
+
|
95
|
+
<script type="text/javascript">
|
96
|
+
// <![CDATA[
|
97
|
+
#{global_scripts}
|
98
|
+
// ]]>
|
99
|
+
</script>
|
100
|
+
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.4.2/jquery.min.js"></script>
|
101
|
+
<script type="text/javascript">
|
102
|
+
// <![CDATA[
|
103
|
+
#{jquery_scripts}
|
104
|
+
// ]]>
|
105
|
+
</script>
|
106
|
+
<style type="text/css">
|
107
|
+
#{global_styles}
|
108
|
+
</style>
|
109
|
+
</head>
|
110
|
+
<body>
|
111
|
+
EOF
|
188
112
|
end
|
189
113
|
|
190
114
|
def report_header
|
191
115
|
<<-EOF
|
192
|
-
<div class="rspec-report">
|
193
|
-
|
194
|
-
<div id="rspec-header">
|
195
|
-
|
196
|
-
|
197
|
-
|
198
|
-
|
199
|
-
|
200
|
-
|
201
|
-
|
202
|
-
|
203
|
-
</div>
|
204
|
-
|
205
|
-
<div class="results">
|
206
|
-
<a id="toogle" href="#">Collapse</a>
|
207
|
-
EOF
|
116
|
+
<div class="rspec-report">
|
117
|
+
|
118
|
+
<div id="rspec-header">
|
119
|
+
<div id="label">
|
120
|
+
<h1>RSpec Code Examples</h1>
|
121
|
+
</div>
|
122
|
+
|
123
|
+
<div id="summary">
|
124
|
+
<p id="totals"> </p>
|
125
|
+
<p id="duration"> </p>
|
126
|
+
</div>
|
127
|
+
</div>
|
128
|
+
|
129
|
+
<div class="results">
|
130
|
+
<a id="toogle" href="#">Collapse</a>
|
131
|
+
EOF
|
208
132
|
end
|
209
133
|
|
210
134
|
def jquery_scripts
|
211
135
|
<<-EOF
|
212
|
-
var pare = 0;
|
213
|
-
|
214
|
-
function changeClass(selector) {
|
215
|
-
var str = "#" + selector;
|
216
|
-
$(str).addClass("last");
|
217
|
-
}
|
218
|
-
|
219
|
-
function addParentKey(index) {
|
220
|
-
var sel = "#example_group_" + index ;
|
221
|
-
var b = $(sel).attr("class");
|
222
|
-
if (b != "last"){
|
223
|
-
$(sel).parentsUntil("div.results").last().attr("class","example_group_" + pare.toString());
|
224
|
-
pare = pare + 1;
|
225
|
-
}
|
226
|
-
}
|
227
|
-
|
228
136
|
function findLastId(){
|
229
137
|
var i = $("dt[id*='example_group']").last().attr("id").split("_")[2];
|
230
138
|
return i;
|
231
139
|
}
|
232
140
|
|
233
141
|
$(document).ready(function(){
|
234
|
-
$("
|
142
|
+
$("div[class*='group_']").toggle(
|
235
143
|
function () {
|
236
|
-
$(this).
|
144
|
+
$(this).children("div[class!='description']").hide();
|
237
145
|
},
|
238
146
|
function () {
|
239
|
-
$(this).
|
147
|
+
$(this).children("div[class!='description']").show();
|
240
148
|
}
|
241
149
|
);
|
242
150
|
|
243
|
-
$("dt[id*='example_group_'][class!='last']").toggle(
|
244
|
-
function () {
|
245
|
-
$(this).parent().parent().nextUntil("div[class*=example_group_]").hide();
|
246
|
-
},
|
247
|
-
function () {
|
248
|
-
$(this).parent().parent().nextUntil("div[class*=example_group_]").show();
|
249
|
-
}
|
250
|
-
);
|
251
|
-
|
252
|
-
var last = parseInt(findLastId());
|
253
|
-
for(i=1;i<last+1;i++){
|
254
|
-
addParentKey(i);
|
255
|
-
}
|
256
|
-
|
257
151
|
$("#toogle").toggle(
|
258
152
|
function(e){
|
259
153
|
e.preventDefault();
|
260
154
|
$(this).html("Expand");
|
261
|
-
$("
|
155
|
+
$("div[class*='group_']").children("div[class!='description']").hide();
|
262
156
|
},
|
263
157
|
function(e){
|
264
158
|
e.preventDefault();
|
265
159
|
$(this).html("Collapse");
|
266
|
-
$("
|
160
|
+
$("div[class*='group_']").children("div[class!='description']").show();
|
267
161
|
}
|
268
162
|
);
|
269
163
|
})
|
270
|
-
EOF
|
164
|
+
EOF
|
271
165
|
end
|
272
166
|
|
273
167
|
def global_scripts
|
274
168
|
<<-EOF
|
275
|
-
function moveProgressBar(percentDone) {
|
276
|
-
|
277
|
-
}
|
278
|
-
function makeRed(element_id) {
|
279
|
-
|
280
|
-
|
281
|
-
}
|
282
|
-
|
283
|
-
function makeYellow(element_id) {
|
284
|
-
|
285
|
-
|
286
|
-
|
287
|
-
|
288
|
-
|
289
|
-
|
290
|
-
|
291
|
-
|
292
|
-
|
293
|
-
|
294
|
-
}
|
295
|
-
EOF
|
169
|
+
function moveProgressBar(percentDone) {
|
170
|
+
document.getElementById("rspec-header").style.width = percentDone +"%";
|
171
|
+
}
|
172
|
+
function makeRed(element_id) {
|
173
|
+
document.getElementById(element_id).style.background = '#C40D0D';
|
174
|
+
document.getElementById(element_id).style.color = '#FFFFFF';
|
175
|
+
}
|
176
|
+
|
177
|
+
function makeYellow(element_id) {
|
178
|
+
if (element_id == "rspec-header" && document.getElementById(element_id).style.background != '#C40D0D')
|
179
|
+
{
|
180
|
+
document.getElementById(element_id).style.background = '#FAF834';
|
181
|
+
document.getElementById(element_id).style.color = '#000000';
|
182
|
+
}
|
183
|
+
else
|
184
|
+
{
|
185
|
+
document.getElementById(element_id).style.background = '#FAF834';
|
186
|
+
document.getElementById(element_id).style.color = '#000000';
|
187
|
+
}
|
188
|
+
}
|
189
|
+
EOF
|
296
190
|
end
|
297
191
|
|
298
192
|
def global_styles
|
299
193
|
<<-EOF
|
300
|
-
#rspec-header {
|
301
|
-
|
302
|
-
}
|
303
|
-
|
304
|
-
.
|
305
|
-
|
306
|
-
|
307
|
-
|
308
|
-
|
309
|
-
|
310
|
-
|
311
|
-
|
312
|
-
|
313
|
-
|
314
|
-
|
315
|
-
|
316
|
-
|
317
|
-
|
318
|
-
|
319
|
-
|
320
|
-
|
321
|
-
|
322
|
-
|
323
|
-
}
|
324
|
-
|
325
|
-
|
326
|
-
|
327
|
-
|
328
|
-
|
329
|
-
|
330
|
-
|
331
|
-
|
332
|
-
|
333
|
-
|
334
|
-
|
335
|
-
|
336
|
-
|
337
|
-
|
338
|
-
|
339
|
-
|
340
|
-
|
341
|
-
|
342
|
-
|
343
|
-
|
344
|
-
|
345
|
-
|
346
|
-
|
347
|
-
|
348
|
-
|
349
|
-
|
350
|
-
|
351
|
-
|
352
|
-
|
353
|
-
|
354
|
-
|
355
|
-
|
356
|
-
|
357
|
-
|
358
|
-
|
359
|
-
|
360
|
-
|
361
|
-
|
362
|
-
|
363
|
-
|
364
|
-
|
365
|
-
}
|
366
|
-
|
367
|
-
|
368
|
-
|
369
|
-
|
370
|
-
|
371
|
-
|
372
|
-
|
373
|
-
|
374
|
-
|
375
|
-
|
376
|
-
|
377
|
-
|
378
|
-
|
379
|
-
|
380
|
-
|
381
|
-
|
382
|
-
}
|
383
|
-
|
384
|
-
|
385
|
-
|
386
|
-
}
|
387
|
-
|
388
|
-
|
389
|
-
|
390
|
-
|
391
|
-
|
392
|
-
|
393
|
-
|
394
|
-
|
395
|
-
|
396
|
-
|
397
|
-
|
398
|
-
|
399
|
-
|
400
|
-
|
401
|
-
|
402
|
-
|
403
|
-
|
404
|
-
|
405
|
-
|
406
|
-
|
407
|
-
|
408
|
-
|
409
|
-
|
410
|
-
|
411
|
-
|
412
|
-
|
413
|
-
|
414
|
-
|
415
|
-
|
416
|
-
|
417
|
-
|
418
|
-
|
419
|
-
|
420
|
-
|
421
|
-
|
422
|
-
|
423
|
-
|
194
|
+
#rspec-header {
|
195
|
+
background: #65C400; color: #fff; height: 4em;
|
196
|
+
}
|
197
|
+
|
198
|
+
div.group_0 {
|
199
|
+
margin: 10px 15px 30px 5px;
|
200
|
+
}
|
201
|
+
|
202
|
+
div.group_1 {
|
203
|
+
margin-left: 15px;
|
204
|
+
margin-bottom: 10px;
|
205
|
+
margin-top: 10px;
|
206
|
+
}
|
207
|
+
|
208
|
+
a {
|
209
|
+
color: #445767;
|
210
|
+
}
|
211
|
+
|
212
|
+
#toogle {
|
213
|
+
margin-left: 5px;
|
214
|
+
color: #424242;
|
215
|
+
font-weight: bold;
|
216
|
+
text-transform: uppercase;
|
217
|
+
}
|
218
|
+
|
219
|
+
div.group_2 {
|
220
|
+
margin-left: 15px;
|
221
|
+
margin-bottom: 10px;
|
222
|
+
margin-top: 10px;
|
223
|
+
}
|
224
|
+
|
225
|
+
div.group_3 {
|
226
|
+
margin-left: 15px;
|
227
|
+
margin-bottom: 10px;
|
228
|
+
margin-top: 10px;
|
229
|
+
}
|
230
|
+
|
231
|
+
div.description {
|
232
|
+
font-weight: bold;
|
233
|
+
border-left: 5px solid #00000a;
|
234
|
+
border-bottom: 1px solid #000;
|
235
|
+
color: #000; background: #d5d5d5;
|
236
|
+
padding-left: 5px;
|
237
|
+
}
|
238
|
+
|
239
|
+
div.passed {
|
240
|
+
margin-top: 5px;
|
241
|
+
margin-bottom: 5px;
|
242
|
+
padding-left: 5px;
|
243
|
+
border-left: 5px solid #65C400;
|
244
|
+
border-bottom: 1px solid #65C400;
|
245
|
+
background: #DBFFB4; color: #3D7700;
|
246
|
+
}
|
247
|
+
|
248
|
+
div.failed {
|
249
|
+
margin-top: 5px;
|
250
|
+
margin-bottom: 5px;
|
251
|
+
padding-left: 5px;
|
252
|
+
border-left: 5px solid #C20000;
|
253
|
+
border-bottom: 1px solid #C20000;
|
254
|
+
color: #830705; background: #fa7b7a;
|
255
|
+
}
|
256
|
+
|
257
|
+
div#rspec-header {
|
258
|
+
background-color: #65c400;
|
259
|
+
}
|
260
|
+
|
261
|
+
div.pending {
|
262
|
+
margin-top: 5px;
|
263
|
+
margin-bottom: 5px;
|
264
|
+
padding-left: 5px;
|
265
|
+
border-left: 5px solid #eeef33;
|
266
|
+
border-bottom: 1px solid #FAF834;
|
267
|
+
background: #faffcc; color: #131313;
|
268
|
+
}
|
269
|
+
|
270
|
+
body {
|
271
|
+
font-family: "Lucida Grande", Lucida, Verdana, sans-serif;
|
272
|
+
}
|
273
|
+
|
274
|
+
.level_1 {
|
275
|
+
margin-left: 15px;
|
276
|
+
}
|
277
|
+
|
278
|
+
.level_2 {
|
279
|
+
margin-left: 15px;
|
280
|
+
}
|
281
|
+
|
282
|
+
.level_3 {
|
283
|
+
margin-left: 15px;
|
284
|
+
}
|
285
|
+
|
286
|
+
.level_4 {
|
287
|
+
margin-left: 15px;
|
288
|
+
}
|
289
|
+
|
290
|
+
.rspec-report h1 {
|
291
|
+
margin: 0px 10px 0px 10px;
|
292
|
+
padding: 10px;
|
293
|
+
font-family: "Lucida Grande", Helvetica, sans-serif;
|
294
|
+
font-size: 1.8em;
|
295
|
+
position: absolute;
|
296
|
+
}
|
297
|
+
|
298
|
+
#summary {
|
299
|
+
margin: 0; padding: 5px 10px;
|
300
|
+
font-family: "Lucida Grande", Helvetica, sans-serif;
|
301
|
+
text-align: right;
|
302
|
+
top: 0px;
|
303
|
+
right: 0px;
|
304
|
+
float:right;
|
305
|
+
}
|
306
|
+
|
307
|
+
#summary p {
|
308
|
+
margin: 0 0 0 2px;
|
309
|
+
}
|
310
|
+
|
311
|
+
#summary #totals {
|
312
|
+
font-size: 1.2em;
|
313
|
+
}
|
314
|
+
|
315
|
+
.example_group {
|
316
|
+
margin: 0 10px 5px;
|
317
|
+
background: #fff;
|
318
|
+
}
|
319
|
+
|
320
|
+
dl {
|
321
|
+
margin: 0; padding: 0 0 5px;
|
322
|
+
font: normal 11px "Lucida Grande", Helvetica, sans-serif;
|
323
|
+
}
|
324
|
+
|
325
|
+
dt {
|
326
|
+
padding: 3px;
|
327
|
+
background: #65C400;
|
328
|
+
color: #fff;
|
329
|
+
font-weight: bold;
|
330
|
+
}
|
331
|
+
|
332
|
+
dt.last {
|
333
|
+
margin-left: 10px;
|
334
|
+
}
|
335
|
+
|
336
|
+
dd {
|
337
|
+
margin: 5px 0 5px 25px;
|
338
|
+
padding: 3px 3px 3px 18px;
|
339
|
+
}
|
340
|
+
|
341
|
+
dd.spec.passed {
|
342
|
+
border-left: 5px solid #65C400;
|
343
|
+
border-bottom: 1px solid #65C400;
|
344
|
+
background: #DBFFB4; color: #3D7700;
|
345
|
+
}
|
346
|
+
|
347
|
+
dd.spec.failed {
|
348
|
+
border-left: 5px solid #C20000;
|
349
|
+
border-bottom: 1px solid #C20000;
|
350
|
+
color: #C20000; background: #FFFBD3;
|
351
|
+
}
|
352
|
+
|
353
|
+
dd.spec.not_implemented {
|
354
|
+
border-left: 5px solid #FAF834;
|
355
|
+
border-bottom: 1px solid #FAF834;
|
356
|
+
background: #FCFB98; color: #131313;
|
357
|
+
}
|
358
|
+
|
359
|
+
dd.spec.pending_fixed {
|
360
|
+
border-left: 5px solid #0000C2;
|
361
|
+
border-bottom: 1px solid #0000C2;
|
362
|
+
color: #0000C2; background: #D3FBFF;
|
363
|
+
}
|
364
|
+
|
365
|
+
.backtrace {
|
366
|
+
color: #000;
|
367
|
+
font-size: 12px;
|
368
|
+
}
|
369
|
+
|
370
|
+
a {
|
371
|
+
color: #BE5C00;
|
372
|
+
}
|
373
|
+
|
374
|
+
/* Ruby code, style similar to vibrant ink */
|
375
|
+
.ruby {
|
376
|
+
font-size: 12px;
|
377
|
+
font-family: monospace;
|
378
|
+
color: white;
|
379
|
+
background-color: black;
|
380
|
+
padding: 0.1em 0 0.2em 0;
|
381
|
+
}
|
382
|
+
|
383
|
+
.ruby .keyword { color: #FF6600; }
|
384
|
+
.ruby .constant { color: #339999; }
|
385
|
+
.ruby .attribute { color: white; }
|
386
|
+
.ruby .global { color: white; }
|
387
|
+
.ruby .module { color: white; }
|
388
|
+
.ruby .class { color: white; }
|
389
|
+
.ruby .string { color: #66FF00; }
|
390
|
+
.ruby .ident { color: white; }
|
391
|
+
.ruby .method { color: #FFCC00; }
|
392
|
+
.ruby .number { color: white; }
|
393
|
+
.ruby .char { color: white; }
|
394
|
+
.ruby .comment { color: #9933CC; }
|
395
|
+
.ruby .symbol { color: white; }
|
396
|
+
.ruby .regex { color: #44B4CC; }
|
397
|
+
.ruby .punct { color: white; }
|
398
|
+
.ruby .escape { color: white; }
|
399
|
+
.ruby .interp { color: white; }
|
400
|
+
.ruby .expr { color: white; }
|
401
|
+
|
402
|
+
.ruby .offending { background-color: gray; }
|
403
|
+
.ruby .linenum {
|
404
|
+
width: 75px;
|
405
|
+
padding: 0.1em 1em 0.2em 0;
|
406
|
+
color: #000000;
|
407
|
+
background-color: #FFFBD3;
|
408
|
+
}
|
409
|
+
EOF
|
424
410
|
end
|
425
411
|
end
|
426
412
|
end
|
data/spektacular.gemspec
CHANGED
@@ -5,11 +5,11 @@
|
|
5
5
|
|
6
6
|
Gem::Specification.new do |s|
|
7
7
|
s.name = %q{spektacular}
|
8
|
-
s.version = "0.
|
8
|
+
s.version = "0.1.3"
|
9
9
|
|
10
10
|
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
11
11
|
s.authors = ["damselem"]
|
12
|
-
s.date = %q{2010-09-
|
12
|
+
s.date = %q{2010-09-23}
|
13
13
|
s.description = %q{An improved HTML RSpec formatter}
|
14
14
|
s.email = %q{damselem@gmail.com}
|
15
15
|
s.extra_rdoc_files = [
|
@@ -24,6 +24,7 @@ Gem::Specification.new do |s|
|
|
24
24
|
"Rakefile",
|
25
25
|
"VERSION",
|
26
26
|
"lib/spektacular.rb",
|
27
|
+
"lib/spektacular/html_formatter.rb",
|
27
28
|
"spektacular.gemspec",
|
28
29
|
"test/helper.rb",
|
29
30
|
"test/test_spektacular.rb"
|
metadata
CHANGED
@@ -4,9 +4,9 @@ version: !ruby/object:Gem::Version
|
|
4
4
|
prerelease: false
|
5
5
|
segments:
|
6
6
|
- 0
|
7
|
-
-
|
8
|
-
-
|
9
|
-
version: 0.
|
7
|
+
- 1
|
8
|
+
- 3
|
9
|
+
version: 0.1.3
|
10
10
|
platform: ruby
|
11
11
|
authors:
|
12
12
|
- damselem
|
@@ -14,7 +14,7 @@ autorequire:
|
|
14
14
|
bindir: bin
|
15
15
|
cert_chain: []
|
16
16
|
|
17
|
-
date: 2010-09-
|
17
|
+
date: 2010-09-23 00:00:00 +02:00
|
18
18
|
default_executable:
|
19
19
|
dependencies: []
|
20
20
|
|
@@ -35,6 +35,7 @@ files:
|
|
35
35
|
- Rakefile
|
36
36
|
- VERSION
|
37
37
|
- lib/spektacular.rb
|
38
|
+
- lib/spektacular/html_formatter.rb
|
38
39
|
- spektacular.gemspec
|
39
40
|
- test/helper.rb
|
40
41
|
- test/test_spektacular.rb
|