opal-rspec-cj 0.4.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (176) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +3 -0
  3. data/.gitmodules +15 -0
  4. data/.travis.yml +13 -0
  5. data/.yardopts +5 -0
  6. data/CHANGELOG.md +25 -0
  7. data/Gemfile +8 -0
  8. data/README.md +147 -0
  9. data/Rakefile +26 -0
  10. data/config.ru +10 -0
  11. data/example/Gemfile +4 -0
  12. data/example/README.md +13 -0
  13. data/example/Rakefile +8 -0
  14. data/example/opal/user.rb +11 -0
  15. data/example/spec/user_spec.rb +15 -0
  16. data/lib/opal-rspec.rb +2 -0
  17. data/lib/opal/rspec.rb +20 -0
  18. data/lib/opal/rspec/rake_task.rb +63 -0
  19. data/lib/opal/rspec/version.rb +5 -0
  20. data/opal-rspec.gemspec +21 -0
  21. data/opal/opal-rspec.rb +1 -0
  22. data/opal/opal/rspec.rb +25 -0
  23. data/opal/opal/rspec/async.rb +289 -0
  24. data/opal/opal/rspec/browser_formatter.rb +188 -0
  25. data/opal/opal/rspec/fixes.rb +116 -0
  26. data/opal/opal/rspec/requires.rb +45 -0
  27. data/opal/opal/rspec/runner.rb +69 -0
  28. data/opal/opal/rspec/sprockets_runner.rb.erb +11 -0
  29. data/opal/opal/rspec/text_formatter.rb +74 -0
  30. data/spec/async_spec.rb +38 -0
  31. data/spec/example_spec.rb +163 -0
  32. data/spec/matchers_spec.rb +201 -0
  33. data/spec/mock_spec.rb +63 -0
  34. data/spec/named_subject_spec.rb +11 -0
  35. data/spec/should_syntax_spec.rb +17 -0
  36. data/vendor/spec_runner.js +50 -0
  37. data/vendor_lib/rspec-expectations.rb +1 -0
  38. data/vendor_lib/rspec.rb +3 -0
  39. data/vendor_lib/rspec/autorun.rb +2 -0
  40. data/vendor_lib/rspec/core.rb +203 -0
  41. data/vendor_lib/rspec/core/backport_random.rb +302 -0
  42. data/vendor_lib/rspec/core/backtrace_formatter.rb +65 -0
  43. data/vendor_lib/rspec/core/command_line.rb +36 -0
  44. data/vendor_lib/rspec/core/configuration.rb +1129 -0
  45. data/vendor_lib/rspec/core/configuration_options.rb +143 -0
  46. data/vendor_lib/rspec/core/drb_command_line.rb +26 -0
  47. data/vendor_lib/rspec/core/drb_options.rb +87 -0
  48. data/vendor_lib/rspec/core/dsl.rb +26 -0
  49. data/vendor_lib/rspec/core/example.rb +312 -0
  50. data/vendor_lib/rspec/core/example_group.rb +540 -0
  51. data/vendor_lib/rspec/core/filter_manager.rb +224 -0
  52. data/vendor_lib/rspec/core/flat_map.rb +17 -0
  53. data/vendor_lib/rspec/core/formatters.rb +54 -0
  54. data/vendor_lib/rspec/core/formatters/base_formatter.rb +291 -0
  55. data/vendor_lib/rspec/core/formatters/base_text_formatter.rb +307 -0
  56. data/vendor_lib/rspec/core/formatters/deprecation_formatter.rb +193 -0
  57. data/vendor_lib/rspec/core/formatters/documentation_formatter.rb +67 -0
  58. data/vendor_lib/rspec/core/formatters/helpers.rb +82 -0
  59. data/vendor_lib/rspec/core/formatters/html_formatter.rb +155 -0
  60. data/vendor_lib/rspec/core/formatters/html_printer.rb +408 -0
  61. data/vendor_lib/rspec/core/formatters/json_formatter.rb +99 -0
  62. data/vendor_lib/rspec/core/formatters/progress_formatter.rb +32 -0
  63. data/vendor_lib/rspec/core/formatters/snippet_extractor.rb +101 -0
  64. data/vendor_lib/rspec/core/hooks.rb +535 -0
  65. data/vendor_lib/rspec/core/memoized_helpers.rb +431 -0
  66. data/vendor_lib/rspec/core/metadata.rb +313 -0
  67. data/vendor_lib/rspec/core/mocking/with_absolutely_nothing.rb +11 -0
  68. data/vendor_lib/rspec/core/mocking/with_flexmock.rb +27 -0
  69. data/vendor_lib/rspec/core/mocking/with_mocha.rb +52 -0
  70. data/vendor_lib/rspec/core/mocking/with_rr.rb +27 -0
  71. data/vendor_lib/rspec/core/mocking/with_rspec.rb +27 -0
  72. data/vendor_lib/rspec/core/option_parser.rb +234 -0
  73. data/vendor_lib/rspec/core/ordering.rb +154 -0
  74. data/vendor_lib/rspec/core/pending.rb +110 -0
  75. data/vendor_lib/rspec/core/project_initializer.rb +88 -0
  76. data/vendor_lib/rspec/core/rake_task.rb +128 -0
  77. data/vendor_lib/rspec/core/reporter.rb +132 -0
  78. data/vendor_lib/rspec/core/ruby_project.rb +44 -0
  79. data/vendor_lib/rspec/core/runner.rb +97 -0
  80. data/vendor_lib/rspec/core/shared_context.rb +53 -0
  81. data/vendor_lib/rspec/core/shared_example_group.rb +146 -0
  82. data/vendor_lib/rspec/core/shared_example_group/collection.rb +27 -0
  83. data/vendor_lib/rspec/core/version.rb +7 -0
  84. data/vendor_lib/rspec/core/warnings.rb +22 -0
  85. data/vendor_lib/rspec/core/world.rb +131 -0
  86. data/vendor_lib/rspec/expectations.rb +75 -0
  87. data/vendor_lib/rspec/expectations/differ.rb +154 -0
  88. data/vendor_lib/rspec/expectations/errors.rb +9 -0
  89. data/vendor_lib/rspec/expectations/expectation_target.rb +87 -0
  90. data/vendor_lib/rspec/expectations/extensions.rb +1 -0
  91. data/vendor_lib/rspec/expectations/extensions/object.rb +29 -0
  92. data/vendor_lib/rspec/expectations/fail_with.rb +79 -0
  93. data/vendor_lib/rspec/expectations/handler.rb +68 -0
  94. data/vendor_lib/rspec/expectations/syntax.rb +182 -0
  95. data/vendor_lib/rspec/expectations/version.rb +8 -0
  96. data/vendor_lib/rspec/matchers.rb +633 -0
  97. data/vendor_lib/rspec/matchers/built_in.rb +39 -0
  98. data/vendor_lib/rspec/matchers/built_in/base_matcher.rb +68 -0
  99. data/vendor_lib/rspec/matchers/built_in/be.rb +213 -0
  100. data/vendor_lib/rspec/matchers/built_in/be_instance_of.rb +15 -0
  101. data/vendor_lib/rspec/matchers/built_in/be_kind_of.rb +11 -0
  102. data/vendor_lib/rspec/matchers/built_in/be_within.rb +55 -0
  103. data/vendor_lib/rspec/matchers/built_in/change.rb +141 -0
  104. data/vendor_lib/rspec/matchers/built_in/cover.rb +21 -0
  105. data/vendor_lib/rspec/matchers/built_in/eq.rb +22 -0
  106. data/vendor_lib/rspec/matchers/built_in/eql.rb +23 -0
  107. data/vendor_lib/rspec/matchers/built_in/equal.rb +48 -0
  108. data/vendor_lib/rspec/matchers/built_in/exist.rb +26 -0
  109. data/vendor_lib/rspec/matchers/built_in/has.rb +48 -0
  110. data/vendor_lib/rspec/matchers/built_in/include.rb +61 -0
  111. data/vendor_lib/rspec/matchers/built_in/match.rb +17 -0
  112. data/vendor_lib/rspec/matchers/built_in/match_array.rb +51 -0
  113. data/vendor_lib/rspec/matchers/built_in/raise_error.rb +154 -0
  114. data/vendor_lib/rspec/matchers/built_in/respond_to.rb +74 -0
  115. data/vendor_lib/rspec/matchers/built_in/satisfy.rb +30 -0
  116. data/vendor_lib/rspec/matchers/built_in/start_and_end_with.rb +48 -0
  117. data/vendor_lib/rspec/matchers/built_in/throw_symbol.rb +94 -0
  118. data/vendor_lib/rspec/matchers/built_in/yield.rb +297 -0
  119. data/vendor_lib/rspec/matchers/compatibility.rb +14 -0
  120. data/vendor_lib/rspec/matchers/configuration.rb +113 -0
  121. data/vendor_lib/rspec/matchers/dsl.rb +23 -0
  122. data/vendor_lib/rspec/matchers/generated_descriptions.rb +35 -0
  123. data/vendor_lib/rspec/matchers/matcher.rb +301 -0
  124. data/vendor_lib/rspec/matchers/method_missing.rb +12 -0
  125. data/vendor_lib/rspec/matchers/operator_matcher.rb +99 -0
  126. data/vendor_lib/rspec/matchers/pretty.rb +70 -0
  127. data/vendor_lib/rspec/matchers/test_unit_integration.rb +11 -0
  128. data/vendor_lib/rspec/mocks.rb +100 -0
  129. data/vendor_lib/rspec/mocks/any_instance/chain.rb +92 -0
  130. data/vendor_lib/rspec/mocks/any_instance/expectation_chain.rb +47 -0
  131. data/vendor_lib/rspec/mocks/any_instance/message_chains.rb +75 -0
  132. data/vendor_lib/rspec/mocks/any_instance/recorder.rb +200 -0
  133. data/vendor_lib/rspec/mocks/any_instance/stub_chain.rb +45 -0
  134. data/vendor_lib/rspec/mocks/any_instance/stub_chain_chain.rb +23 -0
  135. data/vendor_lib/rspec/mocks/argument_list_matcher.rb +104 -0
  136. data/vendor_lib/rspec/mocks/argument_matchers.rb +264 -0
  137. data/vendor_lib/rspec/mocks/arity_calculator.rb +66 -0
  138. data/vendor_lib/rspec/mocks/configuration.rb +111 -0
  139. data/vendor_lib/rspec/mocks/error_generator.rb +203 -0
  140. data/vendor_lib/rspec/mocks/errors.rb +12 -0
  141. data/vendor_lib/rspec/mocks/example_methods.rb +201 -0
  142. data/vendor_lib/rspec/mocks/extensions/marshal.rb +17 -0
  143. data/vendor_lib/rspec/mocks/framework.rb +36 -0
  144. data/vendor_lib/rspec/mocks/instance_method_stasher.rb +112 -0
  145. data/vendor_lib/rspec/mocks/matchers/have_received.rb +99 -0
  146. data/vendor_lib/rspec/mocks/matchers/receive.rb +112 -0
  147. data/vendor_lib/rspec/mocks/matchers/receive_messages.rb +72 -0
  148. data/vendor_lib/rspec/mocks/message_expectation.rb +643 -0
  149. data/vendor_lib/rspec/mocks/method_double.rb +209 -0
  150. data/vendor_lib/rspec/mocks/method_reference.rb +95 -0
  151. data/vendor_lib/rspec/mocks/mock.rb +7 -0
  152. data/vendor_lib/rspec/mocks/mutate_const.rb +406 -0
  153. data/vendor_lib/rspec/mocks/object_reference.rb +90 -0
  154. data/vendor_lib/rspec/mocks/order_group.rb +82 -0
  155. data/vendor_lib/rspec/mocks/proxy.rb +269 -0
  156. data/vendor_lib/rspec/mocks/proxy_for_nil.rb +37 -0
  157. data/vendor_lib/rspec/mocks/space.rb +95 -0
  158. data/vendor_lib/rspec/mocks/standalone.rb +3 -0
  159. data/vendor_lib/rspec/mocks/stub_chain.rb +51 -0
  160. data/vendor_lib/rspec/mocks/syntax.rb +374 -0
  161. data/vendor_lib/rspec/mocks/targets.rb +90 -0
  162. data/vendor_lib/rspec/mocks/test_double.rb +109 -0
  163. data/vendor_lib/rspec/mocks/verifying_double.rb +77 -0
  164. data/vendor_lib/rspec/mocks/verifying_message_expecation.rb +60 -0
  165. data/vendor_lib/rspec/mocks/verifying_proxy.rb +151 -0
  166. data/vendor_lib/rspec/mocks/version.rb +7 -0
  167. data/vendor_lib/rspec/support.rb +6 -0
  168. data/vendor_lib/rspec/support/caller_filter.rb +56 -0
  169. data/vendor_lib/rspec/support/spec.rb +14 -0
  170. data/vendor_lib/rspec/support/spec/deprecation_helpers.rb +29 -0
  171. data/vendor_lib/rspec/support/spec/in_sub_process.rb +40 -0
  172. data/vendor_lib/rspec/support/spec/stderr_splitter.rb +50 -0
  173. data/vendor_lib/rspec/support/version.rb +7 -0
  174. data/vendor_lib/rspec/support/warnings.rb +41 -0
  175. data/vendor_lib/rspec/version.rb +5 -0
  176. metadata +268 -0
@@ -0,0 +1,143 @@
1
+ require 'erb'
2
+ require 'shellwords'
3
+
4
+ module RSpec
5
+ module Core
6
+ # @private
7
+ class ConfigurationOptions
8
+ attr_reader :options
9
+
10
+ def initialize(args)
11
+ @args = args.map {|a|
12
+ a.sub("default_path", "default-path").sub("line_number", "line-number")
13
+ }
14
+ end
15
+
16
+ def configure(config)
17
+ config.filter_manager = filter_manager
18
+
19
+ config.libs = options[:libs] || []
20
+ config.setup_load_path_and_require(options[:requires] || [])
21
+
22
+ process_options_into config
23
+ load_formatters_into config
24
+ end
25
+
26
+ def parse_options
27
+ @options = (file_options << command_line_options << env_options).
28
+ each {|opts|
29
+ filter_manager.include opts.delete(:inclusion_filter) if opts.has_key?(:inclusion_filter)
30
+ filter_manager.exclude opts.delete(:exclusion_filter) if opts.has_key?(:exclusion_filter)
31
+ }.
32
+ inject {|h, opts|
33
+ h.merge(opts) {|k, oldval, newval|
34
+ [:libs, :requires].include?(k) ? oldval + newval : newval
35
+ }
36
+ }
37
+ end
38
+
39
+ def drb_argv
40
+ DrbOptions.new(options, filter_manager).options
41
+ end
42
+
43
+ def filter_manager
44
+ @filter_manager ||= RSpec::configuration.filter_manager
45
+ end
46
+
47
+ private
48
+
49
+ UNFORCED_OPTIONS = [
50
+ :requires, :profile, :drb, :libs, :files_or_directories_to_run,
51
+ :line_numbers, :full_description, :full_backtrace, :tty
52
+ ].to_set
53
+
54
+ UNPROCESSABLE_OPTIONS = [:libs, :formatters, :requires].to_set
55
+
56
+ def force?(key)
57
+ !UNFORCED_OPTIONS.include?(key)
58
+ end
59
+
60
+ def order(keys, *ordered)
61
+ ordered.reverse.each do |key|
62
+ keys.unshift(key) if keys.delete(key)
63
+ end
64
+ keys
65
+ end
66
+
67
+ def process_options_into(config)
68
+ opts = options.reject { |k, _| UNPROCESSABLE_OPTIONS.include? k }
69
+
70
+ order(opts.keys, :default_path, :pattern).each do |key|
71
+ force?(key) ? config.force(key => opts[key]) : config.send("#{key}=", opts[key])
72
+ end
73
+ end
74
+
75
+ def load_formatters_into(config)
76
+ options[:formatters].each { |pair| config.add_formatter(*pair) } if options[:formatters]
77
+ end
78
+
79
+ def file_options
80
+ custom_options_file ? [custom_options] : [global_options, project_options, local_options]
81
+ end
82
+
83
+ def env_options
84
+ ENV["SPEC_OPTS"] ? Parser.parse!(Shellwords.split(ENV["SPEC_OPTS"])) : {}
85
+ end
86
+
87
+ def command_line_options
88
+ @command_line_options ||= Parser.parse!(@args).merge :files_or_directories_to_run => @args
89
+ end
90
+
91
+ def custom_options
92
+ options_from(custom_options_file)
93
+ end
94
+
95
+ def local_options
96
+ @local_options ||= options_from(local_options_file)
97
+ end
98
+
99
+ def project_options
100
+ @project_options ||= options_from(project_options_file)
101
+ end
102
+
103
+ def global_options
104
+ @global_options ||= options_from(global_options_file)
105
+ end
106
+
107
+ def options_from(path)
108
+ Parser.parse(args_from_options_file(path))
109
+ end
110
+
111
+ def args_from_options_file(path)
112
+ return [] unless path && File.exist?(path)
113
+ config_string = options_file_as_erb_string(path)
114
+ FlatMap.flat_map(config_string.split(/\n+/), &:shellsplit)
115
+ end
116
+
117
+ def options_file_as_erb_string(path)
118
+ ERB.new(File.read(path), nil, '-').result(binding)
119
+ end
120
+
121
+ def custom_options_file
122
+ command_line_options[:custom_options_file]
123
+ end
124
+
125
+ def project_options_file
126
+ ".rspec"
127
+ end
128
+
129
+ def local_options_file
130
+ ".rspec-local"
131
+ end
132
+
133
+ def global_options_file
134
+ begin
135
+ File.join(File.expand_path("~"), ".rspec")
136
+ rescue ArgumentError
137
+ RSpec.warning "Unable to find ~/.rspec because the HOME environment variable is not set"
138
+ nil
139
+ end
140
+ end
141
+ end
142
+ end
143
+ end
@@ -0,0 +1,26 @@
1
+ require 'drb/drb'
2
+ require 'rspec/core/drb_options'
3
+
4
+ module RSpec
5
+ module Core
6
+ class DRbCommandLine
7
+ def initialize(options)
8
+ @options = options
9
+ end
10
+
11
+ def drb_port
12
+ @options.options[:drb_port] || ENV['RSPEC_DRB'] || 8989
13
+ end
14
+
15
+ def run(err, out)
16
+ begin
17
+ DRb.start_service("druby://localhost:0")
18
+ rescue SocketError, Errno::EADDRNOTAVAIL
19
+ DRb.start_service("druby://:0")
20
+ end
21
+ spec_server = DRbObject.new_with_uri("druby://127.0.0.1:#{drb_port}")
22
+ spec_server.run(@options.drb_argv, err, out)
23
+ end
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,87 @@
1
+ # Builds command line arguments to pass to the rspec command over DRb
2
+
3
+ module RSpec::Core
4
+ # @private
5
+ class DrbOptions
6
+ def initialize(submitted_options, filter_manager)
7
+ @submitted_options = submitted_options
8
+ @filter_manager = filter_manager
9
+ end
10
+
11
+ def options
12
+ argv = []
13
+ argv << "--color" if @submitted_options[:color]
14
+ argv << "--profile" if @submitted_options[:profile_examples]
15
+ argv << "--backtrace" if @submitted_options[:full_backtrace]
16
+ argv << "--tty" if @submitted_options[:tty]
17
+ argv << "--fail-fast" if @submitted_options[:fail_fast]
18
+ argv << "--options" << @submitted_options[:custom_options_file] if @submitted_options[:custom_options_file]
19
+ argv << "--order" << @submitted_options[:order] if @submitted_options[:order]
20
+
21
+ add_failure_exit_code(argv)
22
+ add_full_description(argv)
23
+ add_line_numbers(argv)
24
+ add_filter(argv, :inclusion, @filter_manager.inclusions)
25
+ add_filter(argv, :exclusion, @filter_manager.exclusions)
26
+ add_formatters(argv)
27
+ add_libs(argv)
28
+ add_requires(argv)
29
+
30
+ argv + @submitted_options[:files_or_directories_to_run]
31
+ end
32
+
33
+ def add_failure_exit_code(argv)
34
+ if @submitted_options[:failure_exit_code]
35
+ argv << "--failure-exit-code" << @submitted_options[:failure_exit_code].to_s
36
+ end
37
+ end
38
+
39
+ def add_full_description(argv)
40
+ if @submitted_options[:full_description]
41
+ # The argument to --example is regexp-escaped before being stuffed
42
+ # into a regexp when received for the first time (see OptionParser).
43
+ # Hence, merely grabbing the source of this regexp will retain the
44
+ # backslashes, so we must remove them.
45
+ @submitted_options[:full_description].each do |description|
46
+ argv << "--example" << description.source.delete('\\')
47
+ end
48
+ end
49
+ end
50
+
51
+ def add_line_numbers(argv)
52
+ if @submitted_options[:line_numbers]
53
+ argv.push(*@submitted_options[:line_numbers].inject([]){|a,l| a << "--line_number" << l})
54
+ end
55
+ end
56
+
57
+ CONDITIONAL_FILTERS = [:if, :unless]
58
+
59
+ def add_filter(argv, name, hash)
60
+ hash.each_pair do |k, v|
61
+ next if CONDITIONAL_FILTERS.include?(k)
62
+ tag = name == :inclusion ? k.to_s : "~#{k}"
63
+ tag << ":#{v}" if v.is_a?(String)
64
+ argv << "--tag" << tag
65
+ end unless hash.empty?
66
+ end
67
+
68
+ def add_formatters(argv)
69
+ @submitted_options[:formatters].each do |pair|
70
+ argv << "--format" << pair[0]
71
+ argv << "--out" << pair[1] if pair[1]
72
+ end if @submitted_options[:formatters]
73
+ end
74
+
75
+ def add_libs(argv)
76
+ @submitted_options[:libs].each do |path|
77
+ argv << "-I" << path
78
+ end if @submitted_options[:libs]
79
+ end
80
+
81
+ def add_requires(argv)
82
+ @submitted_options[:requires].each do |path|
83
+ argv << "--require" << path
84
+ end if @submitted_options[:requires]
85
+ end
86
+ end
87
+ end
@@ -0,0 +1,26 @@
1
+ module RSpec
2
+ module Core
3
+ # Adds the `describe` method to the top-level namespace.
4
+ module DSL
5
+ # Generates a subclass of {ExampleGroup}
6
+ #
7
+ # ## Examples:
8
+ #
9
+ # describe "something" do
10
+ # it "does something" do
11
+ # # example code goes here
12
+ # end
13
+ # end
14
+ #
15
+ # @see ExampleGroup
16
+ # @see ExampleGroup.describe
17
+ def describe(*args, &example_group_block)
18
+ RSpec::Core::ExampleGroup.describe(*args, &example_group_block).register
19
+ end
20
+ end
21
+ end
22
+ end
23
+
24
+ extend RSpec::Core::DSL
25
+ Module.send(:include, RSpec::Core::DSL)
26
+
@@ -0,0 +1,312 @@
1
+ module RSpec
2
+ module Core
3
+ # Wrapper for an instance of a subclass of {ExampleGroup}. An instance of
4
+ # `Example` is returned by the {ExampleGroup#example example} method
5
+ # exposed to examples, {Hooks#before before} and {Hooks#after after} hooks,
6
+ # and yielded to {Hooks#around around} hooks.
7
+ #
8
+ # Useful for configuring logging and/or taking some action based
9
+ # on the state of an example's metadata.
10
+ #
11
+ # @example
12
+ #
13
+ # RSpec.configure do |config|
14
+ # config.before do
15
+ # log example.description
16
+ # end
17
+ #
18
+ # config.after do
19
+ # log example.description
20
+ # end
21
+ #
22
+ # config.around do |ex|
23
+ # log example.description
24
+ # ex.run
25
+ # end
26
+ # end
27
+ #
28
+ # shared_examples "auditable" do
29
+ # it "does something" do
30
+ # log "#{example.full_description}: #{auditable.inspect}"
31
+ # auditable.should do_something
32
+ # end
33
+ # end
34
+ #
35
+ # @see ExampleGroup
36
+ class Example
37
+ # @private
38
+ #
39
+ # Used to define methods that delegate to this example's metadata
40
+ def self.delegate_to_metadata(*keys)
41
+ keys.each { |key| define_method(key) { @metadata[key] } }
42
+ end
43
+
44
+ delegate_to_metadata :full_description, :execution_result, :file_path, :pending, :location
45
+
46
+ # Returns the string submitted to `example` or its aliases (e.g.
47
+ # `specify`, `it`, etc). If no string is submitted (e.g. `it { should
48
+ # do_something }`) it returns the message generated by the matcher if
49
+ # there is one, otherwise returns a message including the location of the
50
+ # example.
51
+ def description
52
+ description = metadata[:description].to_s.empty? ? "example at #{location}" : metadata[:description]
53
+ RSpec.configuration.format_docstrings_block.call(description)
54
+ end
55
+
56
+ # @attr_reader
57
+ #
58
+ # Returns the first exception raised in the context of running this
59
+ # example (nil if no exception is raised)
60
+ attr_reader :exception
61
+
62
+ # @attr_reader
63
+ #
64
+ # Returns the metadata object associated with this example.
65
+ attr_reader :metadata
66
+
67
+ # @attr_reader
68
+ # @private
69
+ #
70
+ # Returns the example_group_instance that provides the context for
71
+ # running this example.
72
+ attr_reader :example_group_instance
73
+
74
+ # Creates a new instance of Example.
75
+ # @param example_group_class the subclass of ExampleGroup in which this Example is declared
76
+ # @param description the String passed to the `it` method (or alias)
77
+ # @param metadata additional args passed to `it` to be used as metadata
78
+ # @param example_block the block of code that represents the example
79
+ def initialize(example_group_class, description, metadata, example_block=nil)
80
+ @example_group_class, @options, @example_block = example_group_class, metadata, example_block
81
+ @metadata = @example_group_class.metadata.for_example(description, metadata)
82
+ @example_group_instance = @exception = nil
83
+ @pending_declared_in_example = false
84
+ end
85
+
86
+ # @deprecated access options via metadata instead
87
+ def options
88
+ @options
89
+ end
90
+
91
+ # Returns the example group class that provides the context for running
92
+ # this example.
93
+ def example_group
94
+ @example_group_class
95
+ end
96
+
97
+ alias_method :pending?, :pending
98
+
99
+ # @api private
100
+ # instance_evals the block passed to the constructor in the context of
101
+ # the instance of {ExampleGroup}.
102
+ # @param example_group_instance the instance of an ExampleGroup subclass
103
+ def run(example_group_instance, reporter)
104
+ @example_group_instance = example_group_instance
105
+ RSpec.current_example = self
106
+
107
+ start(reporter)
108
+
109
+ begin
110
+ unless pending || RSpec.configuration.dry_run?
111
+ with_around_each_hooks do
112
+ begin
113
+ run_before_each
114
+ @example_group_instance.instance_exec(self, &@example_block)
115
+ rescue Pending::PendingDeclaredInExample => e
116
+ @pending_declared_in_example = e.message
117
+ rescue Exception => e
118
+ set_exception(e)
119
+ ensure
120
+ run_after_each
121
+ end
122
+ end
123
+ end
124
+ rescue Exception => e
125
+ set_exception(e)
126
+ ensure
127
+ @example_group_instance.instance_variables.each do |ivar|
128
+ @example_group_instance.instance_variable_set(ivar, nil)
129
+ end
130
+ @example_group_instance = nil
131
+
132
+ begin
133
+ assign_generated_description
134
+ rescue Exception => e
135
+ set_exception(e, "while assigning the example description")
136
+ end
137
+ end
138
+
139
+ finish(reporter)
140
+ ensure
141
+ RSpec.current_example = nil
142
+ end
143
+
144
+ # Wraps a `Proc` and exposes a `run` method for use in {Hooks#around
145
+ # around} hooks.
146
+ #
147
+ # @note Procsy, itself, is not a public API, but we're documenting it
148
+ # here to document how to interact with the object yielded to an
149
+ # `around` hook.
150
+ #
151
+ # @example
152
+ #
153
+ # RSpec.configure do |c|
154
+ # c.around do |ex| # Procsy which wraps the example
155
+ # if ex.metadata[:key] == :some_value && some_global_condition
156
+ # raise "some message"
157
+ # end
158
+ # ex.run # run delegates to ex.call
159
+ # end
160
+ # end
161
+ class Procsy
162
+ # The `metadata` of the {Example} instance.
163
+ attr_reader :metadata
164
+
165
+ Proc.public_instance_methods(false).each do |name|
166
+ define_method(name) { |*a, &b| @proc.__send__(name, *a, &b) }
167
+ end
168
+ alias run call
169
+
170
+ def initialize(metadata, &block)
171
+ @metadata = metadata
172
+ @proc = block
173
+ end
174
+
175
+ # @api private
176
+ def wrap(&block)
177
+ self.class.new(metadata, &block)
178
+ end
179
+ end
180
+
181
+ # @private
182
+ def any_apply?(filters)
183
+ metadata.any_apply?(filters)
184
+ end
185
+
186
+ # @private
187
+ def all_apply?(filters)
188
+ @metadata.all_apply?(filters) || @example_group_class.all_apply?(filters)
189
+ end
190
+
191
+ # @private
192
+ def around_each_hooks
193
+ @around_each_hooks ||= example_group.around_each_hooks_for(self)
194
+ end
195
+
196
+ # @private
197
+ #
198
+ # Used internally to set an exception in an after hook, which
199
+ # captures the exception but doesn't raise it.
200
+ def set_exception(exception, context=nil)
201
+ if @exception && context != :dont_print
202
+ # An error has already been set; we don't want to override it,
203
+ # but we also don't want silence the error, so let's print it.
204
+ msg = <<-EOS
205
+
206
+ An error occurred #{context}
207
+ #{exception.class}: #{exception.message}
208
+ occurred at #{exception.backtrace.first}
209
+
210
+ EOS
211
+ RSpec.configuration.reporter.message(msg)
212
+ end
213
+
214
+ @exception ||= exception
215
+ end
216
+
217
+ # @private
218
+ #
219
+ # Used internally to set an exception and fail without actually executing
220
+ # the example when an exception is raised in before(:all).
221
+ def fail_with_exception(reporter, exception)
222
+ start(reporter)
223
+ set_exception(exception)
224
+ finish(reporter)
225
+ end
226
+
227
+ # @private
228
+ def instance_exec_with_rescue(context = nil, &block)
229
+ @example_group_instance.instance_exec_with_rescue(self, context, &block)
230
+ end
231
+
232
+ # @private
233
+ def instance_exec(*args, &block)
234
+ @example_group_instance.instance_exec(*args, &block)
235
+ end
236
+
237
+ private
238
+
239
+ def with_around_each_hooks(&block)
240
+ if around_each_hooks.empty?
241
+ yield
242
+ else
243
+ @example_group_class.run_around_each_hooks(self, Procsy.new(metadata, &block))
244
+ end
245
+ rescue Exception => e
246
+ set_exception(e, "in an around(:each) hook")
247
+ end
248
+
249
+ def start(reporter)
250
+ reporter.example_started(self)
251
+ record :started_at => RSpec::Core::Time.now
252
+ end
253
+
254
+ def finish(reporter)
255
+ if @exception
256
+ record_finished 'failed', :exception => @exception
257
+ reporter.example_failed self
258
+ false
259
+ elsif @pending_declared_in_example
260
+ record_finished 'pending', :pending_message => @pending_declared_in_example
261
+ reporter.example_pending self
262
+ true
263
+ elsif pending
264
+ record_finished 'pending', :pending_message => String === pending ? pending : Pending::NO_REASON_GIVEN
265
+ reporter.example_pending self
266
+ true
267
+ else
268
+ record_finished 'passed'
269
+ reporter.example_passed self
270
+ true
271
+ end
272
+ end
273
+
274
+ def record_finished(status, results={})
275
+ finished_at = RSpec::Core::Time.now
276
+ record results.merge(:status => status, :finished_at => finished_at, :run_time => (finished_at - execution_result[:started_at]).to_f)
277
+ end
278
+
279
+ def run_before_each
280
+ @example_group_instance.setup_mocks_for_rspec
281
+ @example_group_class.run_before_each_hooks(self)
282
+ end
283
+
284
+ def run_after_each
285
+ @example_group_class.run_after_each_hooks(self)
286
+ verify_mocks
287
+ rescue Exception => e
288
+ set_exception(e, "in an after(:each) hook")
289
+ ensure
290
+ @example_group_instance.teardown_mocks_for_rspec
291
+ end
292
+
293
+ def verify_mocks
294
+ @example_group_instance.verify_mocks_for_rspec
295
+ rescue Exception => e
296
+ set_exception(e, :dont_print)
297
+ end
298
+
299
+ def assign_generated_description
300
+ return unless RSpec.configuration.expecting_with_rspec?
301
+ if metadata[:description_args].empty? and !pending?
302
+ metadata[:description_args] << RSpec::Matchers.generated_description
303
+ end
304
+ RSpec::Matchers.clear_generated_description
305
+ end
306
+
307
+ def record(results={})
308
+ execution_result.update(results)
309
+ end
310
+ end
311
+ end
312
+ end