rspec-sleeping_king_studios 2.4.1 → 2.5.0.rc.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +24 -0
- data/DEVELOPMENT.md +17 -13
- data/README.md +62 -0
- data/lib/rspec/sleeping_king_studios/examples/rspec_matcher_examples.rb +4 -0
- data/lib/rspec/sleeping_king_studios/matchers/core/be_a_uuid.rb +17 -0
- data/lib/rspec/sleeping_king_studios/matchers/core/be_a_uuid_matcher.rb +81 -0
- data/lib/rspec/sleeping_king_studios/matchers/core/deep_match.rb +11 -0
- data/lib/rspec/sleeping_king_studios/matchers/core/deep_matcher.rb +219 -0
- data/lib/rspec/sleeping_king_studios/matchers/core/have_changed_matcher.rb +5 -3
- data/lib/rspec/sleeping_king_studios/support/value_spy.rb +32 -7
- data/lib/rspec/sleeping_king_studios/version.rb +9 -9
- metadata +29 -12
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: e854f91985c71006beaaa55711a807e4074b58a6a56e1740e85d76400bb5ad05
|
4
|
+
data.tar.gz: 0603c970cca0d9f995ef901ad6e98a844e3423a77bc25c9b74422f8d516f2aed
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 8f1a4abd6c237cc396fc955165b66b26387760d22ea361eceec439f8aa9148768fb4d0570daafa1bfb5e1f5e536c4642c634e7ebc2f82e7f4bb29bb6b201b2cd
|
7
|
+
data.tar.gz: b774a8555643bebcb1604576db9c12058ef27e93f3511e4ac7de80c7d87959a376f9c928c4705e8c3e161b856fe3b52ce504f861b33629997355c44a3bac115b
|
data/CHANGELOG.md
CHANGED
@@ -1,5 +1,29 @@
|
|
1
1
|
# Changelog
|
2
2
|
|
3
|
+
## 2.5.0
|
4
|
+
|
5
|
+
Added support for Ruby 2.6, dropped support for Ruby 2.3.
|
6
|
+
|
7
|
+
### Matchers
|
8
|
+
|
9
|
+
Implemented the BeAUuidMatcher, which expects the value to be a UUID string.
|
10
|
+
|
11
|
+
Implemented the DeepMatcher, which recursively compares data structures.
|
12
|
+
|
13
|
+
expect(response).to deep_match(
|
14
|
+
status: 200,
|
15
|
+
body: {
|
16
|
+
order: {
|
17
|
+
id: an_instance_of(Integer),
|
18
|
+
total: '9.99'
|
19
|
+
}
|
20
|
+
}
|
21
|
+
)
|
22
|
+
|
23
|
+
Improved the HaveChangedMatcher to check the before and after `hash` value. This detects when an object is replaced by different but equal object, or when the initial object is a nested data structure (e.g. an Array of Hashes) and the internal elements are modified.
|
24
|
+
|
25
|
+
Improved failure message of the HaveChangedMatcher when given a receiver and message.
|
26
|
+
|
3
27
|
## 2.4.1
|
4
28
|
|
5
29
|
Added support for RSpec 3.8.
|
data/DEVELOPMENT.md
CHANGED
@@ -1,22 +1,28 @@
|
|
1
1
|
# Development Notes
|
2
2
|
|
3
|
-
## Version 2.
|
3
|
+
## Version 2.5
|
4
4
|
|
5
|
-
###
|
5
|
+
### Maintenance
|
6
6
|
|
7
|
-
-
|
7
|
+
- Refactor all macro specs from spec/rspec/sleeping_king_studios/matchers/macros to the directories corresponding to the source files.
|
8
8
|
|
9
|
-
|
9
|
+
## Version 2.6
|
10
10
|
|
11
|
-
|
12
|
-
- Also alias shared examples.
|
13
|
-
- Alias `have_constant` as `define_constant`.
|
14
|
-
- Alias #immutable as #frozen.
|
15
|
-
- Also alias shared examples.
|
11
|
+
### Features - Matchers
|
16
12
|
|
17
|
-
|
13
|
+
- RespondToMatcher: |
|
14
|
+
update to match core respond_to matcher
|
15
|
+
- uses the signature from initialize to validate checks for new
|
16
|
+
- see https://github.com/rspec/rspec-expectations/blob/master/Changelog.md
|
17
|
+
subclass BeConstructibleMatcher from RespondTo ?
|
18
18
|
|
19
|
-
|
19
|
+
## Version 2.6+
|
20
|
+
|
21
|
+
- DeepMatcher: |
|
22
|
+
- indifferent - symbol/string keys
|
23
|
+
- ordered - pre-sort arrays?
|
24
|
+
- only homogenous arrays?
|
25
|
+
- odd results unless equality comparison
|
20
26
|
|
21
27
|
## Version 3.0
|
22
28
|
|
@@ -58,8 +64,6 @@
|
|
58
64
|
|
59
65
|
- BeImmutableMatcher (NEW):
|
60
66
|
- Implement be_immutable matcher.
|
61
|
-
- HaveChangedMatcher (NEW):
|
62
|
-
- Add spy+matcher for expect(my_object, :my_method).to have_changed ?
|
63
67
|
- RespondToMatcher:
|
64
68
|
- Implement RespondToMatcher#with_optional_keywords, #with_required_keywords.
|
65
69
|
- Implement RespondToMatcher#with_at_least(N).arguments, equivalent to with(N).arguments.and_unlimited_arguments.
|
data/README.md
CHANGED
@@ -447,6 +447,22 @@ Checks if the object aliases the specified method with the specified other name.
|
|
447
447
|
|
448
448
|
* **`#as`:** Required. Expects one String or Symbol, which is the name of the generated method.
|
449
449
|
|
450
|
+
#### `#be_a_uuid` Matcher
|
451
|
+
|
452
|
+
require 'rspec/sleeping_king_studios/matchers/core/be_a_uuid'
|
453
|
+
|
454
|
+
**Aliases:** `#a_uuid`.
|
455
|
+
|
456
|
+
**How To Use:**
|
457
|
+
|
458
|
+
# With an object comparison.
|
459
|
+
expect(string).to be_a_uuid
|
460
|
+
|
461
|
+
# Inside a composable matcher.
|
462
|
+
expect(array).to include(a_uuid)
|
463
|
+
|
464
|
+
**Parameters:** None.
|
465
|
+
|
450
466
|
#### `#be_boolean` Matcher
|
451
467
|
|
452
468
|
require 'rspec/sleeping_king_studios/matchers/core/be_boolean'
|
@@ -488,6 +504,52 @@ Verifies that the actual object can be constructed using `::new`. Can take an op
|
|
488
504
|
* **`#with_keywords`:** (also `and_keywords`) Expects one or more String or Symbol arguments. Verifies that the class's constructor accepts each provided keyword or has a variadic keyword of the form `**params`. As of 2.1.0 and required keywords, verifies that all required keywords are provided.
|
489
505
|
* **`#with_arbitrary_keywords`:** (also `and_arbitrary_keywords`) No parameters. Verifies that the class's constructor accepts any keyword arguments via a variadic keyword of the form `**params`.
|
490
506
|
|
507
|
+
#### `#deep_match` Matcher
|
508
|
+
|
509
|
+
require 'rspec/sleeping_king_studios/matchers/core/deep_match'
|
510
|
+
|
511
|
+
Performs a recursive comparison between two object or data structures. Also supports using RSpec matchers as values in the expected object.
|
512
|
+
|
513
|
+
**How To Use:**
|
514
|
+
|
515
|
+
expected = {
|
516
|
+
status: 200,
|
517
|
+
body: {
|
518
|
+
order: {
|
519
|
+
id: an_instance_of(Integer),
|
520
|
+
total: '9.99'
|
521
|
+
}
|
522
|
+
}
|
523
|
+
}
|
524
|
+
expect(response).to deep_match(expected)
|
525
|
+
|
526
|
+
When the value does not match the expectation, the failure message will provide a detailed diff showing added, missing, and changed values.
|
527
|
+
|
528
|
+
response = {
|
529
|
+
status: 400,
|
530
|
+
body: {
|
531
|
+
order: {
|
532
|
+
fulfilled: false,
|
533
|
+
total: '19.99'
|
534
|
+
}
|
535
|
+
},
|
536
|
+
errors: ['Insufficient funds']
|
537
|
+
}
|
538
|
+
expect(response).to deep_match(expected)
|
539
|
+
# Failure/Error: expect(response).to deep_match(expected)
|
540
|
+
#
|
541
|
+
# expected: == {:body=>{:order=>{:id=>an instance of Integer, :total=>"9.99"}}, :status=>200}
|
542
|
+
# got: {:status=>400, :body=>{:order=>{:fulfilled=>false, :total=>"19.99"}}, :errors=>["Insufficient funds"]}
|
543
|
+
#
|
544
|
+
# (compared using HashDiff)
|
545
|
+
#
|
546
|
+
# Diff:
|
547
|
+
# + :body.:order.:fulfilled => got false
|
548
|
+
# - :body.:order.:id => expected an instance of Integer
|
549
|
+
# ~ :body.:order.:total => expected "9.99", got "19.99"
|
550
|
+
# + :errors => got ["Insufficient funds"]
|
551
|
+
# ~ :status => expected 200, got 400
|
552
|
+
|
491
553
|
#### `#delegate_method` Matcher
|
492
554
|
|
493
555
|
require 'rspec/sleeping_king_studios/matchers/core/delegate_method'
|
@@ -29,6 +29,10 @@ module RSpec::SleepingKingStudios::Examples::RSpecMatcherExamples
|
|
29
29
|
end # when
|
30
30
|
end # method compare_message
|
31
31
|
|
32
|
+
private def format_expected(object)
|
33
|
+
RSpec::Support::ObjectFormatter.format(object)
|
34
|
+
end
|
35
|
+
|
32
36
|
private def handle_missing_failure_message message
|
33
37
|
case config.examples.handle_missing_failure_message_with
|
34
38
|
when :pending
|
@@ -0,0 +1,17 @@
|
|
1
|
+
# frozen_string_literals: true
|
2
|
+
|
3
|
+
require 'rspec/sleeping_king_studios/matchers/core/be_a_uuid_matcher'
|
4
|
+
require 'rspec/sleeping_king_studios/matchers/macros'
|
5
|
+
|
6
|
+
module RSpec::SleepingKingStudios::Matchers::Macros
|
7
|
+
# @see RSpec::SleepingKingStudios::Matchers::Core::BeAUuidMatcher#matches?
|
8
|
+
def be_a_uuid
|
9
|
+
RSpec::SleepingKingStudios::Matchers::Core::BeAUuidMatcher.new
|
10
|
+
end
|
11
|
+
|
12
|
+
# @!method a_uuid
|
13
|
+
# @see RSpec::SleepingKingStudios::Matchers::Core::BeBooleanMatcher#matches?
|
14
|
+
alias_matcher :a_uuid, :be_a_uuid do |description|
|
15
|
+
'a UUID'
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,81 @@
|
|
1
|
+
# frozen_string_literals: true
|
2
|
+
|
3
|
+
require 'rspec/sleeping_king_studios/matchers/base_matcher'
|
4
|
+
require 'rspec/sleeping_king_studios/matchers/core'
|
5
|
+
|
6
|
+
module RSpec::SleepingKingStudios::Matchers::Core
|
7
|
+
# Matcher for testing whether an object is a UUID string.
|
8
|
+
#
|
9
|
+
# @since 2.5.0
|
10
|
+
class BeAUuidMatcher < RSpec::SleepingKingStudios::Matchers::BaseMatcher
|
11
|
+
# (see BaseMatcher#description)
|
12
|
+
def description
|
13
|
+
'be a UUID'
|
14
|
+
end
|
15
|
+
|
16
|
+
# (see BaseMatcher#failure_message)
|
17
|
+
def failure_message
|
18
|
+
message = super() + ', but '
|
19
|
+
|
20
|
+
return message + 'was not a String' unless string?
|
21
|
+
|
22
|
+
return message + 'was too short' if too_short?
|
23
|
+
|
24
|
+
return message + 'was too long' if too_long?
|
25
|
+
|
26
|
+
return message + 'has invalid characters' if invalid_characters?
|
27
|
+
|
28
|
+
return message + 'the format is invalid' unless valid_format?
|
29
|
+
|
30
|
+
message
|
31
|
+
end
|
32
|
+
|
33
|
+
# Checks if the object is a UUID string.
|
34
|
+
#
|
35
|
+
# @param [Object] actual The object to check.
|
36
|
+
#
|
37
|
+
# @return [Boolean] true if the object is a string with the correct format;
|
38
|
+
# otherwise false.
|
39
|
+
def matches?(actual)
|
40
|
+
super
|
41
|
+
|
42
|
+
string? && valid_length? && valid_characters? && valid_format?
|
43
|
+
end
|
44
|
+
|
45
|
+
private
|
46
|
+
|
47
|
+
def invalid_characters?
|
48
|
+
@invalid_characters ||= @actual.match?(/[^A-Fa-f0-9\-]/)
|
49
|
+
end
|
50
|
+
|
51
|
+
def string?
|
52
|
+
@string ||= @actual.is_a?(String)
|
53
|
+
end
|
54
|
+
|
55
|
+
def too_long?
|
56
|
+
@too_long ||= @actual.length > 36
|
57
|
+
end
|
58
|
+
|
59
|
+
def too_short?
|
60
|
+
@too_short ||= @actual.length < 36
|
61
|
+
end
|
62
|
+
|
63
|
+
def uuid_format
|
64
|
+
chars = '[A-Fa-f0-9\-]'
|
65
|
+
|
66
|
+
/\A#{chars}{8}-#{chars}{4}-#{chars}{4}-#{chars}{4}-#{chars}{12}\z/
|
67
|
+
end
|
68
|
+
|
69
|
+
def valid_characters?
|
70
|
+
!invalid_characters?
|
71
|
+
end
|
72
|
+
|
73
|
+
def valid_format?
|
74
|
+
@valid_format || @actual.match?(uuid_format)
|
75
|
+
end
|
76
|
+
|
77
|
+
def valid_length?
|
78
|
+
!too_short? && !too_long?
|
79
|
+
end
|
80
|
+
end
|
81
|
+
end
|
@@ -0,0 +1,11 @@
|
|
1
|
+
# frozen_string_literals: true
|
2
|
+
|
3
|
+
require 'rspec/sleeping_king_studios/matchers/core/deep_matcher'
|
4
|
+
require 'rspec/sleeping_king_studios/matchers/macros'
|
5
|
+
|
6
|
+
module RSpec::SleepingKingStudios::Matchers::Macros
|
7
|
+
# @see RSpec::SleepingKingStudios::Matchers::Core::BeBooleanMatcher#matches?
|
8
|
+
def deep_match(expected)
|
9
|
+
RSpec::SleepingKingStudios::Matchers::Core::DeepMatcher.new(expected)
|
10
|
+
end
|
11
|
+
end
|
@@ -0,0 +1,219 @@
|
|
1
|
+
# frozen_string_literals: true
|
2
|
+
|
3
|
+
require 'hashdiff'
|
4
|
+
|
5
|
+
require 'rspec/sleeping_king_studios/matchers/base_matcher'
|
6
|
+
require 'rspec/sleeping_king_studios/matchers/core'
|
7
|
+
|
8
|
+
module RSpec::SleepingKingStudios::Matchers::Core
|
9
|
+
# Matcher for performing a deep comparison between two objects.
|
10
|
+
#
|
11
|
+
# @since 2.5.0
|
12
|
+
class DeepMatcher < RSpec::SleepingKingStudios::Matchers::BaseMatcher
|
13
|
+
# @param [Object] expected The expected object.
|
14
|
+
def initialize(expected)
|
15
|
+
@expected = expected
|
16
|
+
end
|
17
|
+
|
18
|
+
# (see BaseMatcher#description)
|
19
|
+
def description
|
20
|
+
"match #{format_expected(@expected)}"
|
21
|
+
end # method description
|
22
|
+
|
23
|
+
# Inverse of #matches? method.
|
24
|
+
#
|
25
|
+
# @param [Object] actual The object to check.
|
26
|
+
#
|
27
|
+
# @return [Boolean] true if the actual object does not match the
|
28
|
+
# expectation, otherwise true.
|
29
|
+
#
|
30
|
+
# @see #matches?
|
31
|
+
def does_not_match? actual
|
32
|
+
super
|
33
|
+
|
34
|
+
if matcher?(@expected)
|
35
|
+
delegate_to_negated_matcher(@expected)
|
36
|
+
elsif @expected.is_a?(Array) && actual.is_a?(Array)
|
37
|
+
diff_arrays_negated
|
38
|
+
elsif @expected.is_a?(Hash) && actual.is_a?(Hash)
|
39
|
+
diff_hashes_negated
|
40
|
+
else
|
41
|
+
delegate_to_negated_matcher(equality_matcher)
|
42
|
+
end
|
43
|
+
|
44
|
+
!@matches
|
45
|
+
end
|
46
|
+
|
47
|
+
# (see BaseMatcher#failure_message)
|
48
|
+
def failure_message
|
49
|
+
@failure_message
|
50
|
+
end
|
51
|
+
|
52
|
+
# (see BaseMatcher#failure_message_when_negated)
|
53
|
+
def failure_message_when_negated
|
54
|
+
@failure_message_when_negated
|
55
|
+
end
|
56
|
+
|
57
|
+
# Performs a deep comparison between the actual object and the expected
|
58
|
+
# object. The type of comparison depends on the type of the expected object:
|
59
|
+
#
|
60
|
+
# - If the expected object is an RSpec matcher, the #matches? method on the
|
61
|
+
# matcher is called with the expected object.
|
62
|
+
# - If the expected object is an Array, then each item is compared based on
|
63
|
+
# the type of the expected item.
|
64
|
+
# - If the expected object is a Hash, then the keys must match and each
|
65
|
+
# value is compared based on the type of the expected value.
|
66
|
+
# - Otherwise, the two objects are compared using an equality comparison.
|
67
|
+
#
|
68
|
+
# @param [Object] actual The object to check.
|
69
|
+
#
|
70
|
+
# @return [Boolean] true if the actual object matches the expectation,
|
71
|
+
# otherwise false.
|
72
|
+
def matches?(actual)
|
73
|
+
super
|
74
|
+
|
75
|
+
if matcher?(@expected)
|
76
|
+
delegate_to_matcher(@expected)
|
77
|
+
elsif @expected.is_a?(Array) && actual.is_a?(Array)
|
78
|
+
diff_arrays
|
79
|
+
elsif @expected.is_a?(Hash) && actual.is_a?(Hash)
|
80
|
+
diff_hashes
|
81
|
+
else
|
82
|
+
delegate_to_matcher(equality_matcher)
|
83
|
+
end
|
84
|
+
|
85
|
+
@matches
|
86
|
+
end
|
87
|
+
|
88
|
+
private
|
89
|
+
|
90
|
+
def compare_arrays(expected, actual)
|
91
|
+
compare_hashes({ _ary: expected }, { _ary: actual })
|
92
|
+
.map { |(char, path, *values)| [char, path[1..-1], *values] }
|
93
|
+
end
|
94
|
+
|
95
|
+
def compare_hashes(expected, actual)
|
96
|
+
HashDiff.diff(expected, actual, array_path: true, use_lcs: false) \
|
97
|
+
do |path, exp, act|
|
98
|
+
# Handle missing keys with matcher values.
|
99
|
+
next nil unless nested_key?(actual, path)
|
100
|
+
|
101
|
+
next exp.matches?(act) if matcher?(exp)
|
102
|
+
end
|
103
|
+
end
|
104
|
+
|
105
|
+
def delegate_to_matcher(matcher)
|
106
|
+
@matches = matcher.matches?(actual)
|
107
|
+
|
108
|
+
return if @matches
|
109
|
+
|
110
|
+
@failure_message = matcher.failure_message
|
111
|
+
end
|
112
|
+
|
113
|
+
def delegate_to_negated_matcher(matcher)
|
114
|
+
@matches =
|
115
|
+
if matcher.respond_to?(:does_not_match?)
|
116
|
+
!matcher.does_not_match?(actual)
|
117
|
+
else
|
118
|
+
matcher.matches?(actual)
|
119
|
+
end
|
120
|
+
|
121
|
+
return unless @matches
|
122
|
+
|
123
|
+
@failure_message_when_negated = matcher.failure_message_when_negated
|
124
|
+
end
|
125
|
+
|
126
|
+
def diff_arrays
|
127
|
+
diff = compare_arrays(@expected, actual)
|
128
|
+
@matches = diff.empty?
|
129
|
+
|
130
|
+
@failure_message = format_message(diff)
|
131
|
+
end
|
132
|
+
|
133
|
+
def diff_arrays_negated
|
134
|
+
diff = compare_arrays(@expected, actual)
|
135
|
+
@matches = diff.empty?
|
136
|
+
|
137
|
+
@failure_message_when_negated =
|
138
|
+
"`expect(#{format_expected(@expected)}).not_to be == #{actual.inspect}`"
|
139
|
+
end
|
140
|
+
|
141
|
+
def diff_hashes
|
142
|
+
diff = compare_hashes(@expected, actual)
|
143
|
+
@matches = diff.empty?
|
144
|
+
|
145
|
+
@failure_message = format_message(diff)
|
146
|
+
end
|
147
|
+
|
148
|
+
def diff_hashes_negated
|
149
|
+
diff = compare_hashes(@expected, actual)
|
150
|
+
@matches = diff.empty?
|
151
|
+
|
152
|
+
@failure_message_when_negated =
|
153
|
+
"`expect(#{format_expected(@expected)}).not_to be == #{actual.inspect}`"
|
154
|
+
end
|
155
|
+
|
156
|
+
def equality_matcher
|
157
|
+
matchers_delegate.be == @expected
|
158
|
+
end
|
159
|
+
|
160
|
+
def format_diff(diff)
|
161
|
+
diff
|
162
|
+
.sort_by { |(char, path, *_values)| [path.map(&:to_s)] }
|
163
|
+
.map { |item| format_diff_item(*item) }
|
164
|
+
.join "\n"
|
165
|
+
end
|
166
|
+
|
167
|
+
def format_diff_item(char, path, *values)
|
168
|
+
"#{char} #{format_diff_path(path)} => #{format_diff_values(char, values)}"
|
169
|
+
end
|
170
|
+
|
171
|
+
def format_diff_path(path)
|
172
|
+
path.map(&:inspect).join('.')
|
173
|
+
end
|
174
|
+
|
175
|
+
def format_diff_values(char, values)
|
176
|
+
case char
|
177
|
+
when '-'
|
178
|
+
"expected #{format_expected(values.first)}"
|
179
|
+
when '~'
|
180
|
+
"expected #{format_expected(values.first)}, got #{values.last.inspect}"
|
181
|
+
when '+'
|
182
|
+
"got #{values.last.inspect}"
|
183
|
+
end
|
184
|
+
end
|
185
|
+
|
186
|
+
def format_expected(object)
|
187
|
+
RSpec::Support::ObjectFormatter.format(object)
|
188
|
+
end
|
189
|
+
|
190
|
+
def format_message(diff)
|
191
|
+
"expected: == #{format_expected(@expected)}\n" \
|
192
|
+
" got: #{@actual.inspect}\n" \
|
193
|
+
"\n" \
|
194
|
+
"(compared using HashDiff)\n" \
|
195
|
+
"\n" \
|
196
|
+
"Diff:\n" \
|
197
|
+
"#{format_diff(diff)}"
|
198
|
+
end
|
199
|
+
|
200
|
+
def matcher?(object)
|
201
|
+
%i[description failure_message failure_message_when_negated matches?]
|
202
|
+
.all? { |method_name| object.respond_to?(method_name) }
|
203
|
+
end
|
204
|
+
|
205
|
+
def matchers_delegate
|
206
|
+
Object.new.extend RSpec::Matchers
|
207
|
+
end
|
208
|
+
|
209
|
+
def nested_key?(object, path)
|
210
|
+
key = path.last
|
211
|
+
object = object.dig(*path[0...-1]) if path.size > 1
|
212
|
+
|
213
|
+
return object.key?(key) if object.is_a?(Hash)
|
214
|
+
return object.size > key if object.is_a?(Array)
|
215
|
+
|
216
|
+
false
|
217
|
+
end
|
218
|
+
end
|
219
|
+
end
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literals: true
|
2
|
+
|
1
3
|
require 'rspec/sleeping_king_studios/matchers/base_matcher'
|
2
4
|
require 'rspec/sleeping_king_studios/matchers/core'
|
3
5
|
require 'rspec/sleeping_king_studios/support/value_spy'
|
@@ -76,7 +78,7 @@ module RSpec::SleepingKingStudios::Matchers::Core
|
|
76
78
|
unless @match_initial_value.nil? || @match_initial_value
|
77
79
|
return "expected #{value_spy.description} to have initially " \
|
78
80
|
"been #{@expected_initial_value.inspect}, but was " \
|
79
|
-
"#{
|
81
|
+
"#{value_spy.initial_inspect}"
|
80
82
|
end
|
81
83
|
|
82
84
|
message = "expected #{value_spy.description} to have changed"
|
@@ -107,13 +109,13 @@ module RSpec::SleepingKingStudios::Matchers::Core
|
|
107
109
|
unless @match_initial_value.nil? || @match_initial_value
|
108
110
|
return "expected #{value_spy.description} to have initially " \
|
109
111
|
"been #{@expected_initial_value.inspect}, but was " \
|
110
|
-
"#{
|
112
|
+
"#{value_spy.initial_inspect}"
|
111
113
|
end
|
112
114
|
|
113
115
|
message = "expected #{value_spy.description} not to have changed"
|
114
116
|
|
115
117
|
message <<
|
116
|
-
", but did change from #{
|
118
|
+
", but did change from #{value_spy.initial_inspect} to " <<
|
117
119
|
current_value.inspect
|
118
120
|
|
119
121
|
message
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literals: true
|
2
|
+
|
1
3
|
require 'rspec/sleeping_king_studios/support'
|
2
4
|
|
3
5
|
module RSpec::SleepingKingStudios::Support
|
@@ -23,8 +25,8 @@ module RSpec::SleepingKingStudios::Support
|
|
23
25
|
# value.initial_value #=> 4
|
24
26
|
# value.current_value #=> 3
|
25
27
|
class ValueSpy
|
26
|
-
# @overload initialize(
|
27
|
-
# @param [Object]
|
28
|
+
# @overload initialize(receiver, method_name)
|
29
|
+
# @param [Object] receiver The object to watch.
|
28
30
|
#
|
29
31
|
# @param [Symbol, String] method_name The name of the method to watch.
|
30
32
|
#
|
@@ -32,23 +34,34 @@ module RSpec::SleepingKingStudios::Support
|
|
32
34
|
# @yield The value to watch. The block will be called each time the value
|
33
35
|
# is requested, and the return value of the block will be given as the
|
34
36
|
# current value.
|
35
|
-
def initialize(
|
37
|
+
def initialize(receiver = nil, method_name = nil, &block)
|
36
38
|
@observed_block = if block_given?
|
37
39
|
block
|
38
40
|
else
|
39
41
|
@method_name = method_name
|
40
42
|
|
41
|
-
-> {
|
43
|
+
-> { receiver.send(method_name) }
|
42
44
|
end
|
43
45
|
|
44
|
-
@
|
46
|
+
@receiver = receiver
|
47
|
+
@initial_hash = current_value.hash
|
48
|
+
@initial_inspect = current_value.inspect
|
49
|
+
@initial_value = current_value
|
45
50
|
end
|
46
51
|
|
52
|
+
# @return [Integer] the hash of the watched value at the time the spy was
|
53
|
+
# initialized.
|
54
|
+
attr_reader :initial_hash
|
55
|
+
|
56
|
+
# @return [String] the string representation of the watched value at the
|
57
|
+
# time the spy was initialized
|
58
|
+
attr_reader :initial_inspect
|
59
|
+
|
47
60
|
# @return [Object] the watched value at the time the spy was initialized.
|
48
61
|
attr_reader :initial_value
|
49
62
|
|
50
63
|
def changed?
|
51
|
-
|
64
|
+
initial_value != current_value || initial_hash != current_value.hash
|
52
65
|
end
|
53
66
|
|
54
67
|
# @return [Object] the watched value when #current_value is called.
|
@@ -61,7 +74,19 @@ module RSpec::SleepingKingStudios::Support
|
|
61
74
|
def description
|
62
75
|
return 'result' unless @method_name
|
63
76
|
|
64
|
-
|
77
|
+
format_message
|
78
|
+
end
|
79
|
+
|
80
|
+
private
|
81
|
+
|
82
|
+
attr_reader :method_name
|
83
|
+
|
84
|
+
attr_reader :receiver
|
85
|
+
|
86
|
+
def format_message
|
87
|
+
return "#{receiver}.#{method_name}" if receiver.is_a?(Module)
|
88
|
+
|
89
|
+
"#{receiver.class}##{method_name}"
|
65
90
|
end
|
66
91
|
end
|
67
92
|
end
|
@@ -1,4 +1,4 @@
|
|
1
|
-
#
|
1
|
+
# frozen_string_literals: true
|
2
2
|
|
3
3
|
module RSpec
|
4
4
|
module SleepingKingStudios
|
@@ -11,13 +11,13 @@ module RSpec
|
|
11
11
|
# Major version.
|
12
12
|
MAJOR = 2
|
13
13
|
# Minor version.
|
14
|
-
MINOR =
|
14
|
+
MINOR = 5
|
15
15
|
# Patch version.
|
16
|
-
PATCH =
|
16
|
+
PATCH = 0
|
17
17
|
# Prerelease version.
|
18
|
-
PRERELEASE =
|
18
|
+
PRERELEASE = :rc
|
19
19
|
# Build metadata.
|
20
|
-
BUILD =
|
20
|
+
BUILD = 0
|
21
21
|
|
22
22
|
# Generates the gem version string from the Version constants.
|
23
23
|
#
|
@@ -36,9 +36,9 @@ module RSpec
|
|
36
36
|
str << ".#{build}" unless build.nil? || (build.respond_to?(:empty?) && build.empty?)
|
37
37
|
|
38
38
|
str
|
39
|
-
end
|
40
|
-
end
|
39
|
+
end
|
40
|
+
end
|
41
41
|
|
42
42
|
VERSION = Version.to_gem_version
|
43
|
-
end
|
44
|
-
end
|
43
|
+
end
|
44
|
+
end
|
metadata
CHANGED
@@ -1,15 +1,29 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: rspec-sleeping_king_studios
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 2.
|
4
|
+
version: 2.5.0.rc.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Rob "Merlin" Smith
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2019-02-03 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: hashdiff
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: 0.3.8
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - "~>"
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: 0.3.8
|
13
27
|
- !ruby/object:Gem::Dependency
|
14
28
|
name: rspec
|
15
29
|
requirement: !ruby/object:Gem::Requirement
|
@@ -84,22 +98,22 @@ dependencies:
|
|
84
98
|
name: thor
|
85
99
|
requirement: !ruby/object:Gem::Requirement
|
86
100
|
requirements:
|
87
|
-
- - "~>"
|
88
|
-
- !ruby/object:Gem::Version
|
89
|
-
version: '0.20'
|
90
101
|
- - ">="
|
91
102
|
- !ruby/object:Gem::Version
|
92
103
|
version: 0.19.4
|
104
|
+
- - "~>"
|
105
|
+
- !ruby/object:Gem::Version
|
106
|
+
version: '0.20'
|
93
107
|
type: :development
|
94
108
|
prerelease: false
|
95
109
|
version_requirements: !ruby/object:Gem::Requirement
|
96
110
|
requirements:
|
97
|
-
- - "~>"
|
98
|
-
- !ruby/object:Gem::Version
|
99
|
-
version: '0.20'
|
100
111
|
- - ">="
|
101
112
|
- !ruby/object:Gem::Version
|
102
113
|
version: 0.19.4
|
114
|
+
- - "~>"
|
115
|
+
- !ruby/object:Gem::Version
|
116
|
+
version: '0.20'
|
103
117
|
- !ruby/object:Gem::Dependency
|
104
118
|
name: sleeping_king_studios-tasks
|
105
119
|
requirement: !ruby/object:Gem::Requirement
|
@@ -217,10 +231,14 @@ files:
|
|
217
231
|
- lib/rspec/sleeping_king_studios/matchers/core/alias_method.rb
|
218
232
|
- lib/rspec/sleeping_king_studios/matchers/core/alias_method_matcher.rb
|
219
233
|
- lib/rspec/sleeping_king_studios/matchers/core/all.rb
|
234
|
+
- lib/rspec/sleeping_king_studios/matchers/core/be_a_uuid.rb
|
235
|
+
- lib/rspec/sleeping_king_studios/matchers/core/be_a_uuid_matcher.rb
|
220
236
|
- lib/rspec/sleeping_king_studios/matchers/core/be_boolean.rb
|
221
237
|
- lib/rspec/sleeping_king_studios/matchers/core/be_boolean_matcher.rb
|
222
238
|
- lib/rspec/sleeping_king_studios/matchers/core/construct.rb
|
223
239
|
- lib/rspec/sleeping_king_studios/matchers/core/construct_matcher.rb
|
240
|
+
- lib/rspec/sleeping_king_studios/matchers/core/deep_match.rb
|
241
|
+
- lib/rspec/sleeping_king_studios/matchers/core/deep_matcher.rb
|
224
242
|
- lib/rspec/sleeping_king_studios/matchers/core/delegate_method.rb
|
225
243
|
- lib/rspec/sleeping_king_studios/matchers/core/delegate_method_matcher.rb
|
226
244
|
- lib/rspec/sleeping_king_studios/matchers/core/have_changed.rb
|
@@ -259,12 +277,11 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
259
277
|
version: '0'
|
260
278
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
261
279
|
requirements:
|
262
|
-
- - "
|
280
|
+
- - ">"
|
263
281
|
- !ruby/object:Gem::Version
|
264
|
-
version:
|
282
|
+
version: 1.3.1
|
265
283
|
requirements: []
|
266
|
-
|
267
|
-
rubygems_version: 2.7.6
|
284
|
+
rubygems_version: 3.0.1
|
268
285
|
signing_key:
|
269
286
|
specification_version: 4
|
270
287
|
summary: A collection of RSpec patches and custom matchers.
|