rspec-core 2.14.8 → 2.99.0.beta1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +8 -8
- data/Changelog.md +54 -8
- data/features/command_line/order.feature +5 -8
- data/features/configuration/custom_settings.feature +10 -10
- data/features/configuration/deprecation_stream.feature +3 -3
- data/features/configuration/read_options_from_file.feature +1 -1
- data/features/example_groups/shared_examples.feature +2 -2
- data/features/hooks/around_hooks.feature +1 -1
- data/features/metadata/current_example.feature +43 -4
- data/features/metadata/user_defined.feature +12 -12
- data/lib/autotest/rspec2.rb +60 -56
- data/lib/rspec/core.rb +40 -2
- data/lib/rspec/core/caller_filter.rb +55 -0
- data/lib/rspec/core/command_line.rb +2 -2
- data/lib/rspec/core/configuration.rb +201 -13
- data/lib/rspec/core/deprecation.rb +2 -7
- data/lib/rspec/core/example.rb +5 -8
- data/lib/rspec/core/example_group.rb +101 -17
- data/lib/rspec/core/filter_manager.rb +2 -2
- data/lib/rspec/core/formatters/deprecation_formatter.rb +173 -15
- data/lib/rspec/core/formatters/text_mate_formatter.rb +0 -12
- data/lib/rspec/core/hooks.rb +1 -1
- data/lib/rspec/core/memoized_helpers.rb +49 -17
- data/lib/rspec/core/metadata.rb +1 -1
- data/lib/rspec/core/option_parser.rb +8 -3
- data/lib/rspec/core/pending.rb +14 -10
- data/lib/rspec/core/rake_task.rb +30 -6
- data/lib/rspec/core/runner.rb +9 -0
- data/lib/rspec/core/shared_example_group.rb +11 -9
- data/lib/rspec/core/shared_example_group/collection.rb +3 -1
- data/lib/rspec/core/version.rb +1 -2
- data/spec/command_line/order_spec.rb +4 -4
- data/spec/rspec/core/backtrace_cleaner_spec.rb +10 -10
- data/spec/rspec/core/caller_filter_spec.rb +58 -0
- data/spec/rspec/core/command_line_spec.rb +1 -0
- data/spec/rspec/core/configuration_options_spec.rb +6 -6
- data/spec/rspec/core/configuration_spec.rb +285 -52
- data/spec/rspec/core/deprecation_spec.rb +10 -29
- data/spec/rspec/core/deprecations_spec.rb +0 -14
- data/spec/rspec/core/example_group_spec.rb +74 -56
- data/spec/rspec/core/example_spec.rb +54 -17
- data/spec/rspec/core/filter_manager_spec.rb +2 -2
- data/spec/rspec/core/formatters/deprecation_formatter_spec.rb +156 -52
- data/spec/rspec/core/formatters/html_formatter_spec.rb +1 -1
- data/spec/rspec/core/formatters/text_mate_formatter_spec.rb +1 -2
- data/spec/rspec/core/hooks_spec.rb +2 -0
- data/spec/rspec/core/memoized_helpers_spec.rb +154 -113
- data/spec/rspec/core/metadata_spec.rb +25 -25
- data/spec/rspec/core/option_parser_spec.rb +19 -1
- data/spec/rspec/core/project_initializer_spec.rb +4 -4
- data/spec/rspec/core/rake_task_spec.rb +25 -4
- data/spec/rspec/core/shared_context_spec.rb +4 -4
- data/spec/rspec/core/shared_example_group_spec.rb +1 -1
- data/spec/rspec/core_spec.rb +36 -2
- data/spec/spec_helper.rb +3 -0
- data/spec/support/helper_methods.rb +16 -1
- data/spec/support/shared_example_groups.rb +1 -0
- data/spec/support/silence_dsl_deprecations.rb +32 -0
- metadata +10 -7
- 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
|
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
|
-
|
31
|
-
|
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
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
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
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
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
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
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
|
-
|
57
|
-
|
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
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
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
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
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
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
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
|
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
|
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
|
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
|
346
|
+
expect(group.run).to be_truthy
|
323
347
|
end
|
324
348
|
end
|
325
349
|
|
326
350
|
describe "#its" do
|
327
|
-
|
328
|
-
|
329
|
-
|
330
|
-
|
331
|
-
|
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
|
347
|
-
|
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
|
-
|
355
|
-
|
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
|
-
|
368
|
-
|
369
|
-
|
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
|
-
|
377
|
-
|
378
|
-
|
379
|
-
|
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
|
-
|
382
|
-
|
383
|
-
|
384
|
-
|
385
|
-
|
386
|
-
|
387
|
-
|
388
|
-
|
389
|
-
|
390
|
-
|
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
|
-
|
397
|
-
|
427
|
+
context "when it does not respond to #[]" do
|
428
|
+
subject { Object.new }
|
398
429
|
|
399
|
-
|
400
|
-
|
401
|
-
|
402
|
-
|
403
|
-
|
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
|
-
|
409
|
-
|
410
|
-
|
411
|
-
|
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
|
-
|
444
|
+
its(:last) { should eq("a") }
|
414
445
|
|
415
|
-
|
416
|
-
|
446
|
+
describe '.first' do
|
447
|
+
def subject; super().first; end
|
417
448
|
|
418
|
-
|
449
|
+
its(:next) { should eq(2) }
|
450
|
+
end
|
419
451
|
end
|
420
|
-
end
|
421
452
|
|
422
|
-
|
453
|
+
expect(group.run).to be_truthy
|
454
|
+
end
|
423
455
|
end
|
424
|
-
end
|
425
456
|
|
426
|
-
|
427
|
-
|
428
|
-
|
429
|
-
|
430
|
-
|
431
|
-
|
432
|
-
|
433
|
-
|
434
|
-
|
435
|
-
|
436
|
-
|
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
|
-
|
442
|
-
|
443
|
-
|
444
|
-
|
445
|
-
|
446
|
-
|
447
|
-
|
448
|
-
|
449
|
-
|
450
|
-
|
451
|
-
|
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
|
-
|
457
|
-
|
458
|
-
|
459
|
-
|
460
|
-
|
461
|
-
|
462
|
-
|
463
|
-
|
464
|
-
|
465
|
-
|
466
|
-
|
467
|
-
|
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
|