attribute_matcher 0.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/.gitignore +4 -0
- data/.rubocop.yml +23 -0
- data/.travis.yml +11 -0
- data/Gemfile +4 -0
- data/Gemfile.lock +89 -0
- data/LICENSE.txt +22 -0
- data/README.md +65 -0
- data/Rakefile +8 -0
- data/attribute_matcher.gemspec +30 -0
- data/lib/attribute_matcher.rb +5 -0
- data/lib/attribute_matcher/attribute_matcher.rb +88 -0
- data/lib/attribute_matcher/ext/rspec/chain_group.rb +37 -0
- data/lib/attribute_matcher/ext/rspec/failure_messages.rb +17 -0
- data/lib/attribute_matcher/version.rb +3 -0
- data/spec/lib/have_attribute_matcher/have_attribute_matcher_spec.rb +169 -0
- data/spec/lib/have_attribute_matcher/usage_spec.rb +31 -0
- data/spec/lib/have_attribute_matcher/version_spec.rb +7 -0
- data/spec/spec_helper.rb +26 -0
- metadata +178 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: cd3d45f431f347f663a0632e3836f04782197fb6
|
4
|
+
data.tar.gz: bc6713a711774c046f8c91f2d6bbfd0af6a51af5
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 5613b8387d0ac7cdd62bb1cd1f19d73291e71ff27acdc334acb1d205da57057dd2c70434308c27aed5e1278a5d535f36c4a56a655b85cffe59254cc03803e8af
|
7
|
+
data.tar.gz: 059b516a4758668aa39b8066d804547e3a961b8f81f00de1c292e4257769ac1e55fc145b7047c57064d6f88d86a576059696107b2212f0337cb30f8b4d0539b1
|
data/.gitignore
ADDED
data/.rubocop.yml
ADDED
@@ -0,0 +1,23 @@
|
|
1
|
+
Metrics/LineLength:
|
2
|
+
Enabled: false
|
3
|
+
|
4
|
+
Lint/AmbiguousRegexpLiteral:
|
5
|
+
Enabled: false
|
6
|
+
|
7
|
+
Lint/Eval:
|
8
|
+
Enabled: false
|
9
|
+
|
10
|
+
Style/TrailingComma:
|
11
|
+
EnforcedStyleForMultiline: comma
|
12
|
+
|
13
|
+
Style/EmptyLineBetweenDefs:
|
14
|
+
Enabled: false
|
15
|
+
|
16
|
+
Style/HashSyntax:
|
17
|
+
Enabled: false
|
18
|
+
|
19
|
+
Style/SingleSpaceBeforeFirstArg:
|
20
|
+
Enabled: false
|
21
|
+
|
22
|
+
Style/Documentation:
|
23
|
+
Enabled: false
|
data/.travis.yml
ADDED
data/Gemfile
ADDED
data/Gemfile.lock
ADDED
@@ -0,0 +1,89 @@
|
|
1
|
+
PATH
|
2
|
+
remote: .
|
3
|
+
specs:
|
4
|
+
attribute_matcher (0.0.1)
|
5
|
+
|
6
|
+
GEM
|
7
|
+
remote: https://rubygems.org/
|
8
|
+
specs:
|
9
|
+
ast (2.1.0)
|
10
|
+
astrolabe (1.3.1)
|
11
|
+
parser (~> 2.2)
|
12
|
+
codeclimate-test-reporter (0.4.8)
|
13
|
+
simplecov (>= 0.7.1, < 1.0.0)
|
14
|
+
coveralls (0.8.2)
|
15
|
+
json (~> 1.8)
|
16
|
+
rest-client (>= 1.6.8, < 2)
|
17
|
+
simplecov (~> 0.10.0)
|
18
|
+
term-ansicolor (~> 1.3)
|
19
|
+
thor (~> 0.19.1)
|
20
|
+
diff-lcs (1.2.5)
|
21
|
+
docile (1.1.5)
|
22
|
+
domain_name (0.5.24)
|
23
|
+
unf (>= 0.0.5, < 1.0.0)
|
24
|
+
http-cookie (1.0.2)
|
25
|
+
domain_name (~> 0.5)
|
26
|
+
json (1.8.3)
|
27
|
+
mime-types (2.6.2)
|
28
|
+
netrc (0.10.3)
|
29
|
+
parser (2.2.2.6)
|
30
|
+
ast (>= 1.1, < 3.0)
|
31
|
+
powerpack (0.1.1)
|
32
|
+
rainbow (2.0.0)
|
33
|
+
rake (10.4.2)
|
34
|
+
rest-client (1.8.0)
|
35
|
+
http-cookie (>= 1.0.2, < 2.0)
|
36
|
+
mime-types (>= 1.16, < 3.0)
|
37
|
+
netrc (~> 0.7)
|
38
|
+
rspec (3.3.0)
|
39
|
+
rspec-core (~> 3.3.0)
|
40
|
+
rspec-expectations (~> 3.3.0)
|
41
|
+
rspec-mocks (~> 3.3.0)
|
42
|
+
rspec-core (3.3.2)
|
43
|
+
rspec-support (~> 3.3.0)
|
44
|
+
rspec-expectations (3.3.1)
|
45
|
+
diff-lcs (>= 1.2.0, < 2.0)
|
46
|
+
rspec-support (~> 3.3.0)
|
47
|
+
rspec-its (1.2.0)
|
48
|
+
rspec-core (>= 3.0.0)
|
49
|
+
rspec-expectations (>= 3.0.0)
|
50
|
+
rspec-mocks (3.3.2)
|
51
|
+
diff-lcs (>= 1.2.0, < 2.0)
|
52
|
+
rspec-support (~> 3.3.0)
|
53
|
+
rspec-support (3.3.0)
|
54
|
+
rubocop (0.34.1)
|
55
|
+
astrolabe (~> 1.3)
|
56
|
+
parser (>= 2.2.2.5, < 3.0)
|
57
|
+
powerpack (~> 0.1)
|
58
|
+
rainbow (>= 1.99.1, < 3.0)
|
59
|
+
ruby-progressbar (~> 1.4)
|
60
|
+
ruby-progressbar (1.7.5)
|
61
|
+
simplecov (0.10.0)
|
62
|
+
docile (~> 1.1.0)
|
63
|
+
json (~> 1.8)
|
64
|
+
simplecov-html (~> 0.10.0)
|
65
|
+
simplecov-html (0.10.0)
|
66
|
+
term-ansicolor (1.3.2)
|
67
|
+
tins (~> 1.0)
|
68
|
+
thor (0.19.1)
|
69
|
+
tins (1.6.0)
|
70
|
+
unf (0.1.4)
|
71
|
+
unf_ext
|
72
|
+
unf_ext (0.0.7.1)
|
73
|
+
|
74
|
+
PLATFORMS
|
75
|
+
ruby
|
76
|
+
|
77
|
+
DEPENDENCIES
|
78
|
+
attribute_matcher!
|
79
|
+
bundler (~> 1.7)
|
80
|
+
codeclimate-test-reporter (~> 0.4)
|
81
|
+
coveralls (~> 0.8)
|
82
|
+
rake (~> 10.0)
|
83
|
+
rspec (~> 3.0)
|
84
|
+
rspec-its (~> 1.2)
|
85
|
+
rubocop (~> 0.30)
|
86
|
+
simplecov (~> 0.9)
|
87
|
+
|
88
|
+
BUNDLED WITH
|
89
|
+
1.10.6
|
data/LICENSE.txt
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
Copyright (c) 2015 Declan Whelan
|
2
|
+
|
3
|
+
MIT License
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
6
|
+
a copy of this software and associated documentation files (the
|
7
|
+
"Software"), to deal in the Software without restriction, including
|
8
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
9
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
10
|
+
permit persons to whom the Software is furnished to do so, subject to
|
11
|
+
the following conditions:
|
12
|
+
|
13
|
+
The above copyright notice and this permission notice shall be
|
14
|
+
included in all copies or substantial portions of the Software.
|
15
|
+
|
16
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
17
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
18
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
19
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
20
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
21
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
22
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,65 @@
|
|
1
|
+
[](http://badge.fury.io/rb/attribute_matcher)
|
2
|
+
[](https://travis-ci.org/dwhelan/attribute_matcher)
|
3
|
+
[](https://codeclimate.com/github/dwhelan/attribute_matcher)
|
4
|
+
|
5
|
+
# Attribute Matcher
|
6
|
+
|
7
|
+
An RSpec matcher for validating attributes.
|
8
|
+
|
9
|
+
## Installation
|
10
|
+
|
11
|
+
Add this line to your application's Gemfile:
|
12
|
+
|
13
|
+
```ruby
|
14
|
+
gem 'attribute_matcher'
|
15
|
+
```
|
16
|
+
|
17
|
+
And then execute:
|
18
|
+
|
19
|
+
$ bundle
|
20
|
+
|
21
|
+
Or install it yourself as:
|
22
|
+
|
23
|
+
$ gem install attribute_matcher
|
24
|
+
|
25
|
+
## Usage
|
26
|
+
|
27
|
+
```ruby
|
28
|
+
class Person
|
29
|
+
attr_accessor :name
|
30
|
+
attr_reader :age
|
31
|
+
attr_writer :status
|
32
|
+
|
33
|
+
protected
|
34
|
+
|
35
|
+
attr_accessor :address
|
36
|
+
|
37
|
+
private
|
38
|
+
|
39
|
+
attr_accessor :ssn
|
40
|
+
end
|
41
|
+
|
42
|
+
describe Person do
|
43
|
+
it { is_expected.to have_attribute(:name) }
|
44
|
+
it { is_expected.to have_attribute(:age) }
|
45
|
+
it { is_expected.to have_attribute(:status) }
|
46
|
+
|
47
|
+
it { is_expected.to have_attribute(:name).read_write }
|
48
|
+
it { is_expected.to have_attribute(:age).read_only }
|
49
|
+
it { is_expected.to have_attribute(:status).write_only }
|
50
|
+
|
51
|
+
it { is_expected.to have_attribute(:address).with_reader(:protected) }
|
52
|
+
it { is_expected.to have_attribute(:address).with_writer(:protected) }
|
53
|
+
|
54
|
+
it { is_expected.to have_attribute(:ssn).with_reader(:private) }
|
55
|
+
it { is_expected.to have_attribute(:ssn).with_writer(:private) }
|
56
|
+
end
|
57
|
+
```
|
58
|
+
|
59
|
+
## Contributing
|
60
|
+
|
61
|
+
1. Fork it ( https://github.com/dwhelan/attribute_matcher/fork )
|
62
|
+
2. Create your feature branch (`git checkout -b my-new-feature`)
|
63
|
+
3. Commit your changes (`git commit -am 'Add some feature'`)
|
64
|
+
4. Push to the branch (`git push origin my-new-feature`)
|
65
|
+
5. Create a new Pull Request
|
data/Rakefile
ADDED
@@ -0,0 +1,30 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
|
5
|
+
require 'attribute_matcher/version'
|
6
|
+
|
7
|
+
Gem::Specification.new do |gem|
|
8
|
+
gem.name = 'attribute_matcher'
|
9
|
+
gem.version = HaveAttributeMatcher::VERSION
|
10
|
+
gem.authors = ['Declan Whelan']
|
11
|
+
gem.email = ['declan@pleanintuit.com']
|
12
|
+
gem.summary = 'A matcher for testing object attributes.'
|
13
|
+
gem.description = 'A matcher for testing object attributes.'
|
14
|
+
gem.homepage = 'https://github.com/dwhelan/attribute_matcher'
|
15
|
+
gem.license = 'MIT'
|
16
|
+
|
17
|
+
gem.files = `git ls-files -z`.split("\x0")
|
18
|
+
gem.executables = gem.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
19
|
+
gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
|
20
|
+
gem.require_paths = ['lib']
|
21
|
+
|
22
|
+
gem.add_development_dependency 'bundler', '~> 1.7'
|
23
|
+
gem.add_development_dependency 'codeclimate-test-reporter', '~> 0.4'
|
24
|
+
gem.add_development_dependency 'coveralls', '~> 0.8'
|
25
|
+
gem.add_development_dependency 'rake', '~> 10.0'
|
26
|
+
gem.add_development_dependency 'rspec', '~> 3.0'
|
27
|
+
gem.add_development_dependency 'rspec-its', '~> 1.2'
|
28
|
+
gem.add_development_dependency 'rubocop', '~> 0.30'
|
29
|
+
gem.add_development_dependency 'simplecov', '~> 0.9'
|
30
|
+
end
|
@@ -0,0 +1,88 @@
|
|
1
|
+
RSpec::Matchers.define(:have_attribute) do
|
2
|
+
match do
|
3
|
+
exists? && access_match? && visibility_match?(:reader) && visibility_match?(:writer)
|
4
|
+
end
|
5
|
+
|
6
|
+
chain_group :access, :read_only, :write_only, :read_write
|
7
|
+
|
8
|
+
chain(:with_reader) { |visibility| @reader_visibility = ensure_valid_visibility(visibility) }
|
9
|
+
chain(:with_writer) { |visibility| @writer_visibility = ensure_valid_visibility(visibility) }
|
10
|
+
|
11
|
+
private
|
12
|
+
|
13
|
+
def exists?
|
14
|
+
reader || writer
|
15
|
+
end
|
16
|
+
|
17
|
+
def read_only_match?
|
18
|
+
reader_ok? && writer.nil?
|
19
|
+
end
|
20
|
+
|
21
|
+
def write_only_match?
|
22
|
+
writer_ok? && reader.nil?
|
23
|
+
end
|
24
|
+
|
25
|
+
def read_write_match?
|
26
|
+
reader_ok? && writer_ok?
|
27
|
+
end
|
28
|
+
|
29
|
+
def reader_ok?
|
30
|
+
reader && reader.arity.eql?(0)
|
31
|
+
end
|
32
|
+
|
33
|
+
def writer_ok?
|
34
|
+
writer && writer.arity.eql?(1)
|
35
|
+
end
|
36
|
+
|
37
|
+
def reader
|
38
|
+
method(expected)
|
39
|
+
end
|
40
|
+
|
41
|
+
def writer
|
42
|
+
method("#{expected}=")
|
43
|
+
end
|
44
|
+
|
45
|
+
def method(name)
|
46
|
+
actual.method(name)
|
47
|
+
rescue NameError
|
48
|
+
nil
|
49
|
+
end
|
50
|
+
|
51
|
+
failure_messages do
|
52
|
+
[
|
53
|
+
arity_failure_message(reader, 0),
|
54
|
+
arity_failure_message(writer, 1),
|
55
|
+
]
|
56
|
+
end
|
57
|
+
|
58
|
+
def arity_failure_message(method, expected_arity)
|
59
|
+
format('%s() takes %d argument%s instead of %d', method.name, method.arity, method.arity == 1 ? '' : 's', expected_arity) if method && method.arity != expected_arity
|
60
|
+
end
|
61
|
+
|
62
|
+
def visibility_match?(accessor)
|
63
|
+
method = accessor == :reader ? reader : writer
|
64
|
+
expected_visibility = instance_variable_get(:"@#{accessor}_visibility")
|
65
|
+
|
66
|
+
method.nil? || expected_visibility.nil? || expected_visibility == visibility(method)
|
67
|
+
end
|
68
|
+
|
69
|
+
def visibility(method)
|
70
|
+
klass = method.receiver.class
|
71
|
+
|
72
|
+
case
|
73
|
+
when klass.private_method_defined?(method.name)
|
74
|
+
:private
|
75
|
+
when klass.protected_method_defined?(method.name)
|
76
|
+
:protected
|
77
|
+
else
|
78
|
+
:public
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
82
|
+
VALID_VISIBILITIES ||= [:private, :protected, :public]
|
83
|
+
|
84
|
+
def ensure_valid_visibility(visibility)
|
85
|
+
fail format('%s is an invalid visibility; should be one of %s', visibility, VALID_VISIBILITIES.join(', ')) unless VALID_VISIBILITIES.include?(visibility)
|
86
|
+
visibility
|
87
|
+
end
|
88
|
+
end
|
@@ -0,0 +1,37 @@
|
|
1
|
+
# An RSpec extension for mutually exclusive chained methods
|
2
|
+
module RSpec
|
3
|
+
module Matchers
|
4
|
+
module DSL
|
5
|
+
class Matcher
|
6
|
+
class << self
|
7
|
+
def chain_group(group_name, *method_names)
|
8
|
+
create_match_method(group_name, *method_names)
|
9
|
+
create_description_method(group_name, method_names)
|
10
|
+
chain_methods(method_names)
|
11
|
+
end
|
12
|
+
|
13
|
+
private
|
14
|
+
|
15
|
+
def create_match_method(group_name, *method_names)
|
16
|
+
define_method :"#{group_name}_match?" do
|
17
|
+
active_method_name = method_names.find { |method_name| instance_variable_get("@#{method_name}") }
|
18
|
+
active_method_name ? send("#{active_method_name}_match?") : true
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
def create_description_method(group_name, method_names)
|
23
|
+
define_method :"#{group_name}_description" do
|
24
|
+
method_names.find { |method_name| instance_variable_get("@#{method_name}") }.to_s.gsub(%r{[_/]}, ' ')
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
def chain_methods(method_names)
|
29
|
+
method_names.each do |method_name|
|
30
|
+
chain(method_name) { instance_variable_set("@#{method_name}", true) }
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
# An RSpec extension for building failure messages
|
2
|
+
module RSpec
|
3
|
+
module Matchers
|
4
|
+
module DSL
|
5
|
+
class Matcher
|
6
|
+
class << self
|
7
|
+
def failure_messages(&block)
|
8
|
+
define_method :failure_message do
|
9
|
+
failures = instance_eval(&block).compact.join(' and ')
|
10
|
+
[super(), failures].join(' but ')
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,169 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
shared_context 'matcher messages' do
|
4
|
+
let(:matcher) { self.class.parent_groups[1].description }
|
5
|
+
subject { eval matcher }
|
6
|
+
before { subject.matches? klass.new }
|
7
|
+
end
|
8
|
+
|
9
|
+
describe 'have_attribute matcher' do
|
10
|
+
subject { klass.new }
|
11
|
+
|
12
|
+
describe 'basic attributes' do
|
13
|
+
let(:klass) do
|
14
|
+
Class.new do
|
15
|
+
attr_reader :r
|
16
|
+
attr_writer :w
|
17
|
+
attr_accessor :rw
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
describe 'attr_reader :r' do
|
22
|
+
it { is_expected.to have_attribute(:r) }
|
23
|
+
it { is_expected.to have_attribute(:r).read_only }
|
24
|
+
it { is_expected.not_to have_attribute(:r).write_only }
|
25
|
+
it { is_expected.not_to have_attribute(:r).read_write }
|
26
|
+
end
|
27
|
+
|
28
|
+
describe 'attr_writer :w' do
|
29
|
+
it { is_expected.to have_attribute(:w) }
|
30
|
+
it { is_expected.to have_attribute(:w).write_only }
|
31
|
+
it { is_expected.not_to have_attribute(:w).read_only }
|
32
|
+
it { is_expected.not_to have_attribute(:w).read_write }
|
33
|
+
end
|
34
|
+
|
35
|
+
describe 'attr_accessor :rw' do
|
36
|
+
it { is_expected.to have_attribute(:rw) }
|
37
|
+
it { is_expected.to have_attribute(:rw).read_write }
|
38
|
+
it { is_expected.not_to have_attribute(:rw).read_only }
|
39
|
+
it { is_expected.not_to have_attribute(:rw).write_only }
|
40
|
+
end
|
41
|
+
|
42
|
+
it_behaves_like 'matcher messages' do
|
43
|
+
{
|
44
|
+
:'have_attribute(:name)' => 'have attribute :name',
|
45
|
+
:'have_attribute(:name).read_only' => 'have attribute :name read only',
|
46
|
+
:'have_attribute(:name).write_only' => 'have attribute :name write only',
|
47
|
+
:'have_attribute(:name).read_write' => 'have attribute :name read write',
|
48
|
+
:'have_attribute(:rw).read_only' => 'have attribute :rw read only',
|
49
|
+
:'have_attribute(:rw).write_only' => 'have attribute :rw write only',
|
50
|
+
:'have_attribute(:w).read_only' => 'have attribute :w read only',
|
51
|
+
:'have_attribute(:r).write_only' => 'have attribute :r write only',
|
52
|
+
}.each do |expectation, expected_description|
|
53
|
+
describe(expectation) do
|
54
|
+
its(:description) { is_expected.to eql expected_description }
|
55
|
+
its(:failure_message) { is_expected.to match /expected .+ to #{expected_description}/ }
|
56
|
+
its(:failure_message_when_negated) { is_expected.to match /expected .+ not to #{expected_description}/ }
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
{
|
61
|
+
:'have_attribute(:rw)' => 'expected .+ not to have attribute :rw',
|
62
|
+
:'have_attribute(:r).read_only' => 'expected .+ not to have attribute :r read only',
|
63
|
+
:'have_attribute(:w).write_only' => 'expected .+ not to have attribute :w write only',
|
64
|
+
}.each do |expectation, expected_description|
|
65
|
+
describe(expectation) do
|
66
|
+
its(:failure_message_when_negated) { is_expected.to match /#{expected_description}/ }
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
context 'have_attribute(:rw)' do
|
71
|
+
its(:failure_message_when_negated) { is_expected.to match /not to have attribute :rw/ }
|
72
|
+
end
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
76
|
+
describe 'method arity' do
|
77
|
+
let(:klass) do
|
78
|
+
Class.new do
|
79
|
+
def no_args=; end
|
80
|
+
|
81
|
+
def one_arg(_); end
|
82
|
+
|
83
|
+
def two_args(_arg1, _arg2); end
|
84
|
+
def two_args=(_arg1, _arg2); end
|
85
|
+
end
|
86
|
+
end
|
87
|
+
|
88
|
+
describe 'reader should take no arguments' do
|
89
|
+
it { is_expected.not_to have_attribute(:one_arg).read_only }
|
90
|
+
end
|
91
|
+
|
92
|
+
describe 'writer should take one argument' do
|
93
|
+
it { is_expected.not_to have_attribute(:no_args=).write_only }
|
94
|
+
it { is_expected.not_to have_attribute(:two_args=).write_only }
|
95
|
+
end
|
96
|
+
|
97
|
+
it_behaves_like 'matcher messages' do
|
98
|
+
{
|
99
|
+
:'have_attribute(:no_args).write_only' => 'have attribute :no_args write only but no_args=\(\) takes 0 arguments instead of 1',
|
100
|
+
:'have_attribute(:one_arg).read_only' => 'have attribute :one_arg read only but one_arg\(\) takes 1 argument instead of 0',
|
101
|
+
:'have_attribute(:two_args)' => 'have attribute :two_args but two_args\(\) takes 2 arguments instead of 0 and two_args=\(\) takes 2 arguments instead of 1',
|
102
|
+
}.each do |expectation, expected_description|
|
103
|
+
describe(expectation) do
|
104
|
+
its(:failure_message) { is_expected.to match /expected .+ to #{expected_description}/ }
|
105
|
+
end
|
106
|
+
end
|
107
|
+
end
|
108
|
+
end
|
109
|
+
|
110
|
+
describe 'method visibility' do
|
111
|
+
let(:klass) do
|
112
|
+
Class.new do
|
113
|
+
def public_reader; end
|
114
|
+
def public_writer=(_); end
|
115
|
+
|
116
|
+
protected
|
117
|
+
|
118
|
+
def protected_reader; end
|
119
|
+
def protected_writer=(_); end
|
120
|
+
|
121
|
+
private
|
122
|
+
|
123
|
+
def private_reader; end
|
124
|
+
def private_writer=(_); end
|
125
|
+
end
|
126
|
+
end
|
127
|
+
|
128
|
+
[:private, :protected, :public].each do |visibility|
|
129
|
+
[:private, :protected, :public].each do |prefix|
|
130
|
+
if visibility == prefix
|
131
|
+
it { is_expected.to have_attribute(:"#{prefix}_reader").with_reader(visibility) }
|
132
|
+
it { is_expected.to have_attribute(:"#{prefix}_writer").with_writer(visibility) }
|
133
|
+
else
|
134
|
+
it { is_expected.not_to have_attribute(:"#{prefix}_reader").with_reader(visibility) }
|
135
|
+
it { is_expected.not_to have_attribute(:"#{prefix}_writer").with_writer(visibility) }
|
136
|
+
end
|
137
|
+
it { is_expected.not_to have_attribute(:missing).with_reader(visibility) }
|
138
|
+
it { is_expected.not_to have_attribute(:missing).with_writer(visibility) }
|
139
|
+
end
|
140
|
+
end
|
141
|
+
|
142
|
+
it_behaves_like 'matcher messages' do
|
143
|
+
{
|
144
|
+
:'have_attribute(:private_reader).with_reader(:private)' => 'have attribute :private_reader with reader :private',
|
145
|
+
:'have_attribute(:protected_reader).with_reader(:protected)' => 'have attribute :protected_reader with reader :protected',
|
146
|
+
:'have_attribute(:public_reader).with_reader(:public)' => 'have attribute :public_reader with reader :public',
|
147
|
+
|
148
|
+
}.each do |expectation, expected_description|
|
149
|
+
describe(expectation) do
|
150
|
+
its(:description) { is_expected.to eql expected_description }
|
151
|
+
its(:failure_message) { is_expected.to match /expected .+ to #{expected_description}/ }
|
152
|
+
its(:failure_message_when_negated) { is_expected.to match /expected .+ not to #{expected_description}/ }
|
153
|
+
end
|
154
|
+
end
|
155
|
+
end
|
156
|
+
|
157
|
+
it 'should fail if the reader visibility is invalid' do
|
158
|
+
expect { have_attribute(:private_reader).with_reader(:foo) }.to raise_error do |error|
|
159
|
+
expect(error.message).to match /foo is an invalid visibility; should be one of private, protected, public/
|
160
|
+
end
|
161
|
+
end
|
162
|
+
|
163
|
+
it 'should fail if the write visibility is invalid' do
|
164
|
+
expect { have_attribute(:private_writer).with_writer(:foo) }.to raise_error do |error|
|
165
|
+
expect(error.message).to match /foo is an invalid visibility; should be one of private, protected, public/
|
166
|
+
end
|
167
|
+
end
|
168
|
+
end
|
169
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
class Person
|
4
|
+
attr_accessor :name
|
5
|
+
attr_reader :age
|
6
|
+
attr_writer :status
|
7
|
+
|
8
|
+
protected
|
9
|
+
|
10
|
+
attr_accessor :address
|
11
|
+
|
12
|
+
private
|
13
|
+
|
14
|
+
attr_accessor :ssn
|
15
|
+
end
|
16
|
+
|
17
|
+
describe Person do
|
18
|
+
it { is_expected.to have_attribute(:name) }
|
19
|
+
it { is_expected.to have_attribute(:age) }
|
20
|
+
it { is_expected.to have_attribute(:status) }
|
21
|
+
|
22
|
+
it { is_expected.to have_attribute(:name).read_write }
|
23
|
+
it { is_expected.to have_attribute(:age).read_only }
|
24
|
+
it { is_expected.to have_attribute(:status).write_only }
|
25
|
+
|
26
|
+
it { is_expected.to have_attribute(:address).with_reader(:protected) }
|
27
|
+
it { is_expected.to have_attribute(:address).with_writer(:protected) }
|
28
|
+
|
29
|
+
it { is_expected.to have_attribute(:ssn).with_reader(:private) }
|
30
|
+
it { is_expected.to have_attribute(:ssn).with_writer(:private) }
|
31
|
+
end
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,26 @@
|
|
1
|
+
require 'codeclimate-test-reporter'
|
2
|
+
CodeClimate::TestReporter.start
|
3
|
+
|
4
|
+
require 'rspec'
|
5
|
+
require 'rspec/its'
|
6
|
+
require 'coveralls'
|
7
|
+
require 'simplecov'
|
8
|
+
|
9
|
+
SimpleCov.formatter = SimpleCov::Formatter::MultiFormatter[
|
10
|
+
SimpleCov::Formatter::HTMLFormatter,
|
11
|
+
Coveralls::SimpleCov::Formatter
|
12
|
+
]
|
13
|
+
SimpleCov.start
|
14
|
+
|
15
|
+
Coveralls.wear!
|
16
|
+
|
17
|
+
RSpec.configure do |config|
|
18
|
+
config.color = true
|
19
|
+
config.filter_run focus: true
|
20
|
+
config.run_all_when_everything_filtered = true
|
21
|
+
config.expect_with :rspec do |expectations|
|
22
|
+
expectations.include_chain_clauses_in_custom_matcher_descriptions = true
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
require 'attribute_matcher'
|
metadata
ADDED
@@ -0,0 +1,178 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: attribute_matcher
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.1
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Declan Whelan
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2015-09-21 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: bundler
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '1.7'
|
20
|
+
type: :development
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - "~>"
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '1.7'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: codeclimate-test-reporter
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - "~>"
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '0.4'
|
34
|
+
type: :development
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - "~>"
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '0.4'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: coveralls
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - "~>"
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '0.8'
|
48
|
+
type: :development
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - "~>"
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '0.8'
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: rake
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - "~>"
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '10.0'
|
62
|
+
type: :development
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - "~>"
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '10.0'
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
name: rspec
|
71
|
+
requirement: !ruby/object:Gem::Requirement
|
72
|
+
requirements:
|
73
|
+
- - "~>"
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
version: '3.0'
|
76
|
+
type: :development
|
77
|
+
prerelease: false
|
78
|
+
version_requirements: !ruby/object:Gem::Requirement
|
79
|
+
requirements:
|
80
|
+
- - "~>"
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: '3.0'
|
83
|
+
- !ruby/object:Gem::Dependency
|
84
|
+
name: rspec-its
|
85
|
+
requirement: !ruby/object:Gem::Requirement
|
86
|
+
requirements:
|
87
|
+
- - "~>"
|
88
|
+
- !ruby/object:Gem::Version
|
89
|
+
version: '1.2'
|
90
|
+
type: :development
|
91
|
+
prerelease: false
|
92
|
+
version_requirements: !ruby/object:Gem::Requirement
|
93
|
+
requirements:
|
94
|
+
- - "~>"
|
95
|
+
- !ruby/object:Gem::Version
|
96
|
+
version: '1.2'
|
97
|
+
- !ruby/object:Gem::Dependency
|
98
|
+
name: rubocop
|
99
|
+
requirement: !ruby/object:Gem::Requirement
|
100
|
+
requirements:
|
101
|
+
- - "~>"
|
102
|
+
- !ruby/object:Gem::Version
|
103
|
+
version: '0.30'
|
104
|
+
type: :development
|
105
|
+
prerelease: false
|
106
|
+
version_requirements: !ruby/object:Gem::Requirement
|
107
|
+
requirements:
|
108
|
+
- - "~>"
|
109
|
+
- !ruby/object:Gem::Version
|
110
|
+
version: '0.30'
|
111
|
+
- !ruby/object:Gem::Dependency
|
112
|
+
name: simplecov
|
113
|
+
requirement: !ruby/object:Gem::Requirement
|
114
|
+
requirements:
|
115
|
+
- - "~>"
|
116
|
+
- !ruby/object:Gem::Version
|
117
|
+
version: '0.9'
|
118
|
+
type: :development
|
119
|
+
prerelease: false
|
120
|
+
version_requirements: !ruby/object:Gem::Requirement
|
121
|
+
requirements:
|
122
|
+
- - "~>"
|
123
|
+
- !ruby/object:Gem::Version
|
124
|
+
version: '0.9'
|
125
|
+
description: A matcher for testing object attributes.
|
126
|
+
email:
|
127
|
+
- declan@pleanintuit.com
|
128
|
+
executables: []
|
129
|
+
extensions: []
|
130
|
+
extra_rdoc_files: []
|
131
|
+
files:
|
132
|
+
- ".gitignore"
|
133
|
+
- ".rubocop.yml"
|
134
|
+
- ".travis.yml"
|
135
|
+
- Gemfile
|
136
|
+
- Gemfile.lock
|
137
|
+
- LICENSE.txt
|
138
|
+
- README.md
|
139
|
+
- Rakefile
|
140
|
+
- attribute_matcher.gemspec
|
141
|
+
- lib/attribute_matcher.rb
|
142
|
+
- lib/attribute_matcher/attribute_matcher.rb
|
143
|
+
- lib/attribute_matcher/ext/rspec/chain_group.rb
|
144
|
+
- lib/attribute_matcher/ext/rspec/failure_messages.rb
|
145
|
+
- lib/attribute_matcher/version.rb
|
146
|
+
- spec/lib/have_attribute_matcher/have_attribute_matcher_spec.rb
|
147
|
+
- spec/lib/have_attribute_matcher/usage_spec.rb
|
148
|
+
- spec/lib/have_attribute_matcher/version_spec.rb
|
149
|
+
- spec/spec_helper.rb
|
150
|
+
homepage: https://github.com/dwhelan/attribute_matcher
|
151
|
+
licenses:
|
152
|
+
- MIT
|
153
|
+
metadata: {}
|
154
|
+
post_install_message:
|
155
|
+
rdoc_options: []
|
156
|
+
require_paths:
|
157
|
+
- lib
|
158
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
159
|
+
requirements:
|
160
|
+
- - ">="
|
161
|
+
- !ruby/object:Gem::Version
|
162
|
+
version: '0'
|
163
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
164
|
+
requirements:
|
165
|
+
- - ">="
|
166
|
+
- !ruby/object:Gem::Version
|
167
|
+
version: '0'
|
168
|
+
requirements: []
|
169
|
+
rubyforge_project:
|
170
|
+
rubygems_version: 2.4.5
|
171
|
+
signing_key:
|
172
|
+
specification_version: 4
|
173
|
+
summary: A matcher for testing object attributes.
|
174
|
+
test_files:
|
175
|
+
- spec/lib/have_attribute_matcher/have_attribute_matcher_spec.rb
|
176
|
+
- spec/lib/have_attribute_matcher/usage_spec.rb
|
177
|
+
- spec/lib/have_attribute_matcher/version_spec.rb
|
178
|
+
- spec/spec_helper.rb
|