rspec_virtus 1.1.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
+ SHA1:
3
+ metadata.gz: 8cf549d7ff73eca8bdc70f761c478fbf5a0eff85
4
+ data.tar.gz: 9288e5325620c75deff55965f3d65b73c107551a
5
+ SHA512:
6
+ metadata.gz: d88daee24f73e62aa1926736896686586328e8da97081a25a1e763102fd754f3f027ee93165d7c1ea619d8a3651294b7affd9c53e8d482ff9fac2e4c1ea51255
7
+ data.tar.gz: c19e6e567174acce747ce1ed08bec2e6b6b0824903609c906ec5e624f1cbf01c4aec72cc69e5c23cbb0ac40af9c7eb3ac0dba25a069391a50ff1cd9365b136f1
@@ -0,0 +1,18 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ .yardoc
6
+ Gemfile.lock
7
+ InstalledFiles
8
+ _yardoc
9
+ coverage
10
+ doc/
11
+ lib/bundler/man
12
+ pkg
13
+ rdoc
14
+ spec/reports
15
+ test/tmp
16
+ test/version_tmp
17
+ tmp
18
+ .idea
data/.rspec ADDED
@@ -0,0 +1,2 @@
1
+ --color
2
+ --require spec_helper
@@ -0,0 +1,17 @@
1
+ AllCops:
2
+ Include:
3
+ - '**/Rakefile'
4
+ Exclude:
5
+ - 'spec/**/*'
6
+ Style/LineLength:
7
+ Enabled: false
8
+ Style/FileName:
9
+ Enabled: false
10
+ Style/ModuleFunction:
11
+ Enabled: false
12
+ Style/Encoding:
13
+ Enabled: false
14
+ Documentation:
15
+ Enabled: false
16
+ Style/MethodLength:
17
+ Max: 15
@@ -0,0 +1,3 @@
1
+ SimpleCov.start do
2
+ add_filter "/spec/"
3
+ end
@@ -0,0 +1,8 @@
1
+ language: ruby
2
+ rvm:
3
+ - 1.9.3
4
+ - jruby-19mode # JRuby in 1.9 mode
5
+ - rbx-2
6
+ - 2.0.0
7
+ - 2.1
8
+ - 2.2
data/Gemfile ADDED
@@ -0,0 +1,20 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in rspec-virtus.gemspec
4
+ gemspec
5
+
6
+ group :test do
7
+ # additional testing libs
8
+ gem 'simplecov', '>= 0.10.0', require: false
9
+ gem 'coveralls', require: false
10
+ end
11
+
12
+ group :local_development do
13
+ gem 'terminal-notifier-guard', require: false if RUBY_PLATFORM.downcase.include?('darwin')
14
+ gem 'guard-rspec', '>= 4.3.1', require: false
15
+ gem 'guard-bundler', require: false
16
+ gem 'guard-preek', require: false
17
+ gem 'guard-rubocop', require: false
18
+ gem 'guard-reek', github: 'pericles/guard-reek', require: false
19
+ gem 'pry'
20
+ end
@@ -0,0 +1,23 @@
1
+ Copyright (c) 2013 Michael Smith
2
+ Copyright (c) 2015 Alexander Simonov
3
+
4
+ MIT License
5
+
6
+ Permission is hereby granted, free of charge, to any person obtaining
7
+ a copy of this software and associated documentation files (the
8
+ "Software"), to deal in the Software without restriction, including
9
+ without limitation the rights to use, copy, modify, merge, publish,
10
+ distribute, sublicense, and/or sell copies of the Software, and to
11
+ permit persons to whom the Software is furnished to do so, subject to
12
+ the following conditions:
13
+
14
+ The above copyright notice and this permission notice shall be
15
+ included in all copies or substantial portions of the Software.
16
+
17
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
18
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
19
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
20
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
21
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
22
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
23
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,71 @@
1
+ # RSpec::Virtus [![Build Status](https://travis-ci.org/simonoff/rspec_virtus.png?branch=master)](https://travis-ci.org/simonoff/rspec_virtus) [![Code Climate](https://codeclimate.com/github/simonoff/rspec_virtus.png)](https://codeclimate.com/github/simonoff/rspec_virtus)
2
+
3
+ Simple RSpec matchers for your Virtus objects
4
+
5
+ ## Installation
6
+
7
+ Add this line to your application's Gemfile:
8
+
9
+ gem 'rspec_virtus'
10
+
11
+ And then execute:
12
+
13
+ $ bundle
14
+
15
+ Or install it yourself as:
16
+
17
+ $ gem install rspec_virtus
18
+
19
+ ## Usage
20
+
21
+ Here is a sample Virtus object
22
+
23
+ class Post
24
+ include Virtus.model
25
+ attribute :title, String
26
+ attribute :body, String
27
+ attribute :some_default, String, default: 'WOW!'
28
+ attribute :comments, Array[String]
29
+ end
30
+
31
+ And with `rspec_virtus` we can now make simple assertions about these models
32
+
33
+ require 'spec_helper'
34
+
35
+ describe Post
36
+ describe 'attributes' do
37
+ it { is_expected.to have_attribute(:title) }
38
+
39
+ it { is_expected.to have_attribute(:body).of_type(String) }
40
+
41
+ it { is_expected.to have_attribute(:some_default).with_default('WOW!') }
42
+
43
+ it { is_expected.to have_attribute(:comments).of_type(String, member_type: String) }
44
+
45
+ end
46
+ end
47
+
48
+ ## Contributing
49
+
50
+ 1. Fork it
51
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
52
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
53
+ 4. Push to the branch (`git push origin my-new-feature`)
54
+ 5. Create new Pull Request
55
+
56
+ ## Changelog
57
+
58
+ - Version 1.1.0
59
+ - Refactor gem
60
+ - Rename gem
61
+ - Make possibility to use default subject
62
+ - Support for default values
63
+ - Support for required option
64
+
65
+ - Version 1.0.1
66
+ - Remove deprecation notices about legacy matcher syntax
67
+ - Add description to match RSpec 3 matchers
68
+ - Version 1.0.0
69
+ - Upgrade syntax to work with Virtus 1.0.x
70
+ - Version 0.2.0
71
+ - Upgrade to RSpec 3.0
@@ -0,0 +1,20 @@
1
+ require 'bundler/gem_tasks'
2
+ require 'rspec/core/rake_task'
3
+
4
+ RSpec::Core::RakeTask.new(:spec)
5
+
6
+ # rubocop
7
+ require 'rubocop/rake_task'
8
+ RuboCop::RakeTask.new(:rubocop)
9
+
10
+ # reek
11
+ require 'reek/rake/task'
12
+
13
+ Reek::Rake::Task.new do |t|
14
+ t.fail_on_error = false
15
+ t.source_files = Dir['lib/**/*.rb']
16
+ end
17
+
18
+ default_tasks = [:spec, :rubocop, :reek]
19
+
20
+ task default: default_tasks
@@ -0,0 +1,16 @@
1
+ require 'rspec/core'
2
+ require 'rspec_virtus/matcher'
3
+ require 'rspec_virtus/version'
4
+
5
+ module RSpec
6
+ module Virtus
7
+ # rubocop:disable Style/PredicateName
8
+ def have_attribute(attribute_name)
9
+ Matcher.new(attribute_name)
10
+ end
11
+ end
12
+ end
13
+
14
+ RSpec.configure do |config|
15
+ config.include RSpec::Virtus
16
+ end
@@ -0,0 +1,97 @@
1
+ module RSpec
2
+ module Virtus
3
+ class Matcher
4
+ def initialize(attribute_name)
5
+ @attribute_name = attribute_name
6
+ @options = {}
7
+ end
8
+
9
+ def description
10
+ msg = "have attribute #{@attribute_name}"
11
+ msg << ", #{@options[:type]}" if @options[:type]
12
+ msg << ", default: #{@options[:default_value]}" if @options[:default_value]
13
+ msg
14
+ end
15
+
16
+ def of_type(type)
17
+ @options[:type] = type
18
+ self
19
+ end
20
+
21
+ def with_default(default_value)
22
+ @options[:default_value] = default_value
23
+ self
24
+ end
25
+
26
+ def with_required(value)
27
+ @options[:required] = value
28
+ self
29
+ end
30
+
31
+ def matches?(instance)
32
+ @instance = instance
33
+ @subject = instance.class
34
+ attribute_exists? && type_correct? && default_value_correct? && required?
35
+ end
36
+
37
+ def failure_message
38
+ "should #{@attribute_name} to be defined"
39
+ end
40
+
41
+ def failure_message_when_negated
42
+ "should #{@attribute_name} not to be defined"
43
+ end
44
+
45
+ private
46
+
47
+ def attribute
48
+ @subject.attribute_set[@attribute_name]
49
+ end
50
+
51
+ def member_type
52
+ attribute.member_type.primitive
53
+ end
54
+
55
+ def attribute_type
56
+ attribute.primitive
57
+ end
58
+
59
+ def attribute_exists?
60
+ !attribute.nil?
61
+ end
62
+
63
+ def attribute_default_value
64
+ value = attribute.default_value.value
65
+
66
+ case value
67
+ when ::Proc
68
+ value.call(@instance, attribute)
69
+ when ::Symbol
70
+ @instance.__send__(value)
71
+ else
72
+ value
73
+ end
74
+ end
75
+
76
+ def type_correct?
77
+ if @options[:type].is_a?(::Array)
78
+ attribute_type == Array && member_type == @options[:type].first
79
+ elsif @options[:type]
80
+ attribute_type == @options[:type]
81
+ else
82
+ true
83
+ end
84
+ end
85
+
86
+ def default_value_correct?
87
+ return true unless @options[:default_value]
88
+ attribute_default_value == @options[:default_value]
89
+ end
90
+
91
+ def required?
92
+ return true if @options[:required].nil?
93
+ attribute.required? == @options[:required]
94
+ end
95
+ end
96
+ end
97
+ end
@@ -0,0 +1,5 @@
1
+ module RSpec
2
+ module Virtus
3
+ VERSION = '1.1.0'
4
+ end
5
+ end
@@ -0,0 +1,25 @@
1
+ # -*- encoding: utf-8 -*-
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'rspec_virtus/version'
5
+
6
+ Gem::Specification.new do |gem|
7
+ gem.name = 'rspec_virtus'
8
+ gem.version = RSpec::Virtus::VERSION
9
+ gem.authors = ['Michael Smith', 'Alexander Simonov']
10
+ gem.email = ['mike@spokefire.co.uk', 'alex@simonov.me']
11
+ gem.description = 'Simple RSpec matchers for Virtus objects'
12
+ gem.summary = 'Simple RSpec matchers for Virtus objects'
13
+ gem.homepage = 'https://github.com/simonoff/rspec_virtus'
14
+ gem.license = 'MIT'
15
+
16
+ gem.files = `git ls-files`.split($INPUT_RECORD_SEPARATOR)
17
+ gem.executables = gem.files.grep(%r{^bin/}).map { |f| File.basename(f) }
18
+ gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
19
+ gem.require_paths = ['lib']
20
+
21
+ gem.add_dependency 'rspec', '>= 3.0'
22
+ gem.add_dependency 'virtus', '>= 1.0'
23
+
24
+ gem.add_development_dependency 'rake', '~> 10.0.0'
25
+ end
@@ -0,0 +1,29 @@
1
+ require 'spec_helper'
2
+ require 'virtus'
3
+
4
+ class DummyPost
5
+ include Virtus.model
6
+
7
+ attribute :title, String
8
+ attribute :body, String
9
+ attribute :comments, Array[String]
10
+ attribute :greeting, String, default: 'Hello!'
11
+ attribute :default_lambda, String, default: ->(_, _) { 'Wow!' }
12
+ attribute :customs, String, default: :custom_default_via_method
13
+ attribute :some_required, String, default: 'FooBar', required: true
14
+
15
+ def custom_default_via_method
16
+ 'Foo!'
17
+ end
18
+
19
+ end
20
+
21
+ describe ::DummyPost do
22
+ it { is_expected.to have_attribute(:title) }
23
+ it { is_expected.to have_attribute(:body).of_type(String) }
24
+ it { is_expected.to have_attribute(:comments).of_type(Array[String]) }
25
+ it { is_expected.to have_attribute(:greeting).of_type(String).with_default('Hello!') }
26
+ it { is_expected.to have_attribute(:default_lambda).of_type(String).with_default('Wow!') }
27
+ it { is_expected.to have_attribute(:customs).of_type(String).with_default('Foo!') }
28
+ it { is_expected.to have_attribute(:some_required).of_type(String).with_default('FooBar').with_required(true) }
29
+ end
@@ -0,0 +1,166 @@
1
+ require 'spec_helper'
2
+ require 'virtus'
3
+
4
+ describe RSpec::Virtus::Matcher do
5
+ let(:instance) { described_class.new(attribute_name) }
6
+ let(:attribute_name) { :the_attribute }
7
+
8
+ class DummyVirtus
9
+ include Virtus.model
10
+
11
+ attribute :the_attribute, String
12
+ attribute :the_array_attribute, Array[String]
13
+ attribute :the_integer_attribute_with_default, Integer, default: 5
14
+ end
15
+
16
+ describe '#matches?' do
17
+ subject { instance.matches?(actual) }
18
+ let(:actual) { DummyVirtus.new }
19
+
20
+ context 'successful match on attribute name' do
21
+ it { is_expected.to eql(true) }
22
+ end
23
+
24
+ context 'successful match on attribute name and type' do
25
+ before do
26
+ instance.of_type(String)
27
+ end
28
+
29
+ it { is_expected.to eql(true) }
30
+ end
31
+
32
+ context 'successful match on attribute name, type and member_type' do
33
+ let(:attribute_name) { :the_array_attribute }
34
+
35
+ before do
36
+ instance.of_type(Array[String])
37
+ end
38
+
39
+ it { is_expected.to eql(true) }
40
+ end
41
+
42
+ context 'successful match with default value' do
43
+ let(:attribute_name) { :the_integer_attribute_with_default }
44
+ before do
45
+ instance.with_default(5)
46
+ end
47
+ it { is_expected.to eql(true) }
48
+ end
49
+
50
+ context 'successful match with type and default value' do
51
+ let(:attribute_name) { :the_integer_attribute_with_default }
52
+ before do
53
+ instance.of_type(Integer).with_default(5)
54
+ end
55
+ it { is_expected.to eql(true) }
56
+ end
57
+
58
+ context 'unsuccessful match on attribute name' do
59
+ let(:attribute_name) { :something_else }
60
+
61
+ it { is_expected.to eql(false) }
62
+ end
63
+
64
+ context 'unsuccessful match on attribute name and type' do
65
+ let(:attribute_name) { :something_else }
66
+
67
+ before do
68
+ instance.of_type(Integer)
69
+ end
70
+
71
+ it { is_expected.to eql(false) }
72
+ end
73
+
74
+ context 'unsuccessful match on attribute name, type and member_type' do
75
+ let(:attribute_name) { :the_array_attribute }
76
+
77
+ before do
78
+ instance.of_type(Array[Integer])
79
+ end
80
+
81
+ it { is_expected.to eql(false) }
82
+ end
83
+
84
+ context 'unsuccessful match with default value' do
85
+ let(:attribute_name) { :the_integer_attribute_with_default }
86
+ before do
87
+ instance.with_default(-1)
88
+ end
89
+ it { is_expected.to eql(false) }
90
+ end
91
+
92
+ context 'unsuccessful match with type and default value' do
93
+ let(:attribute_name) { :the_integer_attribute_with_default }
94
+ before do
95
+ instance.of_type(Integer).with_default(-5)
96
+ end
97
+ it { is_expected.to eql(false) }
98
+ end
99
+ end
100
+
101
+ describe '#of_type' do
102
+ subject { instance.of_type(String) }
103
+
104
+ it 'returns itsself so it can be chained' do
105
+ expect(subject).to eql(instance)
106
+ end
107
+
108
+ context 'singular values' do
109
+ it 'adds an option to allow the type to be checked' do
110
+ options_type = subject.instance_variable_get(:@options)[:type]
111
+ expect(options_type).to eql(String)
112
+ end
113
+ end
114
+
115
+ context 'arrays of values' do
116
+ subject { instance.of_type(Array[String]) }
117
+
118
+ it 'adds an option to allow the type to be checked' do
119
+ options_type = subject.instance_variable_get(:@options)[:type].class
120
+ expect(options_type).to eql(Array)
121
+ end
122
+
123
+ it 'adds an option to allow the member_type to be checked' do
124
+ member_options_type = subject.instance_variable_get(:@options)[:type].first
125
+ expect(member_options_type).to eql(String)
126
+ end
127
+ end
128
+ end
129
+
130
+ describe '#with_default' do
131
+ subject { instance.with_default('My Default') }
132
+
133
+ it 'returns itsself so it can be chained' do
134
+ expect(subject).to eql(instance)
135
+ end
136
+
137
+ it 'adds an option to allow the default value to be checked' do
138
+ options_default_value = subject.instance_variable_get(:@options)[:default_value]
139
+ expect(options_default_value).to eql('My Default')
140
+ end
141
+ end
142
+
143
+ describe '#description' do
144
+ subject { instance.description }
145
+
146
+ it 'tells you which attribute we are testing' do
147
+ expect(subject).to include(attribute_name.to_s)
148
+ end
149
+ end
150
+
151
+ describe '#failure_message' do
152
+ subject { instance.failure_message }
153
+
154
+ it 'tells you which attribute failed' do
155
+ expect(subject).to include(attribute_name.to_s)
156
+ end
157
+ end
158
+
159
+ describe '#failure_message_when_negated' do
160
+ subject { instance.failure_message_when_negated }
161
+
162
+ it 'tells you which attribute failed' do
163
+ expect(subject).to include(attribute_name.to_s)
164
+ end
165
+ end
166
+ end
@@ -0,0 +1,13 @@
1
+ require 'spec_helper'
2
+
3
+ describe RSpec::Virtus do
4
+ let(:instance) { Class.new { include RSpec::Virtus }.new }
5
+
6
+ describe '#have_attribute' do
7
+ subject { instance.have_attribute(:attribute_name) }
8
+
9
+ it 'returns a new matcher instance' do
10
+ expect(subject).to be_an_instance_of(RSpec::Virtus::Matcher)
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,6 @@
1
+ require 'simplecov'
2
+ require 'rspec_virtus'
3
+
4
+ RSpec.configure do |config|
5
+ config.order = :random
6
+ end
metadata ADDED
@@ -0,0 +1,109 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: rspec_virtus
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Michael Smith
8
+ - Alexander Simonov
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2015-06-02 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: rspec
16
+ requirement: !ruby/object:Gem::Requirement
17
+ requirements:
18
+ - - ">="
19
+ - !ruby/object:Gem::Version
20
+ version: '3.0'
21
+ type: :runtime
22
+ prerelease: false
23
+ version_requirements: !ruby/object:Gem::Requirement
24
+ requirements:
25
+ - - ">="
26
+ - !ruby/object:Gem::Version
27
+ version: '3.0'
28
+ - !ruby/object:Gem::Dependency
29
+ name: virtus
30
+ requirement: !ruby/object:Gem::Requirement
31
+ requirements:
32
+ - - ">="
33
+ - !ruby/object:Gem::Version
34
+ version: '1.0'
35
+ type: :runtime
36
+ prerelease: false
37
+ version_requirements: !ruby/object:Gem::Requirement
38
+ requirements:
39
+ - - ">="
40
+ - !ruby/object:Gem::Version
41
+ version: '1.0'
42
+ - !ruby/object:Gem::Dependency
43
+ name: rake
44
+ requirement: !ruby/object:Gem::Requirement
45
+ requirements:
46
+ - - "~>"
47
+ - !ruby/object:Gem::Version
48
+ version: 10.0.0
49
+ type: :development
50
+ prerelease: false
51
+ version_requirements: !ruby/object:Gem::Requirement
52
+ requirements:
53
+ - - "~>"
54
+ - !ruby/object:Gem::Version
55
+ version: 10.0.0
56
+ description: Simple RSpec matchers for Virtus objects
57
+ email:
58
+ - mike@spokefire.co.uk
59
+ - alex@simonov.me
60
+ executables: []
61
+ extensions: []
62
+ extra_rdoc_files: []
63
+ files:
64
+ - ".gitignore"
65
+ - ".rspec"
66
+ - ".rubocop.yml"
67
+ - ".simplecov"
68
+ - ".travis.yml"
69
+ - Gemfile
70
+ - LICENSE.txt
71
+ - README.md
72
+ - Rakefile
73
+ - lib/rspec_virtus.rb
74
+ - lib/rspec_virtus/matcher.rb
75
+ - lib/rspec_virtus/version.rb
76
+ - rspec_virtus.gemspec
77
+ - spec/acceptance/rspec_virtus_spec.rb
78
+ - spec/lib/rspec_virtus/matcher_spec.rb
79
+ - spec/lib/rspec_virtus_spec.rb
80
+ - spec/spec_helper.rb
81
+ homepage: https://github.com/simonoff/rspec_virtus
82
+ licenses:
83
+ - MIT
84
+ metadata: {}
85
+ post_install_message:
86
+ rdoc_options: []
87
+ require_paths:
88
+ - lib
89
+ required_ruby_version: !ruby/object:Gem::Requirement
90
+ requirements:
91
+ - - ">="
92
+ - !ruby/object:Gem::Version
93
+ version: '0'
94
+ required_rubygems_version: !ruby/object:Gem::Requirement
95
+ requirements:
96
+ - - ">="
97
+ - !ruby/object:Gem::Version
98
+ version: '0'
99
+ requirements: []
100
+ rubyforge_project:
101
+ rubygems_version: 2.4.6
102
+ signing_key:
103
+ specification_version: 4
104
+ summary: Simple RSpec matchers for Virtus objects
105
+ test_files:
106
+ - spec/acceptance/rspec_virtus_spec.rb
107
+ - spec/lib/rspec_virtus/matcher_spec.rb
108
+ - spec/lib/rspec_virtus_spec.rb
109
+ - spec/spec_helper.rb