rspec-core 2.14.8 → 2.99.0.beta1

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 (60) hide show
  1. checksums.yaml +8 -8
  2. data/Changelog.md +54 -8
  3. data/features/command_line/order.feature +5 -8
  4. data/features/configuration/custom_settings.feature +10 -10
  5. data/features/configuration/deprecation_stream.feature +3 -3
  6. data/features/configuration/read_options_from_file.feature +1 -1
  7. data/features/example_groups/shared_examples.feature +2 -2
  8. data/features/hooks/around_hooks.feature +1 -1
  9. data/features/metadata/current_example.feature +43 -4
  10. data/features/metadata/user_defined.feature +12 -12
  11. data/lib/autotest/rspec2.rb +60 -56
  12. data/lib/rspec/core.rb +40 -2
  13. data/lib/rspec/core/caller_filter.rb +55 -0
  14. data/lib/rspec/core/command_line.rb +2 -2
  15. data/lib/rspec/core/configuration.rb +201 -13
  16. data/lib/rspec/core/deprecation.rb +2 -7
  17. data/lib/rspec/core/example.rb +5 -8
  18. data/lib/rspec/core/example_group.rb +101 -17
  19. data/lib/rspec/core/filter_manager.rb +2 -2
  20. data/lib/rspec/core/formatters/deprecation_formatter.rb +173 -15
  21. data/lib/rspec/core/formatters/text_mate_formatter.rb +0 -12
  22. data/lib/rspec/core/hooks.rb +1 -1
  23. data/lib/rspec/core/memoized_helpers.rb +49 -17
  24. data/lib/rspec/core/metadata.rb +1 -1
  25. data/lib/rspec/core/option_parser.rb +8 -3
  26. data/lib/rspec/core/pending.rb +14 -10
  27. data/lib/rspec/core/rake_task.rb +30 -6
  28. data/lib/rspec/core/runner.rb +9 -0
  29. data/lib/rspec/core/shared_example_group.rb +11 -9
  30. data/lib/rspec/core/shared_example_group/collection.rb +3 -1
  31. data/lib/rspec/core/version.rb +1 -2
  32. data/spec/command_line/order_spec.rb +4 -4
  33. data/spec/rspec/core/backtrace_cleaner_spec.rb +10 -10
  34. data/spec/rspec/core/caller_filter_spec.rb +58 -0
  35. data/spec/rspec/core/command_line_spec.rb +1 -0
  36. data/spec/rspec/core/configuration_options_spec.rb +6 -6
  37. data/spec/rspec/core/configuration_spec.rb +285 -52
  38. data/spec/rspec/core/deprecation_spec.rb +10 -29
  39. data/spec/rspec/core/deprecations_spec.rb +0 -14
  40. data/spec/rspec/core/example_group_spec.rb +74 -56
  41. data/spec/rspec/core/example_spec.rb +54 -17
  42. data/spec/rspec/core/filter_manager_spec.rb +2 -2
  43. data/spec/rspec/core/formatters/deprecation_formatter_spec.rb +156 -52
  44. data/spec/rspec/core/formatters/html_formatter_spec.rb +1 -1
  45. data/spec/rspec/core/formatters/text_mate_formatter_spec.rb +1 -2
  46. data/spec/rspec/core/hooks_spec.rb +2 -0
  47. data/spec/rspec/core/memoized_helpers_spec.rb +154 -113
  48. data/spec/rspec/core/metadata_spec.rb +25 -25
  49. data/spec/rspec/core/option_parser_spec.rb +19 -1
  50. data/spec/rspec/core/project_initializer_spec.rb +4 -4
  51. data/spec/rspec/core/rake_task_spec.rb +25 -4
  52. data/spec/rspec/core/shared_context_spec.rb +4 -4
  53. data/spec/rspec/core/shared_example_group_spec.rb +1 -1
  54. data/spec/rspec/core_spec.rb +36 -2
  55. data/spec/spec_helper.rb +3 -0
  56. data/spec/support/helper_methods.rb +16 -1
  57. data/spec/support/shared_example_groups.rb +1 -0
  58. data/spec/support/silence_dsl_deprecations.rb +32 -0
  59. metadata +10 -7
  60. data/spec/rspec/core/formatters/text_mate_formatted-2.1.0.html +0 -425
@@ -165,7 +165,7 @@ module RSpec::Core
165
165
  describe "#inclusions#description" do
166
166
  it 'cleans up the description' do
167
167
  project_dir = File.expand_path('.')
168
- expect(lambda { }.inspect).to include(project_dir)
168
+ expect(lambda { }.inspect).to include(project_dir) unless defined?(JRUBY_VERSION) && JRUBY_VERSION == '1.7.4'
169
169
  expect(lambda { }.inspect).to include(' (lambda)') if RUBY_VERSION > '1.9'
170
170
  expect(lambda { }.inspect).to include('0x')
171
171
 
@@ -181,7 +181,7 @@ module RSpec::Core
181
181
  describe "#exclusions#description" do
182
182
  it 'cleans up the description' do
183
183
  project_dir = File.expand_path('.')
184
- expect(lambda { }.inspect).to include(project_dir)
184
+ expect(lambda { }.inspect).to include(project_dir) unless defined?(JRUBY_VERSION) && JRUBY_VERSION == '1.7.4'
185
185
  expect(lambda { }.inspect).to include(' (lambda)') if RUBY_VERSION > '1.9'
186
186
  expect(lambda { }.inspect).to include('0x')
187
187
 
@@ -6,7 +6,7 @@ module RSpec::Core::Formatters
6
6
  describe DeprecationFormatter do
7
7
  let(:deprecation_stream) { StringIO.new }
8
8
  let(:summary_stream) { StringIO.new }
9
- let(:formatter) { DeprecationFormatter.new deprecation_stream, summary_stream }
9
+ let(:formatter) { DeprecationFormatter.new(deprecation_stream, summary_stream) }
10
10
 
11
11
  def with_start_defined_on_kernel
12
12
  return yield if ::Kernel.method_defined?(:start)
@@ -27,69 +27,173 @@ module RSpec::Core::Formatters
27
27
  end
28
28
 
29
29
  describe "#deprecation" do
30
- it "includes the method" do
31
- formatter.deprecation(:deprecated => "i_am_deprecated")
32
- deprecation_stream.rewind
33
- expect(deprecation_stream.read).to match(/i_am_deprecated is deprecated/)
34
- end
30
+ let(:formatter) { DeprecationFormatter.new(deprecation_stream, summary_stream) }
31
+ let(:summary_stream) { StringIO.new }
35
32
 
36
- it "includes the replacement" do
37
- formatter.deprecation(:replacement => "use_me")
38
- deprecation_stream.rewind
39
- expect(deprecation_stream.read).to match(/Use use_me instead/)
40
- end
33
+ context "with a File deprecation_stream" do
34
+ let(:deprecation_stream) { File.open("#{Dir.tmpdir}/deprecation_summary_example_output", "w+") }
35
+
36
+ it "prints a message if provided, ignoring other data" do
37
+ formatter.deprecation(:message => "this message", :deprecated => "x", :replacement => "y", :call_site => "z")
38
+ deprecation_stream.rewind
39
+ expect(deprecation_stream.read).to eq "this message\n"
40
+ end
41
41
 
42
- it "includes the call site if provided" do
43
- formatter.deprecation(:call_site => "somewhere")
44
- deprecation_stream.rewind
45
- expect(deprecation_stream.read).to match(/Called from somewhere/)
42
+ it "includes the method" do
43
+ formatter.deprecation(:deprecated => "i_am_deprecated")
44
+ deprecation_stream.rewind
45
+ expect(deprecation_stream.read).to match(/i_am_deprecated is deprecated/)
46
+ end
47
+
48
+ it "includes the replacement" do
49
+ formatter.deprecation(:replacement => "use_me")
50
+ deprecation_stream.rewind
51
+ expect(deprecation_stream.read).to match(/Use use_me instead/)
52
+ end
53
+
54
+ it "includes the call site if provided" do
55
+ formatter.deprecation(:call_site => "somewhere")
56
+ deprecation_stream.rewind
57
+ expect(deprecation_stream.read).to match(/Called from somewhere/)
58
+ end
46
59
  end
47
60
 
48
- it "prints a message if provided, ignoring other data" do
49
- formatter.deprecation(:message => "this message", :deprecated => "x", :replacement => "y", :call_site => "z")
50
- deprecation_stream.rewind
51
- expect(deprecation_stream.read).to eq "this message"
61
+ context "with an IO deprecation stream" do
62
+ let(:deprecation_stream) { StringIO.new }
63
+
64
+ it "prints nothing" do
65
+ 5.times { formatter.deprecation(:deprecated => 'i_am_deprecated') }
66
+ expect(deprecation_stream.string).to eq ""
67
+ end
52
68
  end
53
69
  end
54
70
 
55
71
  describe "#deprecation_summary" do
56
- it "is printed when deprecations go to a file" do
57
- file = File.open("#{Dir.tmpdir}/deprecation_summary_example_output", "w")
58
- summary_stream = StringIO.new
59
- formatter = DeprecationFormatter.new file, summary_stream
60
- formatter.deprecation(:deprecated => 'i_am_deprecated')
61
- formatter.deprecation_summary
62
- summary_stream.rewind
63
- expect(summary_stream.read).to match(/1 deprecation logged to .*deprecation_summary_example_output/)
64
- end
72
+ let(:formatter) { DeprecationFormatter.new(deprecation_stream, summary_stream) }
73
+ let(:summary_stream) { StringIO.new }
65
74
 
66
- it "pluralizes for more than one deprecation" do
67
- file = File.open("#{Dir.tmpdir}/deprecation_summary_example_output", "w")
68
- summary_stream = StringIO.new
69
- formatter = DeprecationFormatter.new file, summary_stream
70
- formatter.deprecation(:deprecated => 'i_am_deprecated')
71
- formatter.deprecation(:deprecated => 'i_am_deprecated_also')
72
- formatter.deprecation_summary
73
- summary_stream.rewind
74
- expect(summary_stream.read).to match(/2 deprecations/)
75
- end
75
+ context "with a File deprecation_stream" do
76
+ let(:deprecation_stream) { File.open("#{Dir.tmpdir}/deprecation_summary_example_output", "w") }
77
+
78
+ it "prints a count of the deprecations" do
79
+ formatter.deprecation(:deprecated => 'i_am_deprecated')
80
+ formatter.deprecation_summary
81
+ expect(summary_stream.string).to match(/1 deprecation logged to .*deprecation_summary_example_output/)
82
+ end
83
+
84
+ it "pluralizes the reported deprecation count for more than one deprecation" do
85
+ formatter.deprecation(:deprecated => 'i_am_deprecated')
86
+ formatter.deprecation(:deprecated => 'i_am_deprecated_also')
87
+ formatter.deprecation_summary
88
+ expect(summary_stream.string).to match(/2 deprecations/)
89
+ end
90
+
91
+ it "is not printed when there are no deprecations" do
92
+ formatter.deprecation_summary
93
+ expect(summary_stream.string).to eq ""
94
+ end
76
95
 
77
- it "is not printed when there are no deprecations" do
78
- file = File.open("#{Dir.tmpdir}/deprecation_summary_example_output", "w")
79
- summary_stream = StringIO.new
80
- formatter = DeprecationFormatter.new file, summary_stream
81
- formatter.deprecation_summary
82
- summary_stream.rewind
83
- expect(summary_stream.read).to eq ""
96
+ it 'uses synchronized/non-buffered output to work around odd duplicate output behavior we have observed' do
97
+ expect {
98
+ formatter.deprecation(:deprecated => 'foo')
99
+ }.to change { deprecation_stream.sync }.from(false).to(true)
100
+ end
101
+
102
+ it 'does not print duplicate messages' do
103
+ 3.times { formatter.deprecation(:deprecated => 'foo') }
104
+ formatter.deprecation_summary
105
+
106
+ expect(summary_stream.string).to match(/1 deprecation/)
107
+ expect(File.read(deprecation_stream.path)).to eq("foo is deprecated.\n#{DeprecationFormatter::RAISE_ERROR_CONFIG_NOTICE}")
108
+ end
84
109
  end
85
110
 
86
- it "is not printed when deprecations go to an IO instance" do
87
- summary_stream = StringIO.new
88
- formatter = DeprecationFormatter.new StringIO.new, summary_stream
89
- formatter.deprecation(:deprecated => 'i_am_deprecated')
90
- formatter.deprecation_summary
91
- summary_stream.rewind
92
- expect(summary_stream.read).to eq ""
111
+ context "with an IO deprecation_stream" do
112
+ let(:deprecation_stream) { StringIO.new }
113
+
114
+ it "groups similar deprecations together" do
115
+ formatter.deprecation(:deprecated => 'i_am_deprecated', :call_site => "foo.rb:1")
116
+ formatter.deprecation(:deprecated => 'i_am_a_different_deprecation')
117
+ formatter.deprecation(:deprecated => 'i_am_deprecated', :call_site => "foo.rb:2")
118
+ formatter.deprecation_summary
119
+
120
+ expected = <<-EOS.gsub(/^\s+\|/, '')
121
+ |
122
+ |Deprecation Warnings:
123
+ |
124
+ |i_am_a_different_deprecation is deprecated.
125
+ |
126
+ |i_am_deprecated is deprecated. Called from foo.rb:1.
127
+ |i_am_deprecated is deprecated. Called from foo.rb:2.
128
+ |
129
+ |#{DeprecationFormatter::RAISE_ERROR_CONFIG_NOTICE}
130
+ EOS
131
+ expect(deprecation_stream.string).to eq expected.chomp
132
+ end
133
+
134
+ it "limits the deprecation warnings after 3 calls" do
135
+ 5.times { |i| formatter.deprecation(:deprecated => 'i_am_deprecated', :call_site => "foo.rb:#{i + 1}") }
136
+ formatter.deprecation_summary
137
+ expected = <<-EOS.gsub(/^\s+\|/, '')
138
+ |
139
+ |Deprecation Warnings:
140
+ |
141
+ |i_am_deprecated is deprecated. Called from foo.rb:1.
142
+ |i_am_deprecated is deprecated. Called from foo.rb:2.
143
+ |i_am_deprecated is deprecated. Called from foo.rb:3.
144
+ |Too many uses of deprecated 'i_am_deprecated'. Set config.deprecation_stream to a File for full output.
145
+ |
146
+ |#{DeprecationFormatter::RAISE_ERROR_CONFIG_NOTICE}
147
+ EOS
148
+ expect(deprecation_stream.string).to eq expected.chomp
149
+ end
150
+
151
+ it "limits :message deprecation warnings with different callsites after 3 calls" do
152
+ 5.times do |n|
153
+ message = "This is a long string with some callsite info: /path/#{n}/to/some/file.rb:2#{n}3. And some more stuff can come after."
154
+ formatter.deprecation(:message => message)
155
+ end
156
+ formatter.deprecation_summary
157
+ expected = <<-EOS.gsub(/^\s+\|/, '')
158
+ |
159
+ |Deprecation Warnings:
160
+ |
161
+ |This is a long string with some callsite info: /path/0/to/some/file.rb:203. And some more stuff can come after.
162
+ |This is a long string with some callsite info: /path/1/to/some/file.rb:213. And some more stuff can come after.
163
+ |This is a long string with some callsite info: /path/2/to/some/file.rb:223. And some more stuff can come after.
164
+ |Too many similar deprecation messages reported, disregarding further reports. Set config.deprecation_stream to a File for full output.
165
+ |
166
+ |#{DeprecationFormatter::RAISE_ERROR_CONFIG_NOTICE}
167
+ EOS
168
+ expect(deprecation_stream.string).to eq expected.chomp
169
+ end
170
+
171
+ it "prints the true deprecation count to the summary_stream" do
172
+ 5.times { |i| formatter.deprecation(:deprecated => 'i_am_deprecated', :call_site => "foo.rb:#{i + 1}") }
173
+ 5.times do |n|
174
+ formatter.deprecation(:message => "callsite info: /path/#{n}/to/some/file.rb:2#{n}3. And some more stuff")
175
+ end
176
+ formatter.deprecation_summary
177
+ expect(summary_stream.string).to match(/10 deprecation warnings total/)
178
+ end
179
+
180
+ it 'does not print duplicate messages' do
181
+ 3.times { formatter.deprecation(:deprecated => 'foo') }
182
+ formatter.deprecation_summary
183
+
184
+ expect(summary_stream.string).to match(/1 deprecation/)
185
+
186
+ expected = <<-EOS.gsub(/^\s+\|/, '')
187
+ |
188
+ |Deprecation Warnings:
189
+ |
190
+ |foo is deprecated.
191
+ |
192
+ |#{DeprecationFormatter::RAISE_ERROR_CONFIG_NOTICE}
193
+ EOS
194
+
195
+ expect(deprecation_stream.string).to eq expected.chomp
196
+ end
93
197
  end
94
198
  end
95
199
  end
@@ -24,7 +24,7 @@ module RSpec
24
24
 
25
25
  let(:generated_html) do
26
26
  options = RSpec::Core::ConfigurationOptions.new(
27
- %w[spec/rspec/core/resources/formatter_specs.rb --format html --order default]
27
+ %w[spec/rspec/core/resources/formatter_specs.rb --format html --order defined]
28
28
  )
29
29
  options.parse_options
30
30
 
@@ -24,7 +24,7 @@ module RSpec
24
24
 
25
25
  let(:generated_html) do
26
26
  options = RSpec::Core::ConfigurationOptions.new(
27
- %w[spec/rspec/core/resources/formatter_specs.rb --format textmate --order default]
27
+ %w[spec/rspec/core/resources/formatter_specs.rb --format textmate --order defined]
28
28
  )
29
29
  options.parse_options
30
30
 
@@ -72,7 +72,6 @@ module RSpec
72
72
 
73
73
  expect(actual_doc.inner_html).to eq(expected_doc.inner_html)
74
74
 
75
- expect(backtrace_lines).to_not be_empty
76
75
  backtrace_lines.each do |backtrace_line|
77
76
  expect(backtrace_line['href']).to include("txmt://open?url=")
78
77
  end
@@ -26,6 +26,7 @@ module RSpec::Core
26
26
  context "when RSpec.configuration.treat_symbols_as_metadata_keys_with_true_values is set to #{config_value}" do
27
27
  before(:each) do
28
28
  Kernel.stub(:warn)
29
+ allow_deprecation unless config_value
29
30
  RSpec.configure { |c| c.treat_symbols_as_metadata_keys_with_true_values = config_value }
30
31
  end
31
32
 
@@ -57,6 +58,7 @@ module RSpec::Core
57
58
  [true, false].each do |config_value|
58
59
  context "when RSpec.configuration.treat_symbols_as_metadata_keys_with_true_values is set to #{config_value}" do
59
60
  before(:each) do
61
+ allow_deprecation unless config_value
60
62
  RSpec.configure { |c| c.treat_symbols_as_metadata_keys_with_true_values = config_value }
61
63
  end
62
64
 
@@ -56,6 +56,18 @@ module RSpec::Core
56
56
  end
57
57
 
58
58
  describe "explicit subject" do
59
+ it "yields the example in which it is eval'd" do
60
+ example_yielded_to_subject = nil
61
+ example_yielded_to_example = nil
62
+
63
+ group = ExampleGroup.describe
64
+ group.subject { |e| example_yielded_to_subject = e }
65
+ group.example { |e| subject; example_yielded_to_example = e }
66
+ group.run
67
+
68
+ expect(example_yielded_to_subject).to eq example_yielded_to_example
69
+ end
70
+
59
71
  [false, nil].each do |falsy_value|
60
72
  context "with a value of #{falsy_value.inspect}" do
61
73
  it "is evaluated once per example" do
@@ -70,7 +82,7 @@ module RSpec::Core
70
82
  subject
71
83
  subject
72
84
  end
73
- expect(group.run).to be_true, "expected subject block to be evaluated only once"
85
+ expect(group.run).to be_truthy, "expected subject block to be evaluated only once"
74
86
  end
75
87
  end
76
88
  end
@@ -184,6 +196,18 @@ module RSpec::Core
184
196
  end
185
197
 
186
198
  describe "with a name" do
199
+ it "yields the example in which it is eval'd" do
200
+ example_yielded_to_subject = nil
201
+ example_yielded_to_example = nil
202
+
203
+ group = ExampleGroup.describe
204
+ group.subject(:foo) { |e| example_yielded_to_subject = e }
205
+ group.example { |e| foo; example_yielded_to_example = e }
206
+ group.run
207
+
208
+ expect(example_yielded_to_subject).to eq example_yielded_to_example
209
+ end
210
+
187
211
  it "defines a method that returns the memoized subject" do
188
212
  list_value_1 = list_value_2 = subject_value_1 = subject_value_2 = nil
189
213
 
@@ -319,152 +343,160 @@ module RSpec::Core
319
343
  it { should_not be_not_ok }
320
344
  end
321
345
 
322
- expect(group.run).to be_true
346
+ expect(group.run).to be_truthy
323
347
  end
324
348
  end
325
349
 
326
350
  describe "#its" do
327
- subject do
328
- Class.new do
329
- def initialize
330
- @call_count = 0
331
- end
332
-
333
- def call_count
334
- @call_count += 1
335
- end
336
- end.new
337
- end
338
-
339
- context "with a call counter" do
340
- its(:call_count) { should eq(1) }
341
- end
351
+ extend SilenceDSLDeprecations
352
+ silence_dsl_deprecations do
353
+ it "should issue deprecation warning" do
354
+ expect_deprecation_with_call_site(__FILE__, __LINE__+1, '`its` method')
355
+ RSpec::Core::ExampleGroup.its(nil) {}
356
+ end
342
357
 
343
- context "with nil value" do
344
358
  subject do
345
359
  Class.new do
346
- def nil_value
347
- nil
360
+ def initialize
361
+ @call_count = 0
348
362
  end
349
- end.new
350
- end
351
- its(:nil_value) { should be_nil }
352
- end
353
363
 
354
- context "with nested attributes" do
355
- subject do
356
- Class.new do
357
- def name
358
- "John"
364
+ def call_count
365
+ @call_count += 1
359
366
  end
360
367
  end.new
361
368
  end
362
- its("name") { should eq("John") }
363
- its("name.size") { should eq(4) }
364
- its("name.size.class") { should eq(Fixnum) }
365
- end
366
369
 
367
- context "when it responds to #[]" do
368
- subject do
369
- Class.new do
370
- def [](*objects)
371
- objects.map do |object|
372
- "#{object.class}: #{object.to_s}"
373
- end.join("; ")
374
- end
370
+ context "with a call counter" do
371
+ its(:call_count) { should eq(1) }
372
+ end
375
373
 
376
- def name
377
- "George"
378
- end
379
- end.new
374
+ context "with nil value" do
375
+ subject do
376
+ Class.new do
377
+ def nil_value
378
+ nil
379
+ end
380
+ end.new
381
+ end
382
+ its(:nil_value) { should be_nil }
380
383
  end
381
- its([:a]) { should eq("Symbol: a") }
382
- its(['a']) { should eq("String: a") }
383
- its([:b, 'c', 4]) { should eq("Symbol: b; String: c; Fixnum: 4") }
384
- its(:name) { should eq("George") }
385
- context "when referring to an attribute without the proper array syntax" do
386
- context "it raises an error" do
387
- its(:age) do
388
- expect do
389
- should eq(64)
390
- end.to raise_error(NoMethodError)
384
+
385
+ context "with nested attributes" do
386
+ subject do
387
+ Class.new do
388
+ def name
389
+ "John"
390
+ end
391
+ end.new
392
+ end
393
+ its("name") { should eq("John") }
394
+ its("name.size") { should eq(4) }
395
+ its("name.size.class") { should eq(Fixnum) }
396
+ end
397
+
398
+ context "when it responds to #[]" do
399
+ subject do
400
+ Class.new do
401
+ def [](*objects)
402
+ objects.map do |object|
403
+ "#{object.class}: #{object.to_s}"
404
+ end.join("; ")
405
+ end
406
+
407
+ def name
408
+ "George"
409
+ end
410
+ end.new
411
+ end
412
+ its([:a]) { should eq("Symbol: a") }
413
+ its(['a']) { should eq("String: a") }
414
+ its([:b, 'c', 4]) { should eq("Symbol: b; String: c; Fixnum: 4") }
415
+ its(:name) { should eq("George") }
416
+ context "when referring to an attribute without the proper array syntax" do
417
+ context "it raises an error" do
418
+ its(:age) do
419
+ expect do
420
+ should eq(64)
421
+ end.to raise_error(NoMethodError)
422
+ end
391
423
  end
392
424
  end
393
425
  end
394
- end
395
426
 
396
- context "when it does not respond to #[]" do
397
- subject { Object.new }
427
+ context "when it does not respond to #[]" do
428
+ subject { Object.new }
398
429
 
399
- context "it raises an error" do
400
- its([:a]) do
401
- expect do
402
- should eq("Symbol: a")
403
- end.to raise_error(NoMethodError)
430
+ context "it raises an error" do
431
+ its([:a]) do
432
+ expect do
433
+ should eq("Symbol: a")
434
+ end.to raise_error(NoMethodError)
435
+ end
404
436
  end
405
437
  end
406
- end
407
438
 
408
- context "calling and overriding super" do
409
- it "calls to the subject defined in the parent group" do
410
- group = ExampleGroup.describe(Array) do
411
- subject { [1, 'a'] }
439
+ context "calling and overriding super" do
440
+ it "calls to the subject defined in the parent group" do
441
+ group = ExampleGroup.describe(Array) do
442
+ subject { [1, 'a'] }
412
443
 
413
- its(:last) { should eq("a") }
444
+ its(:last) { should eq("a") }
414
445
 
415
- describe '.first' do
416
- def subject; super().first; end
446
+ describe '.first' do
447
+ def subject; super().first; end
417
448
 
418
- its(:next) { should eq(2) }
449
+ its(:next) { should eq(2) }
450
+ end
419
451
  end
420
- end
421
452
 
422
- expect(group.run).to be_true
453
+ expect(group.run).to be_truthy
454
+ end
423
455
  end
424
- end
425
456
 
426
- context "with nil subject" do
427
- subject do
428
- Class.new do
429
- def initialize
430
- @counter = -1
431
- end
432
- def nil_if_first_time
433
- @counter += 1
434
- @counter == 0 ? nil : true
435
- end
436
- end.new
457
+ context "with nil subject" do
458
+ subject do
459
+ Class.new do
460
+ def initialize
461
+ @counter = -1
462
+ end
463
+ def nil_if_first_time
464
+ @counter += 1
465
+ @counter == 0 ? nil : true
466
+ end
467
+ end.new
468
+ end
469
+ its(:nil_if_first_time) { should be(nil) }
437
470
  end
438
- its(:nil_if_first_time) { should be(nil) }
439
- end
440
471
 
441
- context "with false subject" do
442
- subject do
443
- Class.new do
444
- def initialize
445
- @counter = -1
446
- end
447
- def false_if_first_time
448
- @counter += 1
449
- @counter > 0
450
- end
451
- end.new
472
+ context "with false subject" do
473
+ subject do
474
+ Class.new do
475
+ def initialize
476
+ @counter = -1
477
+ end
478
+ def false_if_first_time
479
+ @counter += 1
480
+ @counter > 0
481
+ end
482
+ end.new
483
+ end
484
+ its(:false_if_first_time) { should be(false) }
452
485
  end
453
- its(:false_if_first_time) { should be(false) }
454
- end
455
486
 
456
- describe 'accessing `subject` in `before` and `let`' do
457
- subject { 'my subject' }
458
- before { @subject_in_before = subject }
459
- let(:subject_in_let) { subject }
460
- let!(:eager_loaded_subject_in_let) { subject }
461
-
462
- # These examples read weird, because we're actually
463
- # specifying the behaviour of `its` itself
464
- its(nil) { expect(subject).to eq('my subject') }
465
- its(nil) { expect(@subject_in_before).to eq('my subject') }
466
- its(nil) { expect(subject_in_let).to eq('my subject') }
467
- its(nil) { expect(eager_loaded_subject_in_let).to eq('my subject') }
487
+ describe 'accessing `subject` in `before` and `let`' do
488
+ subject { 'my subject' }
489
+ before { @subject_in_before = subject }
490
+ let(:subject_in_let) { subject }
491
+ let!(:eager_loaded_subject_in_let) { subject }
492
+
493
+ # These examples read weird, because we're actually
494
+ # specifying the behaviour of `its` itself
495
+ its(nil) { expect(subject).to eq('my subject') }
496
+ its(nil) { expect(@subject_in_before).to eq('my subject') }
497
+ its(nil) { expect(subject_in_let).to eq('my subject') }
498
+ its(nil) { expect(eager_loaded_subject_in_let).to eq('my subject') }
499
+ end
468
500
  end
469
501
  end
470
502
 
@@ -516,6 +548,15 @@ module RSpec::Core
516
548
  expect(@nil_value_count).to eq(1)
517
549
  end
518
550
 
551
+ let(:yield_the_example) do |example_yielded_to_let|
552
+ @example_yielded_to_let = example_yielded_to_let
553
+ end
554
+
555
+ it "yields the example" do |example_yielded_to_example|
556
+ yield_the_example
557
+ expect(@example_yielded_to_let).to equal example_yielded_to_example
558
+ end
559
+
519
560
  let(:regex_with_capture) { %r[RegexWithCapture(\d)] }
520
561
 
521
562
  it 'does not pass the block up the ancestor chain' do