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.
- 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
|