expected 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: '0954ddfccf5072455413c702650c98e39ccdbd72a1db7806463598e5c6c0e52b'
4
+ data.tar.gz: c41841fcb0cfcfde9dfff9c1c27445f88c10a168254c965ea681a0e62676ee0c
5
+ SHA512:
6
+ metadata.gz: a6cf5251016d8d3f9b36af9ac429a0e9c8f433ee4c03b687a438e339d84361c913df7b63f6779597b49f0fb675ca4998c9da8a066e1371458ad04c1dff3675b5
7
+ data.tar.gz: bb7461e7f4e02295962c7b52288e86a710bf72f93f7a6ab4129eb29a8f9b7d27a66c50c95eea4b0d8681d0ed620b95f0237cf02818b5c5fda5de1e30f81f82c7
@@ -0,0 +1,22 @@
1
+ Copyright 2019 Taylor Yelverton
2
+
3
+ Permission is hereby granted, free of charge, to any person
4
+ obtaining a copy of this software and associated documentation
5
+ files (the "Software"), to deal in the Software without
6
+ restriction, including without limitation the rights to use,
7
+ copy, modify, merge, publish, distribute, sublicense, and/or sell
8
+ copies of the Software, and to permit persons to whom the
9
+ Software is furnished to do so, subject to the following
10
+ conditions:
11
+
12
+ The above copyright notice and this permission notice shall be
13
+ included in all copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
17
+ OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
19
+ HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
20
+ WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21
+ FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
22
+ OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,94 @@
1
+ # Expected: RSpec Matchers - Extended [![Gem Version][version-badge]][rubygems] [![Total Downloads][downloads-total]][rubygems] [![Downloads][downloads-badge]][rubygems]
2
+
3
+ [version-badge]: https://img.shields.io/gem/v/expected.svg
4
+ [rubygems]: https://rubygems.org/gems/expected
5
+ [downloads-total]: https://img.shields.io/gem/dt/expected.svg
6
+ [downloads-badge]: https://img.shields.io/gem/dtv/expected.svg
7
+
8
+ Adds several simple matchers to RSpec
9
+
10
+
11
+
12
+ ## Installation
13
+
14
+ ### Add to Gemfile
15
+ ```ruby
16
+ group :test do
17
+ gem 'expected'
18
+ end
19
+ ```
20
+
21
+ ### Add to RSpec
22
+ Add the following to your projects `spec/rails_helper.rb` for Rails apps, or `spec/spec_helper.rb for non-Rails apps.
23
+ ```ruby
24
+ Expected.configure do |config|
25
+ end
26
+ ```
27
+
28
+
29
+
30
+
31
+
32
+ ## Usage
33
+
34
+
35
+
36
+ ### `inherit_from`
37
+ Used to test inheritance
38
+
39
+ ```ruby
40
+ # Test if the subject inherits from the supplied Class
41
+ it { is_expected.to inherit_from(SomeClass) }
42
+ ```
43
+
44
+
45
+
46
+ ### `have_constant`
47
+ Used to test constants
48
+
49
+ ```ruby
50
+ # Test if a constant exists
51
+ it { is_expected.to have_constant(:FOO) }
52
+
53
+ # Test if a constant has a specific value
54
+ it { is_expected.to have_constant(:FOO).with_value("bar") }
55
+
56
+ # Test if a constant's value is a specific type
57
+ it { is_expected.to have_constant(:FOO).of_type(String) }
58
+ ```
59
+
60
+
61
+
62
+ ### `have_attr_reader`
63
+ Used to test inclusion of `attr_reader :attribute`
64
+
65
+ ```ruby
66
+ # Test if the subject has `attr_reader :attribute`
67
+ it { is_expected.to have_attr_reader(:attribute) }
68
+ ```
69
+
70
+
71
+
72
+ ### `have_attr_writer`
73
+ Used to test inclusion of `attr_writer :attribute`
74
+
75
+ ```ruby
76
+ # Test if the subject has `attr_writer :attribute`
77
+ it { is_expected.to have_attr_writer(:attribute) }
78
+ ```
79
+
80
+
81
+
82
+ ### `have_attr_accessor`
83
+ Used to test inclusion of `attr_accessor :attribute`
84
+
85
+ ```ruby
86
+ # Test if the subject has `attr_accessor :attribute`
87
+ it { is_expected.to have_attr_accessor(:attribute) }
88
+ ```
89
+
90
+
91
+
92
+ ## License
93
+ Expected is copyright © 2019-2020 Taylor Yelverton.
94
+ It is free software, and may be redistributed under the terms specified in the MIT-LICENSE file.
@@ -0,0 +1,13 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Container Module
4
+ module Expected
5
+
6
+ end
7
+
8
+ require 'active_support/hash_with_indifferent_access'
9
+ require 'active_support/core_ext/hash/indifferent_access'
10
+
11
+ require 'expected/version'
12
+ require 'expected/configuration'
13
+ require 'expected/matchers'
@@ -0,0 +1,25 @@
1
+ # frozen_string_literal: true
2
+
3
+ # :nodoc:
4
+ module Expected
5
+ class << self
6
+
7
+ # Configure the library
8
+ # @yield [Configuration]
9
+ def configure
10
+ yield configuration
11
+ end
12
+
13
+ # Memoized {Configuration}
14
+ # @return [Configuration]
15
+ def configuration
16
+ @configuration ||= Configuration.new
17
+ end
18
+
19
+ end
20
+
21
+ # Configuration class
22
+ class Configuration
23
+ end
24
+
25
+ end
@@ -0,0 +1,13 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Expected
4
+ # Matchers container
5
+ module Matchers
6
+ end
7
+ end
8
+
9
+ require 'expected/matchers/have_constant'
10
+ require 'expected/matchers/inherit_from'
11
+ require 'expected/matchers/have_attr_reader'
12
+ require 'expected/matchers/have_attr_writer'
13
+ require 'expected/matchers/have_attr_accessor'
@@ -0,0 +1,88 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'securerandom'
4
+
5
+ module Expected
6
+ # :nodoc:
7
+ module Matchers
8
+
9
+ # Used to test inclusion of `attr_accessor :attribute` on the subject
10
+ # @param attribute [String, Symbol]
11
+ # @return [HaveAttrAccessorMatcher]
12
+ #
13
+ # @example Test if the subject has `attr_accessor :attribute`
14
+ # it { is_expected.to have_attr_accessor(:some_attribute) }
15
+ #
16
+ def have_attr_accessor(attribute) # rubocop:disable Naming/PredicateName
17
+ HaveAttrAccessorMatcher.new(attribute)
18
+ end
19
+
20
+ # Class used by {#have_constant}
21
+ class HaveAttrAccessorMatcher
22
+ attr_reader :attribute, :subject, :has_attr_reader, :has_attr_writer
23
+
24
+ # @param attribute [String, Symbol] The attribute the {#subject} is expected to have an attr_accessor for
25
+ def initialize(attribute)
26
+ unless attribute.is_a?(String) || attribute.is_a?(Symbol)
27
+ raise 'HaveAttrAccessorMatcher attribute must be a String or Symbol'
28
+ end
29
+ @attribute = attribute.to_sym
30
+ @has_attr_reader = HaveAttrReaderMatcher.new(attribute)
31
+ @has_attr_writer = HaveAttrWriterMatcher.new(attribute)
32
+ end
33
+
34
+ # Run the test
35
+ # @param subject The thing to test against
36
+ # @return [True] If the test passes
37
+ # @return [False] if the test fails
38
+ def matches?(subject)
39
+ self.subject = subject
40
+ matches_attr_reader? && matches_attr_writer?
41
+ end
42
+
43
+ # @return [String]
44
+ def failure_message
45
+ "Expected #{expectation} (#{@failure})"
46
+ end
47
+
48
+ # @return [String]
49
+ def failure_message_when_negated
50
+ "Did not expect #{expectation}"
51
+ end
52
+
53
+ # @return [String]
54
+ def description
55
+ "have_attr_accessor: `#{attribute}`"
56
+ end
57
+
58
+ private
59
+
60
+ # The thing to test against
61
+ # @return [Class, Module]
62
+ def subject=(subject) # rubocop:disable Style/TrivialAccessors
63
+ @subject = subject
64
+ end
65
+
66
+ def matches_attr_reader?
67
+ ret = has_attr_reader.matches?(subject)
68
+ msg = has_attr_reader.instance_variable_get(:@failure)
69
+ @failure = msg if msg
70
+ ret
71
+ end
72
+
73
+ def matches_attr_writer?
74
+ ret = has_attr_writer.matches?(subject)
75
+ msg = has_attr_writer.instance_variable_get(:@failure)
76
+ @failure = msg if msg
77
+ ret
78
+ end
79
+
80
+ # @return String
81
+ def expectation
82
+ "<#{subject}> to have attr_accessor `#{attribute}`"
83
+ end
84
+
85
+ end
86
+
87
+ end
88
+ end
@@ -0,0 +1,103 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'securerandom'
4
+
5
+ module Expected
6
+ # :nodoc:
7
+ module Matchers
8
+
9
+ # Used to test inclusion of `attr_reader :attribute` on the subject
10
+ # @param attribute [String, Symbol]
11
+ # @return [HaveAttrReaderMatcher]
12
+ #
13
+ # @example Test if the subject has `attr_reader :attribute`
14
+ # it { is_expected.to have_attr_reader(:some_attribute) }
15
+ #
16
+ def have_attr_reader(attribute) # rubocop:disable Naming/PredicateName
17
+ HaveAttrReaderMatcher.new(attribute)
18
+ end
19
+
20
+ # Class used by {#have_constant}
21
+ class HaveAttrReaderMatcher
22
+ attr_reader :attribute, :subject
23
+
24
+ # @param attribute [String, Symbol] The attribute the {#subject} is expected to have an attr_reader for
25
+ def initialize(attribute)
26
+ unless attribute.is_a?(String) || attribute.is_a?(Symbol)
27
+ raise 'HaveAttrReaderMatcher attribute must be a String or Symbol'
28
+ end
29
+ @attribute = attribute.to_sym
30
+ end
31
+
32
+ # Run the test
33
+ # @param subject The thing to test against
34
+ # @return [True] If the test passes
35
+ # @return [False] if the test fails
36
+ def matches?(subject)
37
+ self.subject = subject
38
+ method? &&
39
+ returns_correct_value?
40
+ end
41
+
42
+ # @return [String]
43
+ def failure_message
44
+ "Expected #{expectation} (#{@failure})"
45
+ end
46
+
47
+ # @return [String]
48
+ def failure_message_when_negated
49
+ "Did not expect #{expectation}"
50
+ end
51
+
52
+ # @return [String]
53
+ def description
54
+ "have_attr_reader: `#{attribute}`"
55
+ end
56
+
57
+ private
58
+
59
+ # The thing to test against
60
+ # @return [Class, Module]
61
+ def subject=(subject)
62
+ @original_subject = subject
63
+ @subject = subject.instance_of?(Class) ? subject.allocate : subject
64
+ end
65
+
66
+ # @return [Symbol]
67
+ def attribute_ivar
68
+ @attribute_ivar ||= :"@#{attribute}"
69
+ end
70
+
71
+ def method?
72
+ if subject.respond_to? attribute
73
+ true
74
+ else
75
+ @failure = "no method `#{attribute}`"
76
+ false
77
+ end
78
+ end
79
+
80
+ def returns_correct_value? # rubocop:disable Metrics/AbcSize, Metrics/MethodLength
81
+ has_original_val = subject.instance_variable_defined?(attribute_ivar)
82
+ original_val = subject.instance_variable_get(attribute_ivar)
83
+ test_val = SecureRandom.hex
84
+ subject.instance_variable_set(attribute_ivar, test_val)
85
+ ret = if subject.send(attribute) == test_val
86
+ true
87
+ else
88
+ @failure = "method `#{attribute}` did not return the value of #{attribute_ivar}"
89
+ false
90
+ end
91
+ subject.instance_variable_set(attribute_ivar, original_val) if has_original_val
92
+ ret
93
+ end
94
+
95
+ # @return String
96
+ def expectation
97
+ "<#{@original_subject}> to have attr_reader `#{attribute}`"
98
+ end
99
+
100
+ end
101
+
102
+ end
103
+ end
@@ -0,0 +1,108 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'securerandom'
4
+
5
+ module Expected
6
+ # :nodoc:
7
+ module Matchers
8
+
9
+ # Used to test inclusion of `attr_writer :attribute` on the subject
10
+ # @param attribute [String, Symbol]
11
+ # @return [HaveAttrWriterMatcher]
12
+ #
13
+ # @example Test if the subject has `attr_writer :attribute`
14
+ # it { is_expected.to have_attr_writer(:some_attribute) }
15
+ #
16
+ def have_attr_writer(attribute) # rubocop:disable Naming/PredicateName
17
+ HaveAttrWriterMatcher.new(attribute)
18
+ end
19
+
20
+ # Class used by {#have_constant}
21
+ class HaveAttrWriterMatcher
22
+ attr_reader :attribute, :subject
23
+
24
+ # @param attribute [String, Symbol] The attribute the {#subject} is expected to have an attr_writer for
25
+ def initialize(attribute)
26
+ unless attribute.is_a?(String) || attribute.is_a?(Symbol)
27
+ raise 'HaveAttrWriterMatcher attribute must be a String or Symbol'
28
+ end
29
+ @attribute = attribute.to_sym
30
+ end
31
+
32
+ # Run the test
33
+ # @param subject The thing to test against
34
+ # @return [True] If the test passes
35
+ # @return [False] if the test fails
36
+ def matches?(subject)
37
+ self.subject = subject
38
+ method? &&
39
+ sets_correct_value?
40
+ end
41
+
42
+ # @return [String]
43
+ def failure_message
44
+ "Expected #{expectation} (#{@failure})"
45
+ end
46
+
47
+ # @return [String]
48
+ def failure_message_when_negated
49
+ "Did not expect #{expectation}"
50
+ end
51
+
52
+ # @return [String]
53
+ def description
54
+ "have_attr_writer: `#{attribute}`"
55
+ end
56
+
57
+ private
58
+
59
+ # The thing to test against
60
+ # @return [Class, Module]
61
+ def subject=(subject)
62
+ @original_subject = subject
63
+ @subject = subject.instance_of?(Class) ? subject.allocate : subject
64
+ end
65
+
66
+ # @return [Symbol]
67
+ def attribute_ivar
68
+ @attribute_ivar ||= :"@#{attribute}"
69
+ end
70
+
71
+ # @return [Symbol]
72
+ def method_name
73
+ @method_name ||= :"#{attribute}="
74
+ end
75
+
76
+ def method?
77
+ if subject.respond_to? method_name
78
+ true
79
+ else
80
+ @failure = "no method `#{method_name}`"
81
+ false
82
+ end
83
+ end
84
+
85
+ def sets_correct_value? # rubocop:disable Metrics/AbcSize, Metrics/MethodLength
86
+ has_original_val = subject.instance_variable_defined?(attribute_ivar)
87
+ original_val = subject.instance_variable_get(attribute_ivar)
88
+ test_val = SecureRandom.hex
89
+ subject.send(method_name, test_val)
90
+ ret = if subject.instance_variable_get(attribute_ivar) == test_val
91
+ true
92
+ else
93
+ @failure = "method `#{method_name}` did not set the value of #{attribute_ivar}"
94
+ false
95
+ end
96
+ subject.instance_variable_set(attribute_ivar, original_val) if has_original_val
97
+ ret
98
+ end
99
+
100
+ # @return String
101
+ def expectation
102
+ "<#{@original_subject}> to have attr_writer `#{attribute}`"
103
+ end
104
+
105
+ end
106
+
107
+ end
108
+ end
@@ -0,0 +1,143 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Expected
4
+ # :nodoc:
5
+ module Matchers
6
+
7
+ # Used to test constants
8
+ # @param name [String, Symbol]
9
+ # @return [HaveConstantMatcher]
10
+ #
11
+ # @example Test if a constant exists
12
+ # it { is_expected.to have_constant(:FOO) }
13
+ #
14
+ # @example Test if a constant has a specific value
15
+ # it { is_expected.to have_constant(:FOO).with_value("bar") }
16
+ #
17
+ # @example Test if a constant's value is a specific type
18
+ # it { is_expected.to have_constant(:FOO).of_type(String) }
19
+ #
20
+ def have_constant(name) # rubocop:disable Naming/PredicateName
21
+ HaveConstantMatcher.new(name)
22
+ end
23
+
24
+ # Class used by {#have_constant}
25
+ class HaveConstantMatcher
26
+ attr_reader :name, :subject
27
+
28
+ # @raise If the provided name is not a {String} or {Symbol}
29
+ # @param name [String, Symbol] The name of the constant
30
+ def initialize(name)
31
+ unless name.is_a?(String) || name.is_a?(Symbol)
32
+ raise 'HaveConstantMatcher constant name must be a String or Symbol'
33
+ end
34
+ @name = name
35
+ end
36
+
37
+ # Sets the expected value of the constant
38
+ # @param value The expected value of the constant
39
+ # @return [self]
40
+ def with_value(value)
41
+ options[:value] = value
42
+ self
43
+ end
44
+
45
+ # Sets the expected type of the constant's value
46
+ # @param type [Module, Class] The expected type of the constant's value
47
+ # @return [self]
48
+ def of_type(type)
49
+ options[:type] = type
50
+ self
51
+ end
52
+
53
+ # Run the test
54
+ # @param subject The thing to test against
55
+ # @return [True] If the test passes
56
+ # @return [False] if the test fails
57
+ def matches?(subject)
58
+ self.subject = subject
59
+ constant_exists? &&
60
+ correct_type? &&
61
+ correct_value?
62
+ end
63
+
64
+ # @return [String]
65
+ def failure_message
66
+ "Expected #{expectation} (#{@failure})"
67
+ end
68
+
69
+ # @return [String]
70
+ def failure_message_when_negated
71
+ "Did not expect #{expectation}"
72
+ end
73
+
74
+ # @return [String]
75
+ def description
76
+ description = "have_constant: #{name}"
77
+ description += " of_type => #{options[:type].inspect}" if options.key? :type
78
+ description += " with_value => #{options[:value].inspect}" if options.key? :value
79
+ description
80
+ end
81
+
82
+ private
83
+
84
+ # @return [Hash]
85
+ def options
86
+ @options ||= {}.with_indifferent_access
87
+ end
88
+
89
+ # The thing to test against
90
+ # @return [Class, Module]
91
+ def subject=(subject)
92
+ @subject = subject.instance_of?(Class) || subject.is_a?(Module) ? subject : subject.class
93
+ end
94
+
95
+ # Check if the {#subject} has the constant
96
+ # @return Boolean
97
+ def constant_exists?
98
+ if subject.const_defined? name
99
+ true
100
+ else
101
+ @failure = 'missing constant'
102
+ false
103
+ end
104
+ end
105
+
106
+ # Check if the constants value is the correct type, specified from {#of_type}
107
+ # @return Boolean
108
+ def correct_type?
109
+ return true unless options.key? :type
110
+ value = subject.const_get(name)
111
+ if value.is_a? options[:type]
112
+ true
113
+ else
114
+ @failure = "type was <#{value.class}>"
115
+ false
116
+ end
117
+ end
118
+
119
+ # Check if the constants value is correct, specified from {#with_value}
120
+ # @return Boolean
121
+ def correct_value?
122
+ return true unless options.key? :value
123
+ value = subject.const_get(name)
124
+ if value == options[:value]
125
+ true
126
+ else
127
+ @failure = "value was #{value.inspect}"
128
+ false
129
+ end
130
+ end
131
+
132
+ # @return String
133
+ def expectation
134
+ expectation = "<#{subject}> to have a constant named #{name}"
135
+ expectation += " with a type of <#{options[:type]}>" if options[:type]
136
+ expectation += " with a value of #{options[:value].inspect}" if options[:value]
137
+ expectation
138
+ end
139
+
140
+ end
141
+
142
+ end
143
+ end
@@ -0,0 +1,67 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Expected
4
+ # :nodoc:
5
+ module Matchers
6
+
7
+ # Used to test inheritance
8
+ # @param expected_ancestor [Class]
9
+ # @return [InheritFromMatcher]
10
+ #
11
+ # @example Test if the subject inherits from the supplied Class
12
+ # it { is_expected.to inherit_from(SomeClass) }
13
+ #
14
+ def inherit_from(expected_ancestor)
15
+ InheritFromMatcher.new(expected_ancestor)
16
+ end
17
+
18
+ # Class used by {#have_constant}
19
+ class InheritFromMatcher
20
+ attr_reader :expected_ancestor, :subject
21
+
22
+ # @param expected_ancestor [Class] The ancestor the {#subject} is expected to inherit from
23
+ def initialize(expected_ancestor)
24
+ @expected_ancestor = expected_ancestor
25
+ end
26
+
27
+ # Run the test
28
+ # @param subject The thing to test against
29
+ # @return [True] If the test passes
30
+ # @return [False] if the test fails
31
+ def matches?(subject)
32
+ self.subject = subject
33
+ self.subject.ancestors.include? expected_ancestor
34
+ end
35
+
36
+ # @return [String]
37
+ def failure_message
38
+ "Expected #{expectation}"
39
+ end
40
+
41
+ # @return [String]
42
+ def failure_message_when_negated
43
+ "Did not expect #{expectation}"
44
+ end
45
+
46
+ # @return [String]
47
+ def description
48
+ "inherit_from: <#{expected_ancestor.inspect}>"
49
+ end
50
+
51
+ private
52
+
53
+ # The thing to test against
54
+ # @return [Class, Module]
55
+ def subject=(subject)
56
+ @subject = subject.instance_of?(Class) || subject.is_a?(Module) ? subject : subject.class
57
+ end
58
+
59
+ # @return String
60
+ def expectation
61
+ "<#{subject.inspect}> to inherit from <#{expected_ancestor.inspect}>"
62
+ end
63
+
64
+ end
65
+
66
+ end
67
+ end
@@ -0,0 +1,19 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Expected
4
+
5
+ # Contains version information
6
+ module Version
7
+ MAJOR = 1
8
+ MINOR = 0
9
+ PATCH = 0
10
+
11
+ end
12
+
13
+ VERSION = [
14
+ Version::MAJOR,
15
+ Version::MINOR,
16
+ Version::PATCH,
17
+ ].join('.').freeze
18
+
19
+ end
metadata ADDED
@@ -0,0 +1,78 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: expected
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.0.0
5
+ platform: ruby
6
+ authors:
7
+ - Taylor Yelverton
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2020-03-07 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: activesupport
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: 5.0.0
20
+ - - "~>"
21
+ - !ruby/object:Gem::Version
22
+ version: '5.0'
23
+ type: :runtime
24
+ prerelease: false
25
+ version_requirements: !ruby/object:Gem::Requirement
26
+ requirements:
27
+ - - ">="
28
+ - !ruby/object:Gem::Version
29
+ version: 5.0.0
30
+ - - "~>"
31
+ - !ruby/object:Gem::Version
32
+ version: '5.0'
33
+ description: RSpec's missing matchers
34
+ email: rubygems@yelvert.io
35
+ executables: []
36
+ extensions: []
37
+ extra_rdoc_files: []
38
+ files:
39
+ - MIT-LICENSE
40
+ - README.md
41
+ - lib/expected.rb
42
+ - lib/expected/configuration.rb
43
+ - lib/expected/matchers.rb
44
+ - lib/expected/matchers/have_attr_accessor.rb
45
+ - lib/expected/matchers/have_attr_reader.rb
46
+ - lib/expected/matchers/have_attr_writer.rb
47
+ - lib/expected/matchers/have_constant.rb
48
+ - lib/expected/matchers/inherit_from.rb
49
+ - lib/expected/version.rb
50
+ homepage: https://github.com/yelvert/expected
51
+ licenses:
52
+ - MIT
53
+ metadata:
54
+ bug_tracker_uri: https://github.com/yelvert/expected/issues
55
+ changelog_uri: https://github.com/yelvert/expected/commits/master
56
+ documentation_uri: https://github.com/yelvert/expected/wiki
57
+ homepage_uri: https://github.com/yelvert/expected
58
+ source_code_uri: https://github.com/yelvert/expected
59
+ post_install_message:
60
+ rdoc_options: []
61
+ require_paths:
62
+ - lib
63
+ required_ruby_version: !ruby/object:Gem::Requirement
64
+ requirements:
65
+ - - ">="
66
+ - !ruby/object:Gem::Version
67
+ version: 2.4.0
68
+ required_rubygems_version: !ruby/object:Gem::Requirement
69
+ requirements:
70
+ - - ">="
71
+ - !ruby/object:Gem::Version
72
+ version: '0'
73
+ requirements: []
74
+ rubygems_version: 3.0.4
75
+ signing_key:
76
+ specification_version: 4
77
+ summary: RSpec's missing matchers
78
+ test_files: []