dolly 3.0.0 → 3.1.2

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,273 @@
1
+ require 'test_helper'
2
+
3
+ class FooBar < BaseDolly
4
+ property :foo, :bar
5
+ property :with_default, default: 1
6
+ property :boolean, class_name: TrueClass, default: true
7
+ property :date, class_name: Date
8
+ property :time, class_name: Time
9
+ property :datetime, class_name: DateTime
10
+ property :is_nil, class_name: NilClass, default: nil
11
+
12
+ timestamps!
13
+ end
14
+
15
+ class FooBarTyped < BaseDolly
16
+ typed_model
17
+ end
18
+
19
+ class MangoTest < Test::Unit::TestCase
20
+ DB_BASE_PATH = "http://localhost:5984/test".freeze
21
+
22
+ def setup
23
+ data = {foo: 'Foo', bar: 'Bar', type: 'foo_bar'}
24
+
25
+ all_docs = [ {foo: 'Foo B', bar: 'Bar B', type: 'foo_bar'}, {foo: 'Foo A', bar: 'Bar A', type: 'foo_bar'}]
26
+
27
+ view_resp = build_view_response [data]
28
+ empty_resp = build_view_response []
29
+ not_found_resp = generic_response [{ key: "foo_bar/2", error: "not_found" }]
30
+ @multi_resp = build_view_response all_docs
31
+ @multi_type_resp = build_view_collation_response all_docs
32
+
33
+ build_request [["foo_bar","1"]], view_resp
34
+ build_request [["foo_bar","2"]], empty_resp
35
+ build_request [["foo_bar","1"],["foo_bar","2"]], @multi_resp
36
+
37
+ stub_request(:get, "#{query_base_path}?startkey=%22foo_bar%2F%22&endkey=%22foo_bar%2F%EF%BF%B0%22&include_docs=true").
38
+ to_return(body: @multi_resp.to_json)
39
+
40
+ stub_request(:get, "#{all_docs_path}?key=\"index_foo\"").
41
+ to_return(body: {
42
+ total_rows: 2,
43
+ offset: 0,
44
+ rows: [{
45
+ id: '_design/index_foo',
46
+ key: '_design/index_foo',
47
+ value: { rev: '1-c5457a0d26da85f15c4ad6bd739e441d' }
48
+ }]}.to_json)
49
+
50
+ stub_request(:get, "#{all_docs_path}?key=\"index_date\"").
51
+ to_return(body: {
52
+ total_rows: 2,
53
+ offset: 0,
54
+ rows: []}.to_json)
55
+ end
56
+
57
+ test '#find_by' do
58
+ #TODO: clean up all the fake request creation
59
+ resp = { docs: [{ foo: 'bar', id: "foo_bar/1"} ] }
60
+
61
+ stub_request(:post, query_base_path).
62
+ to_return(body: resp.to_json)
63
+
64
+ key = 'foo'
65
+ stub_request(:get, "#{all_docs_path}?key=\"_design/index_#{key}\"").
66
+ to_return(body: index_response(key).to_json)
67
+
68
+ assert_equal(FooBar.find_by(foo: 'bar').class, FooBar)
69
+ end
70
+
71
+ test '#find_by for a property that does not have an index' do
72
+ #TODO: clean up all the fake request creation
73
+ resp = { docs: [{ foo: 'bar', id: "foo_bar/1"} ] }
74
+ key = 'date'
75
+
76
+ stub_request(:post, query_base_path).
77
+ to_return(body: resp.to_json)
78
+
79
+ stub_request(:get, "#{all_docs_path}?key=\"_design/index_#{key}\"").
80
+ to_return(body: { rows: [] }.to_json)
81
+
82
+ assert_raise Dolly::IndexNotFoundError do
83
+ FooBar.find_by(date: Date.today)
84
+ end
85
+ end
86
+
87
+ test '#find_by with no returned data' do
88
+ resp = { docs: [] }
89
+
90
+ stub_request(:post, query_base_path).
91
+ to_return(body: resp.to_json)
92
+
93
+ key = 'foo'
94
+ stub_request(:get, "#{all_docs_path}?key=\"_design/index_#{key}\"").
95
+ to_return(body: index_response(key).to_json)
96
+
97
+ assert_equal(FooBar.find_by(foo: 'bar'), nil)
98
+ end
99
+
100
+ test '#find_doc_by' do
101
+ #TODO: clean up all the fake request creation
102
+ resp = { docs: [{ foo: 'bar', id: "foo_bar/1"} ] }
103
+
104
+ stub_request(:post, query_base_path).
105
+ to_return(body: resp.to_json)
106
+
107
+ key = 'foo'
108
+ stub_request(:get, "#{all_docs_path}?key=\"_design/index_#{key}\"").
109
+ to_return(body: index_response(key).to_json)
110
+
111
+ assert_equal(FooBar.find_doc_by(foo: 'bar').class, Hash)
112
+ end
113
+
114
+ test '#where' do
115
+ #TODO: clean up all the fake request creation
116
+ resp = { docs: [{ foo: 'bar', id: "foo_bar/1"} ] }
117
+
118
+ stub_request(:post, query_base_path).
119
+ to_return(body: resp.to_json)
120
+
121
+ key = 'foo'
122
+ stub_request(:get, "#{all_docs_path}?key=\"_design/index_#{key}\"").
123
+ to_return(body: index_response(key).to_json)
124
+
125
+ assert_equal(FooBar.where(foo: { eq: 'bar' }).map(&:class).uniq, [FooBar])
126
+ end
127
+
128
+ test '#where for a property that does not have an index' do
129
+ #TODO: clean up all the fake request creation
130
+ resp = { docs: [{ foo: 'bar', id: "foo_bar/1"} ] }
131
+
132
+ stub_request(:post, query_base_path).
133
+ to_return(body: resp.to_json)
134
+
135
+ key = 'date'
136
+ stub_request(:get, "#{all_docs_path}?key=\"_design/index_#{key}\"").
137
+ to_return(body: { rows: [] }.to_json)
138
+
139
+ assert_raise Dolly::IndexNotFoundError do
140
+ FooBar.where(date: Date.today)
141
+ end
142
+ end
143
+
144
+ test '#where with no returned data' do
145
+ resp = { docs: [] }
146
+
147
+ stub_request(:post, query_base_path).
148
+ to_return(body: resp.to_json)
149
+
150
+ key = 'foo'
151
+ stub_request(:get, "#{all_docs_path}?key=\"_design/index_#{key}\"").
152
+ to_return(body: index_response(key).to_json)
153
+
154
+ assert_equal(FooBar.where(foo: 'bar'), [])
155
+ end
156
+
157
+ test '#docs_where' do
158
+ #TODO: clean up all the fake request creation
159
+ resp = { docs: [{ foo: 'bar', id: "foo_bar/1"} ] }
160
+
161
+ stub_request(:post, query_base_path).
162
+ to_return(body: resp.to_json)
163
+
164
+ key = 'foo'
165
+ stub_request(:get, "#{all_docs_path}?key=\"_design/index_#{key}\"").
166
+ to_return(body: index_response(key).to_json)
167
+
168
+ assert_equal(FooBar.docs_where(foo: { eq: 'bar' }).map(&:class).uniq, [Hash])
169
+ end
170
+
171
+ test '#build_query' do
172
+ query = { and: [{ _id: { eq: 'foo_bar/1' } } , { foo: { eq: 'bar'}} ] }
173
+ opts = {}
174
+ expected = {"selector"=>{"$and"=>[{:_id=>{"$eq"=>"foo_bar/1"}}, {:foo=>{"$eq"=>"bar"}}]}}
175
+
176
+ assert_equal(FooBar.send(:build_query, query, opts), expected)
177
+ end
178
+
179
+ test '#build_query with options' do
180
+ query = { and: [{ _id: { eq: 'foo_bar/1' } } , { foo: { eq: 'bar'}} ] }
181
+ opts = { limit: 1, fields: ['foo']}
182
+ expected = {"selector"=>{"$and"=>[{:_id=>{"$eq"=>"foo_bar/1"}}, {:foo=>{"$eq"=>"bar"}}]}, limit: 1, fields: ['foo']}
183
+
184
+ assert_equal(FooBar.send(:build_query, query, opts), expected)
185
+ end
186
+
187
+ test '#build_selectors with invalid operator' do
188
+ query = { _id: { eeeq: 'foo_bar/1' } }
189
+
190
+ assert_raise Dolly::InvalidMangoOperatorError do
191
+ FooBar.send(:build_selectors, query)
192
+ end
193
+ end
194
+
195
+ test '#build_selectors with type operator' do
196
+ query = { _id: { type: "user" } }
197
+
198
+ assert_nothing_raised Dolly::InvalidMangoOperatorError do
199
+ FooBarTyped.send(:build_selectors, query)
200
+ end
201
+ end
202
+
203
+ test '#build_selectors with $type operator' do
204
+ query = { _id: { "$type" => "null" } }
205
+
206
+ assert_nothing_raised Dolly::InvalidMangoOperatorError do
207
+ FooBarTyped.send(:build_selectors, query)
208
+ end
209
+ end
210
+
211
+ private
212
+
213
+ def generic_response rows, count = 1
214
+ {total_rows: count, offset:0, rows: rows}
215
+ end
216
+
217
+ def build_view_response properties
218
+ rows = properties.map.with_index do |v, i|
219
+ {
220
+ id: "foo_bar/#{i}",
221
+ key: "foo_bar",
222
+ value: 1,
223
+ doc: {_id: "foo_bar/#{i}", _rev: SecureRandom.hex}.merge!(v)
224
+ }
225
+ end
226
+ generic_response rows, properties.count
227
+ end
228
+
229
+ def build_view_collation_response properties
230
+ rows = properties.map.with_index do |v, i|
231
+ id = i.zero? ? "foo_bar/#{i}" : "baz/#{i}"
232
+ {
233
+ id: id,
234
+ key: "foo_bar",
235
+ value: 1,
236
+ doc: {_id: id, _rev: SecureRandom.hex}.merge!(v)
237
+ }
238
+ end
239
+ generic_response rows, properties.count
240
+ end
241
+
242
+
243
+ def build_request keys, body, view_name = 'foo_bar'
244
+ query = "keys=#{CGI::escape keys.to_s.gsub(' ','')}&" unless keys&.empty?
245
+ stub_request(:get, "#{query_base_path}?#{query.to_s}include_docs=true").
246
+ to_return(body: body.to_json)
247
+ end
248
+
249
+ def query_base_path
250
+ "#{DB_BASE_PATH}/_find"
251
+ end
252
+
253
+ def all_docs_path
254
+ "#{DB_BASE_PATH}/_all_docs"
255
+ end
256
+
257
+ def build_save_request(obj)
258
+ stub_request(:put, "#{DB_BASE_PATH}/#{CGI.escape(obj.id)}").
259
+ to_return(body: {ok: true, id: obj.id, rev: "FF0000" }.to_json)
260
+ end
261
+
262
+ def index_response(key)
263
+ {
264
+ rows: [
265
+ {
266
+ id: "_design/index_#{key}",
267
+ key: "_design/index_#{key}",
268
+ value: { rev: '1-c5457a0d26da85f15c4ad6bd739e441d' }
269
+ }
270
+ ]
271
+ }
272
+ end
273
+ end
@@ -0,0 +1,18 @@
1
+ require 'test_helper'
2
+
3
+ class TestDoc < Dolly::Document
4
+ property :name, class_name: String
5
+ property :email, class_name: String
6
+ property :last_name, class_name: String
7
+ end
8
+
9
+ class PropertyManagerTest < Test::Unit::TestCase
10
+ test 'write_attribute with nil value' do
11
+ doc = TestDoc.new(name: 'name', last_name: nil, email: 'does not change')
12
+ assert_equal(doc.name, 'name')
13
+ doc.update_properties(name: nil)
14
+ assert_equal(doc.name, nil)
15
+ assert_equal(doc.last_name, nil)
16
+ assert_equal(doc.email, 'does not change')
17
+ end
18
+ end
data/test/test_helper.rb CHANGED
@@ -13,6 +13,7 @@ Dir["#{File.dirname(__FILE__)}/support/**/*.rb"].each { |f| require f }
13
13
 
14
14
  class Test::Unit::TestCase
15
15
  DEFAULT_DB = 'test'
16
+ DB_BASE_PATH = "http://localhost:5984/test".freeze
16
17
 
17
18
  setup :global_setup
18
19
 
@@ -28,4 +29,54 @@ class Test::Unit::TestCase
28
29
  def base_path
29
30
  %r{http://.*:5984/#{DEFAULT_DB}}
30
31
  end
32
+
33
+ def generic_response rows, count = 1
34
+ {total_rows: count, offset:0, rows: rows}
35
+ end
36
+
37
+ def build_view_response properties
38
+ rows = properties.map.with_index do |v, i|
39
+ {
40
+ id: "foo_bar/#{i}",
41
+ key: "foo_bar",
42
+ value: 1,
43
+ doc: {_id: "foo_bar/#{i}", _rev: SecureRandom.hex}.merge!(v)
44
+ }
45
+ end
46
+ generic_response rows, properties.count
47
+ end
48
+
49
+ def build_view_collation_response properties
50
+ rows = properties.map.with_index do |v, i|
51
+ id = i.zero? ? "foo_bar/#{i}" : "baz/#{i}"
52
+ {
53
+ id: id,
54
+ key: "foo_bar",
55
+ value: 1,
56
+ doc_type: id.split("/").first,
57
+ doc: {
58
+ _id: id, _rev: SecureRandom.hex
59
+ }.merge!(v)
60
+ }
61
+ end
62
+ generic_response rows, properties.count
63
+ end
64
+
65
+
66
+ def build_request keys, body, view_name = 'foo_bar'
67
+ query = "keys=#{CGI::escape keys.to_s.gsub(' ','')}&" unless keys&.empty?
68
+ stub_request(:get, "#{query_base_path}?#{query.to_s}include_docs=true").
69
+ to_return(body: body.to_json)
70
+ end
71
+
72
+ def query_base_path
73
+ "#{DB_BASE_PATH}/_all_docs"
74
+ end
75
+
76
+ def build_save_request(obj)
77
+ stub_request(:put, "#{DB_BASE_PATH}/#{CGI.escape(obj.id)}").
78
+ to_return(body: {ok: true, id: obj.id, rev: "FF0000" }.to_json)
79
+ end
31
80
  end
81
+
82
+ class BaseDolly < Dolly::Document; end
@@ -0,0 +1,27 @@
1
+ require 'test_helper'
2
+
3
+ class Foo < Dolly::Document
4
+ end
5
+
6
+ class ViewQueryTest < Test::Unit::TestCase
7
+
8
+ def setup
9
+ all_docs = [ {foo: 'Foo B', bar: 'Bar B', type: 'foo_bar'}, {foo: 'Foo A', bar: 'Bar A', type: 'foo_bar'}]
10
+ @multi_type_resp = build_view_collation_response all_docs
11
+
12
+ stub_request(:get, "http://localhost:5984/test/_design/doc/_view/id?include_docs=true").
13
+ to_return(body: @multi_type_resp.to_json)
14
+
15
+ end
16
+
17
+ test 'raw_view' do
18
+ assert_equal(Foo.raw_view('doc', 'id'), @multi_type_resp)
19
+ assert_equal(Foo.raw_view('doc', 'id')[:rows].any?, true)
20
+ assert_equal(Foo.raw_view('doc', 'id')[:total_rows].nil?, false)
21
+ end
22
+
23
+ test 'view_value' do
24
+ expected = @multi_type_resp[:rows].flat_map{|res| res[:value]}
25
+ assert_equal(Foo.view_value('doc', 'id'), expected)
26
+ end
27
+ end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: dolly
3
3
  version: !ruby/object:Gem::Version
4
- version: 3.0.0
4
+ version: 3.1.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - javierg
8
- autorequire:
8
+ autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2019-06-20 00:00:00.000000000 Z
11
+ date: 2021-10-08 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: oj
@@ -24,6 +24,20 @@ dependencies:
24
24
  - - ">="
25
25
  - !ruby/object:Gem::Version
26
26
  version: '0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: curb
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - '='
32
+ - !ruby/object:Gem::Version
33
+ version: 0.9.8
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - '='
39
+ - !ruby/object:Gem::Version
40
+ version: 0.9.8
27
41
  - !ruby/object:Gem::Dependency
28
42
  name: bundler
29
43
  requirement: !ruby/object:Gem::Requirement
@@ -44,14 +58,14 @@ dependencies:
44
58
  requirements:
45
59
  - - "~>"
46
60
  - !ruby/object:Gem::Version
47
- version: '10.0'
61
+ version: '13.0'
48
62
  type: :development
49
63
  prerelease: false
50
64
  version_requirements: !ruby/object:Gem::Requirement
51
65
  requirements:
52
66
  - - "~>"
53
67
  - !ruby/object:Gem::Version
54
- version: '10.0'
68
+ version: '13.0'
55
69
  - !ruby/object:Gem::Dependency
56
70
  name: test-unit-full
57
71
  requirement: !ruby/object:Gem::Requirement
@@ -115,7 +129,10 @@ files:
115
129
  - lib/dolly/document_state.rb
116
130
  - lib/dolly/document_type.rb
117
131
  - lib/dolly/exceptions.rb
132
+ - lib/dolly/framework_helper.rb
118
133
  - lib/dolly/identity_properties.rb
134
+ - lib/dolly/mango.rb
135
+ - lib/dolly/mango_index.rb
119
136
  - lib/dolly/properties.rb
120
137
  - lib/dolly/property.rb
121
138
  - lib/dolly/property_manager.rb
@@ -126,19 +143,27 @@ files:
126
143
  - lib/dolly/request_header.rb
127
144
  - lib/dolly/timestamp.rb
128
145
  - lib/dolly/version.rb
146
+ - lib/dolly/view_query.rb
129
147
  - lib/railties/railtie.rb
148
+ - lib/refinements/hash_refinements.rb
130
149
  - lib/refinements/string_refinements.rb
131
150
  - lib/tasks/db.rake
132
151
  - test/bulk_document_test.rb
133
152
  - test/document_test.rb
153
+ - test/document_type_test.rb
134
154
  - test/dummy/config/initializers/filter_parameter_logging.rb
135
155
  - test/dummy/log/test.log
156
+ - test/inheritance_test.rb
157
+ - test/mango_index_test.rb
158
+ - test/mango_test.rb
159
+ - test/property_manager_test.rb
136
160
  - test/support/test.txt
137
161
  - test/test_helper.rb
162
+ - test/view_query_test.rb
138
163
  homepage: https://www.amco.me
139
164
  licenses: []
140
165
  metadata: {}
141
- post_install_message:
166
+ post_install_message:
142
167
  rdoc_options: []
143
168
  require_paths:
144
169
  - lib
@@ -153,15 +178,20 @@ required_rubygems_version: !ruby/object:Gem::Requirement
153
178
  - !ruby/object:Gem::Version
154
179
  version: '0'
155
180
  requirements: []
156
- rubyforge_project:
157
- rubygems_version: 2.6.13
158
- signing_key:
181
+ rubygems_version: 3.0.3
182
+ signing_key:
159
183
  specification_version: 4
160
184
  summary: will write something
161
185
  test_files:
162
186
  - test/dummy/config/initializers/filter_parameter_logging.rb
163
187
  - test/dummy/log/test.log
188
+ - test/inheritance_test.rb
189
+ - test/document_type_test.rb
190
+ - test/mango_index_test.rb
164
191
  - test/bulk_document_test.rb
192
+ - test/view_query_test.rb
193
+ - test/mango_test.rb
165
194
  - test/support/test.txt
166
195
  - test/test_helper.rb
167
196
  - test/document_test.rb
197
+ - test/property_manager_test.rb