neo4j-rspec 0.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: a0ad68a0d597c5eb07fd04204d67753160f3ca37
4
+ data.tar.gz: 10796e7f9d7fd0237f04259862e41173e932378c
5
+ SHA512:
6
+ metadata.gz: 17f1dbc7daaf197cbda8d4c06ce0d6ada2b759a0d1e0bd1399e24894b51702bd67405f3777bbd76823e65a0c2da7252808f50d6756e593635ea2ebc68520695d
7
+ data.tar.gz: 2a455fc7025658b6970828ed7c9f10e84d22cbfa6e5fe5b7e827fc84d7372cc2a1836d43d9662462cee3695053b509f2adac53fc604be11dcc5162443c73d1f0
@@ -0,0 +1,9 @@
1
+ /.bundle/
2
+ /.yardoc
3
+ /Gemfile.lock
4
+ /_yardoc/
5
+ /coverage/
6
+ /doc/
7
+ /pkg/
8
+ /spec/reports/
9
+ /tmp/
data/.rspec ADDED
@@ -0,0 +1 @@
1
+ --color
@@ -0,0 +1,4 @@
1
+ language: ruby
2
+ rvm:
3
+ - 2.2.0
4
+ - 2.3.0
data/Gemfile ADDED
@@ -0,0 +1,8 @@
1
+ source "https://rubygems.org"
2
+
3
+ gemspec
4
+
5
+ group :test do
6
+ gem "rspec"
7
+ gem "pry"
8
+ end
@@ -0,0 +1,21 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2016 Denis Tataurov
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in
13
+ all copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
+ THE SOFTWARE.
@@ -0,0 +1,38 @@
1
+ # Neo4j::Rspec [![Build Status](https://travis-ci.org/sineed/neo4j-rspec.svg?branch=master)](https://travis-ci.org/sineed/neo4j-rspec)
2
+
3
+ ## Examples
4
+
5
+ ```ruby
6
+ subject { ModelClass }
7
+
8
+ # Properties
9
+
10
+ it { is_expected.to define_property :general }
11
+ it { is_expected.to define_property :string, String }
12
+ it { is_expected.to define_property :boolean, Boolean } # This might need to be `ActiveAttr::Typecasting::Boolean`
13
+
14
+ it { is_expected.to have_many(:written_things).with_direction(:in).without_type.with_model_class([:Post, :Comment]) }
15
+
16
+ # etc...
17
+
18
+ # `has_one` and `has_many`
19
+
20
+ it { is_expected.to have_many(:comments) }
21
+ it { is_expected.to have_many(:comments).with_direction(:in) }
22
+ it { is_expected.to have_many(:comments).with_direction(:in).with_origin(:post) }
23
+
24
+ # Constraints
25
+
26
+ it { is_expected.to define_constraint :name, :unique }
27
+
28
+ # `created_at` and `updated_at`
29
+
30
+ it { is_expected.to track_creations } # `created_at`
31
+ it { is_expected.to track_modifications } # `updated_at`
32
+
33
+ ```
34
+
35
+ TODO: Put some examples of usage:
36
+ - [ ] define_index
37
+ - [ ] come_from_model
38
+ - [ ] lead_to_model
@@ -0,0 +1,8 @@
1
+ require "bundler/gem_tasks"
2
+ require "rspec/core/rake_task"
3
+
4
+ task default: :spec
5
+
6
+ RSpec::Core::RakeTask.new(:spec) do |spec|
7
+ spec.pattern = "./spec/**/*_spec.rb"
8
+ end
@@ -0,0 +1,7 @@
1
+ require "neo4j/rspec/matchers"
2
+ require "neo4j/rspec/version"
3
+
4
+ module Neo4j
5
+ module RSpec
6
+ end
7
+ end
@@ -0,0 +1,11 @@
1
+ require "neo4j/rspec/matchers/has_n"
2
+ require "neo4j/rspec/matchers/properties"
3
+
4
+ module Neo4j
5
+ module RSpec
6
+ module Matchers
7
+ include HasN
8
+ include Properties
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,223 @@
1
+ module Neo4j
2
+ module RSpec
3
+ module Matchers
4
+ module HasN
5
+ class BaseMatcher
6
+ attr_reader :matcher, :value, :key, :actual
7
+
8
+ def initialize(matcher, value)
9
+ @matcher = matcher
10
+ @value = convert_value(value)
11
+ end
12
+
13
+ def add
14
+ matcher.expectation_message << expectation_message
15
+ matcher.association[key] = self
16
+ matcher
17
+ end
18
+
19
+ def add_negative
20
+ matcher.expectation_message << negative_expectation_message
21
+ matcher.association[key] = self
22
+ matcher
23
+ end
24
+
25
+ def matches?(actual)
26
+ @actual = extact_actual(actual)
27
+ if matches
28
+ matcher.negative_result_message = result_message
29
+ false
30
+ else
31
+ matcher.positive_result_message = result_message
32
+ true
33
+ end
34
+ end
35
+
36
+ private
37
+
38
+ def matches
39
+ value != actual
40
+ end
41
+
42
+ def convert_value(val)
43
+ val
44
+ end
45
+ end
46
+
47
+ class DirectionMatcher < BaseMatcher
48
+ private
49
+
50
+ def key
51
+ :direction
52
+ end
53
+
54
+ def extact_actual(actual)
55
+ actual.direction
56
+ end
57
+
58
+ def expectation_message
59
+ " with #{value} direction"
60
+ end
61
+
62
+ def result_message
63
+ "#{actual} direction"
64
+ end
65
+ end
66
+
67
+ class TypeMatcher < BaseMatcher
68
+ private
69
+
70
+ def key
71
+ :type
72
+ end
73
+
74
+ def extact_actual(actual)
75
+ actual.relationship_type
76
+ end
77
+
78
+ def expectation_message
79
+ " with #{value} relationship type"
80
+ end
81
+
82
+ def negative_expectation_message
83
+ " without relationship type"
84
+ end
85
+
86
+ def result_message
87
+ "#{actual} relationship type"
88
+ end
89
+ end
90
+
91
+ class OriginMatcher < BaseMatcher
92
+ private
93
+
94
+ def key
95
+ :origin
96
+ end
97
+
98
+ def extact_actual(actual)
99
+ actual.relationship_type
100
+ end
101
+
102
+ def expectation_message
103
+ " with #{value} origin"
104
+ end
105
+
106
+ def result_message
107
+ "#{actual} origin"
108
+ end
109
+ end
110
+
111
+ class ModelClassesMatcher < BaseMatcher
112
+ private
113
+
114
+ def key
115
+ :model_classes
116
+ end
117
+
118
+ def convert_value(val)
119
+ Array(val)
120
+ end
121
+
122
+ def extact_actual(actual)
123
+ Array(actual.model_class)
124
+ end
125
+
126
+ def matches
127
+ (value & actual) != value
128
+ end
129
+
130
+ def expectation_message
131
+ " with #{value.join(", ")} model classes"
132
+ end
133
+
134
+ def result_message
135
+ "#{actual.join(", ")} model classes"
136
+ end
137
+ end
138
+
139
+
140
+ class AssociationMatcher
141
+ attr_accessor :association, :expectation_message, :negative_result_message,
142
+ :positive_result_message
143
+
144
+ def initialize(name, macro)
145
+ @association = {}
146
+ @association[:name] = name.to_sym
147
+ @association[:macro] = macro
148
+ @expectation_message = "#{macro_description} #{@association[:name]}"
149
+ end
150
+
151
+ def macro_description
152
+ case association[:macro]
153
+ when :has_many then "have many"
154
+ when :has_one then "have one"
155
+ end
156
+ end
157
+
158
+ def matchers
159
+ association.select { |_, v| v.is_a? BaseMatcher }
160
+ end
161
+
162
+ def with_direction(direction)
163
+ DirectionMatcher.new(self, direction).add
164
+ end
165
+
166
+ def with_type(type)
167
+ TypeMatcher.new(self, type).add
168
+ end
169
+
170
+ def without_type
171
+ TypeMatcher.new(self, false).add_negative
172
+ end
173
+
174
+ def with_origin(origin)
175
+ OriginMatcher.new(self, origin).add
176
+ end
177
+
178
+ def with_model_class(model_class)
179
+ ModelClassesMatcher.new(self, model_class).add
180
+ end
181
+
182
+ def matches?(actual)
183
+ @actual = actual
184
+ actual_association = actual.class.associations[association[:name]]
185
+
186
+ unless actual_association
187
+ self.negative_result_message = "no association named #{association[:name]}"
188
+ return false
189
+ else
190
+ self.positive_result_message = "association named #{association[:name]}"
191
+ end
192
+
193
+ matchers.each do |_, matcher|
194
+ return false unless matcher.matches?(actual_association)
195
+ end
196
+
197
+ true
198
+ end
199
+
200
+ def failure_message
201
+ "Expected #{@actual.class} to #{expectation_message}, got #{negative_result_message}"
202
+ end
203
+
204
+ def failure_message_when_negated
205
+ "Expected #{@actual.class} to not #{expectation_message}, got #{positive_result_message}"
206
+ end
207
+
208
+ def description
209
+ expectation_message
210
+ end
211
+ end
212
+
213
+ def have_many(association_name)
214
+ AssociationMatcher.new(association_name, :has_many)
215
+ end
216
+
217
+ def have_one(association_name)
218
+ AssociationMatcher.new(association_name, :has_one)
219
+ end
220
+ end
221
+ end
222
+ end
223
+ end
@@ -0,0 +1,65 @@
1
+ require 'rspec/expectations'
2
+
3
+ module Neo4j
4
+ module RSpec
5
+ module Matchers
6
+ module Properties
7
+ extend ::RSpec::Matchers::DSL
8
+
9
+ matcher :track_creations do
10
+ match do |model|
11
+ model.attributes[:created_at] && model.attributes[:created_at][:type] == DateTime
12
+ end
13
+
14
+ failure_message do |model|
15
+ "expected the #{model.name} model to track creations (`created_at`)"
16
+ end
17
+ end
18
+
19
+ matcher :track_modifications do
20
+ match do |model|
21
+ model.attributes[:updated_at] && model.attributes[:updated_at][:type] == DateTime
22
+ end
23
+
24
+ failure_message do |model|
25
+ "expected the #{model.name} model to track modifications (`updated_at`)"
26
+ end
27
+ end
28
+
29
+ matcher :define_property do |name, type = nil|
30
+ match do |model|
31
+ model.attributes.key?(name.to_s) &&
32
+ (type ? model.attributes[name.to_s][:type] == type : true)
33
+ end
34
+
35
+ failure_message do |model|
36
+ "expected the #{model.name} model to have a `#{type}` property #{name}"
37
+ end
38
+
39
+ failure_message_when_negated do |model|
40
+ "expected the #{model.name} model not to have a `#{type}` property #{name}"
41
+ end
42
+ end
43
+
44
+ matcher :define_constraint do |name, type|
45
+ fail ArgumentError, 'constraint name should be given' if name.blank?
46
+ fail ArgumentError, 'constraint type should be given' if type.blank?
47
+
48
+ match do |model|
49
+ model.attributes.key?(name.to_s) &&
50
+ model.attributes[name.to_s][:constraint] == type
51
+ end
52
+
53
+ failure_message do |model|
54
+ "expected the #{model.name} model to have a #{type} constraint on #{name}"
55
+ end
56
+
57
+ failure_message_when_negated do |model|
58
+ "expected the #{model.name} model not to have a #{type} constraint on #{name}"
59
+ end
60
+ end
61
+ end
62
+ end
63
+ end
64
+ end
65
+
@@ -0,0 +1,5 @@
1
+ module Neo4j
2
+ module RSpec
3
+ VERSION = "0.1.0"
4
+ end
5
+ end
@@ -0,0 +1,21 @@
1
+ lib = File.expand_path("../lib", __FILE__)
2
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
3
+ require "neo4j/rspec/version"
4
+
5
+ Gem::Specification.new do |spec|
6
+ spec.name = "neo4j-rspec"
7
+ spec.version = Neo4j::RSpec::VERSION
8
+ spec.authors = ["Denis Tataurov"]
9
+ spec.email = ["sineedus@mail.ru"]
10
+
11
+ spec.summary = "RSpec matchers for Neo4j.rb"
12
+ spec.description = "RSpec matchers for Neo4j.rb"
13
+ spec.homepage = "https://github.com/sineed/neo4j-rspec"
14
+ spec.license = "MIT"
15
+
16
+ spec.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
17
+ spec.require_paths = ["lib"]
18
+
19
+ spec.add_dependency "neo4j", "~> 6"
20
+ spec.add_dependency "rspec", "~> 3.4"
21
+ end
metadata ADDED
@@ -0,0 +1,85 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: neo4j-rspec
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Denis Tataurov
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2016-03-01 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: neo4j
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '6'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '6'
27
+ - !ruby/object:Gem::Dependency
28
+ name: rspec
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '3.4'
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '3.4'
41
+ description: RSpec matchers for Neo4j.rb
42
+ email:
43
+ - sineedus@mail.ru
44
+ executables: []
45
+ extensions: []
46
+ extra_rdoc_files: []
47
+ files:
48
+ - ".gitignore"
49
+ - ".rspec"
50
+ - ".travis.yml"
51
+ - Gemfile
52
+ - LICENSE.txt
53
+ - README.md
54
+ - Rakefile
55
+ - lib/neo4j/rspec.rb
56
+ - lib/neo4j/rspec/matchers.rb
57
+ - lib/neo4j/rspec/matchers/has_n.rb
58
+ - lib/neo4j/rspec/matchers/properties.rb
59
+ - lib/neo4j/rspec/version.rb
60
+ - neo4j-rspec.gemspec
61
+ homepage: https://github.com/sineed/neo4j-rspec
62
+ licenses:
63
+ - MIT
64
+ metadata: {}
65
+ post_install_message:
66
+ rdoc_options: []
67
+ require_paths:
68
+ - lib
69
+ required_ruby_version: !ruby/object:Gem::Requirement
70
+ requirements:
71
+ - - ">="
72
+ - !ruby/object:Gem::Version
73
+ version: '0'
74
+ required_rubygems_version: !ruby/object:Gem::Requirement
75
+ requirements:
76
+ - - ">="
77
+ - !ruby/object:Gem::Version
78
+ version: '0'
79
+ requirements: []
80
+ rubyforge_project:
81
+ rubygems_version: 2.5.1
82
+ signing_key:
83
+ specification_version: 4
84
+ summary: RSpec matchers for Neo4j.rb
85
+ test_files: []