jahtml_formatter 1.0.0 → 1.0.1

Sign up to get free protection for your applications and to get access to all the features.
data/Gemfile CHANGED
File without changes
@@ -2,7 +2,7 @@
2
2
 
3
3
  Gem::Specification.new do |s|
4
4
  s.name = "jahtml_formatter"
5
- s.version = '1.0.0'
5
+ s.version = '1.0.1'
6
6
  s.platform = Gem::Platform::RUBY
7
7
  s.authors = ["Martin Westin"]
8
8
  s.email = ["martin@eimermusic.com"]
@@ -0,0 +1,14 @@
1
+ # coding: UTF-8
2
+ module IsoExampleGroupMethods
3
+ def self.included(klass)
4
+ klass.extend ClassMethods
5
+ end
6
+ module ClassMethods
7
+ def description
8
+ if iso_id = metadata.delete(:iso_id)
9
+ metadata[:example_group][:description] = "#{iso_id} #{metadata[:example_group][:description]}"
10
+ end
11
+ super
12
+ end
13
+ end
14
+ end
@@ -1,231 +1,15 @@
1
1
  require 'erb'
2
2
  require 'rspec/core/formatters/html_formatter'
3
+ require 'jahtml_printer'
4
+ require 'iso_example_group_methods'
3
5
 
4
6
  class JahtmlFormatter < RSpec::Core::Formatters::HtmlFormatter
5
-
6
- def html_header
7
- <<-EOF
8
- <?xml version="1.0" encoding="UTF-8"?>
9
- <!DOCTYPE html
10
- PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
11
- "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
12
- <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
13
- <head>
14
- <title>RSpec results</title>
15
- <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
16
- <meta http-equiv="Expires" content="-1" />
17
- <meta http-equiv="Pragma" content="no-cache" />
18
- <style type="text/css">
19
- body {
20
- margin: 0;
21
- padding: 0;
22
- background: #fff;
23
- font-size: 80%;
24
- }
25
- </style>
26
- <script type="text/javascript">
27
- // <![CDATA[
28
- #{global_scripts}
29
- // ]]>
30
- </script>
31
- <style type="text/css">
32
- #{global_styles}
33
- </style>
34
- </head>
35
- <body>
36
- EOF
37
- end
38
-
39
- def report_header
40
- <<-EOF
41
- <div class="rspec-report">
42
-
43
- <div id="rspec-header">
44
- <div id="label">
45
- <h1>Automated Software Test Report</h1>
46
- </div>
47
-
48
- <div id="summary">
49
- <p id="totals">&nbsp;</p>
50
- <p id="duration">&nbsp;</p>
51
- </div>
52
- </div>
53
-
54
-
55
- <div class="results">
56
- EOF
57
- end
58
-
59
- def global_styles
60
- <<-EOF
61
- #rspec-header {
62
- color: #000; height: 4em; border-top: 1em solid #65C400;
63
- }
64
-
65
- .rspec-report h1 {
66
- margin: 0px 10px 0px 10px;
67
- padding: 10px;
68
- font-family: "Lucida Grande", Helvetica, sans-serif;
69
- font-size: 1.8em;
70
- position: absolute;
71
- }
72
-
73
- #label {
74
- float:left;
75
- }
76
-
77
- #display-filters {
78
- float:left;
79
- padding: 28px 0 0 40%;
80
- font-family: "Lucida Grande", Helvetica, sans-serif;
81
- }
82
-
83
- #summary {
84
- float:right;
85
- padding: 5px 10px;
86
- font-family: "Lucida Grande", Helvetica, sans-serif;
87
- text-align: right;
88
- }
89
-
90
- #summary p {
91
- margin: 0 0 0 2px;
92
- }
93
-
94
- #summary #totals {
95
- font-size: 1.2em;
96
- }
97
-
98
- .example_group {
99
- margin: 0 10px 5px;
100
- background: #fff;
101
- }
102
-
103
- dl {
104
- margin: 0; padding: 0 0 5px;
105
- font: normal 11px "Lucida Grande", Helvetica, sans-serif;
106
- }
107
-
108
- dt {
109
- color: #000;
110
- font-weight: bold;
111
- padding:3px;
112
- }
113
-
114
- dd {
115
- margin: 5px 0 5px 5px;
116
- padding: 3px 3px 3px 18px;
117
- }
118
-
119
- dd .duration {
120
- padding-left: 5px;
121
- text-align: right;
122
- right: 0px;
123
- float:right;
124
- }
125
-
126
- dd.example.passed {
127
- border-left: 5px solid #65C400;
128
- border-bottom: 1px solid #65C400;
129
- color: #000;
130
- }
131
-
132
- dd.example.not_implemented {
133
- border-left: 5px solid #FAF834;
134
- border-bottom: 1px solid #FAF834;
135
- color: #000;
136
- }
137
-
138
- dd.example.pending_fixed {
139
- border-left: 5px solid #0000C2;
140
- border-bottom: 1px solid #0000C2;
141
- color: #000;
142
- }
143
-
144
- dd.example.failed {
145
- border-left: 5px solid #C20000;
146
- border-bottom: 1px solid #C20000;
147
- color: #000;
148
- }
149
-
150
- dd.example.passed:after {
151
- content: " PASSED, ";
152
- float:right;
153
- white-space: nowrap;
154
- border-left: 1em solid #65C400;
155
- padding-left: .5em;
156
- }
157
-
158
-
159
- dt.not_implemented {
160
- color: #000000; background: #FAF834;
161
- }
162
-
163
- dt.pending_fixed {
164
- color: #FFFFFF; background: #C40D0D;
165
- }
166
-
167
- dt.failed {
168
- border-left: 5px solid #C20000;
169
- }
170
-
171
-
172
- #rspec-header.not_implemented {
173
- border-top: 1em solid #FAF834;
174
- }
175
-
176
- #rspec-header.pending_fixed {
177
- border-top: 1em solid #C40D0D;
178
- }
179
-
180
- #rspec-header.failed {
181
- border-top: 1em solid #C40D0D;
182
- }
183
-
184
-
185
- .backtrace {
186
- color: #000;
187
- font-size: 12px;
188
- }
189
-
190
- a {
191
- color: #BE5C00;
192
- }
193
-
194
- /* Ruby code, style similar to vibrant ink */
195
- .ruby {
196
- font-size: 12px;
197
- font-family: monospace;
198
- color: white;
199
- background-color: black;
200
- padding: 0.1em 0 0.2em 0;
201
- }
202
-
203
- .ruby .keyword { color: #FF6600; }
204
- .ruby .constant { color: #339999; }
205
- .ruby .attribute { color: white; }
206
- .ruby .global { color: white; }
207
- .ruby .module { color: white; }
208
- .ruby .class { color: white; }
209
- .ruby .string { color: #66FF00; }
210
- .ruby .ident { color: white; }
211
- .ruby .method { color: #FFCC00; }
212
- .ruby .number { color: white; }
213
- .ruby .char { color: white; }
214
- .ruby .comment { color: #9933CC; }
215
- .ruby .symbol { color: white; }
216
- .ruby .regex { color: #44B4CC; }
217
- .ruby .punct { color: white; }
218
- .ruby .escape { color: white; }
219
- .ruby .interp { color: white; }
220
- .ruby .expr { color: white; }
221
-
222
- .ruby .offending { background-color: gray; }
223
- .ruby .linenum {
224
- width: 75px;
225
- padding: 0.1em 1em 0.2em 0;
226
- color: #000000;
227
- background-color: #FFFBD3;
228
- }
229
- EOF
7
+ def initialize(output)
8
+ super(output)
9
+ @printer = JahtmlPrinter.new(output)
230
10
  end
231
11
  end
12
+
13
+ RSpec.configure do |config|
14
+ config.include IsoExampleGroupMethods
15
+ end
@@ -0,0 +1,402 @@
1
+ require 'erb'
2
+
3
+ class JahtmlPrinter
4
+ include ERB::Util # for the #h method
5
+ def initialize(output)
6
+ @output = output
7
+ end
8
+
9
+ def print_html_start
10
+ @output.puts HTML_HEADER
11
+ @output.puts REPORT_HEADER
12
+ end
13
+
14
+ def print_example_group_end
15
+ @output.puts " </dl>"
16
+ @output.puts "</div>"
17
+ end
18
+
19
+ def print_example_group_start( group_id, description, number_of_parents )
20
+ @output.puts "<div id=\"div_group_#{group_id}\" class=\"example_group passed\">"
21
+ @output.puts " <dl #{indentation_style(number_of_parents)}>"
22
+ @output.puts " <dt id=\"example_group_#{group_id}\" class=\"passed\">#{h(description)}</dt>"
23
+ end
24
+
25
+ def print_example_passed( description, run_time )
26
+ formatted_run_time = sprintf("%.5f", run_time)
27
+ @output.puts " <dd class=\"example passed\"><span class=\"passed_spec_name\">#{h(description)}</span><span class='duration'>#{formatted_run_time}s</span></dd>"
28
+ end
29
+
30
+ def print_example_failed( pending_fixed, description, run_time, failure_id, exception, extra_content )
31
+ formatted_run_time = sprintf("%.5f", run_time)
32
+
33
+ @output.puts " <dd class=\"example #{pending_fixed ? 'pending_fixed' : 'failed'}\">"
34
+ @output.puts " <span class=\"failed_spec_name\">#{h(description)}</span>"
35
+ @output.puts " <span class=\"duration\">#{formatted_run_time}s</span>"
36
+ @output.puts " <div class=\"failure\" id=\"failure_#{failure_id}\">"
37
+ if exception
38
+ @output.puts " <div class=\"message\"><pre>#{h(exception[:message])}</pre></div>"
39
+ @output.puts " <div class=\"backtrace\"><pre>#{exception[:backtrace]}</pre></div>"
40
+ end
41
+ @output.puts extra_content if extra_content
42
+ @output.puts " </div>"
43
+ @output.puts " </dd>"
44
+ end
45
+
46
+ def print_example_pending( description, pending_message )
47
+ @output.puts " <dd class=\"example not_implemented\"><span class=\"not_implemented_spec_name\">#{h(description)} (PENDING: #{h(pending_message)})</span></dd>"
48
+ end
49
+
50
+ def print_summary( was_dry_run, duration, example_count, failure_count, pending_count )
51
+ # TODO - kill dry_run?
52
+ if was_dry_run
53
+ totals = "This was a dry-run"
54
+ else
55
+ totals = "#{example_count} example#{'s' unless example_count == 1}, "
56
+ totals << "#{failure_count} failure#{'s' unless failure_count == 1}"
57
+ totals << ", #{pending_count} pending" if pending_count > 0
58
+ end
59
+
60
+ formatted_duration = sprintf("%.5f", duration)
61
+
62
+ @output.puts "<script type=\"text/javascript\">document.getElementById('duration').innerHTML = \"Finished in <strong>#{formatted_duration} seconds</strong>\";</script>"
63
+ @output.puts "<script type=\"text/javascript\">document.getElementById('totals').innerHTML = \"#{totals}\";</script>"
64
+ @output.puts "</div>"
65
+ @output.puts "</div>"
66
+ @output.puts "</body>"
67
+ @output.puts "</html>"
68
+ end
69
+
70
+ def flush
71
+ @output.flush
72
+ end
73
+
74
+ def move_progress( percent_done )
75
+ @output.puts " <script type=\"text/javascript\">moveProgressBar('#{percent_done}');</script>"
76
+ @output.flush
77
+ end
78
+
79
+ def make_header_red
80
+ @output.puts " <script type=\"text/javascript\">makeRed('rspec-header');</script>"
81
+ end
82
+
83
+ def make_header_yellow
84
+ @output.puts " <script type=\"text/javascript\">makeYellow('rspec-header');</script>"
85
+ end
86
+
87
+ def make_example_group_header_red(group_id)
88
+ @output.puts " <script type=\"text/javascript\">makeRed('div_group_#{group_id}');</script>"
89
+ @output.puts " <script type=\"text/javascript\">makeRed('example_group_#{group_id}');</script>"
90
+ end
91
+
92
+ def make_example_group_header_yellow(group_id)
93
+ @output.puts " <script type=\"text/javascript\">makeYellow('div_group_#{group_id}');</script>"
94
+ @output.puts " <script type=\"text/javascript\">makeYellow('example_group_#{group_id}');</script>"
95
+ end
96
+
97
+
98
+ private
99
+
100
+ def indentation_style( number_of_parents )
101
+ "style=\"margin-left: #{(number_of_parents - 1) * 15}px;\""
102
+ end
103
+
104
+
105
+ REPORT_HEADER = <<-EOF
106
+ <div class="rspec-report">
107
+
108
+ <div id="rspec-header">
109
+ <div id="label">
110
+ <h1>Automated Software Test Report</h1>
111
+ </div>
112
+
113
+ <div id="summary">
114
+ <p id="totals">&nbsp;</p>
115
+ <p id="duration">&nbsp;</p>
116
+ </div>
117
+ </div>
118
+
119
+
120
+ <div class="results">
121
+ EOF
122
+
123
+ GLOBAL_SCRIPTS = <<-EOF
124
+
125
+ function addClass(element_id, classname) {
126
+ document.getElementById(element_id).className += (" " + classname);
127
+ }
128
+
129
+ function removeClass(element_id, classname) {
130
+ var elem = document.getElementById(element_id);
131
+ var classlist = elem.className.replace(classname,'');
132
+ elem.className = classlist;
133
+ }
134
+
135
+ function moveProgressBar(percentDone) {
136
+ document.getElementById("rspec-header").style.width = percentDone +"%";
137
+ }
138
+
139
+ function makeRed(element_id) {
140
+ removeClass(element_id, 'passed');
141
+ removeClass(element_id, 'not_implemented');
142
+ addClass(element_id,'failed');
143
+ }
144
+
145
+ function makeYellow(element_id) {
146
+ var elem = document.getElementById(element_id);
147
+ if (elem.className.indexOf("failed") == -1) { // class doesn't includes failed
148
+ if (elem.className.indexOf("not_implemented") == -1) { // class doesn't include not_implemented
149
+ removeClass(element_id, 'passed');
150
+ addClass(element_id,'not_implemented');
151
+ }
152
+ }
153
+ }
154
+
155
+ function apply_filters() {
156
+ var passed_filter = document.getElementById('passed_checkbox').checked;
157
+ var failed_filter = document.getElementById('failed_checkbox').checked;
158
+ var pending_filter = document.getElementById('pending_checkbox').checked;
159
+
160
+ assign_display_style("example passed", passed_filter);
161
+ assign_display_style("example failed", failed_filter);
162
+ assign_display_style("example not_implemented", pending_filter);
163
+
164
+ assign_display_style_for_group("example_group passed", passed_filter);
165
+ assign_display_style_for_group("example_group not_implemented", pending_filter, pending_filter || passed_filter);
166
+ assign_display_style_for_group("example_group failed", failed_filter, failed_filter || pending_filter || passed_filter);
167
+ }
168
+
169
+ function get_display_style(display_flag) {
170
+ var style_mode = 'none';
171
+ if (display_flag == true) {
172
+ style_mode = 'block';
173
+ }
174
+ return style_mode;
175
+ }
176
+
177
+ function assign_display_style(classname, display_flag) {
178
+ var style_mode = get_display_style(display_flag);
179
+ var elems = document.getElementsByClassName(classname)
180
+ for (var i=0; i<elems.length;i++) {
181
+ elems[i].style.display = style_mode;
182
+ }
183
+ }
184
+
185
+ function assign_display_style_for_group(classname, display_flag, subgroup_flag) {
186
+ var display_style_mode = get_display_style(display_flag);
187
+ var subgroup_style_mode = get_display_style(subgroup_flag);
188
+ var elems = document.getElementsByClassName(classname)
189
+ for (var i=0; i<elems.length;i++) {
190
+ var style_mode = display_style_mode;
191
+ if ((display_flag != subgroup_flag) && (elems[i].getElementsByTagName('dt')[0].innerHTML.indexOf(", ") != -1)) {
192
+ elems[i].style.display = subgroup_style_mode;
193
+ } else {
194
+ elems[i].style.display = display_style_mode;
195
+ }
196
+ }
197
+ }
198
+ EOF
199
+
200
+ GLOBAL_STYLES = <<-EOF
201
+ #rspec-header {
202
+ color: #000; height: 4em; border-top: 1em solid #65C400;
203
+ }
204
+
205
+ .rspec-report h1 {
206
+ margin: 0px 10px 0px 10px;
207
+ padding: 10px;
208
+ font-family: "Lucida Grande", Helvetica, sans-serif;
209
+ font-size: 1.8em;
210
+ position: absolute;
211
+ }
212
+
213
+ #label {
214
+ float:left;
215
+ }
216
+
217
+ #display-filters {
218
+ float:left;
219
+ padding: 28px 0 0 40%;
220
+ font-family: "Lucida Grande", Helvetica, sans-serif;
221
+ }
222
+
223
+ #summary {
224
+ float:right;
225
+ padding: 5px 10px;
226
+ font-family: "Lucida Grande", Helvetica, sans-serif;
227
+ text-align: right;
228
+ }
229
+
230
+ #summary p {
231
+ margin: 0 0 0 2px;
232
+ }
233
+
234
+ #summary #totals {
235
+ font-size: 1.2em;
236
+ }
237
+
238
+ .example_group {
239
+ margin: 0 10px 5px;
240
+ background: #fff;
241
+ }
242
+
243
+ dl {
244
+ margin: 0; padding: 0 0 5px;
245
+ font: normal 11px "Lucida Grande", Helvetica, sans-serif;
246
+ }
247
+
248
+ dt {
249
+ color: #000;
250
+ font-weight: bold;
251
+ padding:3px;
252
+ }
253
+
254
+ dd {
255
+ margin: 5px 0 5px 5px;
256
+ padding: 3px 3px 3px 18px;
257
+ }
258
+
259
+ dd .duration {
260
+ padding-left: 5px;
261
+ text-align: right;
262
+ right: 0px;
263
+ float:right;
264
+ }
265
+
266
+ dd.example.passed {
267
+ border-left: 5px solid #65C400;
268
+ border-bottom: 1px solid #65C400;
269
+ color: #000;
270
+ }
271
+
272
+ dd.example.not_implemented {
273
+ border-left: 5px solid #FAF834;
274
+ border-bottom: 1px solid #FAF834;
275
+ color: #000;
276
+ }
277
+
278
+ dd.example.pending_fixed {
279
+ border-left: 5px solid #0000C2;
280
+ border-bottom: 1px solid #0000C2;
281
+ color: #000;
282
+ }
283
+
284
+ dd.example.failed {
285
+ border-left: 5px solid #C20000;
286
+ border-bottom: 1px solid #C20000;
287
+ color: #000;
288
+ }
289
+
290
+ dd.passed:after {
291
+ content: " PASSED, ";
292
+ float:right;
293
+ white-space: nowrap;
294
+ border-left: 1em solid #65C400;
295
+ padding-left: .5em;
296
+ }
297
+
298
+
299
+ dt.not_implemented {
300
+ color: #000000; background: #FAF834;
301
+ }
302
+
303
+ dt.pending_fixed {
304
+ color: #FFFFFF; background: #C40D0D;
305
+ }
306
+
307
+ dt.failed {
308
+ border-left: 5px solid #C20000;
309
+ }
310
+
311
+
312
+ #rspec-header.not_implemented {
313
+ border-top: 1em solid #FAF834;
314
+ }
315
+
316
+ #rspec-header.pending_fixed {
317
+ border-top: 1em solid #C40D0D;
318
+ }
319
+
320
+ #rspec-header.failed {
321
+ border-top: 1em solid #C40D0D;
322
+ }
323
+
324
+
325
+ .backtrace {
326
+ color: #000;
327
+ font-size: 12px;
328
+ }
329
+
330
+ a {
331
+ color: #BE5C00;
332
+ }
333
+
334
+ /* Ruby code, style similar to vibrant ink */
335
+ .ruby {
336
+ font-size: 12px;
337
+ font-family: monospace;
338
+ color: white;
339
+ background-color: black;
340
+ padding: 0.1em 0 0.2em 0;
341
+ }
342
+
343
+ .ruby .keyword { color: #FF6600; }
344
+ .ruby .constant { color: #339999; }
345
+ .ruby .attribute { color: white; }
346
+ .ruby .global { color: white; }
347
+ .ruby .module { color: white; }
348
+ .ruby .class { color: white; }
349
+ .ruby .string { color: #66FF00; }
350
+ .ruby .ident { color: white; }
351
+ .ruby .method { color: #FFCC00; }
352
+ .ruby .number { color: white; }
353
+ .ruby .char { color: white; }
354
+ .ruby .comment { color: #9933CC; }
355
+ .ruby .symbol { color: white; }
356
+ .ruby .regex { color: #44B4CC; }
357
+ .ruby .punct { color: white; }
358
+ .ruby .escape { color: white; }
359
+ .ruby .interp { color: white; }
360
+ .ruby .expr { color: white; }
361
+
362
+ .ruby .offending { background-color: gray; }
363
+ .ruby .linenum {
364
+ width: 75px;
365
+ padding: 0.1em 1em 0.2em 0;
366
+ color: #000000;
367
+ background-color: #FFFBD3;
368
+ }
369
+ EOF
370
+
371
+ HTML_HEADER = <<-EOF
372
+ <?xml version="1.0" encoding="UTF-8"?>
373
+ <!DOCTYPE html
374
+ PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
375
+ "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
376
+ <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
377
+ <head>
378
+ <title>Automated Software Test Report</title>
379
+ <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
380
+ <meta http-equiv="Expires" content="-1" />
381
+ <meta http-equiv="Pragma" content="no-cache" />
382
+ <style type="text/css">
383
+ body {
384
+ margin: 0;
385
+ padding: 0;
386
+ background: #fff;
387
+ font-size: 80%;
388
+ }
389
+ </style>
390
+ <script type="text/javascript">
391
+ // <![CDATA[
392
+ #{GLOBAL_SCRIPTS}
393
+ // ]]>
394
+ </script>
395
+ <style type="text/css">
396
+ #{GLOBAL_STYLES}
397
+ </style>
398
+ </head>
399
+ <body>
400
+ EOF
401
+
402
+ end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: jahtml_formatter
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.0
4
+ version: 1.0.1
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2012-11-15 00:00:00.000000000 Z
12
+ date: 2012-12-04 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: rspec
@@ -41,7 +41,9 @@ files:
41
41
  - LICENSE
42
42
  - README.md
43
43
  - jahtml_formatter.gemspec
44
+ - lib/iso_example_group_methods.rb
44
45
  - lib/jahtml_formatter.rb
46
+ - lib/jahtml_printer.rb
45
47
  homepage: https://github.com/eimermusic/jahtml_formatter
46
48
  licenses: []
47
49
  post_install_message: