rspec-support 3.0.0.beta2 → 3.0.0.rc1
Sign up to get free protection for your applications and to get access to all the features.
- 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
|