rspec-support 3.0.4 → 3.1.0
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 +4 -4
- checksums.yaml.gz.sig +2 -2
- data.tar.gz.sig +0 -0
- data/Changelog.md +10 -0
- data/lib/rspec/support/caller_filter.rb +1 -2
- data/lib/rspec/support/differ.rb +25 -16
- data/lib/rspec/support/directory_maker.rb +30 -0
- data/lib/rspec/support/encoded_string.rb +8 -5
- data/lib/rspec/support/fuzzy_matcher.rb +1 -2
- data/lib/rspec/support/hunk_generator.rb +0 -1
- data/lib/rspec/support/matcher_definition.rb +31 -0
- data/lib/rspec/support/method_signature_verifier.rb +99 -36
- data/lib/rspec/support/recursive_const_methods.rb +76 -0
- data/lib/rspec/support/spec.rb +31 -22
- data/lib/rspec/support/spec/deprecation_helpers.rb +2 -3
- data/lib/rspec/support/spec/in_sub_process.rb +4 -1
- data/lib/rspec/support/spec/prevent_load_time_warnings.rb +44 -0
- data/lib/rspec/support/spec/shell_out.rb +54 -0
- data/lib/rspec/support/spec/stderr_splitter.rb +5 -6
- data/lib/rspec/support/spec/with_isolated_directory.rb +9 -0
- data/lib/rspec/support/spec/with_isolated_stderr.rb +0 -2
- data/lib/rspec/support/version.rb +1 -1
- data/lib/rspec/support/version_checker.rb +8 -8
- data/lib/rspec/support/warnings.rb +3 -3
- metadata +9 -17
- metadata.gz.sig +0 -0
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 4617d19ee06926ebbcff3a74a7b9f4f4b33c5cea
|
4
|
+
data.tar.gz: d604a3eea3884a0bfdb9e6752d0c9661cab04a57
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 7e1921b73a9af0bd4c3877d51eeac845c47708e1c3bfbe2c4a33a1501d41b2260ca567ee7f5e9c9f46d2102a5a85705c53d37dddf823eedf14fa07d826a649c4
|
7
|
+
data.tar.gz: 98b5498e60ee2901a87243c33b28bc85f60d0815e7a04bf32fb69833dd5dd9f6973d81c52e9a46e726e15a3540ec3aef4987bfb1f5d2de63c6d51e622c4e05b4
|
checksums.yaml.gz.sig
CHANGED
@@ -1,2 +1,2 @@
|
|
1
|
-
|
2
|
-
|
1
|
+
{�BUg�
|
2
|
+
1<�"&����rq'!�an�~WeǺ��e��zD=(�������Xx��a����K�z���$�7K�\�ޝ�7h톎��n�8o^O���>k��"j|��"�������Xb�@���"q9�qQy37db���:3��EG
|
data.tar.gz.sig
CHANGED
Binary file
|
data/Changelog.md
CHANGED
@@ -1,3 +1,13 @@
|
|
1
|
+
### 3.1.0 / 2014-09-04
|
2
|
+
[Full Changelog](http://github.com/rspec/rspec-support/compare/v3.0.4...v3.1.0)
|
3
|
+
|
4
|
+
Bug Fixes:
|
5
|
+
|
6
|
+
* Fix `FuzzyMatcher` so that it does not wrongly match a struct against
|
7
|
+
an array. (Myron Marston, #97)
|
8
|
+
* Prevent infinitely recursing `#flatten` methods from causing the differ
|
9
|
+
to hang. (Jon Rowe, #101)
|
10
|
+
|
1
11
|
### 3.0.4 / 2014-08-14
|
2
12
|
[Full Changelog](http://github.com/rspec/rspec-support/compare/v3.0.3...v3.0.4)
|
3
13
|
|
@@ -4,7 +4,6 @@ module RSpec
|
|
4
4
|
# the code using the library, which is far more useful than the particular
|
5
5
|
# internal method that raised an error.
|
6
6
|
class CallerFilter
|
7
|
-
|
8
7
|
RSPEC_LIBS = %w[
|
9
8
|
core
|
10
9
|
mocks
|
@@ -41,7 +40,7 @@ module RSpec
|
|
41
40
|
i = 1
|
42
41
|
line = nil
|
43
42
|
|
44
|
-
|
43
|
+
until line
|
45
44
|
stack = caller(i, increment)
|
46
45
|
raise "No non-lib lines in stack" unless stack
|
47
46
|
|
data/lib/rspec/support/differ.rb
CHANGED
@@ -5,6 +5,7 @@ require 'pp'
|
|
5
5
|
|
6
6
|
module RSpec
|
7
7
|
module Support
|
8
|
+
# rubocop:disable ClassLength
|
8
9
|
class Differ
|
9
10
|
def diff(actual, expected)
|
10
11
|
diff = ""
|
@@ -22,6 +23,7 @@ module RSpec
|
|
22
23
|
diff.to_s
|
23
24
|
end
|
24
25
|
|
26
|
+
# rubocop:disable MethodLength
|
25
27
|
def diff_as_string(actual, expected)
|
26
28
|
@encoding = pick_encoding actual, expected
|
27
29
|
|
@@ -35,21 +37,20 @@ module RSpec
|
|
35
37
|
if current_hunk.overlaps?(prev_hunk)
|
36
38
|
add_old_hunk_to_hunk(current_hunk, prev_hunk)
|
37
39
|
else
|
38
|
-
add_to_output(output, prev_hunk.diff(
|
40
|
+
add_to_output(output, prev_hunk.diff(format_type).to_s)
|
39
41
|
end
|
40
42
|
ensure
|
41
43
|
add_to_output(output, "\n")
|
42
44
|
end
|
43
45
|
end
|
44
46
|
|
45
|
-
if hunks.last
|
46
|
-
finalize_output(output, hunks.last.diff(format).to_s)
|
47
|
-
end
|
47
|
+
finalize_output(output, hunks.last.diff(format_type).to_s) if hunks.last
|
48
48
|
|
49
49
|
color_diff output
|
50
50
|
rescue Encoding::CompatibilityError
|
51
51
|
handle_encoding_errors
|
52
52
|
end
|
53
|
+
# rubocop:enable MethodLength
|
53
54
|
|
54
55
|
def diff_as_object(actual, expected)
|
55
56
|
actual_as_string = object_to_string(actual)
|
@@ -68,19 +69,19 @@ module RSpec
|
|
68
69
|
private
|
69
70
|
|
70
71
|
def no_procs?(*args)
|
71
|
-
args.
|
72
|
+
safely_flatten(args).none? { |a| Proc === a }
|
72
73
|
end
|
73
74
|
|
74
75
|
def all_strings?(*args)
|
75
|
-
args.
|
76
|
+
safely_flatten(args).all? { |a| String === a }
|
76
77
|
end
|
77
78
|
|
78
79
|
def any_multiline_strings?(*args)
|
79
|
-
all_strings?(*args) && args.
|
80
|
+
all_strings?(*args) && safely_flatten(args).any? { |a| multiline?(a) }
|
80
81
|
end
|
81
82
|
|
82
83
|
def no_numbers?(*args)
|
83
|
-
args.
|
84
|
+
safely_flatten(args).none? { |a| Numeric === a }
|
84
85
|
end
|
85
86
|
|
86
87
|
def coerce_to_string(string_or_array)
|
@@ -125,7 +126,12 @@ module RSpec
|
|
125
126
|
hunk.merge(oldhunk)
|
126
127
|
end
|
127
128
|
|
128
|
-
def
|
129
|
+
def safely_flatten(array)
|
130
|
+
array = array.flatten(1) until (array == array.flatten(1))
|
131
|
+
array
|
132
|
+
end
|
133
|
+
|
134
|
+
def format_type
|
129
135
|
:unified
|
130
136
|
end
|
131
137
|
|
@@ -152,7 +158,7 @@ module RSpec
|
|
152
158
|
def color_diff(diff)
|
153
159
|
return diff unless color?
|
154
160
|
|
155
|
-
diff.lines.map
|
161
|
+
diff.lines.map do |line|
|
156
162
|
case line[0].chr
|
157
163
|
when "+"
|
158
164
|
green line
|
@@ -163,7 +169,7 @@ module RSpec
|
|
163
169
|
else
|
164
170
|
normal(line)
|
165
171
|
end
|
166
|
-
|
172
|
+
end.join
|
167
173
|
end
|
168
174
|
|
169
175
|
def object_to_string(object)
|
@@ -179,7 +185,7 @@ module RSpec
|
|
179
185
|
when String
|
180
186
|
object =~ /\n/ ? object : object.inspect
|
181
187
|
else
|
182
|
-
PP.pp(object,"")
|
188
|
+
PP.pp(object, "")
|
183
189
|
end
|
184
190
|
end
|
185
191
|
|
@@ -188,18 +194,21 @@ module RSpec
|
|
188
194
|
Encoding.compatible?(source_a, source_b) || Encoding.default_external
|
189
195
|
end
|
190
196
|
else
|
191
|
-
def pick_encoding(
|
197
|
+
def pick_encoding(_source_a, _source_b)
|
192
198
|
end
|
193
199
|
end
|
194
200
|
|
195
201
|
def handle_encoding_errors
|
196
202
|
if @actual.source_encoding != @expected.source_encoding
|
197
|
-
"Could not produce a diff because the encoding of the actual string
|
198
|
-
|
203
|
+
"Could not produce a diff because the encoding of the actual string " \
|
204
|
+
"(#{@actual.source_encoding}) differs from the encoding of the expected " \
|
205
|
+
"string (#{@expected.source_encoding})"
|
199
206
|
else
|
200
|
-
"Could not produce a diff because of the encoding of the string
|
207
|
+
"Could not produce a diff because of the encoding of the string " \
|
208
|
+
"(#{@expected.source_encoding})"
|
201
209
|
end
|
202
210
|
end
|
203
211
|
end
|
212
|
+
# rubocop:enable ClassLength
|
204
213
|
end
|
205
214
|
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
module RSpec
|
2
|
+
module Support
|
3
|
+
# @api private
|
4
|
+
#
|
5
|
+
# Replacement for fileutils#mkdir_p because we don't want to require parts
|
6
|
+
# of stdlib in RSpec.
|
7
|
+
class DirectoryMaker
|
8
|
+
# @api private
|
9
|
+
#
|
10
|
+
# Implements nested directory construction
|
11
|
+
def self.mkdir_p(path)
|
12
|
+
stack = path.start_with?(File::SEPARATOR) ? File::SEPARATOR : "."
|
13
|
+
path.split(File::SEPARATOR).each do |part|
|
14
|
+
stack = File.join(stack, part)
|
15
|
+
|
16
|
+
begin
|
17
|
+
Dir.mkdir(stack) unless directory_exists?(stack)
|
18
|
+
rescue Errno::ENOTDIR => e
|
19
|
+
raise Errno::EEXIST, e.message
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
def self.directory_exists?(dirname)
|
25
|
+
File.exist?(dirname) && File.directory?(dirname)
|
26
|
+
end
|
27
|
+
private_class_method :directory_exists?
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
@@ -2,10 +2,9 @@ module RSpec
|
|
2
2
|
module Support
|
3
3
|
# @private
|
4
4
|
class EncodedString
|
5
|
-
|
6
5
|
MRI_UNICODE_UNKOWN_CHARACTER = "\xEF\xBF\xBD"
|
7
6
|
|
8
|
-
def initialize(string, encoding
|
7
|
+
def initialize(string, encoding=nil)
|
9
8
|
@encoding = encoding
|
10
9
|
@source_encoding = detect_source_encoding(string)
|
11
10
|
@string = matching_encoding(string)
|
@@ -30,9 +29,10 @@ module RSpec
|
|
30
29
|
end
|
31
30
|
alias :to_str :to_s
|
32
31
|
|
33
|
-
private
|
34
|
-
|
35
32
|
if String.method_defined?(:encoding)
|
33
|
+
|
34
|
+
private
|
35
|
+
|
36
36
|
def matching_encoding(string)
|
37
37
|
string.encode(@encoding)
|
38
38
|
rescue Encoding::UndefinedConversionError, Encoding::InvalidByteSequenceError
|
@@ -53,11 +53,14 @@ module RSpec
|
|
53
53
|
string.encoding
|
54
54
|
end
|
55
55
|
else
|
56
|
+
|
57
|
+
private
|
58
|
+
|
56
59
|
def matching_encoding(string)
|
57
60
|
string
|
58
61
|
end
|
59
62
|
|
60
|
-
def detect_source_encoding(
|
63
|
+
def detect_source_encoding(_string)
|
61
64
|
'US-ASCII'
|
62
65
|
end
|
63
66
|
end
|
@@ -6,7 +6,7 @@ module RSpec
|
|
6
6
|
module FuzzyMatcher
|
7
7
|
# @api private
|
8
8
|
def self.values_match?(expected, actual)
|
9
|
-
if Array === expected && Enumerable === actual
|
9
|
+
if Array === expected && Enumerable === actual && !(Struct === actual)
|
10
10
|
return arrays_match?(expected, actual.to_a)
|
11
11
|
elsif Hash === expected && Hash === actual
|
12
12
|
return hashes_match?(expected, actual)
|
@@ -46,4 +46,3 @@ module RSpec
|
|
46
46
|
end
|
47
47
|
end
|
48
48
|
end
|
49
|
-
|
@@ -0,0 +1,31 @@
|
|
1
|
+
module RSpec
|
2
|
+
module Support
|
3
|
+
# @private
|
4
|
+
def self.matcher_definitions
|
5
|
+
@matcher_definitions ||= []
|
6
|
+
end
|
7
|
+
|
8
|
+
# Used internally to break cyclic dependency between mocks, expectations,
|
9
|
+
# and support. We don't currently have a consistent implementation of our
|
10
|
+
# matchers, though we are considering changing that:
|
11
|
+
# https://github.com/rspec/rspec-mocks/issues/513
|
12
|
+
#
|
13
|
+
# @private
|
14
|
+
def self.register_matcher_definition(&block)
|
15
|
+
matcher_definitions << block
|
16
|
+
end
|
17
|
+
|
18
|
+
# Remove a previously registered matcher. Useful for cleaning up after
|
19
|
+
# yourself in specs.
|
20
|
+
#
|
21
|
+
# @private
|
22
|
+
def self.deregister_matcher_definition(&block)
|
23
|
+
matcher_definitions.delete(block)
|
24
|
+
end
|
25
|
+
|
26
|
+
# @private
|
27
|
+
def self.is_a_matcher?(object)
|
28
|
+
matcher_definitions.any? { |md| md.call(object) }
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
@@ -1,5 +1,6 @@
|
|
1
1
|
require 'rspec/support'
|
2
2
|
RSpec::Support.require_rspec_support "ruby_features"
|
3
|
+
RSpec::Support.require_rspec_support "matcher_definition"
|
3
4
|
|
4
5
|
module RSpec
|
5
6
|
module Support
|
@@ -17,12 +18,17 @@ module RSpec
|
|
17
18
|
|
18
19
|
def non_kw_args_arity_description
|
19
20
|
case max_non_kw_args
|
20
|
-
|
21
|
-
|
22
|
-
|
21
|
+
when min_non_kw_args then min_non_kw_args.to_s
|
22
|
+
when INFINITY then "#{min_non_kw_args} or more"
|
23
|
+
else "#{min_non_kw_args} to #{max_non_kw_args}"
|
23
24
|
end
|
24
25
|
end
|
25
26
|
|
27
|
+
def valid_non_kw_args?(positional_arg_count)
|
28
|
+
min_non_kw_args <= positional_arg_count &&
|
29
|
+
positional_arg_count <= max_non_kw_args
|
30
|
+
end
|
31
|
+
|
26
32
|
if RubyFeatures.optional_and_splat_args_supported?
|
27
33
|
def description
|
28
34
|
@description ||= begin
|
@@ -40,9 +46,7 @@ module RSpec
|
|
40
46
|
parts << "required keyword args (#{@required_kw_args.map(&:inspect).join(", ")})"
|
41
47
|
end
|
42
48
|
|
43
|
-
if @allows_any_kw_args
|
44
|
-
parts << "any additional keyword args"
|
45
|
-
end
|
49
|
+
parts << "any additional keyword args" if @allows_any_kw_args
|
46
50
|
|
47
51
|
parts.join(" and ")
|
48
52
|
end
|
@@ -58,9 +62,13 @@ module RSpec
|
|
58
62
|
end
|
59
63
|
|
60
64
|
def has_kw_args_in?(args)
|
61
|
-
|
62
|
-
|
65
|
+
Hash === args.last && could_contain_kw_args?(args)
|
66
|
+
end
|
63
67
|
|
68
|
+
# Without considering what the last arg is, could it
|
69
|
+
# contain keyword arguments?
|
70
|
+
def could_contain_kw_args?(args)
|
71
|
+
return false if args.count <= min_non_kw_args
|
64
72
|
@allows_any_kw_args || @allowed_kw_args.any?
|
65
73
|
end
|
66
74
|
|
@@ -71,18 +79,18 @@ module RSpec
|
|
71
79
|
|
72
80
|
@method.parameters.each do |(type, name)|
|
73
81
|
case type
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
82
|
+
# def foo(a:)
|
83
|
+
when :keyreq then @required_kw_args << name
|
84
|
+
# def foo(a: 1)
|
85
|
+
when :key then @optional_kw_args << name
|
86
|
+
# def foo(**kw_args)
|
87
|
+
when :keyrest then @allows_any_kw_args = true
|
88
|
+
# def foo(a)
|
89
|
+
when :req then @min_non_kw_args += 1
|
90
|
+
# def foo(a = 1)
|
91
|
+
when :opt then optional_non_kw_args += 1
|
92
|
+
# def foo(*a)
|
93
|
+
when :rest then optional_non_kw_args = INFINITY
|
86
94
|
end
|
87
95
|
end
|
88
96
|
|
@@ -94,15 +102,15 @@ module RSpec
|
|
94
102
|
"arity of #{non_kw_args_arity_description}"
|
95
103
|
end
|
96
104
|
|
97
|
-
def missing_kw_args_from(
|
105
|
+
def missing_kw_args_from(_given_kw_args)
|
98
106
|
[]
|
99
107
|
end
|
100
108
|
|
101
|
-
def invalid_kw_args_from(
|
109
|
+
def invalid_kw_args_from(_given_kw_args)
|
102
110
|
[]
|
103
111
|
end
|
104
112
|
|
105
|
-
def has_kw_args_in?(
|
113
|
+
def has_kw_args_in?(_args)
|
106
114
|
false
|
107
115
|
end
|
108
116
|
|
@@ -120,16 +128,16 @@ module RSpec
|
|
120
128
|
end
|
121
129
|
end
|
122
130
|
|
123
|
-
INFINITY = 1/0.0
|
131
|
+
INFINITY = 1 / 0.0
|
124
132
|
end
|
125
133
|
|
126
134
|
# Deals with the slightly different semantics of block arguments.
|
127
135
|
# For methods, arguments are required unless a default value is provided.
|
128
136
|
# For blocks, arguments are optional, even if no default value is provided.
|
129
137
|
#
|
130
|
-
# However, we want to treat block args as required since you virtually
|
131
|
-
# want to pass a value for each received argument and our
|
132
|
-
# treated block args as required for many years.
|
138
|
+
# However, we want to treat block args as required since you virtually
|
139
|
+
# always want to pass a value for each received argument and our
|
140
|
+
# `and_yield` has treated block args as required for many years.
|
133
141
|
#
|
134
142
|
# @api private
|
135
143
|
class BlockSignature < MethodSignature
|
@@ -141,10 +149,9 @@ module RSpec
|
|
141
149
|
end
|
142
150
|
end
|
143
151
|
|
144
|
-
#
|
145
|
-
# Surprisingly non-trivial.
|
152
|
+
# Abstract base class for signature verifiers.
|
146
153
|
#
|
147
|
-
# @private
|
154
|
+
# @api private
|
148
155
|
class MethodSignatureVerifier
|
149
156
|
attr_reader :non_kw_args, :kw_args
|
150
157
|
|
@@ -154,7 +161,7 @@ module RSpec
|
|
154
161
|
end
|
155
162
|
|
156
163
|
def valid?
|
157
|
-
|
164
|
+
missing_kw_args.empty? &&
|
158
165
|
invalid_kw_args.empty? &&
|
159
166
|
valid_non_kw_args?
|
160
167
|
end
|
@@ -179,8 +186,7 @@ module RSpec
|
|
179
186
|
private
|
180
187
|
|
181
188
|
def valid_non_kw_args?
|
182
|
-
|
183
|
-
@signature.min_non_kw_args <= actual && actual <= @signature.max_non_kw_args
|
189
|
+
@signature.valid_non_kw_args?(non_kw_args.length)
|
184
190
|
end
|
185
191
|
|
186
192
|
def missing_kw_args
|
@@ -193,12 +199,69 @@ module RSpec
|
|
193
199
|
|
194
200
|
def split_args(*args)
|
195
201
|
kw_args = if @signature.has_kw_args_in?(args)
|
196
|
-
|
197
|
-
|
202
|
+
args.pop.keys
|
203
|
+
else
|
204
|
+
[]
|
205
|
+
end
|
206
|
+
|
207
|
+
[args, kw_args]
|
208
|
+
end
|
209
|
+
end
|
210
|
+
|
211
|
+
# Figures out wether a given method can accept various arguments.
|
212
|
+
# Surprisingly non-trivial.
|
213
|
+
#
|
214
|
+
# @private
|
215
|
+
StrictSignatureVerifier = MethodSignatureVerifier
|
216
|
+
|
217
|
+
# Allows matchers to be used instead of providing keyword arguments. In
|
218
|
+
# practice, when this happens only the arity of the method is verified.
|
219
|
+
#
|
220
|
+
# @private
|
221
|
+
class LooseSignatureVerifier < MethodSignatureVerifier
|
222
|
+
private
|
223
|
+
|
224
|
+
def split_args(*args)
|
225
|
+
if RSpec::Support.is_a_matcher?(args.last) && @signature.could_contain_kw_args?(args)
|
226
|
+
args.pop
|
227
|
+
@signature = SignatureWithKeywordArgumentsMatcher.new(@signature)
|
228
|
+
end
|
229
|
+
|
230
|
+
super(*args)
|
231
|
+
end
|
232
|
+
|
233
|
+
# If a matcher is used in a signature in place of keyword arguments, all
|
234
|
+
# keyword argument validation needs to be skipped since the matcher is
|
235
|
+
# opaque.
|
236
|
+
#
|
237
|
+
# Instead, keyword arguments will be validated when the method is called
|
238
|
+
# and they are actually known.
|
239
|
+
#
|
240
|
+
# @private
|
241
|
+
class SignatureWithKeywordArgumentsMatcher
|
242
|
+
def initialize(signature)
|
243
|
+
@signature = signature
|
244
|
+
end
|
245
|
+
|
246
|
+
def missing_kw_args_from(_kw_args)
|
198
247
|
[]
|
199
248
|
end
|
200
249
|
|
201
|
-
|
250
|
+
def invalid_kw_args_from(_kw_args)
|
251
|
+
[]
|
252
|
+
end
|
253
|
+
|
254
|
+
def non_kw_args_arity_description
|
255
|
+
@signature.non_kw_args_arity_description
|
256
|
+
end
|
257
|
+
|
258
|
+
def valid_non_kw_args?(*args)
|
259
|
+
@signature.valid_non_kw_args?(*args)
|
260
|
+
end
|
261
|
+
|
262
|
+
def has_kw_args_in?(args)
|
263
|
+
@signature.has_kw_args_in?(args)
|
264
|
+
end
|
202
265
|
end
|
203
266
|
end
|
204
267
|
end
|
@@ -0,0 +1,76 @@
|
|
1
|
+
module RSpec
|
2
|
+
module Support
|
3
|
+
# Provides recursive constant lookup methods useful for
|
4
|
+
# constant stubbing.
|
5
|
+
module RecursiveConstMethods
|
6
|
+
# We only want to consider constants that are defined directly on a
|
7
|
+
# particular module, and not include top-level/inherited constants.
|
8
|
+
# Unfortunately, the constant API changed between 1.8 and 1.9, so
|
9
|
+
# we need to conditionally define methods to ignore the top-level/inherited
|
10
|
+
# constants.
|
11
|
+
#
|
12
|
+
# Given:
|
13
|
+
# class A; B = 1; end
|
14
|
+
# class C < A; end
|
15
|
+
#
|
16
|
+
# On 1.8:
|
17
|
+
# - C.const_get("Hash") # => ::Hash
|
18
|
+
# - C.const_defined?("Hash") # => false
|
19
|
+
# - C.constants # => ["B"]
|
20
|
+
# - None of these methods accept the extra `inherit` argument
|
21
|
+
# On 1.9:
|
22
|
+
# - C.const_get("Hash") # => ::Hash
|
23
|
+
# - C.const_defined?("Hash") # => true
|
24
|
+
# - C.const_get("Hash", false) # => raises NameError
|
25
|
+
# - C.const_defined?("Hash", false) # => false
|
26
|
+
# - C.constants # => [:B]
|
27
|
+
# - C.constants(false) #=> []
|
28
|
+
if Module.method(:const_defined?).arity == 1
|
29
|
+
def const_defined_on?(mod, const_name)
|
30
|
+
mod.const_defined?(const_name)
|
31
|
+
end
|
32
|
+
|
33
|
+
def get_const_defined_on(mod, const_name)
|
34
|
+
return mod.const_get(const_name) if const_defined_on?(mod, const_name)
|
35
|
+
|
36
|
+
raise NameError, "uninitialized constant #{mod.name}::#{const_name}"
|
37
|
+
end
|
38
|
+
|
39
|
+
def constants_defined_on(mod)
|
40
|
+
mod.constants.select { |c| const_defined_on?(mod, c) }
|
41
|
+
end
|
42
|
+
else
|
43
|
+
def const_defined_on?(mod, const_name)
|
44
|
+
mod.const_defined?(const_name, false)
|
45
|
+
end
|
46
|
+
|
47
|
+
def get_const_defined_on(mod, const_name)
|
48
|
+
mod.const_get(const_name, false)
|
49
|
+
end
|
50
|
+
|
51
|
+
def constants_defined_on(mod)
|
52
|
+
mod.constants(false)
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
def recursive_const_get(const_name)
|
57
|
+
normalize_const_name(const_name).split('::').inject(Object) do |mod, name|
|
58
|
+
get_const_defined_on(mod, name)
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
def recursive_const_defined?(const_name)
|
63
|
+
parts = normalize_const_name(const_name).split('::')
|
64
|
+
parts.inject([Object, '']) do |(mod, full_name), name|
|
65
|
+
yield(full_name, name) if block_given? && !(Module === mod)
|
66
|
+
return false unless const_defined_on?(mod, name)
|
67
|
+
[get_const_defined_on(mod, name), [mod, name].join('::')]
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
def normalize_const_name(const_name)
|
72
|
+
const_name.sub(/\A::/, '')
|
73
|
+
end
|
74
|
+
end
|
75
|
+
end
|
76
|
+
end
|
data/lib/rspec/support/spec.rb
CHANGED
@@ -3,6 +3,7 @@ RSpec::Support.require_rspec_support "spec/deprecation_helpers"
|
|
3
3
|
RSpec::Support.require_rspec_support "spec/with_isolated_stderr"
|
4
4
|
RSpec::Support.require_rspec_support "spec/stderr_splitter"
|
5
5
|
RSpec::Support.require_rspec_support "spec/formatting_support"
|
6
|
+
RSpec::Support.require_rspec_support "spec/with_isolated_directory"
|
6
7
|
|
7
8
|
warning_preventer = $stderr = RSpec::Support::StdErrSplitter.new($stderr)
|
8
9
|
|
@@ -30,33 +31,41 @@ RSpec.configure do |c|
|
|
30
31
|
c.run_all_when_everything_filtered = true
|
31
32
|
end
|
32
33
|
|
33
|
-
module RSpec
|
34
|
-
|
35
|
-
|
36
|
-
|
34
|
+
module RSpec
|
35
|
+
module Support
|
36
|
+
module Spec
|
37
|
+
def self.setup_simplecov(&block)
|
38
|
+
# Simplecov emits some ruby warnings when loaded, so silence them.
|
39
|
+
old_verbose, $VERBOSE = $VERBOSE, false
|
37
40
|
|
38
|
-
|
41
|
+
return if ENV['NO_COVERAGE'] || RUBY_VERSION < '1.9.3' || RUBY_ENGINE != 'ruby'
|
39
42
|
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
+
# Don't load it when we're running a single isolated
|
44
|
+
# test file rather than the whole suite.
|
45
|
+
return if RSpec.configuration.files_to_run.one?
|
43
46
|
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
# Filter out `spec` directory except when it is under `lib`
|
51
|
-
# (as is the case in rspec-support)
|
52
|
-
source_file.filename.include?('/spec/') && !source_file.filename.include?('/lib/')
|
47
|
+
require 'simplecov'
|
48
|
+
start_simplecov(&block)
|
49
|
+
rescue LoadError
|
50
|
+
warn "Simplecov could not be loaded"
|
51
|
+
ensure
|
52
|
+
$VERBOSE = old_verbose
|
53
53
|
end
|
54
54
|
|
55
|
-
|
55
|
+
def self.start_simplecov(&block)
|
56
|
+
SimpleCov.start do
|
57
|
+
add_filter "./bundle/"
|
58
|
+
add_filter "./tmp/"
|
59
|
+
add_filter do |source_file|
|
60
|
+
# Filter out `spec` directory except when it is under `lib`
|
61
|
+
# (as is the case in rspec-support)
|
62
|
+
source_file.filename.include?('/spec/') && !source_file.filename.include?('/lib/')
|
63
|
+
end
|
64
|
+
|
65
|
+
instance_eval(&block) if block
|
66
|
+
end
|
67
|
+
end
|
68
|
+
private_class_method :start_simplecov
|
56
69
|
end
|
57
|
-
rescue LoadError
|
58
|
-
ensure
|
59
|
-
$VERBOSE = old_verbose
|
60
70
|
end
|
61
71
|
end
|
62
|
-
|
@@ -1,5 +1,4 @@
|
|
1
1
|
module RSpecHelpers
|
2
|
-
|
3
2
|
def expect_no_deprecation
|
4
3
|
expect(RSpec.configuration.reporter).not_to receive(:deprecation)
|
5
4
|
end
|
@@ -41,14 +40,14 @@ module RSpecHelpers
|
|
41
40
|
expect(RSpec.configuration.reporter).not_to receive(:deprecation)
|
42
41
|
end
|
43
42
|
|
44
|
-
def expect_warning_without_call_site(expected
|
43
|
+
def expect_warning_without_call_site(expected=//)
|
45
44
|
expect(::Kernel).to receive(:warn) do |message|
|
46
45
|
expect(message).to match expected
|
47
46
|
expect(message).to_not match(/Called from/)
|
48
47
|
end
|
49
48
|
end
|
50
49
|
|
51
|
-
def expect_warning_with_call_site(file, line, expected
|
50
|
+
def expect_warning_with_call_site(file, line, expected=//)
|
52
51
|
expect(::Kernel).to receive(:warn) do |message|
|
53
52
|
expect(message).to match expected
|
54
53
|
expect(message).to match(/Called from #{file}:#{line}/)
|
@@ -3,6 +3,8 @@ module RSpec
|
|
3
3
|
module InSubProcess
|
4
4
|
if Process.respond_to?(:fork) && !(RUBY_PLATFORM == 'java' && RUBY_VERSION == '1.8.7')
|
5
5
|
# Useful as a way to isolate a global change to a subprocess.
|
6
|
+
|
7
|
+
# rubocop:disable MethodLength
|
6
8
|
def in_sub_process
|
7
9
|
readme, writeme = IO.pipe
|
8
10
|
|
@@ -31,10 +33,11 @@ module RSpec
|
|
31
33
|
end
|
32
34
|
else
|
33
35
|
def in_sub_process
|
34
|
-
skip "This spec requires forking to work properly, "
|
36
|
+
skip "This spec requires forking to work properly, " \
|
35
37
|
"and your platform does not support forking"
|
36
38
|
end
|
37
39
|
end
|
40
|
+
# rubocop:enable MethodLength
|
38
41
|
end
|
39
42
|
end
|
40
43
|
end
|
@@ -0,0 +1,44 @@
|
|
1
|
+
require 'rspec/support/spec/shell_out'
|
2
|
+
|
3
|
+
module RSpec
|
4
|
+
module Support
|
5
|
+
module WarningsPrevention
|
6
|
+
def files_to_require_for(lib)
|
7
|
+
slash = File::SEPARATOR
|
8
|
+
lib_path_re = /#{slash + lib}[^#{slash}]*#{slash}lib/
|
9
|
+
load_path = $LOAD_PATH.grep(lib_path_re).first
|
10
|
+
files = Dir["#{load_path}/**/*.rb"]
|
11
|
+
extract_regex = /#{Regexp.escape(load_path) + File::SEPARATOR}(.+)\.rb$/
|
12
|
+
|
13
|
+
# We sort to ensure the files are loaded in a consistent order, regardless
|
14
|
+
# of OS. Otherwise, it could load in a different order on Travis than
|
15
|
+
# locally, and potentially trigger a "circular require considered harmful"
|
16
|
+
# warning or similar.
|
17
|
+
files.sort.map { |file| file[extract_regex, 1] }
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
RSpec.shared_examples_for "a library that issues no warnings when loaded" do |lib, *preamble_stmnts|
|
24
|
+
include RSpec::Support::ShellOut
|
25
|
+
include RSpec::Support::WarningsPrevention
|
26
|
+
|
27
|
+
it "issues no warnings when loaded", :slow do
|
28
|
+
# We want to explicitly load every file because each lib has some files that
|
29
|
+
# aren't automatically loaded, instead being delayed based on an autoload
|
30
|
+
# (such as for rspec-expectations' matchers) or based on a config option
|
31
|
+
# (e.g. `config.mock_with :rr` => 'rspec/core/mocking_adapters/rr').
|
32
|
+
statements = preamble_stmnts + files_to_require_for(lib).map do |file|
|
33
|
+
"require '#{file}'"
|
34
|
+
end
|
35
|
+
|
36
|
+
command = statements.join("; ")
|
37
|
+
|
38
|
+
stdout, stderr, status = run_ruby_with_current_load_path(command, "-w")
|
39
|
+
|
40
|
+
expect(stdout).to eq("")
|
41
|
+
expect(stderr).to eq("")
|
42
|
+
expect(status.exitstatus).to eq(0)
|
43
|
+
end
|
44
|
+
end
|
@@ -0,0 +1,54 @@
|
|
1
|
+
require 'open3'
|
2
|
+
require 'rake/file_utils'
|
3
|
+
require 'shellwords'
|
4
|
+
|
5
|
+
module RSpec
|
6
|
+
module Support
|
7
|
+
module ShellOut
|
8
|
+
def with_env(vars)
|
9
|
+
original = ENV.to_hash
|
10
|
+
vars.each { |k, v| ENV[k] = v }
|
11
|
+
|
12
|
+
begin
|
13
|
+
yield
|
14
|
+
ensure
|
15
|
+
ENV.replace(original)
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
if Open3.respond_to?(:capture3) # 1.9+
|
20
|
+
def shell_out(*command)
|
21
|
+
Open3.capture3(*command)
|
22
|
+
end
|
23
|
+
else # 1.8.7
|
24
|
+
def shell_out(*command)
|
25
|
+
stdout = stderr = nil
|
26
|
+
|
27
|
+
Open3.popen3(*command) do |_in, out, err|
|
28
|
+
stdout = out.read
|
29
|
+
stderr = err.read
|
30
|
+
end
|
31
|
+
|
32
|
+
# popen3 doesn't provide the exit status so we fake it out.
|
33
|
+
status = instance_double(Process::Status, :exitstatus => 0)
|
34
|
+
return stdout, stderr, status
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
def run_ruby_with_current_load_path(ruby_command, *flags)
|
39
|
+
command = [
|
40
|
+
FileUtils::RUBY,
|
41
|
+
"-I#{$LOAD_PATH.map(&:shellescape).join(File::PATH_SEPARATOR)}",
|
42
|
+
"-e", ruby_command, *flags
|
43
|
+
]
|
44
|
+
|
45
|
+
# Unset these env vars because `ruby -w` will issue warnings whenever
|
46
|
+
# they are set to non-default values.
|
47
|
+
with_env 'RUBY_GC_HEAP_FREE_SLOTS' => nil, 'RUBY_GC_MALLOC_LIMIT' => nil,
|
48
|
+
'RUBY_FREE_MIN' => nil do
|
49
|
+
shell_out(*command)
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
@@ -25,10 +25,10 @@ module RSpec
|
|
25
25
|
# To work around JRuby error:
|
26
26
|
# TypeError: $stderr must have write method, RSpec::StdErrSplitter given
|
27
27
|
def write(line)
|
28
|
-
if line
|
29
|
-
|
30
|
-
|
31
|
-
|
28
|
+
return if line =~ %r{^\S+/gems/\S+:\d+: warning:} # http://rubular.com/r/kqeUIZOfPG
|
29
|
+
|
30
|
+
@orig_stderr.write(line)
|
31
|
+
@output_tracker.write(line)
|
32
32
|
end
|
33
33
|
|
34
34
|
def has_output?
|
@@ -40,14 +40,13 @@ module RSpec
|
|
40
40
|
end
|
41
41
|
|
42
42
|
def verify_example!(example)
|
43
|
-
example.send(:fail,"Warnings were generated: #{output}") if has_output?
|
43
|
+
example.send(:fail, "Warnings were generated: #{output}") if has_output?
|
44
44
|
reset!
|
45
45
|
end
|
46
46
|
|
47
47
|
def output
|
48
48
|
@output_tracker.string
|
49
49
|
end
|
50
|
-
|
51
50
|
end
|
52
51
|
end
|
53
52
|
end
|
@@ -26,18 +26,18 @@ module RSpec
|
|
26
26
|
|
27
27
|
def raise_too_low_error
|
28
28
|
raise LibraryVersionTooLowError,
|
29
|
-
|
30
|
-
|
29
|
+
"You are using #{@library_name} #{@library_version}. " \
|
30
|
+
"RSpec requires version #{version_requirement}."
|
31
31
|
end
|
32
32
|
|
33
33
|
def compare_version
|
34
34
|
case
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
35
|
+
when @major < @min_major then :too_low
|
36
|
+
when @major > @min_major then :ok
|
37
|
+
when @minor < @min_minor then :too_low
|
38
|
+
when @minor > @min_minor then :ok
|
39
|
+
when @patch < @min_patch then :too_low
|
40
|
+
else :ok
|
41
41
|
end
|
42
42
|
end
|
43
43
|
|
@@ -4,7 +4,7 @@ RSpec::Support.require_rspec_support "caller_filter"
|
|
4
4
|
module RSpec
|
5
5
|
module Support
|
6
6
|
module Warnings
|
7
|
-
def deprecate(deprecated, options
|
7
|
+
def deprecate(deprecated, options={})
|
8
8
|
warn_with "DEPRECATION: #{deprecated} is deprecated.", options
|
9
9
|
end
|
10
10
|
|
@@ -12,7 +12,7 @@ module RSpec
|
|
12
12
|
#
|
13
13
|
# Used internally to print deprecation warnings
|
14
14
|
# when rspec-core isn't loaded
|
15
|
-
def warn_deprecation(message, options
|
15
|
+
def warn_deprecation(message, options={})
|
16
16
|
warn_with "DEPRECATION: \n #{message}", options
|
17
17
|
end
|
18
18
|
|
@@ -26,7 +26,7 @@ module RSpec
|
|
26
26
|
# @private
|
27
27
|
#
|
28
28
|
# Used internally to print longer warnings
|
29
|
-
def warn_with(message, options
|
29
|
+
def warn_with(message, options={})
|
30
30
|
call_site = options.fetch(:call_site) { CallerFilter.first_non_rspec_line }
|
31
31
|
message << " Use #{options[:replacement]} instead." if options[:replacement]
|
32
32
|
message << " Called from #{call_site}." if call_site
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: rspec-support
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 3.0
|
4
|
+
version: 3.1.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- David Chelimsky
|
@@ -36,7 +36,7 @@ cert_chain:
|
|
36
36
|
1yHC1AcSYpvi2dAbOiHT5iQF+krm4wse8KctXgTNnjMsHEoGKulJS2/sZl90jcCz
|
37
37
|
muA=
|
38
38
|
-----END CERTIFICATE-----
|
39
|
-
date: 2014-
|
39
|
+
date: 2014-09-05 00:00:00.000000000 Z
|
40
40
|
dependencies:
|
41
41
|
- !ruby/object:Gem::Dependency
|
42
42
|
name: bundler
|
@@ -66,20 +66,6 @@ dependencies:
|
|
66
66
|
- - "~>"
|
67
67
|
- !ruby/object:Gem::Version
|
68
68
|
version: 10.0.0
|
69
|
-
- !ruby/object:Gem::Dependency
|
70
|
-
name: rspec
|
71
|
-
requirement: !ruby/object:Gem::Requirement
|
72
|
-
requirements:
|
73
|
-
- - ">="
|
74
|
-
- !ruby/object:Gem::Version
|
75
|
-
version: 3.0.0.pre
|
76
|
-
type: :development
|
77
|
-
prerelease: false
|
78
|
-
version_requirements: !ruby/object:Gem::Requirement
|
79
|
-
requirements:
|
80
|
-
- - ">="
|
81
|
-
- !ruby/object:Gem::Version
|
82
|
-
version: 3.0.0.pre
|
83
69
|
description: Support utilities for RSpec gems
|
84
70
|
email: rspec-users@rubyforge.org
|
85
71
|
executables: []
|
@@ -92,16 +78,22 @@ files:
|
|
92
78
|
- lib/rspec/support.rb
|
93
79
|
- lib/rspec/support/caller_filter.rb
|
94
80
|
- lib/rspec/support/differ.rb
|
81
|
+
- lib/rspec/support/directory_maker.rb
|
95
82
|
- lib/rspec/support/encoded_string.rb
|
96
83
|
- lib/rspec/support/fuzzy_matcher.rb
|
97
84
|
- lib/rspec/support/hunk_generator.rb
|
85
|
+
- lib/rspec/support/matcher_definition.rb
|
98
86
|
- lib/rspec/support/method_signature_verifier.rb
|
87
|
+
- lib/rspec/support/recursive_const_methods.rb
|
99
88
|
- lib/rspec/support/ruby_features.rb
|
100
89
|
- lib/rspec/support/spec.rb
|
101
90
|
- lib/rspec/support/spec/deprecation_helpers.rb
|
102
91
|
- lib/rspec/support/spec/formatting_support.rb
|
103
92
|
- lib/rspec/support/spec/in_sub_process.rb
|
93
|
+
- lib/rspec/support/spec/prevent_load_time_warnings.rb
|
94
|
+
- lib/rspec/support/spec/shell_out.rb
|
104
95
|
- lib/rspec/support/spec/stderr_splitter.rb
|
96
|
+
- lib/rspec/support/spec/with_isolated_directory.rb
|
105
97
|
- lib/rspec/support/spec/with_isolated_stderr.rb
|
106
98
|
- lib/rspec/support/version.rb
|
107
99
|
- lib/rspec/support/version_checker.rb
|
@@ -130,5 +122,5 @@ rubyforge_project: rspec
|
|
130
122
|
rubygems_version: 2.2.2
|
131
123
|
signing_key:
|
132
124
|
specification_version: 4
|
133
|
-
summary: rspec-support-3.0
|
125
|
+
summary: rspec-support-3.1.0
|
134
126
|
test_files: []
|
metadata.gz.sig
CHANGED
Binary file
|