rspec-sleeping_king_studios 2.4.1 → 2.6.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 +38 -0
- data/DEVELOPMENT.md +9 -18
- data/README.md +223 -2
- data/lib/rspec/sleeping_king_studios/examples/rspec_matcher_examples.rb +8 -4
- data/lib/rspec/sleeping_king_studios/matchers/built_in/include_matcher.rb +6 -1
- data/lib/rspec/sleeping_king_studios/matchers/built_in/respond_to_matcher.rb +10 -10
- 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/delegate_method_matcher.rb +22 -9
- 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 +7 -7
- metadata +44 -13
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: c218158ac4229d6cd818cec2837832e27086b1407bc54a90b43921be5ad6ef2d
|
4
|
+
data.tar.gz: 1afecef7b021d634b9203b8bab2c72d2faed3498a92eac0081ffab0f2ee4a674
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: b59b280dd97fd18691887d504407c0a70e849a0e9cca3cff65f71078b155050eb0c2590cea2fb5cb192af8c3951f50798b8bc22a3832d58d679a761ab32f4b8a
|
7
|
+
data.tar.gz: b71d3fb856bf0eecb962219edc68103b49b3d71e42699d677db42432f52ef67d1ac97e9232f51c01d807654f1e58d30ded38b9c66fb7ba27b55783d375c1271e
|
data/CHANGELOG.md
CHANGED
@@ -1,5 +1,43 @@
|
|
1
1
|
# Changelog
|
2
2
|
|
3
|
+
## 2.6.0
|
4
|
+
|
5
|
+
Deprecated the DelegateMethod matcher. Use `rspec-mocks` expectations instead.
|
6
|
+
|
7
|
+
Deprecated the Include matcher with a block. Use the `satisfy` matcher instead.
|
8
|
+
|
9
|
+
### Matchers
|
10
|
+
|
11
|
+
Updated RespondToMatcher to check the arity of `#initialize` when matching against a class and the method name is `:new`.
|
12
|
+
|
13
|
+
## 2.5.1
|
14
|
+
|
15
|
+
Fixed a compatibility issue with Rails 6 configuration objects.
|
16
|
+
|
17
|
+
## 2.5.0
|
18
|
+
|
19
|
+
Added support for Ruby 2.6, dropped support for Ruby 2.3.
|
20
|
+
|
21
|
+
### Matchers
|
22
|
+
|
23
|
+
Implemented the BeAUuidMatcher, which expects the value to be a UUID string.
|
24
|
+
|
25
|
+
Implemented the DeepMatcher, which recursively compares data structures.
|
26
|
+
|
27
|
+
expect(response).to deep_match(
|
28
|
+
status: 200,
|
29
|
+
body: {
|
30
|
+
order: {
|
31
|
+
id: an_instance_of(Integer),
|
32
|
+
total: '9.99'
|
33
|
+
}
|
34
|
+
}
|
35
|
+
)
|
36
|
+
|
37
|
+
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.
|
38
|
+
|
39
|
+
Improved failure message of the HaveChangedMatcher when given a receiver and message.
|
40
|
+
|
3
41
|
## 2.4.1
|
4
42
|
|
5
43
|
Added support for RSpec 3.8.
|
data/DEVELOPMENT.md
CHANGED
@@ -1,26 +1,13 @@
|
|
1
1
|
# Development Notes
|
2
2
|
|
3
|
-
## Version 2.
|
3
|
+
## Version 2.6
|
4
4
|
|
5
|
-
|
6
|
-
|
7
|
-
- when skipping a shared example group with xinclude_examples, the generated context is named '(focused)'. It should instead be named '(skipped)'.
|
8
|
-
|
9
|
-
### Features
|
10
|
-
|
11
|
-
- Alias `have_reader`, etc as `define_reader`.
|
12
|
-
- Also alias shared examples.
|
13
|
-
- Alias `have_constant` as `define_constant`.
|
14
|
-
- Alias #immutable as #frozen.
|
15
|
-
- Also alias shared examples.
|
16
|
-
|
17
|
-
### Maintenance
|
18
|
-
|
19
|
-
- Refactor all macro specs from spec/rspec/sleeping_king_studios/matchers/macros to the directories corresponding to the source files.
|
5
|
+
- Deprecate `delegate_method` matcher, `include` matcher with block.
|
20
6
|
|
21
7
|
## Version 3.0
|
22
8
|
|
23
9
|
- Extract out Rails-specific matchers to RSpec::SleepingKingStudios::Rails.
|
10
|
+
- Drop Rails 3 support.
|
24
11
|
- Refactor property, constant matchers to Define$1Matcher.
|
25
12
|
- HaveConstantMatcher, HaveReaderMatcher, HavePredicateMatcher, HavePropertyMatcher, HaveWriterMatcher.
|
26
13
|
- Designate define_* macros as primary, have_* as aliases.
|
@@ -31,6 +18,12 @@
|
|
31
18
|
|
32
19
|
## Future Tasks
|
33
20
|
|
21
|
+
- DeepMatcher: |
|
22
|
+
- indifferent - symbol/string keys
|
23
|
+
- ordered - pre-sort arrays?
|
24
|
+
- only homogenous arrays?
|
25
|
+
- odd results unless equality comparison
|
26
|
+
|
34
27
|
### Bug Fixes
|
35
28
|
|
36
29
|
- false negative on #alias_method?
|
@@ -58,8 +51,6 @@
|
|
58
51
|
|
59
52
|
- BeImmutableMatcher (NEW):
|
60
53
|
- Implement be_immutable matcher.
|
61
|
-
- HaveChangedMatcher (NEW):
|
62
|
-
- Add spy+matcher for expect(my_object, :my_method).to have_changed ?
|
63
54
|
- RespondToMatcher:
|
64
55
|
- Implement RespondToMatcher#with_optional_keywords, #with_required_keywords.
|
65
56
|
- Implement RespondToMatcher#with_at_least(N).arguments, equivalent to with(N).arguments.and_unlimited_arguments.
|
data/README.md
CHANGED
@@ -8,9 +8,9 @@ RSpec::SleepingKingStudios is tested against RSpec 3.3 through 3.7.
|
|
8
8
|
|
9
9
|
Currently, the following versions of Ruby are officially supported:
|
10
10
|
|
11
|
-
* 2.3
|
12
11
|
* 2.4
|
13
12
|
* 2.5
|
13
|
+
* 2.6
|
14
14
|
|
15
15
|
For Ruby 2.0 support, use version 2.1 or earlier: `gem "rspec-sleeping_king_studios", "~> 2.1.1"`.
|
16
16
|
|
@@ -322,7 +322,166 @@ A simplified syntax for re-using shared context or examples without having to ex
|
|
322
322
|
|
323
323
|
(also `::xwrap_context`) A shortcut for wrapping the context or examples in an automatically-skipped `describe` block, similar to the built-in `xit` and `xdescribe` methods.
|
324
324
|
|
325
|
-
##
|
325
|
+
## Contracts
|
326
|
+
|
327
|
+
```ruby
|
328
|
+
require 'rspec/sleepingkingstudios/contract'
|
329
|
+
```
|
330
|
+
|
331
|
+
A Contract encapsulates a set of RSpec expectations, which can then be used when defining a spec.
|
332
|
+
|
333
|
+
```ruby
|
334
|
+
module GreetContract
|
335
|
+
extend RSpec::SleepingKingStudios::Contract
|
336
|
+
|
337
|
+
describe '#greet' do
|
338
|
+
it { expect(subject).to respond_to(:greet).with(1).argument }
|
339
|
+
|
340
|
+
it { expect(subject.greet 'programs').to be == 'Greetings, programs!' }
|
341
|
+
end
|
342
|
+
end
|
343
|
+
|
344
|
+
RSpec.describe Greeter do
|
345
|
+
include GreetContract
|
346
|
+
end
|
347
|
+
```
|
348
|
+
|
349
|
+
Using a contract allows for examples to be shared between different specs, or even between projects.
|
350
|
+
|
351
|
+
### Contract Methods
|
352
|
+
|
353
|
+
Not all RSpec methods are defined in a Contract. Only methods that define an example (`it`) or an example group (`context` or `describe`) can be used at the top level of a Contract. However, all RSpec methods (including methods that modify the current scope, such as `let` and the `before`/`around`/`after` filters) can be used inside an example group as normal.
|
354
|
+
|
355
|
+
#### `::context`
|
356
|
+
|
357
|
+
Defines an example group inside the contract. This example group will be defined on all specs that include the contract.
|
358
|
+
|
359
|
+
```ruby
|
360
|
+
module TransformationContract
|
361
|
+
extend RSpec::SleepingKingStudios::Contract
|
362
|
+
|
363
|
+
context 'when the moon is full' do
|
364
|
+
let(:moon_phase) { :full }
|
365
|
+
|
366
|
+
it { expect(werewolf).to be_transformed }
|
367
|
+
end
|
368
|
+
end
|
369
|
+
```
|
370
|
+
|
371
|
+
#### `::describe`
|
372
|
+
|
373
|
+
Defines an example group inside the contract. This example group will be defined on all specs that include the contract.
|
374
|
+
|
375
|
+
```ruby
|
376
|
+
module SilverContract
|
377
|
+
extend RSpec::SleepingKingStudios::Contract
|
378
|
+
|
379
|
+
describe 'with a silver weapon' do
|
380
|
+
before(:example) do
|
381
|
+
weapon.material = 'silver'
|
382
|
+
end
|
383
|
+
|
384
|
+
it 'should kill the werewolf' do
|
385
|
+
expect(attack(werewolf, weapon)).to change(werewolf, :alive?).to be false
|
386
|
+
end
|
387
|
+
end
|
388
|
+
end
|
389
|
+
```
|
390
|
+
|
391
|
+
#### `::it`
|
392
|
+
|
393
|
+
Defines an example inside the contract.
|
394
|
+
|
395
|
+
```ruby
|
396
|
+
module HowlingContract
|
397
|
+
extend RSpec::SleepingKingStudios::Contract
|
398
|
+
|
399
|
+
it { expect(werewolf).to respond_to(:howl) }
|
400
|
+
end
|
401
|
+
```
|
402
|
+
|
403
|
+
#### `::shared_context`
|
404
|
+
|
405
|
+
Defines a shared example group.
|
406
|
+
|
407
|
+
```ruby
|
408
|
+
module MoonContract
|
409
|
+
extend RSpec::SleepingKingStudios::Contract
|
410
|
+
|
411
|
+
shared_context 'when the moon is full' do
|
412
|
+
before(:example) { moon.phase = :full }
|
413
|
+
end
|
414
|
+
end
|
415
|
+
```
|
416
|
+
|
417
|
+
**Note:** When the `Contract` is included in an RSpec example group, any shared example groups defined at the top level of a contract are also included in that example group, even outside of the contract itself. This may cause namespace collisions with shared example groups defined elsewhere in the example group or by other included contracts.
|
418
|
+
|
419
|
+
#### `::shared_examples`
|
420
|
+
|
421
|
+
Defines a shared example group.
|
422
|
+
|
423
|
+
```ruby
|
424
|
+
module HairContract
|
425
|
+
extend RSpec::SleepingKingStudios::Contract
|
426
|
+
|
427
|
+
shared_examples 'should be hairy' do
|
428
|
+
describe '#hairy?' do
|
429
|
+
it { expect(werewolf.hairy?).to be true }
|
430
|
+
end
|
431
|
+
end
|
432
|
+
end
|
433
|
+
```
|
434
|
+
|
435
|
+
**Note:** When the `Contract` is included in an RSpec example group, any shared example groups defined at the top level of a contract are also included in that example group, even outside of the contract itself. This may cause namespace collisions with shared example groups defined elsewhere in the example group or by other included contracts.
|
436
|
+
|
437
|
+
### Developing Contracts
|
438
|
+
|
439
|
+
```ruby
|
440
|
+
module VampireContract
|
441
|
+
extend RSpec::SleepingKingStudios::Contract
|
442
|
+
extend RSpec::SleepingKingStudios::Contracts::Development
|
443
|
+
|
444
|
+
fdescribe '#drink' do
|
445
|
+
it { expect(drink 'blood').to be true }
|
446
|
+
|
447
|
+
xit { expect(drink 'holy water').to be false }
|
448
|
+
end
|
449
|
+
|
450
|
+
pending
|
451
|
+
end
|
452
|
+
```
|
453
|
+
|
454
|
+
The `RSpec::SleepingKingStudios::Contracts::Development` module provides methods for defining focused or pending examples and example groups. These are intended for use when developing a contract, and should not be included in the final version. Having skipped or focused example groups in a shared contract can have unexpected effects when the contract is included by the end user.
|
455
|
+
|
456
|
+
#### `::fcontext`
|
457
|
+
|
458
|
+
Defines a focused example group inside the contract.
|
459
|
+
|
460
|
+
#### `::fdescribe`
|
461
|
+
|
462
|
+
Defines a focused example group inside the contract.
|
463
|
+
|
464
|
+
#### `::fit`
|
465
|
+
|
466
|
+
Defines a focused example inside the contract.
|
467
|
+
|
468
|
+
#### `::pending`
|
469
|
+
|
470
|
+
Marks the contract as pending.
|
471
|
+
|
472
|
+
#### `::xcontext`
|
473
|
+
|
474
|
+
Defines a skipped example group inside the contract.
|
475
|
+
|
476
|
+
#### `::xdescribe`
|
477
|
+
|
478
|
+
Defines a skipped example group inside the contract.
|
479
|
+
|
480
|
+
#### `::xit`
|
481
|
+
|
482
|
+
Defines a skipped example inside the contract.
|
483
|
+
|
484
|
+
## Matchers
|
326
485
|
|
327
486
|
To enable a custom matcher, simply require the associated file. Matchers can be required individually or by category:
|
328
487
|
|
@@ -447,6 +606,22 @@ Checks if the object aliases the specified method with the specified other name.
|
|
447
606
|
|
448
607
|
* **`#as`:** Required. Expects one String or Symbol, which is the name of the generated method.
|
449
608
|
|
609
|
+
#### `#be_a_uuid` Matcher
|
610
|
+
|
611
|
+
require 'rspec/sleeping_king_studios/matchers/core/be_a_uuid'
|
612
|
+
|
613
|
+
**Aliases:** `#a_uuid`.
|
614
|
+
|
615
|
+
**How To Use:**
|
616
|
+
|
617
|
+
# With an object comparison.
|
618
|
+
expect(string).to be_a_uuid
|
619
|
+
|
620
|
+
# Inside a composable matcher.
|
621
|
+
expect(array).to include(a_uuid)
|
622
|
+
|
623
|
+
**Parameters:** None.
|
624
|
+
|
450
625
|
#### `#be_boolean` Matcher
|
451
626
|
|
452
627
|
require 'rspec/sleeping_king_studios/matchers/core/be_boolean'
|
@@ -488,6 +663,52 @@ Verifies that the actual object can be constructed using `::new`. Can take an op
|
|
488
663
|
* **`#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
664
|
* **`#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
665
|
|
666
|
+
#### `#deep_match` Matcher
|
667
|
+
|
668
|
+
require 'rspec/sleeping_king_studios/matchers/core/deep_match'
|
669
|
+
|
670
|
+
Performs a recursive comparison between two object or data structures. Also supports using RSpec matchers as values in the expected object.
|
671
|
+
|
672
|
+
**How To Use:**
|
673
|
+
|
674
|
+
expected = {
|
675
|
+
status: 200,
|
676
|
+
body: {
|
677
|
+
order: {
|
678
|
+
id: an_instance_of(Integer),
|
679
|
+
total: '9.99'
|
680
|
+
}
|
681
|
+
}
|
682
|
+
}
|
683
|
+
expect(response).to deep_match(expected)
|
684
|
+
|
685
|
+
When the value does not match the expectation, the failure message will provide a detailed diff showing added, missing, and changed values.
|
686
|
+
|
687
|
+
response = {
|
688
|
+
status: 400,
|
689
|
+
body: {
|
690
|
+
order: {
|
691
|
+
fulfilled: false,
|
692
|
+
total: '19.99'
|
693
|
+
}
|
694
|
+
},
|
695
|
+
errors: ['Insufficient funds']
|
696
|
+
}
|
697
|
+
expect(response).to deep_match(expected)
|
698
|
+
# Failure/Error: expect(response).to deep_match(expected)
|
699
|
+
#
|
700
|
+
# expected: == {:body=>{:order=>{:id=>an instance of Integer, :total=>"9.99"}}, :status=>200}
|
701
|
+
# got: {:status=>400, :body=>{:order=>{:fulfilled=>false, :total=>"19.99"}}, :errors=>["Insufficient funds"]}
|
702
|
+
#
|
703
|
+
# (compared using HashDiff)
|
704
|
+
#
|
705
|
+
# Diff:
|
706
|
+
# + :body.:order.:fulfilled => got false
|
707
|
+
# - :body.:order.:id => expected an instance of Integer
|
708
|
+
# ~ :body.:order.:total => expected "9.99", got "19.99"
|
709
|
+
# + :errors => got ["Insufficient funds"]
|
710
|
+
# ~ :status => expected 200, got 400
|
711
|
+
|
491
712
|
#### `#delegate_method` Matcher
|
492
713
|
|
493
714
|
require 'rspec/sleeping_king_studios/matchers/core/delegate_method'
|
@@ -8,14 +8,14 @@ require 'rspec/sleeping_king_studios/matchers/base_matcher'
|
|
8
8
|
module RSpec::SleepingKingStudios::Examples::RSpecMatcherExamples
|
9
9
|
extend RSpec::SleepingKingStudios::Concerns::SharedExampleGroup
|
10
10
|
|
11
|
-
private def
|
11
|
+
private def rspec_config
|
12
12
|
RSpec.configuration.sleeping_king_studios
|
13
|
-
end # method
|
13
|
+
end # method rspec_config
|
14
14
|
|
15
15
|
private def compare_message actual, expected
|
16
16
|
case expected
|
17
17
|
when String
|
18
|
-
if
|
18
|
+
if rspec_config.examples.match_string_failure_message_as == :exact
|
19
19
|
expect(actual).to be == expected
|
20
20
|
else
|
21
21
|
expect(actual).to include expected
|
@@ -29,8 +29,12 @@ 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
|
-
case
|
37
|
+
case rspec_config.examples.handle_missing_failure_message_with
|
34
38
|
when :pending
|
35
39
|
skip message
|
36
40
|
when :exception
|
@@ -17,7 +17,12 @@ module RSpec::SleepingKingStudios::Matchers::BuiltIn
|
|
17
17
|
# should return true if and only if the item matches the desired
|
18
18
|
# predicate.
|
19
19
|
def initialize *expected, &block
|
20
|
-
|
20
|
+
if block_given?
|
21
|
+
SleepingKingStudios::Tools::CoreTools
|
22
|
+
.deprecate('IncludeMatcher with a block')
|
23
|
+
|
24
|
+
expected << block
|
25
|
+
end
|
21
26
|
|
22
27
|
if expected.empty? && !allow_empty_matcher?
|
23
28
|
raise ArgumentError,
|
@@ -87,18 +87,18 @@ module RSpec::SleepingKingStudios::Matchers::BuiltIn
|
|
87
87
|
|
88
88
|
method =
|
89
89
|
begin
|
90
|
-
actual.
|
90
|
+
if actual.is_a?(Class) && method_name.intern == :new
|
91
|
+
actual.instance_method(:initialize)
|
92
|
+
else
|
93
|
+
actual.method(method_name)
|
94
|
+
end
|
91
95
|
rescue NameError
|
92
|
-
|
93
|
-
|
96
|
+
@failing_method_reasons[method_name] = {
|
97
|
+
:is_not_a_method => true
|
98
|
+
} # end hash
|
94
99
|
|
95
|
-
|
96
|
-
|
97
|
-
:is_not_a_method => true
|
98
|
-
} # end hash
|
99
|
-
|
100
|
-
next false
|
101
|
-
end # unless
|
100
|
+
next false
|
101
|
+
end
|
102
102
|
|
103
103
|
next true unless method_signature_expectation?
|
104
104
|
|
@@ -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
|
@@ -125,6 +125,8 @@ module RSpec::SleepingKingStudios::Matchers::Core
|
|
125
125
|
|
126
126
|
# (see BaseMatcher#matches?)
|
127
127
|
def matches? actual
|
128
|
+
SleepingKingStudios::Tools::CoreTools.deprecate('DelegateMethodMatcher')
|
129
|
+
|
128
130
|
super
|
129
131
|
|
130
132
|
raise ArgumentError.new('must specify a target') if @target.nil?
|
@@ -187,14 +189,22 @@ module RSpec::SleepingKingStudios::Matchers::Core
|
|
187
189
|
|
188
190
|
private
|
189
191
|
|
190
|
-
def call_method
|
192
|
+
def call_method(arguments:, keywords:, expected_return: DEFAULT_EXPECTED_RETURN)
|
191
193
|
if @expected_block
|
192
194
|
@received_block = false
|
193
195
|
block = ->(*args, **kwargs, &block) {}
|
194
196
|
|
195
|
-
|
197
|
+
if keywords.empty?
|
198
|
+
return_value = @actual.send(@expected, *arguments, &block)
|
199
|
+
else
|
200
|
+
return_value = @actual.send(@expected, *arguments, **keywords, &block)
|
201
|
+
end
|
196
202
|
else
|
197
|
-
|
203
|
+
if keywords.empty?
|
204
|
+
return_value = @actual.send(@expected, *arguments)
|
205
|
+
else
|
206
|
+
return_value = @actual.send(@expected, *arguments, **keywords)
|
207
|
+
end
|
198
208
|
end
|
199
209
|
|
200
210
|
@received_return_values << return_value
|
@@ -215,19 +225,22 @@ module RSpec::SleepingKingStudios::Matchers::Core
|
|
215
225
|
def delegates_method?
|
216
226
|
stub_target!
|
217
227
|
|
218
|
-
args = @expected_arguments.dup
|
219
|
-
args << @expected_keywords unless @expected_keywords.empty?
|
220
|
-
|
221
228
|
if @expected_return_values.empty?
|
222
|
-
call_method(
|
229
|
+
call_method(arguments: @expected_arguments, keywords: @expected_keywords)
|
223
230
|
else
|
224
231
|
@expected_return_values.each do |return_value|
|
225
|
-
call_method(
|
232
|
+
call_method(arguments: @expected_arguments, keywords: @expected_keywords, expected_return: return_value)
|
226
233
|
end # each
|
227
234
|
end # if-else
|
228
235
|
|
229
236
|
matcher = RSpec::Mocks::Matchers::HaveReceived.new(@expected)
|
230
|
-
|
237
|
+
if !@expected_arguments.empty? && !@expected_keywords.empty?
|
238
|
+
matcher = matcher.with(*@expected_arguments, **@expected_keywords)
|
239
|
+
elsif !@expected_arguments.empty?
|
240
|
+
matcher = matcher.with(*@expected_arguments)
|
241
|
+
elsif !@expected_keywords.empty?
|
242
|
+
matcher = matcher.with(**@expected_keywords)
|
243
|
+
end
|
231
244
|
|
232
245
|
unless @expected_return_values.empty?
|
233
246
|
matcher = matcher.exactly(@expected_return_values.count).times
|
@@ -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_literal: true
|
2
2
|
|
3
3
|
module RSpec
|
4
4
|
module SleepingKingStudios
|
@@ -11,9 +11,9 @@ module RSpec
|
|
11
11
|
# Major version.
|
12
12
|
MAJOR = 2
|
13
13
|
# Minor version.
|
14
|
-
MINOR =
|
14
|
+
MINOR = 6
|
15
15
|
# Patch version.
|
16
|
-
PATCH =
|
16
|
+
PATCH = 0
|
17
17
|
# Prerelease version.
|
18
18
|
PRERELEASE = nil
|
19
19
|
# Build metadata.
|
@@ -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.6.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: 2021-03-13 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
|
@@ -28,16 +42,22 @@ dependencies:
|
|
28
42
|
name: sleeping_king_studios-tools
|
29
43
|
requirement: !ruby/object:Gem::Requirement
|
30
44
|
requirements:
|
31
|
-
- - "
|
45
|
+
- - ">="
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: 0.8.0
|
48
|
+
- - "<"
|
32
49
|
- !ruby/object:Gem::Version
|
33
|
-
version: '
|
50
|
+
version: '2'
|
34
51
|
type: :runtime
|
35
52
|
prerelease: false
|
36
53
|
version_requirements: !ruby/object:Gem::Requirement
|
37
54
|
requirements:
|
38
|
-
- - "
|
55
|
+
- - ">="
|
39
56
|
- !ruby/object:Gem::Version
|
40
|
-
version:
|
57
|
+
version: 0.8.0
|
58
|
+
- - "<"
|
59
|
+
- !ruby/object:Gem::Version
|
60
|
+
version: '2'
|
41
61
|
- !ruby/object:Gem::Dependency
|
42
62
|
name: appraisal
|
43
63
|
requirement: !ruby/object:Gem::Requirement
|
@@ -106,14 +126,20 @@ dependencies:
|
|
106
126
|
requirements:
|
107
127
|
- - "~>"
|
108
128
|
- !ruby/object:Gem::Version
|
109
|
-
version: '0.
|
129
|
+
version: '0.4'
|
130
|
+
- - ">="
|
131
|
+
- !ruby/object:Gem::Version
|
132
|
+
version: 0.4.1
|
110
133
|
type: :development
|
111
134
|
prerelease: false
|
112
135
|
version_requirements: !ruby/object:Gem::Requirement
|
113
136
|
requirements:
|
114
137
|
- - "~>"
|
115
138
|
- !ruby/object:Gem::Version
|
116
|
-
version: '0.
|
139
|
+
version: '0.4'
|
140
|
+
- - ">="
|
141
|
+
- !ruby/object:Gem::Version
|
142
|
+
version: 0.4.1
|
117
143
|
- !ruby/object:Gem::Dependency
|
118
144
|
name: aruba
|
119
145
|
requirement: !ruby/object:Gem::Requirement
|
@@ -151,7 +177,7 @@ dependencies:
|
|
151
177
|
version: '3.0'
|
152
178
|
- - "<"
|
153
179
|
- !ruby/object:Gem::Version
|
154
|
-
version: '
|
180
|
+
version: '7.0'
|
155
181
|
type: :development
|
156
182
|
prerelease: false
|
157
183
|
version_requirements: !ruby/object:Gem::Requirement
|
@@ -161,7 +187,7 @@ dependencies:
|
|
161
187
|
version: '3.0'
|
162
188
|
- - "<"
|
163
189
|
- !ruby/object:Gem::Version
|
164
|
-
version: '
|
190
|
+
version: '7.0'
|
165
191
|
description: |2
|
166
192
|
A collection of RSpec patches and custom matchers. The features can be
|
167
193
|
included individually or by category. For more information, check out the
|
@@ -217,10 +243,14 @@ files:
|
|
217
243
|
- lib/rspec/sleeping_king_studios/matchers/core/alias_method.rb
|
218
244
|
- lib/rspec/sleeping_king_studios/matchers/core/alias_method_matcher.rb
|
219
245
|
- lib/rspec/sleeping_king_studios/matchers/core/all.rb
|
246
|
+
- lib/rspec/sleeping_king_studios/matchers/core/be_a_uuid.rb
|
247
|
+
- lib/rspec/sleeping_king_studios/matchers/core/be_a_uuid_matcher.rb
|
220
248
|
- lib/rspec/sleeping_king_studios/matchers/core/be_boolean.rb
|
221
249
|
- lib/rspec/sleeping_king_studios/matchers/core/be_boolean_matcher.rb
|
222
250
|
- lib/rspec/sleeping_king_studios/matchers/core/construct.rb
|
223
251
|
- lib/rspec/sleeping_king_studios/matchers/core/construct_matcher.rb
|
252
|
+
- lib/rspec/sleeping_king_studios/matchers/core/deep_match.rb
|
253
|
+
- lib/rspec/sleeping_king_studios/matchers/core/deep_matcher.rb
|
224
254
|
- lib/rspec/sleeping_king_studios/matchers/core/delegate_method.rb
|
225
255
|
- lib/rspec/sleeping_king_studios/matchers/core/delegate_method_matcher.rb
|
226
256
|
- lib/rspec/sleeping_king_studios/matchers/core/have_changed.rb
|
@@ -247,7 +277,9 @@ files:
|
|
247
277
|
homepage: http://sleepingkingstudios.com
|
248
278
|
licenses:
|
249
279
|
- MIT
|
250
|
-
metadata:
|
280
|
+
metadata:
|
281
|
+
bug_tracker_uri: https://github.com/sleepingkingstudios/rspec-sleeping_king_studios/issues
|
282
|
+
source_code_uri: https://github.com/sleepingkingstudios/rspec-sleeping_king_studios
|
251
283
|
post_install_message:
|
252
284
|
rdoc_options: []
|
253
285
|
require_paths:
|
@@ -263,8 +295,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
263
295
|
- !ruby/object:Gem::Version
|
264
296
|
version: '0'
|
265
297
|
requirements: []
|
266
|
-
|
267
|
-
rubygems_version: 2.7.6
|
298
|
+
rubygems_version: 3.1.2
|
268
299
|
signing_key:
|
269
300
|
specification_version: 4
|
270
301
|
summary: A collection of RSpec patches and custom matchers.
|