rspec-core 2.11.1 → 2.12.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (116) hide show
  1. data/Changelog.md +59 -0
  2. data/README.md +22 -0
  3. data/features/command_line/example_name_option.feature +5 -5
  4. data/features/command_line/exit_status.feature +6 -6
  5. data/features/command_line/format_option.feature +2 -2
  6. data/features/command_line/line_number_appended_to_path.feature +2 -2
  7. data/features/command_line/line_number_option.feature +2 -2
  8. data/features/command_line/pattern_option.feature +2 -2
  9. data/features/command_line/rake_task.feature +62 -8
  10. data/features/command_line/ruby.feature +1 -1
  11. data/features/command_line/tag.feature +1 -1
  12. data/features/configuration/alias_example_to.feature +2 -2
  13. data/features/configuration/custom_settings.feature +3 -3
  14. data/features/configuration/default_path.feature +3 -3
  15. data/features/configuration/fail_fast.feature +5 -5
  16. data/features/configuration/read_options_from_file.feature +4 -4
  17. data/features/example_groups/basic_structure.feature +2 -2
  18. data/features/example_groups/shared_context.feature +3 -3
  19. data/features/example_groups/shared_examples.feature +25 -7
  20. data/features/expectation_framework_integration/configure_expectation_framework.feature +6 -6
  21. data/features/filtering/exclusion_filters.feature +5 -5
  22. data/features/filtering/if_and_unless.feature +5 -5
  23. data/features/filtering/inclusion_filters.feature +5 -5
  24. data/features/filtering/run_all_when_everything_filtered.feature +3 -3
  25. data/features/formatters/custom_formatter.feature +2 -2
  26. data/features/formatters/json_formatter.feature +30 -0
  27. data/features/formatters/text_formatter.feature +5 -5
  28. data/features/helper_methods/arbitrary_methods.feature +2 -2
  29. data/features/helper_methods/let.feature +2 -2
  30. data/features/helper_methods/modules.feature +6 -6
  31. data/features/hooks/around_hooks.feature +11 -11
  32. data/features/hooks/before_and_after_hooks.feature +15 -11
  33. data/features/hooks/filtering.feature +6 -6
  34. data/features/metadata/current_example.feature +1 -1
  35. data/features/metadata/described_class.feature +1 -1
  36. data/features/metadata/user_defined.feature +4 -4
  37. data/features/mock_framework_integration/use_any_framework.feature +6 -6
  38. data/features/mock_framework_integration/use_flexmock.feature +5 -5
  39. data/features/mock_framework_integration/use_mocha.feature +5 -5
  40. data/features/mock_framework_integration/use_rr.feature +5 -5
  41. data/features/mock_framework_integration/use_rspec.feature +5 -5
  42. data/features/pending/pending_examples.feature +11 -11
  43. data/features/spec_files/arbitrary_file_suffix.feature +1 -1
  44. data/features/step_definitions/additional_cli_steps.rb +2 -0
  45. data/features/subject/attribute_of_subject.feature +5 -5
  46. data/features/subject/explicit_subject.feature +5 -5
  47. data/features/subject/implicit_receiver.feature +2 -2
  48. data/features/subject/implicit_subject.feature +3 -3
  49. data/lib/autotest/rspec2.rb +1 -1
  50. data/lib/rspec/core.rb +53 -32
  51. data/lib/rspec/core/configuration.rb +123 -15
  52. data/lib/rspec/core/configuration_options.rb +17 -2
  53. data/lib/rspec/core/example.rb +5 -4
  54. data/lib/rspec/core/example_group.rb +19 -9
  55. data/lib/rspec/core/extensions/ordered.rb +12 -6
  56. data/lib/rspec/core/formatters.rb +55 -0
  57. data/lib/rspec/core/formatters/base_formatter.rb +43 -38
  58. data/lib/rspec/core/formatters/base_text_formatter.rb +9 -5
  59. data/lib/rspec/core/formatters/documentation_formatter.rb +1 -1
  60. data/lib/rspec/core/formatters/helpers.rb +30 -5
  61. data/lib/rspec/core/formatters/html_formatter.rb +58 -368
  62. data/lib/rspec/core/formatters/html_printer.rb +407 -0
  63. data/lib/rspec/core/formatters/json_formatter.rb +73 -0
  64. data/lib/rspec/core/formatters/snippet_extractor.rb +3 -1
  65. data/lib/rspec/core/hooks.rb +4 -4
  66. data/lib/rspec/core/metadata.rb +14 -6
  67. data/lib/rspec/core/mocking/with_mocha.rb +25 -2
  68. data/lib/rspec/core/mocking/with_rspec.rb +6 -2
  69. data/lib/rspec/core/option_parser.rb +28 -7
  70. data/lib/rspec/core/project_initializer.rb +0 -1
  71. data/lib/rspec/core/rake_task.rb +49 -38
  72. data/lib/rspec/core/reporter.rb +2 -2
  73. data/lib/rspec/core/shared_example_group.rb +89 -41
  74. data/lib/rspec/core/subject.rb +6 -2
  75. data/lib/rspec/core/version.rb +1 -1
  76. data/lib/rspec/core/world.rb +2 -2
  77. data/spec/autotest/rspec_spec.rb +6 -1
  78. data/spec/command_line/order_spec.rb +67 -0
  79. data/spec/rspec/core/configuration_options_spec.rb +45 -38
  80. data/spec/rspec/core/configuration_spec.rb +219 -44
  81. data/spec/rspec/core/deprecations_spec.rb +9 -0
  82. data/spec/rspec/core/drb_command_line_spec.rb +1 -7
  83. data/spec/rspec/core/drb_options_spec.rb +1 -1
  84. data/spec/rspec/core/dsl_spec.rb +17 -9
  85. data/spec/rspec/core/example_group_spec.rb +51 -5
  86. data/spec/rspec/core/example_spec.rb +39 -7
  87. data/spec/rspec/core/filter_manager_spec.rb +20 -30
  88. data/spec/rspec/core/formatters/base_formatter_spec.rb +29 -1
  89. data/spec/rspec/core/formatters/base_text_formatter_spec.rb +6 -2
  90. data/spec/rspec/core/formatters/helpers_spec.rb +12 -0
  91. data/spec/rspec/core/formatters/html_formatted-1.8.7-rbx.html +462 -0
  92. data/spec/rspec/core/formatters/html_formatted-1.9.2-jruby.html +410 -0
  93. data/spec/rspec/core/formatters/html_formatted-1.9.3-rbx.html +462 -0
  94. data/spec/rspec/core/formatters/html_formatter_spec.rb +11 -3
  95. data/spec/rspec/core/formatters/json_formatter_spec.rb +110 -0
  96. data/spec/rspec/core/formatters/snippet_extractor_spec.rb +8 -0
  97. data/spec/rspec/core/formatters/text_mate_formatted-1.8.7-rbx.html +462 -0
  98. data/spec/rspec/core/formatters/text_mate_formatted-1.9.2-jruby.html +410 -0
  99. data/spec/rspec/core/formatters/text_mate_formatted-1.9.3-rbx.html +462 -0
  100. data/spec/rspec/core/formatters/text_mate_formatter_spec.rb +11 -3
  101. data/spec/rspec/core/hooks_filtering_spec.rb +6 -6
  102. data/spec/rspec/core/metadata_spec.rb +29 -0
  103. data/spec/rspec/core/option_parser_spec.rb +42 -0
  104. data/spec/rspec/core/project_initializer_spec.rb +2 -2
  105. data/spec/rspec/core/rake_task_spec.rb +60 -17
  106. data/spec/rspec/core/reporter_spec.rb +17 -0
  107. data/spec/rspec/core/runner_spec.rb +1 -0
  108. data/spec/rspec/core/shared_example_group_spec.rb +17 -5
  109. data/spec/rspec/core/subject_spec.rb +11 -0
  110. data/spec/spec_helper.rb +32 -2
  111. data/spec/support/config_options_helper.rb +1 -10
  112. data/spec/support/helper_methods.rb +13 -0
  113. data/spec/support/isolated_directory.rb +10 -0
  114. data/spec/support/isolated_home_directory.rb +16 -0
  115. metadata +145 -148
  116. data/lib/rspec/core/extensions.rb +0 -4
@@ -4,7 +4,12 @@ require 'stringio'
4
4
  module RSpec
5
5
  module Core
6
6
  module Formatters
7
-
7
+ # RSpec's built-in formatters are all subclasses of RSpec::Core::Formatters::BaseTextFormatter,
8
+ # but the BaseTextFormatter documents all of the methods needed to be implemented by a formatter,
9
+ # as they are called from the reporter.
10
+ #
11
+ # @see RSpec::Core::Formatters::BaseTextFormatter
12
+ # @see RSpec::Core::Reporter
8
13
  class BaseFormatter
9
14
  include Helpers
10
15
  attr_accessor :example_group
@@ -21,54 +26,68 @@ module RSpec
21
26
  @example_group = nil
22
27
  end
23
28
 
24
- # This method is invoked before any examples are run, right after
25
- # they have all been collected. This can be useful for special
26
- # formatters that need to provide progress on feedback (graphical ones)
29
+ # Invoked before any examples are run, right after they have all
30
+ # been collected. This can be useful for formatters that provide
31
+ # feedback on progress through a suite.
27
32
  #
28
- # This will only be invoked once, and the next one to be invoked
29
- # is #example_group_started
33
+ # @param example_count
30
34
  def start(example_count)
31
35
  start_sync_output
32
36
  @example_count = example_count
33
37
  end
34
38
 
35
- # This method is invoked at the beginning of the execution of each example group.
36
- # +example_group+ is the example_group.
39
+ # Invoked at the beginning of the execution of each example
40
+ # group.
37
41
  #
38
- # The next method to be invoked after this is +example_passed+,
39
- # +example_pending+, or +example_finished+
42
+ # @param example_group subclass of `RSpec::Core::ExampleGroup`
40
43
  def example_group_started(example_group)
41
44
  @example_group = example_group
42
45
  end
43
46
 
44
- # This method is invoked at the end of the execution of each example group.
45
- # +example_group+ is the example_group.
47
+ # Invoked at the end of the execution of each example group.
48
+ #
49
+ # @param example_group subclass of `RSpec::Core::ExampleGroup`
46
50
  def example_group_finished(example_group)
47
51
  end
48
52
 
53
+
54
+ # Invoked at the beginning of the execution of each example.
55
+ #
56
+ # @param example instance of subclass of `RSpec::Core::ExampleGroup`
49
57
  def example_started(example)
50
58
  examples << example
51
59
  end
52
60
 
61
+ # Invoked when an example passes.
62
+ #
63
+ # @param example instance of subclass of `RSpec::Core::ExampleGroup`
53
64
  def example_passed(example)
54
65
  end
55
66
 
67
+ # Invoked when an example is pending.
68
+ #
69
+ # @param example instance of subclass of `RSpec::Core::ExampleGroup`
56
70
  def example_pending(example)
57
71
  @pending_examples << example
58
72
  end
59
73
 
74
+ # Invoked when an example fails.
75
+ #
76
+ # @param example instance of subclass of `RSpec::Core::ExampleGroup`
60
77
  def example_failed(example)
61
78
  @failed_examples << example
62
79
  end
63
80
 
81
+ # Used by the reporter to send messages to the output stream.
82
+ # @param [String] message
64
83
  def message(message)
65
84
  end
66
85
 
86
+ # Invoked after all examples have executed, before dumping post-run reports.
67
87
  def stop
68
88
  end
69
89
 
70
- # This method is invoked after all of the examples have executed. The next method
71
- # to be invoked after this one is #dump_failure (once for each failed example),
90
+ # Invoked after all of the examples have executed (after `stop`).
72
91
  def start_dump
73
92
  end
74
93
 
@@ -76,7 +95,7 @@ module RSpec
76
95
  def dump_failures
77
96
  end
78
97
 
79
- # This method is invoked after the dumping of examples and failures.
98
+ # Invoked after the dumping of examples and failures.
80
99
  def dump_summary(duration, example_count, failure_count, pending_count)
81
100
  @duration = duration
82
101
  @example_count = example_count
@@ -84,41 +103,26 @@ module RSpec
84
103
  @pending_count = pending_count
85
104
  end
86
105
 
87
- # This gets invoked after the summary if option is set to do so.
106
+ # Invoked after the summary if option is set to do so.
88
107
  def dump_pending
89
108
  end
90
109
 
110
+ # @private not intended for use outside RSpec.
91
111
  def seed(number)
92
112
  end
93
113
 
94
- # This method is invoked at the very end. Allows the formatter to clean up, like closing open streams.
114
+ # Invoked at the very end, `close` allows the formatter to clean
115
+ # up resources, e.g. open streams, etc.
95
116
  def close
96
117
  restore_sync_output
97
118
  end
98
119
 
99
- def format_backtrace(backtrace, example)
100
- return "" unless backtrace
101
- return backtrace if example.metadata[:full_backtrace] == true
102
-
103
- if at_exit_index = backtrace.index(RSpec::Core::Runner::AT_EXIT_HOOK_BACKTRACE_LINE)
104
- backtrace = backtrace[0, at_exit_index]
105
- end
106
-
107
- cleansed = backtrace.map { |line| backtrace_line(line) }.compact
108
- cleansed.empty? ? backtrace : cleansed
109
- end
110
-
111
120
  protected
112
121
 
113
122
  def configuration
114
123
  RSpec.configuration
115
124
  end
116
125
 
117
- def backtrace_line(line)
118
- return nil if configuration.cleaned_from_backtrace?(line)
119
- RSpec::Core::Metadata::relative_path(line)
120
- end
121
-
122
126
  def read_failed_line(exception, example)
123
127
  unless matching_line = find_failed_line(exception.backtrace, example.file_path)
124
128
  return "Unable to find matching line from backtrace"
@@ -127,10 +131,13 @@ module RSpec
127
131
  file_path, line_number = matching_line.match(/(.+?):(\d+)(|:\d+)/)[1..2]
128
132
 
129
133
  if File.exist?(file_path)
130
- File.readlines(file_path)[line_number.to_i - 1]
134
+ File.readlines(file_path)[line_number.to_i - 1] ||
135
+ "Unable to find matching line in #{file_path}"
131
136
  else
132
137
  "Unable to find #{file_path} to read failed line"
133
138
  end
139
+ rescue SecurityError
140
+ "Unable to read failed line"
134
141
  end
135
142
 
136
143
  def find_failed_line(backtrace, path)
@@ -158,11 +165,9 @@ module RSpec
158
165
  end
159
166
 
160
167
  def color_enabled?
161
- configuration.color_enabled?
168
+ configuration.color_enabled?(output)
162
169
  end
163
-
164
170
  end
165
-
166
171
  end
167
172
  end
168
173
  end
@@ -4,8 +4,12 @@ module RSpec
4
4
  module Core
5
5
  module Formatters
6
6
 
7
+ # Base for all of RSpec's built-in formatters. See RSpec::Core::Formatters::BaseFormatter
8
+ # to learn more about all of the methods called by the reporter.
9
+ #
10
+ # @see RSpec::Core::Formatters::BaseFormatter
11
+ # @see RSpec::Core::Reporter
7
12
  class BaseTextFormatter < BaseFormatter
8
-
9
13
  def message(message)
10
14
  output.puts message
11
15
  end
@@ -156,7 +160,7 @@ module RSpec
156
160
  end
157
161
 
158
162
  def dump_backtrace(example)
159
- format_backtrace(example.execution_result[:exception].backtrace, example).each do |backtrace_info|
163
+ format_backtrace(example.execution_result[:exception].backtrace, example.metadata).each do |backtrace_info|
160
164
  output.puts cyan("#{long_padding}# #{backtrace_info}")
161
165
  end
162
166
  end
@@ -191,11 +195,11 @@ module RSpec
191
195
  end
192
196
 
193
197
  def find_shared_group(example)
194
- group_and_ancestors(example).find {|group| group.metadata[:shared_group_name]}
198
+ group_and_parent_groups(example).find {|group| group.metadata[:shared_group_name]}
195
199
  end
196
200
 
197
- def group_and_ancestors(example)
198
- example.example_group.ancestors + [example.example_group]
201
+ def group_and_parent_groups(example)
202
+ example.example_group.parent_groups + [example.example_group]
199
203
  end
200
204
  end
201
205
  end
@@ -59,7 +59,7 @@ module RSpec
59
59
  end
60
60
 
61
61
  def example_group_chain
62
- example_group.ancestors.reverse
62
+ example_group.parent_groups.reverse
63
63
  end
64
64
  end
65
65
  end
@@ -1,8 +1,34 @@
1
1
  module RSpec
2
2
  module Core
3
- module Formatters
3
+ module BacktraceFormatter
4
+ extend self
5
+
6
+ def format_backtrace(backtrace, options = {})
7
+ return "" unless backtrace
8
+ return backtrace if options[:full_backtrace] == true
9
+
10
+ if at_exit_index = backtrace.index(RSpec::Core::Runner::AT_EXIT_HOOK_BACKTRACE_LINE)
11
+ backtrace = backtrace[0, at_exit_index]
12
+ end
13
+
14
+ cleansed = backtrace.map { |line| backtrace_line(line) }.compact
15
+ cleansed.empty? ? backtrace : cleansed
16
+ end
17
+
18
+ protected
4
19
 
20
+ def backtrace_line(line)
21
+ return nil if RSpec.configuration.cleaned_from_backtrace?(line)
22
+ RSpec::Core::Metadata::relative_path(line)
23
+ rescue SecurityError
24
+ nil
25
+ end
26
+ end
27
+
28
+ module Formatters
5
29
  module Helpers
30
+ include BacktraceFormatter
31
+
6
32
  SUB_SECOND_PRECISION = 5
7
33
  DEFAULT_PRECISION = 2
8
34
 
@@ -11,9 +37,9 @@ module RSpec
11
37
  minutes = duration.to_i / 60
12
38
  seconds = duration - minutes * 60
13
39
 
14
- "#{pluralize(minutes, 'minute')} #{format_seconds(seconds)} seconds"
40
+ "#{pluralize(minutes, 'minute')} #{pluralize(format_seconds(seconds), 'second')}"
15
41
  else
16
- "#{format_seconds(duration)} seconds"
42
+ pluralize(format_seconds(duration), 'second')
17
43
  end
18
44
  end
19
45
 
@@ -29,9 +55,8 @@ module RSpec
29
55
  end
30
56
 
31
57
  def pluralize(count, string)
32
- "#{count} #{string}#{'s' unless count == 1}"
58
+ "#{count} #{string}#{'s' unless count.to_f == 1}"
33
59
  end
34
-
35
60
  end
36
61
 
37
62
  end
@@ -1,17 +1,17 @@
1
- require 'erb'
2
1
  require 'rspec/core/formatters/base_text_formatter'
2
+ require 'rspec/core/formatters/html_printer'
3
3
 
4
4
  module RSpec
5
5
  module Core
6
6
  module Formatters
7
7
  class HtmlFormatter < BaseTextFormatter
8
- include ERB::Util # for the #h method
9
8
 
10
9
  def initialize(output)
11
10
  super(output)
12
11
  @example_group_number = 0
13
12
  @example_number = 0
14
13
  @header_red = nil
14
+ @printer = HtmlPrinter.new(output)
15
15
  end
16
16
 
17
17
  private
@@ -35,29 +35,25 @@ module RSpec
35
35
 
36
36
  def start(example_count)
37
37
  super(example_count)
38
- @output.puts html_header
39
- @output.puts report_header
40
- @output.flush
38
+ @printer.print_html_start
39
+ @printer.flush
41
40
  end
42
41
 
43
42
  def example_group_started(example_group)
44
43
  super(example_group)
45
44
  @example_group_red = false
46
45
  @example_group_number += 1
46
+
47
47
  unless example_group_number == 1
48
- @output.puts " </dl>"
49
- @output.puts "</div>"
48
+ @printer.print_example_group_end
50
49
  end
51
- @output.puts "<div id=\"div_group_#{example_group_number}\" class=\"example_group passed\">"
52
- @output.puts " <dl #{current_indentation}>"
53
- @output.puts " <dt id=\"example_group_#{example_group_number}\" class=\"passed\">#{h(example_group.description)}</dt>"
54
- @output.flush
50
+ @printer.print_example_group_start( example_group_number, example_group.description, example_group.parent_groups.size )
51
+ @printer.flush
55
52
  end
56
53
 
57
54
  def start_dump
58
- @output.puts " </dl>"
59
- @output.puts "</div>"
60
- @output.flush
55
+ @printer.print_example_group_end
56
+ @printer.flush
61
57
  end
62
58
 
63
59
  def example_started(example)
@@ -66,41 +62,55 @@ module RSpec
66
62
  end
67
63
 
68
64
  def example_passed(example)
69
- move_progress
70
- @output.puts " <dd class=\"example passed\"><span class=\"passed_spec_name\">#{h(example.description)}</span><span class='duration'>#{sprintf("%.5f", example.execution_result[:run_time])}s</span></dd>"
71
- @output.flush
65
+ @printer.move_progress(percent_done)
66
+ @printer.print_example_passed( example.description, example.execution_result[:run_time] )
67
+ @printer.flush
72
68
  end
73
69
 
74
70
  def example_failed(example)
75
71
  super(example)
72
+
73
+ unless @header_red
74
+ @header_red = true
75
+ @printer.make_header_red
76
+ end
77
+
78
+ unless @example_group_red
79
+ @example_group_red = true
80
+ @printer.make_example_group_header_red(example_group_number)
81
+ end
82
+
83
+ @printer.move_progress(percent_done)
84
+
76
85
  exception = example.metadata[:execution_result][:exception]
86
+ exception_details = if exception
87
+ {
88
+ :message => exception.message,
89
+ :backtrace => format_backtrace(exception.backtrace, example.metadata).join("\n")
90
+ }
91
+ else
92
+ false
93
+ end
77
94
  extra = extra_failure_content(exception)
78
- @output.puts " <script type=\"text/javascript\">makeRed('rspec-header');</script>" unless @header_red
79
- @header_red = true
80
- @output.puts " <script type=\"text/javascript\">makeRed('div_group_#{example_group_number}');</script>" unless @example_group_red
81
- @output.puts " <script type=\"text/javascript\">makeRed('example_group_#{example_group_number}');</script>" unless @example_group_red
82
- @example_group_red = true
83
- move_progress
84
- @output.puts " <dd class=\"example #{exception.pending_fixed? ? 'pending_fixed' : 'failed'}\">"
85
- @output.puts " <span class=\"failed_spec_name\">#{h(example.description)}</span>"
86
- @output.puts " <span class=\"duration\">#{sprintf('%.5f', example.execution_result[:run_time])}s</span>"
87
- @output.puts " <div class=\"failure\" id=\"failure_#{@failed_examples.size}\">"
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
95
+
96
+ @printer.print_example_failed(
97
+ exception.pending_fixed?,
98
+ example.description,
99
+ example.execution_result[:run_time],
100
+ @failed_examples.size,
101
+ exception_details,
102
+ (extra == "") ? false : extra
103
+ )
104
+ @printer.flush
94
105
  end
95
106
 
96
107
  def example_pending(example)
97
- message = example.metadata[:execution_result][:pending_message]
98
- @output.puts " <script type=\"text/javascript\">makeYellow('rspec-header');</script>" unless @header_red
99
- @output.puts " <script type=\"text/javascript\">makeYellow('div_group_#{example_group_number}');</script>" unless @example_group_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=\"example not_implemented\"><span class=\"not_implemented_spec_name\">#{h(example.description)} (PENDING: #{h(message)})</span></dd>"
103
- @output.flush
108
+
109
+ @printer.make_header_yellow unless @header_red
110
+ @printer.make_example_group_header_yellow(example_group_number) unless @example_group_red
111
+ @printer.move_progress(percent_done)
112
+ @printer.print_example_pending( example.description, example.metadata[:execution_result][:pending_message] )
113
+ @printer.flush
104
114
  end
105
115
 
106
116
  # Override this method if you wish to output extra HTML for a failed spec. For example, you
@@ -114,11 +124,6 @@ module RSpec
114
124
  " <pre class=\"ruby\"><code>#{@snippet_extractor.snippet(backtrace)}</code></pre>"
115
125
  end
116
126
 
117
- def move_progress
118
- @output.puts " <script type=\"text/javascript\">moveProgressBar('#{percent_done}');</script>"
119
- @output.flush
120
- end
121
-
122
127
  def percent_done
123
128
  result = 100.0
124
129
  if @example_count > 0
@@ -134,329 +139,14 @@ module RSpec
134
139
  end
135
140
 
136
141
  def dump_summary(duration, example_count, failure_count, pending_count)
137
- # TODO - kill dry_run?
138
- if dry_run?
139
- totals = "This was a dry-run"
140
- else
141
- totals = "#{example_count} example#{'s' unless example_count == 1}, "
142
- totals << "#{failure_count} failure#{'s' unless failure_count == 1}"
143
- totals << ", #{pending_count} pending" if pending_count > 0
144
- end
145
- @output.puts "<script type=\"text/javascript\">document.getElementById('duration').innerHTML = \"Finished in <strong>#{sprintf("%.5f", duration)} seconds</strong>\";</script>"
146
- @output.puts "<script type=\"text/javascript\">document.getElementById('totals').innerHTML = \"#{totals}\";</script>"
147
- @output.puts "</div>"
148
- @output.puts "</div>"
149
- @output.puts "</body>"
150
- @output.puts "</html>"
151
- @output.flush
152
- end
153
-
154
- def current_indentation
155
- "style=\"margin-left: #{(example_group.ancestors.size - 1) * 15}px;\""
156
- end
157
-
158
- def html_header
159
- <<-EOF
160
- <?xml version="1.0" encoding="UTF-8"?>
161
- <!DOCTYPE html
162
- PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
163
- "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
164
- <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
165
- <head>
166
- <title>RSpec results</title>
167
- <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
168
- <meta http-equiv="Expires" content="-1" />
169
- <meta http-equiv="Pragma" content="no-cache" />
170
- <style type="text/css">
171
- body {
172
- margin: 0;
173
- padding: 0;
174
- background: #fff;
175
- font-size: 80%;
176
- }
177
- </style>
178
- <script type="text/javascript">
179
- // <![CDATA[
180
- #{global_scripts}
181
- // ]]>
182
- </script>
183
- <style type="text/css">
184
- #{global_styles}
185
- </style>
186
- </head>
187
- <body>
188
- EOF
189
- end
190
-
191
- def report_header
192
- <<-EOF
193
- <div class="rspec-report">
194
-
195
- <div id="rspec-header">
196
- <div id="label">
197
- <h1>RSpec Code Examples</h1>
198
- </div>
199
-
200
- <div id="display-filters">
201
- <input id="passed_checkbox" name="passed_checkbox" type="checkbox" checked onchange="apply_filters()" value="1"> <label for="passed_checkbox">Passed</label>
202
- <input id="failed_checkbox" name="failed_checkbox" type="checkbox" checked onchange="apply_filters()" value="2"> <label for="failed_checkbox">Failed</label>
203
- <input id="pending_checkbox" name="pending_checkbox" type="checkbox" checked onchange="apply_filters()" value="3"> <label for="pending_checkbox">Pending</label>
204
- </div>
205
-
206
- <div id="summary">
207
- <p id="totals">&nbsp;</p>
208
- <p id="duration">&nbsp;</p>
209
- </div>
210
- </div>
211
-
212
-
213
- <div class="results">
214
- EOF
215
- end
216
-
217
- def global_scripts
218
- <<-EOF
219
-
220
- function addClass(element_id, classname) {
221
- document.getElementById(element_id).className += (" " + classname);
222
- }
223
-
224
- function removeClass(element_id, classname) {
225
- var elem = document.getElementById(element_id);
226
- var classlist = elem.className.replace(classname,'');
227
- elem.className = classlist;
228
- }
229
-
230
- function moveProgressBar(percentDone) {
231
- document.getElementById("rspec-header").style.width = percentDone +"%";
232
- }
233
-
234
- function makeRed(element_id) {
235
- removeClass(element_id, 'passed');
236
- removeClass(element_id, 'not_implemented');
237
- addClass(element_id,'failed');
238
- }
239
-
240
- function makeYellow(element_id) {
241
- var elem = document.getElementById(element_id);
242
- if (elem.className.indexOf("failed") == -1) { // class doesn't includes failed
243
- if (elem.className.indexOf("not_implemented") == -1) { // class doesn't include not_implemented
244
- removeClass(element_id, 'passed');
245
- addClass(element_id,'not_implemented');
246
- }
247
- }
248
- }
249
-
250
- function apply_filters() {
251
- var passed_filter = document.getElementById('passed_checkbox').checked;
252
- var failed_filter = document.getElementById('failed_checkbox').checked;
253
- var pending_filter = document.getElementById('pending_checkbox').checked;
254
-
255
- assign_display_style("example passed", passed_filter);
256
- assign_display_style("example failed", failed_filter);
257
- assign_display_style("example not_implemented", pending_filter);
258
-
259
- assign_display_style_for_group("example_group passed", passed_filter);
260
- assign_display_style_for_group("example_group not_implemented", pending_filter, pending_filter || passed_filter);
261
- assign_display_style_for_group("example_group failed", failed_filter, failed_filter || pending_filter || passed_filter);
262
- }
263
-
264
- function get_display_style(display_flag) {
265
- var style_mode = 'none';
266
- if (display_flag == true) {
267
- style_mode = 'block';
268
- }
269
- return style_mode;
270
- }
271
-
272
- function assign_display_style(classname, display_flag) {
273
- var style_mode = get_display_style(display_flag);
274
- var elems = document.getElementsByClassName(classname)
275
- for (var i=0; i<elems.length;i++) {
276
- elems[i].style.display = style_mode;
277
- }
278
- }
279
-
280
- function assign_display_style_for_group(classname, display_flag, subgroup_flag) {
281
- var display_style_mode = get_display_style(display_flag);
282
- var subgroup_style_mode = get_display_style(subgroup_flag);
283
- var elems = document.getElementsByClassName(classname)
284
- for (var i=0; i<elems.length;i++) {
285
- var style_mode = display_style_mode;
286
- if ((display_flag != subgroup_flag) && (elems[i].getElementsByTagName('dt')[0].innerHTML.indexOf(", ") != -1)) {
287
- elems[i].style.display = subgroup_style_mode;
288
- } else {
289
- elems[i].style.display = display_style_mode;
290
- }
291
- }
292
- }
293
- EOF
294
- end
295
-
296
- def global_styles
297
- <<-EOF
298
- #rspec-header {
299
- background: #65C400; color: #fff; height: 4em;
300
- }
301
-
302
- .rspec-report h1 {
303
- margin: 0px 10px 0px 10px;
304
- padding: 10px;
305
- font-family: "Lucida Grande", Helvetica, sans-serif;
306
- font-size: 1.8em;
307
- position: absolute;
308
- }
309
-
310
- #label {
311
- float:left;
312
- }
313
-
314
- #display-filters {
315
- float:left;
316
- padding: 28px 0 0 40%;
317
- font-family: "Lucida Grande", Helvetica, sans-serif;
318
- }
319
-
320
- #summary {
321
- float:right;
322
- padding: 5px 10px;
323
- font-family: "Lucida Grande", Helvetica, sans-serif;
324
- text-align: right;
325
- }
326
-
327
- #summary p {
328
- margin: 0 0 0 2px;
329
- }
330
-
331
- #summary #totals {
332
- font-size: 1.2em;
333
- }
334
-
335
- .example_group {
336
- margin: 0 10px 5px;
337
- background: #fff;
338
- }
339
-
340
- dl {
341
- margin: 0; padding: 0 0 5px;
342
- font: normal 11px "Lucida Grande", Helvetica, sans-serif;
343
- }
344
-
345
- dt {
346
- padding: 3px;
347
- background: #65C400;
348
- color: #fff;
349
- font-weight: bold;
350
- }
351
-
352
- dd {
353
- margin: 5px 0 5px 5px;
354
- padding: 3px 3px 3px 18px;
355
- }
356
-
357
- dd .duration {
358
- padding-left: 5px;
359
- text-align: right;
360
- right: 0px;
361
- float:right;
362
- }
363
-
364
- dd.example.passed {
365
- border-left: 5px solid #65C400;
366
- border-bottom: 1px solid #65C400;
367
- background: #DBFFB4; color: #3D7700;
368
- }
369
-
370
- dd.example.not_implemented {
371
- border-left: 5px solid #FAF834;
372
- border-bottom: 1px solid #FAF834;
373
- background: #FCFB98; color: #131313;
374
- }
375
-
376
- dd.example.pending_fixed {
377
- border-left: 5px solid #0000C2;
378
- border-bottom: 1px solid #0000C2;
379
- color: #0000C2; background: #D3FBFF;
380
- }
381
-
382
- dd.example.failed {
383
- border-left: 5px solid #C20000;
384
- border-bottom: 1px solid #C20000;
385
- color: #C20000; background: #FFFBD3;
386
- }
387
-
388
-
389
- dt.not_implemented {
390
- color: #000000; background: #FAF834;
391
- }
392
-
393
- dt.pending_fixed {
394
- color: #FFFFFF; background: #C40D0D;
395
- }
396
-
397
- dt.failed {
398
- color: #FFFFFF; background: #C40D0D;
399
- }
400
-
401
-
402
- #rspec-header.not_implemented {
403
- color: #000000; background: #FAF834;
404
- }
405
-
406
- #rspec-header.pending_fixed {
407
- color: #FFFFFF; background: #C40D0D;
408
- }
409
-
410
- #rspec-header.failed {
411
- color: #FFFFFF; background: #C40D0D;
412
- }
413
-
414
-
415
- .backtrace {
416
- color: #000;
417
- font-size: 12px;
418
- }
419
-
420
- a {
421
- color: #BE5C00;
422
- }
423
-
424
- /* Ruby code, style similar to vibrant ink */
425
- .ruby {
426
- font-size: 12px;
427
- font-family: monospace;
428
- color: white;
429
- background-color: black;
430
- padding: 0.1em 0 0.2em 0;
431
- }
432
-
433
- .ruby .keyword { color: #FF6600; }
434
- .ruby .constant { color: #339999; }
435
- .ruby .attribute { color: white; }
436
- .ruby .global { color: white; }
437
- .ruby .module { color: white; }
438
- .ruby .class { color: white; }
439
- .ruby .string { color: #66FF00; }
440
- .ruby .ident { color: white; }
441
- .ruby .method { color: #FFCC00; }
442
- .ruby .number { color: white; }
443
- .ruby .char { color: white; }
444
- .ruby .comment { color: #9933CC; }
445
- .ruby .symbol { color: white; }
446
- .ruby .regex { color: #44B4CC; }
447
- .ruby .punct { color: white; }
448
- .ruby .escape { color: white; }
449
- .ruby .interp { color: white; }
450
- .ruby .expr { color: white; }
451
-
452
- .ruby .offending { background-color: gray; }
453
- .ruby .linenum {
454
- width: 75px;
455
- padding: 0.1em 1em 0.2em 0;
456
- color: #000000;
457
- background-color: #FFFBD3;
458
- }
459
- EOF
142
+ @printer.print_summary(
143
+ dry_run?,
144
+ duration,
145
+ example_count,
146
+ failure_count,
147
+ pending_count
148
+ )
149
+ @printer.flush
460
150
  end
461
151
  end
462
152
  end