jahtml_formatter 1.0.0 → 1.0.1

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/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: