neo4j-rspec 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -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: []