rspec-support 3.0.0.beta2 → 3.0.0.rc1
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 +7 -0
- checksums.yaml.gz.sig +0 -0
- data.tar.gz.sig +3 -2
- data/Changelog.md +5 -2
- data/lib/rspec/support.rb +28 -2
- data/lib/rspec/support/caller_filter.rb +10 -2
- data/lib/rspec/support/differ.rb +205 -0
- data/lib/rspec/support/encoded_string.rb +66 -0
- data/lib/rspec/support/hunk_generator.rb +48 -0
- data/lib/rspec/support/method_signature_verifier.rb +205 -0
- data/lib/rspec/support/ruby_features.rb +29 -0
- data/lib/rspec/support/spec.rb +14 -9
- data/lib/rspec/support/spec/deprecation_helpers.rb +14 -0
- data/lib/rspec/support/spec/formatting_support.rb +9 -0
- data/lib/rspec/support/spec/stderr_splitter.rb +7 -4
- data/lib/rspec/support/version.rb +1 -1
- data/lib/rspec/support/warnings.rb +28 -34
- metadata +26 -50
- metadata.gz.sig +0 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 8056b6ffe2b19796122cb63098b5f5d31818b0bb
|
4
|
+
data.tar.gz: faa2a0e043eaa9c0a6c97675e1560640f40582c5
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: dd81e590c2160e0656ff7fc4f87d238d1c20b055ba0de0c6149aa74204e78275963b5737c0d9aa699eb35a6c678c717aebaf05a4a5eab9e441bd9b14e0e32edb
|
7
|
+
data.tar.gz: 7ca41367d6087c33f9146bf34089ef9b651be5ed8bd263e8e1ef61289df193171f940dc2ca4f4324560ca4a287ffd7e5d67bd6946716725e0036fd040ec70a39
|
checksums.yaml.gz.sig
ADDED
Binary file
|
data.tar.gz.sig
CHANGED
@@ -1,2 +1,3 @@
|
|
1
|
-
|
2
|
-
|
1
|
+
���e��6d+�{oe���r�x�l���?�aٞ��,#�aEh}��d��m�P����T?,�����iP�\u��������*�7'�����+\b��RUg����z���֠S�
|
2
|
+
?.�Dj��G�v�qs�
|
3
|
+
l���Փ
|
data/Changelog.md
CHANGED
@@ -1,11 +1,14 @@
|
|
1
|
+
### 3.0.0.rc1 / 2014-05-18
|
2
|
+
[Full Changelog](http://github.com/rspec/rspec-support/compare/v3.0.0.beta2...v3.0.0.rc1)
|
3
|
+
|
1
4
|
### 3.0.0.beta2 / 2014-02-17
|
2
|
-
[
|
5
|
+
[Full Changelog](http://github.com/rspec/rspec-support/compare/v3.0.0.beta1...v3.0.0.beta2)
|
3
6
|
|
4
7
|
Bug Fixes:
|
5
8
|
|
6
9
|
* Issue message when :replacement is passed to `RSpec.warn_with`. (Jon Rowe)
|
7
10
|
|
8
11
|
### 3.0.0.beta1 / 2013-11-07
|
9
|
-
[
|
12
|
+
[Full Changelog](https://github.com/rspec/rspec-support/compare/0dc12d1bdbbacc757a9989f8c09cd08ef3a4837e...v3.0.0.beta1)
|
10
13
|
|
11
14
|
Initial release.
|
data/lib/rspec/support.rb
CHANGED
@@ -1,7 +1,33 @@
|
|
1
|
-
require "rspec/support/version"
|
2
|
-
|
3
1
|
module RSpec
|
4
2
|
module Support
|
3
|
+
# @api private
|
4
|
+
#
|
5
|
+
# Defines a helper method that is optimized to require files from the
|
6
|
+
# named lib. The passed block MUST be `{ |f| require_relative f }`
|
7
|
+
# because for `require_relative` to work properly from within the named
|
8
|
+
# lib the line of code must be IN that lib.
|
9
|
+
#
|
10
|
+
# `require_relative` is preferred when available because it is always O(1),
|
11
|
+
# regardless of the number of dirs in $LOAD_PATH. `require`, on the other
|
12
|
+
# hand, does a linear O(N) search over the dirs in the $LOAD_PATH until
|
13
|
+
# it can resolve the file relative to one of the dirs.
|
14
|
+
def self.define_optimized_require_for_rspec(lib, &require_relative)
|
15
|
+
name = "require_rspec_#{lib}"
|
16
|
+
|
17
|
+
if Kernel.respond_to?(:require_relative)
|
18
|
+
(class << self; self; end).__send__(:define_method, name) do |f|
|
19
|
+
require_relative.call("#{lib}/#{f}")
|
20
|
+
end
|
21
|
+
else
|
22
|
+
(class << self; self; end).__send__(:define_method, name) do |f|
|
23
|
+
require "rspec/#{lib}/#{f}"
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
define_optimized_require_for_rspec(:support) { |f| require_relative(f) }
|
29
|
+
require_rspec_support "version"
|
30
|
+
|
5
31
|
# @api private
|
6
32
|
KERNEL_METHOD_METHOD = ::Kernel.instance_method(:method)
|
7
33
|
|
@@ -18,6 +18,14 @@ module RSpec
|
|
18
18
|
|
19
19
|
LIB_REGEX = %r{/lib/rspec/(#{(RSPEC_LIBS + ADDITIONAL_TOP_LEVEL_FILES).join('|')})(\.rb|/)}
|
20
20
|
|
21
|
+
# rubygems/core_ext/kernel_require.rb isn't actually part of rspec (obviously) but we want
|
22
|
+
# it ignored when we are looking for the first meaningful line of the backtrace outside
|
23
|
+
# of RSpec. It can show up in the backtrace as the immediate first caller
|
24
|
+
# when `CallerFilter.first_non_rspec_line` is called from the top level of a required
|
25
|
+
# file, but it depends on if rubygems is loaded or not. We don't want to have to deal
|
26
|
+
# with this complexity in our `RSpec.deprecate` calls, so we ignore it here.
|
27
|
+
IGNORE_REGEX = Regexp.union(LIB_REGEX, "rubygems/core_ext/kernel_require.rb")
|
28
|
+
|
21
29
|
if RUBY_VERSION >= '2.0.0'
|
22
30
|
def self.first_non_rspec_line
|
23
31
|
# `caller` is an expensive method that scales linearly with the size of
|
@@ -37,7 +45,7 @@ module RSpec
|
|
37
45
|
stack = caller(i, increment)
|
38
46
|
raise "No non-lib lines in stack" unless stack
|
39
47
|
|
40
|
-
line = stack.find { |l| l !~
|
48
|
+
line = stack.find { |l| l !~ IGNORE_REGEX }
|
41
49
|
|
42
50
|
i += increment
|
43
51
|
increment *= 2 # The choice of two here is arbitrary.
|
@@ -49,7 +57,7 @@ module RSpec
|
|
49
57
|
# Earlier rubies do not support the two argument form of `caller`. This
|
50
58
|
# fallback is logically the same, but slower.
|
51
59
|
def self.first_non_rspec_line
|
52
|
-
caller.find { |line| line !~
|
60
|
+
caller.find { |line| line !~ IGNORE_REGEX }
|
53
61
|
end
|
54
62
|
end
|
55
63
|
end
|
@@ -0,0 +1,205 @@
|
|
1
|
+
RSpec::Support.require_rspec_support 'encoded_string'
|
2
|
+
RSpec::Support.require_rspec_support 'hunk_generator'
|
3
|
+
|
4
|
+
require 'pp'
|
5
|
+
|
6
|
+
module RSpec
|
7
|
+
module Support
|
8
|
+
class Differ
|
9
|
+
def diff(actual, expected)
|
10
|
+
diff = ""
|
11
|
+
|
12
|
+
if actual && expected
|
13
|
+
if all_strings?(actual, expected)
|
14
|
+
if any_multiline_strings?(actual, expected)
|
15
|
+
diff = diff_as_string(coerce_to_string(actual), coerce_to_string(expected))
|
16
|
+
end
|
17
|
+
elsif no_procs?(actual, expected) && no_numbers?(actual, expected)
|
18
|
+
diff = diff_as_object(actual, expected)
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
diff
|
23
|
+
end
|
24
|
+
|
25
|
+
def diff_as_string(actual, expected)
|
26
|
+
@encoding = pick_encoding actual, expected
|
27
|
+
|
28
|
+
@actual = EncodedString.new(actual, @encoding)
|
29
|
+
@expected = EncodedString.new(expected, @encoding)
|
30
|
+
|
31
|
+
output = EncodedString.new("\n", @encoding)
|
32
|
+
|
33
|
+
hunks.each_cons(2) do |prev_hunk, current_hunk|
|
34
|
+
begin
|
35
|
+
if current_hunk.overlaps?(prev_hunk)
|
36
|
+
add_old_hunk_to_hunk(current_hunk, prev_hunk)
|
37
|
+
else
|
38
|
+
add_to_output(output, prev_hunk.diff(format).to_s)
|
39
|
+
end
|
40
|
+
ensure
|
41
|
+
add_to_output(output, "\n")
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
if hunks.last
|
46
|
+
finalize_output(output, hunks.last.diff(format).to_s)
|
47
|
+
end
|
48
|
+
|
49
|
+
color_diff output
|
50
|
+
rescue Encoding::CompatibilityError
|
51
|
+
handle_encoding_errors
|
52
|
+
end
|
53
|
+
|
54
|
+
def diff_as_object(actual, expected)
|
55
|
+
actual_as_string = object_to_string(actual)
|
56
|
+
expected_as_string = object_to_string(expected)
|
57
|
+
diff_as_string(actual_as_string, expected_as_string)
|
58
|
+
end
|
59
|
+
|
60
|
+
attr_reader :color
|
61
|
+
alias_method :color?, :color
|
62
|
+
|
63
|
+
def initialize(opts={})
|
64
|
+
@color = opts.fetch(:color, false)
|
65
|
+
@object_preparer = opts.fetch(:object_preparer, lambda { |string| string })
|
66
|
+
end
|
67
|
+
|
68
|
+
private
|
69
|
+
|
70
|
+
def no_procs?(*args)
|
71
|
+
args.flatten.none? { |a| Proc === a}
|
72
|
+
end
|
73
|
+
|
74
|
+
def all_strings?(*args)
|
75
|
+
args.flatten.all? { |a| String === a}
|
76
|
+
end
|
77
|
+
|
78
|
+
def any_multiline_strings?(*args)
|
79
|
+
all_strings?(*args) && args.flatten.any? { |a| multiline?(a) }
|
80
|
+
end
|
81
|
+
|
82
|
+
def no_numbers?(*args)
|
83
|
+
args.flatten.none? { |a| Numeric === a}
|
84
|
+
end
|
85
|
+
|
86
|
+
def coerce_to_string(string_or_array)
|
87
|
+
return string_or_array unless Array === string_or_array
|
88
|
+
diffably_stringify(string_or_array).join("\n")
|
89
|
+
end
|
90
|
+
|
91
|
+
def diffably_stringify(array)
|
92
|
+
array.map do |entry|
|
93
|
+
if Array === entry
|
94
|
+
entry.inspect
|
95
|
+
else
|
96
|
+
entry.to_s.gsub("\n", "\\n")
|
97
|
+
end
|
98
|
+
end
|
99
|
+
end
|
100
|
+
|
101
|
+
if String.method_defined?(:encoding)
|
102
|
+
def multiline?(string)
|
103
|
+
string.include?("\n".encode(string.encoding))
|
104
|
+
end
|
105
|
+
else
|
106
|
+
def multiline?(string)
|
107
|
+
string.include?("\n")
|
108
|
+
end
|
109
|
+
end
|
110
|
+
|
111
|
+
def hunks
|
112
|
+
@hunks ||= HunkGenerator.new(@actual, @expected).hunks
|
113
|
+
end
|
114
|
+
|
115
|
+
def finalize_output(output, final_line)
|
116
|
+
add_to_output(output, final_line)
|
117
|
+
add_to_output(output, "\n")
|
118
|
+
end
|
119
|
+
|
120
|
+
def add_to_output(output, string)
|
121
|
+
output << string
|
122
|
+
end
|
123
|
+
|
124
|
+
def add_old_hunk_to_hunk(hunk, oldhunk)
|
125
|
+
hunk.merge(oldhunk)
|
126
|
+
end
|
127
|
+
|
128
|
+
def format
|
129
|
+
:unified
|
130
|
+
end
|
131
|
+
|
132
|
+
def color(text, color_code)
|
133
|
+
"\e[#{color_code}m#{text}\e[0m"
|
134
|
+
end
|
135
|
+
|
136
|
+
def red(text)
|
137
|
+
color(text, 31)
|
138
|
+
end
|
139
|
+
|
140
|
+
def green(text)
|
141
|
+
color(text, 32)
|
142
|
+
end
|
143
|
+
|
144
|
+
def blue(text)
|
145
|
+
color(text, 34)
|
146
|
+
end
|
147
|
+
|
148
|
+
def normal(text)
|
149
|
+
color(text, 0)
|
150
|
+
end
|
151
|
+
|
152
|
+
def color_diff(diff)
|
153
|
+
return diff unless color?
|
154
|
+
|
155
|
+
diff.lines.map { |line|
|
156
|
+
case line[0].chr
|
157
|
+
when "+"
|
158
|
+
green line
|
159
|
+
when "-"
|
160
|
+
red line
|
161
|
+
when "@"
|
162
|
+
line[1].chr == "@" ? blue(line) : normal(line)
|
163
|
+
else
|
164
|
+
normal(line)
|
165
|
+
end
|
166
|
+
}.join
|
167
|
+
end
|
168
|
+
|
169
|
+
def object_to_string(object)
|
170
|
+
object = @object_preparer.call(object)
|
171
|
+
case object
|
172
|
+
when Hash
|
173
|
+
object.keys.sort_by { |k| k.to_s }.map do |key|
|
174
|
+
pp_key = PP.singleline_pp(key, "")
|
175
|
+
pp_value = PP.singleline_pp(object[key], "")
|
176
|
+
|
177
|
+
"#{pp_key} => #{pp_value},"
|
178
|
+
end.join("\n")
|
179
|
+
when String
|
180
|
+
object =~ /\n/ ? object : object.inspect
|
181
|
+
else
|
182
|
+
PP.pp(object,"")
|
183
|
+
end
|
184
|
+
end
|
185
|
+
|
186
|
+
if String.method_defined?(:encoding)
|
187
|
+
def pick_encoding(source_a, source_b)
|
188
|
+
Encoding.compatible?(source_a, source_b) || Encoding.default_external
|
189
|
+
end
|
190
|
+
else
|
191
|
+
def pick_encoding(source_a, source_b)
|
192
|
+
end
|
193
|
+
end
|
194
|
+
|
195
|
+
def handle_encoding_errors
|
196
|
+
if @actual.source_encoding != @expected.source_encoding
|
197
|
+
"Could not produce a diff because the encoding of the actual string (#{@actual.source_encoding}) "+
|
198
|
+
"differs from the encoding of the expected string (#{@expected.source_encoding})"
|
199
|
+
else
|
200
|
+
"Could not produce a diff because of the encoding of the string (#{@expected.source_encoding})"
|
201
|
+
end
|
202
|
+
end
|
203
|
+
end
|
204
|
+
end
|
205
|
+
end
|
@@ -0,0 +1,66 @@
|
|
1
|
+
module RSpec
|
2
|
+
module Support
|
3
|
+
# @private
|
4
|
+
class EncodedString
|
5
|
+
|
6
|
+
MRI_UNICODE_UNKOWN_CHARACTER = "\xEF\xBF\xBD"
|
7
|
+
|
8
|
+
def initialize(string, encoding = nil)
|
9
|
+
@encoding = encoding
|
10
|
+
@source_encoding = detect_source_encoding(string)
|
11
|
+
@string = matching_encoding(string)
|
12
|
+
end
|
13
|
+
attr_reader :source_encoding
|
14
|
+
|
15
|
+
delegated_methods = String.instance_methods.map(&:to_s) & %w[eql? lines == encoding empty?]
|
16
|
+
delegated_methods.each do |name|
|
17
|
+
define_method(name) { |*args, &block| @string.__send__(name, *args, &block) }
|
18
|
+
end
|
19
|
+
|
20
|
+
def <<(string)
|
21
|
+
@string << matching_encoding(string)
|
22
|
+
end
|
23
|
+
|
24
|
+
def split(regex_or_string)
|
25
|
+
@string.split(matching_encoding(regex_or_string))
|
26
|
+
end
|
27
|
+
|
28
|
+
def to_s
|
29
|
+
@string
|
30
|
+
end
|
31
|
+
alias :to_str :to_s
|
32
|
+
|
33
|
+
private
|
34
|
+
|
35
|
+
if String.method_defined?(:encoding)
|
36
|
+
def matching_encoding(string)
|
37
|
+
string.encode(@encoding)
|
38
|
+
rescue Encoding::UndefinedConversionError, Encoding::InvalidByteSequenceError
|
39
|
+
normalize_missing(string.encode(@encoding, :invalid => :replace, :undef => :replace))
|
40
|
+
rescue Encoding::ConverterNotFoundError
|
41
|
+
normalize_missing(string.force_encoding(@encoding).encode(:invalid => :replace))
|
42
|
+
end
|
43
|
+
|
44
|
+
def normalize_missing(string)
|
45
|
+
if @encoding.to_s == "UTF-8"
|
46
|
+
string.gsub(MRI_UNICODE_UNKOWN_CHARACTER.force_encoding(@encoding), "?")
|
47
|
+
else
|
48
|
+
string
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
def detect_source_encoding(string)
|
53
|
+
string.encoding
|
54
|
+
end
|
55
|
+
else
|
56
|
+
def matching_encoding(string)
|
57
|
+
string
|
58
|
+
end
|
59
|
+
|
60
|
+
def detect_source_encoding(string)
|
61
|
+
'US-ASCII'
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
@@ -0,0 +1,48 @@
|
|
1
|
+
require 'diff/lcs'
|
2
|
+
require 'diff/lcs/hunk'
|
3
|
+
|
4
|
+
module RSpec
|
5
|
+
module Support
|
6
|
+
# @private
|
7
|
+
class HunkGenerator
|
8
|
+
def initialize(actual, expected)
|
9
|
+
@actual = actual
|
10
|
+
@expected = expected
|
11
|
+
end
|
12
|
+
|
13
|
+
def hunks
|
14
|
+
@file_length_difference = 0
|
15
|
+
@hunks ||= diffs.map do |piece|
|
16
|
+
build_hunk(piece)
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
private
|
21
|
+
|
22
|
+
def diffs
|
23
|
+
Diff::LCS.diff(expected_lines, actual_lines)
|
24
|
+
end
|
25
|
+
|
26
|
+
def expected_lines
|
27
|
+
@expected.split("\n").map! { |e| e.chomp }
|
28
|
+
end
|
29
|
+
|
30
|
+
def actual_lines
|
31
|
+
@actual.split("\n").map! { |e| e.chomp }
|
32
|
+
end
|
33
|
+
|
34
|
+
def build_hunk(piece)
|
35
|
+
Diff::LCS::Hunk.new(
|
36
|
+
expected_lines, actual_lines, piece, context_lines, @file_length_difference
|
37
|
+
).tap do |h|
|
38
|
+
@file_length_difference = h.file_length_difference
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
def context_lines
|
43
|
+
3
|
44
|
+
end
|
45
|
+
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
@@ -0,0 +1,205 @@
|
|
1
|
+
require 'rspec/support'
|
2
|
+
RSpec::Support.require_rspec_support "ruby_features"
|
3
|
+
|
4
|
+
module RSpec
|
5
|
+
module Support
|
6
|
+
# Extracts info about the number of arguments and allowed/required
|
7
|
+
# keyword args of a given method.
|
8
|
+
#
|
9
|
+
# @private
|
10
|
+
class MethodSignature
|
11
|
+
attr_reader :min_non_kw_args, :max_non_kw_args
|
12
|
+
|
13
|
+
def initialize(method)
|
14
|
+
@method = method
|
15
|
+
classify_parameters
|
16
|
+
end
|
17
|
+
|
18
|
+
def non_kw_args_arity_description
|
19
|
+
case max_non_kw_args
|
20
|
+
when min_non_kw_args then min_non_kw_args.to_s
|
21
|
+
when INFINITY then "#{min_non_kw_args} or more"
|
22
|
+
else "#{min_non_kw_args} to #{max_non_kw_args}"
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
if RubyFeatures.optional_and_splat_args_supported?
|
27
|
+
def description
|
28
|
+
@description ||= begin
|
29
|
+
parts = []
|
30
|
+
|
31
|
+
unless non_kw_args_arity_description == "0"
|
32
|
+
parts << "arity of #{non_kw_args_arity_description}"
|
33
|
+
end
|
34
|
+
|
35
|
+
if @optional_kw_args.any?
|
36
|
+
parts << "optional keyword args (#{@optional_kw_args.map(&:inspect).join(", ")})"
|
37
|
+
end
|
38
|
+
|
39
|
+
if @required_kw_args.any?
|
40
|
+
parts << "required keyword args (#{@required_kw_args.map(&:inspect).join(", ")})"
|
41
|
+
end
|
42
|
+
|
43
|
+
if @allows_any_kw_args
|
44
|
+
parts << "any additional keyword args"
|
45
|
+
end
|
46
|
+
|
47
|
+
parts.join(" and ")
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
def missing_kw_args_from(given_kw_args)
|
52
|
+
@required_kw_args - given_kw_args
|
53
|
+
end
|
54
|
+
|
55
|
+
def invalid_kw_args_from(given_kw_args)
|
56
|
+
return [] if @allows_any_kw_args
|
57
|
+
given_kw_args - @allowed_kw_args
|
58
|
+
end
|
59
|
+
|
60
|
+
def has_kw_args_in?(args)
|
61
|
+
return false unless Hash === args.last
|
62
|
+
return false if args.count <= min_non_kw_args
|
63
|
+
|
64
|
+
@allows_any_kw_args || @allowed_kw_args.any?
|
65
|
+
end
|
66
|
+
|
67
|
+
def classify_parameters
|
68
|
+
optional_non_kw_args = @min_non_kw_args = 0
|
69
|
+
@optional_kw_args, @required_kw_args = [], []
|
70
|
+
@allows_any_kw_args = false
|
71
|
+
|
72
|
+
@method.parameters.each do |(type, name)|
|
73
|
+
case type
|
74
|
+
# def foo(a:)
|
75
|
+
when :keyreq then @required_kw_args << name
|
76
|
+
# def foo(a: 1)
|
77
|
+
when :key then @optional_kw_args << name
|
78
|
+
# def foo(**kw_args)
|
79
|
+
when :keyrest then @allows_any_kw_args = true
|
80
|
+
# def foo(a)
|
81
|
+
when :req then @min_non_kw_args += 1
|
82
|
+
# def foo(a = 1)
|
83
|
+
when :opt then optional_non_kw_args += 1
|
84
|
+
# def foo(*a)
|
85
|
+
when :rest then optional_non_kw_args = INFINITY
|
86
|
+
end
|
87
|
+
end
|
88
|
+
|
89
|
+
@max_non_kw_args = @min_non_kw_args + optional_non_kw_args
|
90
|
+
@allowed_kw_args = @required_kw_args + @optional_kw_args
|
91
|
+
end
|
92
|
+
else
|
93
|
+
def description
|
94
|
+
"arity of #{non_kw_args_arity_description}"
|
95
|
+
end
|
96
|
+
|
97
|
+
def missing_kw_args_from(given_kw_args)
|
98
|
+
[]
|
99
|
+
end
|
100
|
+
|
101
|
+
def invalid_kw_args_from(given_kw_args)
|
102
|
+
[]
|
103
|
+
end
|
104
|
+
|
105
|
+
def has_kw_args_in?(args)
|
106
|
+
false
|
107
|
+
end
|
108
|
+
|
109
|
+
def classify_parameters
|
110
|
+
arity = @method.arity
|
111
|
+
if arity < 0
|
112
|
+
# `~` inverts the one's complement and gives us the
|
113
|
+
# number of required args
|
114
|
+
@min_non_kw_args = ~arity
|
115
|
+
@max_non_kw_args = INFINITY
|
116
|
+
else
|
117
|
+
@min_non_kw_args = arity
|
118
|
+
@max_non_kw_args = arity
|
119
|
+
end
|
120
|
+
end
|
121
|
+
end
|
122
|
+
|
123
|
+
INFINITY = 1/0.0
|
124
|
+
end
|
125
|
+
|
126
|
+
# Deals with the slightly different semantics of block arguments.
|
127
|
+
# For methods, arguments are required unless a default value is provided.
|
128
|
+
# For blocks, arguments are optional, even if no default value is provided.
|
129
|
+
#
|
130
|
+
# However, we want to treat block args as required since you virtually always
|
131
|
+
# want to pass a value for each received argument and our `and_yield` has
|
132
|
+
# treated block args as required for many years.
|
133
|
+
#
|
134
|
+
# @api private
|
135
|
+
class BlockSignature < MethodSignature
|
136
|
+
if RubyFeatures.optional_and_splat_args_supported?
|
137
|
+
def classify_parameters
|
138
|
+
super
|
139
|
+
@min_non_kw_args = @max_non_kw_args unless @max_non_kw_args == INFINITY
|
140
|
+
end
|
141
|
+
end
|
142
|
+
end
|
143
|
+
|
144
|
+
# Figures out wheter a given method can accept various arguments.
|
145
|
+
# Surprisingly non-trivial.
|
146
|
+
#
|
147
|
+
# @private
|
148
|
+
class MethodSignatureVerifier
|
149
|
+
attr_reader :non_kw_args, :kw_args
|
150
|
+
|
151
|
+
def initialize(signature, args)
|
152
|
+
@signature = signature
|
153
|
+
@non_kw_args, @kw_args = split_args(*args)
|
154
|
+
end
|
155
|
+
|
156
|
+
def valid?
|
157
|
+
missing_kw_args.empty? &&
|
158
|
+
invalid_kw_args.empty? &&
|
159
|
+
valid_non_kw_args?
|
160
|
+
end
|
161
|
+
|
162
|
+
def error_message
|
163
|
+
if missing_kw_args.any?
|
164
|
+
"Missing required keyword arguments: %s" % [
|
165
|
+
missing_kw_args.join(", ")
|
166
|
+
]
|
167
|
+
elsif invalid_kw_args.any?
|
168
|
+
"Invalid keyword arguments provided: %s" % [
|
169
|
+
invalid_kw_args.join(", ")
|
170
|
+
]
|
171
|
+
elsif !valid_non_kw_args?
|
172
|
+
"Wrong number of arguments. Expected %s, got %s." % [
|
173
|
+
@signature.non_kw_args_arity_description,
|
174
|
+
non_kw_args.length
|
175
|
+
]
|
176
|
+
end
|
177
|
+
end
|
178
|
+
|
179
|
+
private
|
180
|
+
|
181
|
+
def valid_non_kw_args?
|
182
|
+
actual = non_kw_args.length
|
183
|
+
@signature.min_non_kw_args <= actual && actual <= @signature.max_non_kw_args
|
184
|
+
end
|
185
|
+
|
186
|
+
def missing_kw_args
|
187
|
+
@signature.missing_kw_args_from(kw_args)
|
188
|
+
end
|
189
|
+
|
190
|
+
def invalid_kw_args
|
191
|
+
@signature.invalid_kw_args_from(kw_args)
|
192
|
+
end
|
193
|
+
|
194
|
+
def split_args(*args)
|
195
|
+
kw_args = if @signature.has_kw_args_in?(args)
|
196
|
+
args.pop.keys
|
197
|
+
else
|
198
|
+
[]
|
199
|
+
end
|
200
|
+
|
201
|
+
[args, kw_args]
|
202
|
+
end
|
203
|
+
end
|
204
|
+
end
|
205
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
module RSpec
|
2
|
+
module Support
|
3
|
+
# @api private
|
4
|
+
#
|
5
|
+
# Provides query methods for ruby features that differ among
|
6
|
+
# implementations.
|
7
|
+
module RubyFeatures
|
8
|
+
def optional_and_splat_args_supported?
|
9
|
+
Method.method_defined?(:parameters)
|
10
|
+
end
|
11
|
+
module_function :optional_and_splat_args_supported?
|
12
|
+
|
13
|
+
def kw_args_supported?
|
14
|
+
RUBY_VERSION >= '2.0.0' && RUBY_ENGINE != 'rbx'
|
15
|
+
end
|
16
|
+
module_function :kw_args_supported?
|
17
|
+
|
18
|
+
def required_kw_args_supported?
|
19
|
+
RUBY_VERSION >= '2.1.0' && RUBY_ENGINE != 'rbx'
|
20
|
+
end
|
21
|
+
module_function :required_kw_args_supported?
|
22
|
+
|
23
|
+
def module_prepends_supported?
|
24
|
+
RUBY_VERSION.to_f >= 2.0
|
25
|
+
end
|
26
|
+
module_function :module_prepends_supported?
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
data/lib/rspec/support/spec.rb
CHANGED
@@ -1,24 +1,29 @@
|
|
1
|
-
require 'rspec/support
|
2
|
-
|
3
|
-
|
1
|
+
require 'rspec/support'
|
2
|
+
RSpec::Support.require_rspec_support "spec/deprecation_helpers"
|
3
|
+
RSpec::Support.require_rspec_support "spec/with_isolated_stderr"
|
4
|
+
RSpec::Support.require_rspec_support "spec/stderr_splitter"
|
5
|
+
RSpec::Support.require_rspec_support "spec/formatting_support"
|
4
6
|
|
5
7
|
warning_preventer = $stderr = RSpec::Support::StdErrSplitter.new($stderr)
|
6
8
|
|
7
9
|
RSpec.configure do |c|
|
8
10
|
c.include RSpecHelpers
|
9
11
|
c.include RSpec::Support::WithIsolatedStdErr
|
12
|
+
c.include RSpec::Support::FormattingSupport
|
10
13
|
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
+
unless defined?(Debugger) # debugger causes warnings when used
|
15
|
+
c.before do
|
16
|
+
warning_preventer.reset!
|
17
|
+
end
|
14
18
|
|
15
|
-
|
16
|
-
|
19
|
+
c.after do |example|
|
20
|
+
warning_preventer.verify_example!(example)
|
21
|
+
end
|
17
22
|
end
|
18
23
|
|
19
24
|
if c.files_to_run.one?
|
20
25
|
c.full_backtrace = true
|
21
|
-
c.
|
26
|
+
c.default_formatter = 'doc'
|
22
27
|
end
|
23
28
|
|
24
29
|
c.filter_run :focus
|
@@ -11,6 +11,13 @@ module RSpecHelpers
|
|
11
11
|
end
|
12
12
|
end
|
13
13
|
|
14
|
+
def expect_deprecation_without_call_site(snippet=//)
|
15
|
+
expect(RSpec.configuration.reporter).to receive(:deprecation) do |options|
|
16
|
+
expect(options[:call_site]).to eq nil
|
17
|
+
expect(options[:deprecated]).to match(snippet)
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
14
21
|
def expect_warn_deprecation_with_call_site(file, line, snippet=//)
|
15
22
|
expect(RSpec.configuration.reporter).to receive(:deprecation) do |options|
|
16
23
|
message = options[:message]
|
@@ -19,6 +26,13 @@ module RSpecHelpers
|
|
19
26
|
end
|
20
27
|
end
|
21
28
|
|
29
|
+
def expect_warn_deprecation(snippet=//)
|
30
|
+
expect(RSpec.configuration.reporter).to receive(:deprecation) do |options|
|
31
|
+
message = options[:message]
|
32
|
+
expect(message).to match(snippet)
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
22
36
|
def allow_deprecation
|
23
37
|
allow(RSpec.configuration.reporter).to receive(:deprecation)
|
24
38
|
end
|
@@ -2,7 +2,7 @@ require 'stringio'
|
|
2
2
|
|
3
3
|
module RSpec
|
4
4
|
module Support
|
5
|
-
class StdErrSplitter
|
5
|
+
class StdErrSplitter
|
6
6
|
def initialize(original)
|
7
7
|
@orig_stderr = original
|
8
8
|
@output_tracker = ::StringIO.new
|
@@ -24,9 +24,11 @@ module RSpec
|
|
24
24
|
|
25
25
|
# To work around JRuby error:
|
26
26
|
# TypeError: $stderr must have write method, RSpec::StdErrSplitter given
|
27
|
-
def write(
|
28
|
-
|
29
|
-
|
27
|
+
def write(line)
|
28
|
+
if line !~ /^\S+gems\/ruby\-\S+:\d+: warning:/
|
29
|
+
@orig_stderr.write(line)
|
30
|
+
@output_tracker.write(line)
|
31
|
+
end
|
30
32
|
end
|
31
33
|
|
32
34
|
def has_output?
|
@@ -45,6 +47,7 @@ module RSpec
|
|
45
47
|
def output
|
46
48
|
@output_tracker.string
|
47
49
|
end
|
50
|
+
|
48
51
|
end
|
49
52
|
end
|
50
53
|
end
|
@@ -1,42 +1,36 @@
|
|
1
1
|
module RSpec
|
2
|
+
module Support
|
3
|
+
module Warnings
|
4
|
+
def deprecate(deprecated, options = {})
|
5
|
+
warn_with "DEPRECATION: #{deprecated} is deprecated.", options
|
6
|
+
end
|
2
7
|
|
3
|
-
|
8
|
+
# @private
|
9
|
+
#
|
10
|
+
# Used internally to print deprecation warnings
|
11
|
+
# when rspec-core isn't loaded
|
12
|
+
def warn_deprecation(message, options = {})
|
13
|
+
warn_with "DEPRECATION: \n #{message}", options
|
14
|
+
end
|
4
15
|
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
end
|
12
|
-
end
|
16
|
+
# @private
|
17
|
+
#
|
18
|
+
# Used internally to print warnings
|
19
|
+
def warning(text, options={})
|
20
|
+
warn_with "WARNING: #{text}.", options
|
21
|
+
end
|
13
22
|
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
23
|
+
# @private
|
24
|
+
#
|
25
|
+
# Used internally to print longer warnings
|
26
|
+
def warn_with(message, options = {})
|
27
|
+
call_site = options.fetch(:call_site) { CallerFilter.first_non_rspec_line }
|
28
|
+
message << " Use #{options[:replacement]} instead." if options[:replacement]
|
29
|
+
message << " Called from #{call_site}." if call_site
|
30
|
+
::Kernel.warn message
|
31
|
+
end
|
22
32
|
end
|
23
33
|
end
|
24
34
|
|
25
|
-
|
26
|
-
#
|
27
|
-
# Used internally to print warnings
|
28
|
-
def self.warning(text, options={})
|
29
|
-
warn_with "WARNING: #{text}.", options
|
30
|
-
end
|
31
|
-
|
32
|
-
# @private
|
33
|
-
#
|
34
|
-
# Used internally to print longer warnings
|
35
|
-
def self.warn_with(message, options = {})
|
36
|
-
call_site = options.fetch(:call_site) { CallerFilter.first_non_rspec_line }
|
37
|
-
message << " Use #{options[:replacement]} instead." if options[:replacement]
|
38
|
-
message << " Called from #{call_site}." if call_site
|
39
|
-
::Kernel.warn message
|
40
|
-
end
|
41
|
-
|
35
|
+
extend RSpec::Support::Warnings
|
42
36
|
end
|
metadata
CHANGED
@@ -1,8 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: rspec-support
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 3.0.0.
|
5
|
-
prerelease: 6
|
4
|
+
version: 3.0.0.rc1
|
6
5
|
platform: ruby
|
7
6
|
authors:
|
8
7
|
- David Chelimsky
|
@@ -14,99 +13,71 @@ authors:
|
|
14
13
|
autorequire:
|
15
14
|
bindir: bin
|
16
15
|
cert_chain:
|
17
|
-
-
|
18
|
-
|
16
|
+
- |
|
17
|
+
-----BEGIN CERTIFICATE-----
|
19
18
|
MIIDjjCCAnagAwIBAgIBATANBgkqhkiG9w0BAQUFADBGMRIwEAYDVQQDDAlyc3Bl
|
20
|
-
|
21
19
|
Yy1kZXYxGzAZBgoJkiaJk/IsZAEZFgtnb29nbGVnb3VwczETMBEGCgmSJomT8ixk
|
22
|
-
|
23
20
|
ARkWA2NvbTAeFw0xMzExMDcxOTQyNTlaFw0xNDExMDcxOTQyNTlaMEYxEjAQBgNV
|
24
|
-
|
25
21
|
BAMMCXJzcGVjLWRldjEbMBkGCgmSJomT8ixkARkWC2dvb2dsZWdvdXBzMRMwEQYK
|
26
|
-
|
27
22
|
CZImiZPyLGQBGRYDY29tMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA
|
28
|
-
|
29
23
|
nhCeZouDLXWO55no+EdZNCtjXjfJQ1X9TbPcvBDD29OypIUce2h/VdKXB2gI7ZHs
|
30
|
-
|
31
24
|
F5NkPggslTErGFmWAtIiur7u943RVqHOsyoIsy065F9fCtrykkA+22elvTDha4Iz
|
32
|
-
|
33
25
|
RUCvuhQ3klatYk4jF+cGt1jNONNVdLOiy0bMynvcM7hoVQ2AomwGs+cEOWQ/4dkD
|
34
|
-
|
35
26
|
JcNV3qfzF5QBcTD2372XNM53b25nYVQSX2KH5FF7BhlKyov33bOm2gA9M+mWIujW
|
36
|
-
|
37
27
|
qgkyxVlfrlE+ZBgV3wXn1Cojg1LpTq35yOArgwioyrwwlZZJR9joN9s/nDklfr5A
|
38
|
-
|
39
28
|
+dyETjFc6cmEPWZrt2cJBQIDAQABo4GGMIGDMAkGA1UdEwQCMAAwCwYDVR0PBAQD
|
40
|
-
|
41
29
|
AgSwMB0GA1UdDgQWBBSW+WD7hn1swJ1A7i8tbuFeuNCJCjAkBgNVHREEHTAbgRly
|
42
|
-
|
43
30
|
c3BlYy1kZXZAZ29vZ2xlZ291cHMuY29tMCQGA1UdEgQdMBuBGXJzcGVjLWRldkBn
|
44
|
-
|
45
31
|
b29nbGVnb3Vwcy5jb20wDQYJKoZIhvcNAQEFBQADggEBAH27jAZ8sD7vnXupj6Y+
|
46
|
-
|
47
32
|
BaBdfHtCkFaslLJ0aKuMDIVXwYuKfqoW15cZPDLmSIEBuQFM3lw6d/hEEL4Uo2jZ
|
48
|
-
|
49
33
|
FvtmH5OxifPDzFyUtCL4yp6qgNe/Xf6sDsRg6FmKcpgqCwNOmsViaf0LPSUH/GYQ
|
50
|
-
|
51
34
|
3Teoz8QCaDbD7AKsffT7eDrnbHnKweO1XdemRJC98u/yYxnGzMSWKEsn09etBlZ9
|
52
|
-
|
53
35
|
7H67k5Z3uf6cfLZgToWL6zShzZY3Nun5r73YsNf2/QZOe4UZe4vfGvn6baw53ys9
|
54
|
-
|
55
36
|
1yHC1AcSYpvi2dAbOiHT5iQF+krm4wse8KctXgTNnjMsHEoGKulJS2/sZl90jcCz
|
56
|
-
|
57
37
|
muA=
|
58
|
-
|
59
38
|
-----END CERTIFICATE-----
|
60
|
-
|
61
|
-
'
|
62
|
-
date: 2014-02-18 00:00:00.000000000 Z
|
39
|
+
date: 2014-05-18 00:00:00.000000000 Z
|
63
40
|
dependencies:
|
64
41
|
- !ruby/object:Gem::Dependency
|
65
42
|
name: bundler
|
66
43
|
requirement: !ruby/object:Gem::Requirement
|
67
|
-
none: false
|
68
44
|
requirements:
|
69
|
-
- - ~>
|
45
|
+
- - "~>"
|
70
46
|
- !ruby/object:Gem::Version
|
71
47
|
version: '1.3'
|
72
48
|
type: :development
|
73
49
|
prerelease: false
|
74
50
|
version_requirements: !ruby/object:Gem::Requirement
|
75
|
-
none: false
|
76
51
|
requirements:
|
77
|
-
- - ~>
|
52
|
+
- - "~>"
|
78
53
|
- !ruby/object:Gem::Version
|
79
54
|
version: '1.3'
|
80
55
|
- !ruby/object:Gem::Dependency
|
81
56
|
name: rake
|
82
57
|
requirement: !ruby/object:Gem::Requirement
|
83
|
-
none: false
|
84
58
|
requirements:
|
85
|
-
- - ~>
|
59
|
+
- - "~>"
|
86
60
|
- !ruby/object:Gem::Version
|
87
61
|
version: 10.0.0
|
88
62
|
type: :development
|
89
63
|
prerelease: false
|
90
64
|
version_requirements: !ruby/object:Gem::Requirement
|
91
|
-
none: false
|
92
65
|
requirements:
|
93
|
-
- - ~>
|
66
|
+
- - "~>"
|
94
67
|
- !ruby/object:Gem::Version
|
95
68
|
version: 10.0.0
|
96
69
|
- !ruby/object:Gem::Dependency
|
97
70
|
name: rspec
|
98
71
|
requirement: !ruby/object:Gem::Requirement
|
99
|
-
none: false
|
100
72
|
requirements:
|
101
|
-
- -
|
73
|
+
- - ">="
|
102
74
|
- !ruby/object:Gem::Version
|
103
75
|
version: 3.0.0.pre
|
104
76
|
type: :development
|
105
77
|
prerelease: false
|
106
78
|
version_requirements: !ruby/object:Gem::Requirement
|
107
|
-
none: false
|
108
79
|
requirements:
|
109
|
-
- -
|
80
|
+
- - ">="
|
110
81
|
- !ruby/object:Gem::Version
|
111
82
|
version: 3.0.0.pre
|
112
83
|
description: Support utilities for RSpec gems
|
@@ -115,44 +86,49 @@ executables: []
|
|
115
86
|
extensions: []
|
116
87
|
extra_rdoc_files: []
|
117
88
|
files:
|
89
|
+
- Changelog.md
|
90
|
+
- LICENSE.txt
|
91
|
+
- README.md
|
118
92
|
- lib/rspec/support.rb
|
119
93
|
- lib/rspec/support/caller_filter.rb
|
94
|
+
- lib/rspec/support/differ.rb
|
95
|
+
- lib/rspec/support/encoded_string.rb
|
120
96
|
- lib/rspec/support/fuzzy_matcher.rb
|
97
|
+
- lib/rspec/support/hunk_generator.rb
|
98
|
+
- lib/rspec/support/method_signature_verifier.rb
|
99
|
+
- lib/rspec/support/ruby_features.rb
|
121
100
|
- lib/rspec/support/spec.rb
|
122
101
|
- lib/rspec/support/spec/deprecation_helpers.rb
|
102
|
+
- lib/rspec/support/spec/formatting_support.rb
|
123
103
|
- lib/rspec/support/spec/in_sub_process.rb
|
124
104
|
- lib/rspec/support/spec/stderr_splitter.rb
|
125
105
|
- lib/rspec/support/spec/with_isolated_stderr.rb
|
126
106
|
- lib/rspec/support/version.rb
|
127
107
|
- lib/rspec/support/version_checker.rb
|
128
108
|
- lib/rspec/support/warnings.rb
|
129
|
-
- README.md
|
130
|
-
- LICENSE.txt
|
131
|
-
- Changelog.md
|
132
109
|
homepage: https://github.com/rspec/rspec-support
|
133
110
|
licenses:
|
134
111
|
- MIT
|
112
|
+
metadata: {}
|
135
113
|
post_install_message:
|
136
114
|
rdoc_options:
|
137
|
-
- --charset=UTF-8
|
115
|
+
- "--charset=UTF-8"
|
138
116
|
require_paths:
|
139
117
|
- lib
|
140
118
|
required_ruby_version: !ruby/object:Gem::Requirement
|
141
|
-
none: false
|
142
119
|
requirements:
|
143
|
-
- -
|
120
|
+
- - ">="
|
144
121
|
- !ruby/object:Gem::Version
|
145
122
|
version: 1.8.7
|
146
123
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
147
|
-
none: false
|
148
124
|
requirements:
|
149
|
-
- -
|
125
|
+
- - ">"
|
150
126
|
- !ruby/object:Gem::Version
|
151
127
|
version: 1.3.1
|
152
128
|
requirements: []
|
153
129
|
rubyforge_project: rspec
|
154
|
-
rubygems_version:
|
130
|
+
rubygems_version: 2.2.2
|
155
131
|
signing_key:
|
156
|
-
specification_version:
|
157
|
-
summary: rspec-support-3.0.0.
|
132
|
+
specification_version: 4
|
133
|
+
summary: rspec-support-3.0.0.rc1
|
158
134
|
test_files: []
|
metadata.gz.sig
CHANGED
Binary file
|