couch_potato 1.4.0 → 1.6.3
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 +4 -4
- data/.ruby-version +1 -0
- data/.travis.yml +12 -8
- data/CHANGES.md +4 -0
- data/Gemfile +1 -1
- data/README.md +396 -276
- data/Rakefile +9 -9
- data/couch_potato-rspec.gemspec +20 -0
- data/couch_potato.gemspec +15 -16
- data/{active_support_4_0 → gemfiles/active_support_4_0} +3 -3
- data/{active_support_3_2 → gemfiles/active_support_4_1} +3 -2
- data/gemfiles/active_support_4_2 +11 -0
- data/lib/couch_potato-rspec.rb +3 -0
- data/lib/couch_potato.rb +3 -1
- data/lib/couch_potato/database.rb +42 -39
- data/lib/couch_potato/persistence/magic_timestamps.rb +5 -5
- data/lib/couch_potato/persistence/properties.rb +8 -2
- data/lib/couch_potato/persistence/simple_property.rb +11 -9
- data/lib/couch_potato/persistence/type_caster.rb +1 -1
- data/lib/couch_potato/railtie.rb +2 -0
- data/lib/couch_potato/version.rb +2 -1
- data/lib/couch_potato/view/base_view_spec.rb +18 -8
- data/lib/couch_potato/view/view_query.rb +2 -3
- data/spec/attachments_spec.rb +3 -3
- data/spec/callbacks_spec.rb +193 -113
- data/spec/conflict_handling_spec.rb +4 -4
- data/spec/create_spec.rb +5 -5
- data/spec/default_property_spec.rb +6 -6
- data/spec/destroy_spec.rb +5 -5
- data/spec/property_spec.rb +71 -61
- data/spec/rails_spec.rb +3 -3
- data/spec/railtie_spec.rb +12 -13
- data/spec/spec_helper.rb +3 -3
- data/spec/unit/active_model_compliance_spec.rb +16 -16
- data/spec/unit/attributes_spec.rb +36 -34
- data/spec/unit/base_view_spec_spec.rb +82 -35
- data/spec/unit/callbacks_spec.rb +2 -2
- data/spec/unit/couch_potato_spec.rb +3 -3
- data/spec/unit/create_spec.rb +12 -12
- data/spec/unit/custom_views_spec.rb +1 -1
- data/spec/unit/database_spec.rb +95 -95
- data/spec/unit/date_spec.rb +3 -3
- data/spec/unit/deep_dirty_attributes_spec.rb +104 -104
- data/spec/unit/dirty_attributes_spec.rb +19 -19
- data/spec/unit/forbidden_attributes_protection_spec.rb +4 -4
- data/spec/unit/initialize_spec.rb +37 -19
- data/spec/unit/json_spec.rb +4 -4
- data/spec/unit/lists_spec.rb +8 -8
- data/spec/unit/model_view_spec_spec.rb +14 -14
- data/spec/unit/persistence_spec.rb +6 -6
- data/spec/unit/properties_view_spec_spec.rb +4 -4
- data/spec/unit/rspec_matchers_spec.rb +73 -73
- data/spec/unit/rspec_stub_db_spec.rb +43 -42
- data/spec/unit/string_spec.rb +1 -1
- data/spec/unit/time_spec.rb +2 -2
- data/spec/unit/validation_spec.rb +1 -1
- data/spec/unit/view_query_spec.rb +54 -59
- data/spec/update_spec.rb +5 -5
- data/spec/view_updates_spec.rb +4 -4
- data/spec/views_spec.rb +43 -43
- metadata +18 -22
- data/lib/couch_potato/rspec.rb +0 -2
- data/lib/couch_potato/rspec/matchers.rb +0 -56
- data/lib/couch_potato/rspec/matchers/json2.js +0 -482
- data/lib/couch_potato/rspec/matchers/list_as_matcher.rb +0 -53
- data/lib/couch_potato/rspec/matchers/map_reduce_to_matcher.rb +0 -166
- data/lib/couch_potato/rspec/matchers/map_to_matcher.rb +0 -61
- data/lib/couch_potato/rspec/matchers/reduce_to_matcher.rb +0 -48
- data/lib/couch_potato/rspec/stub_db.rb +0 -57
@@ -1,66 +1,67 @@
|
|
1
1
|
require 'spec_helper'
|
2
|
-
require 'couch_potato
|
2
|
+
require 'couch_potato-rspec'
|
3
3
|
|
4
4
|
class WithStubbedView
|
5
5
|
include CouchPotato::Persistence
|
6
|
-
|
7
|
-
view :stubbed_view, :
|
6
|
+
|
7
|
+
view :stubbed_view, key: :x
|
8
8
|
end
|
9
9
|
|
10
|
-
describe
|
11
|
-
it
|
12
|
-
stub_db
|
13
|
-
|
10
|
+
describe 'stubbing the db' do
|
11
|
+
it 'replaces CouchPotato.database with a double' do
|
12
|
+
CouchPotato.stub_db
|
13
|
+
|
14
|
+
expect(CouchPotato.database).to be_a(RSpec::Mocks::Double)
|
14
15
|
end
|
15
|
-
|
16
|
-
it
|
17
|
-
db = stub_db
|
18
|
-
|
16
|
+
|
17
|
+
it 'returns the stub' do
|
18
|
+
db = CouchPotato.stub_db
|
19
|
+
|
20
|
+
expect(CouchPotato.database).to eq(db)
|
19
21
|
end
|
20
22
|
end
|
21
23
|
|
22
|
-
describe
|
24
|
+
describe 'stubbing a view' do
|
23
25
|
before(:each) do
|
24
|
-
@db = stub_db
|
26
|
+
@db = CouchPotato.stub_db
|
25
27
|
@db.stub_view(WithStubbedView, :stubbed_view).with('123').and_return([:result])
|
26
28
|
end
|
27
|
-
|
28
|
-
it
|
29
|
-
WithStubbedView.stubbed_view('123').
|
29
|
+
|
30
|
+
it 'stubs the view to return a double' do
|
31
|
+
expect(WithStubbedView.stubbed_view('123')).to be_a(RSpec::Mocks::Double)
|
30
32
|
end
|
31
|
-
|
32
|
-
it
|
33
|
-
@db.view(WithStubbedView.stubbed_view('123')).
|
33
|
+
|
34
|
+
it 'stubs the database to return fake results when called with the stub' do
|
35
|
+
expect(@db.view(WithStubbedView.stubbed_view('123'))).to eq([:result])
|
34
36
|
end
|
35
|
-
|
36
|
-
it
|
37
|
-
@db.first(WithStubbedView.stubbed_view('123')).
|
38
|
-
@db.first!(WithStubbedView.stubbed_view('123')).
|
37
|
+
|
38
|
+
it 'stubs the database to return the first fake result' do
|
39
|
+
expect(@db.first(WithStubbedView.stubbed_view('123'))).to eq(:result)
|
40
|
+
expect(@db.first!(WithStubbedView.stubbed_view('123'))).to eq(:result)
|
39
41
|
end
|
40
|
-
|
41
|
-
it
|
42
|
+
|
43
|
+
it 'raises an error if there is no first result' do
|
42
44
|
@db.stub_view(WithStubbedView, :stubbed_view).and_return([])
|
43
|
-
|
45
|
+
expect do
|
44
46
|
@db.first!(WithStubbedView.stubbed_view('123'))
|
45
|
-
|
47
|
+
end.to raise_error(CouchPotato::NotFound)
|
46
48
|
end
|
47
|
-
|
49
|
+
|
48
50
|
it "skips stubbing the first view (i.e. doesn't crash) if the fake result does not respond to first" do
|
49
51
|
@db.stub_view(WithStubbedView, :stubbed_view).with('123').and_return(:results)
|
50
|
-
|
51
|
-
@db.view(WithStubbedView.stubbed_view('123')).
|
52
|
+
|
53
|
+
expect(@db.view(WithStubbedView.stubbed_view('123'))).to eq(:results)
|
52
54
|
end
|
53
|
-
|
54
|
-
it
|
55
|
-
@db.stub_view(WithStubbedView, :stubbed_view).with('123') {:results}
|
56
|
-
|
57
|
-
@db.view(WithStubbedView.stubbed_view('123')).
|
55
|
+
|
56
|
+
it 'supports the block style return syntax with `with`' do
|
57
|
+
@db.stub_view(WithStubbedView, :stubbed_view).with('123') { :results }
|
58
|
+
|
59
|
+
expect(@db.view(WithStubbedView.stubbed_view('123'))).to eq(:results)
|
58
60
|
end
|
59
|
-
|
60
|
-
it
|
61
|
-
@db.stub_view(WithStubbedView, :stubbed_view) {:results}
|
62
|
-
|
63
|
-
@db.view(WithStubbedView.stubbed_view('123')).
|
61
|
+
|
62
|
+
it 'supports the block style return syntax without `with`' do
|
63
|
+
@db.stub_view(WithStubbedView, :stubbed_view) { :results }
|
64
|
+
|
65
|
+
expect(@db.view(WithStubbedView.stubbed_view('123'))).to eq(:results)
|
64
66
|
end
|
65
|
-
|
66
|
-
end
|
67
|
+
end
|
data/spec/unit/string_spec.rb
CHANGED
data/spec/unit/time_spec.rb
CHANGED
@@ -3,13 +3,13 @@ require 'spec_helper'
|
|
3
3
|
describe Time, 'to_json' do
|
4
4
|
it "should convert to utc and format the time in a way that i can use it for sorting in couchdb" do
|
5
5
|
time = Time.parse('2009-01-01 11:12:23 +0200')
|
6
|
-
time.to_json.
|
6
|
+
expect(time.to_json).to eq("\"2009/01/01 09:12:23 +0000\"")
|
7
7
|
end
|
8
8
|
end
|
9
9
|
|
10
10
|
describe Time, 'as_json' do
|
11
11
|
it "should format it in the same way as to_json does so i can use this to do queries over time attributes" do
|
12
12
|
time = Time.parse('2009-01-01 11:12:23 +0200')
|
13
|
-
time.as_json.
|
13
|
+
expect(time.as_json).to eq("2009/01/01 09:12:23 +0000")
|
14
14
|
end
|
15
15
|
end
|
@@ -6,7 +6,7 @@ describe 'CouchPotato Validation' do
|
|
6
6
|
it "should description" do
|
7
7
|
model_class = Class.new
|
8
8
|
model_class.send(:include, CouchPotato::Persistence)
|
9
|
-
model_class.new.errors.
|
9
|
+
expect(model_class.new.errors).to respond_to(:errors)
|
10
10
|
end
|
11
11
|
end
|
12
12
|
|
@@ -1,21 +1,20 @@
|
|
1
1
|
require 'spec_helper'
|
2
2
|
|
3
3
|
describe CouchPotato::View::ViewQuery, 'query_view!' do
|
4
|
+
let(:db) { double 'db', :get => nil, view: nil, :save_doc => nil,
|
5
|
+
connection: double.as_null_object, name: nil }
|
6
|
+
|
4
7
|
before(:each) do
|
5
|
-
CouchRest.stub(:get => nil)
|
6
8
|
CouchPotato::View::ViewQuery.clear_cache
|
7
9
|
end
|
8
10
|
|
9
|
-
it
|
10
|
-
db
|
11
|
-
db.should_receive(:view).with(anything, {})
|
11
|
+
it 'does not pass a key if conditions are empty' do
|
12
|
+
expect(db).to receive(:view).with(anything, {})
|
12
13
|
CouchPotato::View::ViewQuery.new(db, '', {:view0 => {}}).query_view!
|
13
14
|
end
|
14
15
|
|
15
16
|
it 'updates a view if it does not exist' do
|
16
|
-
db
|
17
|
-
|
18
|
-
db.should_receive(:save_doc).with(
|
17
|
+
expect(db).to receive(:save_doc).with(
|
19
18
|
'views' => {'view' => {'map' => '<map_code>', 'reduce' => '<reduce_code>'}, 'lib' => {'test' => '<lib_code>'}},
|
20
19
|
'lists' => {},
|
21
20
|
"_id" => "_design/design",
|
@@ -26,21 +25,19 @@ describe CouchPotato::View::ViewQuery, 'query_view!' do
|
|
26
25
|
end
|
27
26
|
|
28
27
|
it 'only updates a view once' do
|
29
|
-
db
|
30
|
-
db.stub(:get).and_return({'views' => {}}, {'views' => {}, x: 1}) # return something different on the second call otherwise it would never try to update the views twice
|
28
|
+
allow(db).to receive(:get).and_return({'views' => {}}, {'views' => {}, x: 1}) # return something different on the second call otherwise it would never try to update the views twice
|
31
29
|
query = CouchPotato::View::ViewQuery.new(db, 'design', {:view => {:map => '<map_code>', :reduce => '<reduce_code>'}})
|
32
30
|
|
33
|
-
db.
|
31
|
+
expect(db).to receive(:save_doc).once
|
34
32
|
|
35
33
|
2.times { query.query_view! }
|
36
34
|
end
|
37
35
|
|
38
36
|
it 'updates a view again after clearing the view cache' do
|
39
|
-
db
|
40
|
-
db.stub(:get).and_return({'views' => {}}, {'views' => {}, x: 1}) # return something different on the second call otherwise it would never try to update the views twice
|
37
|
+
allow(db).to receive(:get).and_return({'views' => {}}, {'views' => {}, x: 1}) # return something different on the second call otherwise it would never try to update the views twice
|
41
38
|
query = CouchPotato::View::ViewQuery.new(db, 'design', {:view => {:map => '<map_code>', :reduce => '<reduce_code>'}})
|
42
39
|
|
43
|
-
db.
|
40
|
+
expect(db).to receive(:save_doc).twice
|
44
41
|
|
45
42
|
query.query_view!
|
46
43
|
CouchPotato::View::ViewQuery.clear_cache
|
@@ -48,9 +45,7 @@ describe CouchPotato::View::ViewQuery, 'query_view!' do
|
|
48
45
|
end
|
49
46
|
|
50
47
|
it 'updates a view in erlang if it does not exist' do
|
51
|
-
db
|
52
|
-
|
53
|
-
db.should_receive(:save_doc).with(
|
48
|
+
expect(db).to receive(:save_doc).with(
|
54
49
|
'views' => {'view' => {'map' => '<map_code>', 'reduce' => '<reduce_code>'}},
|
55
50
|
'lists' => {}, "_id" => "_design/design", "language" => "erlang")
|
56
51
|
|
@@ -60,48 +55,48 @@ describe CouchPotato::View::ViewQuery, 'query_view!' do
|
|
60
55
|
end
|
61
56
|
|
62
57
|
it "does not update a view when the views object haven't changed" do
|
63
|
-
db
|
64
|
-
db.
|
58
|
+
allow(db).to receive(:get).and_return({'views' => {'view' => {'map' => '<map_code>', 'reduce' => '<reduce_code>'}}})
|
59
|
+
expect(db).not_to receive(:save_doc)
|
65
60
|
CouchPotato::View::ViewQuery.new(db, 'design', {:view => {:map => '<map_code>', :reduce => '<reduce_code>'}}, nil, nil).query_view!
|
66
61
|
end
|
67
62
|
|
68
63
|
it "does not update a view when the list function hasn't changed" do
|
69
|
-
db
|
70
|
-
db.
|
64
|
+
allow(db).to receive(:get).and_return({'views' => {'view' => {'map' => '<map_code>', 'reduce' => '<reduce_code>'}}, 'lists' => {'list0' => '<list_code>'}})
|
65
|
+
expect(db).not_to receive(:save_doc)
|
71
66
|
CouchPotato::View::ViewQuery.new(db, 'design', {:view => {:map => '<map_code>', :reduce => '<reduce_code>'}}, :list0 => '<list_code>').query_view!
|
72
67
|
end
|
73
68
|
|
74
69
|
it "does not update a view when the lib function hasn't changed" do
|
75
|
-
db
|
70
|
+
allow(db).to receive(:get).and_return({'views' => {'view' => {'map' => '<map_code>', 'reduce' => '<reduce_code>'}, 'lib' => {'test' => '<lib_code>'}}})
|
76
71
|
|
77
|
-
db.
|
72
|
+
expect(db).not_to receive(:save_doc)
|
78
73
|
|
79
74
|
CouchPotato::View::ViewQuery.new(db, 'design', {:view => {:map => '<map_code>', :reduce => '<reduce_code>'}}, nil, {'test' => "<lib_code>"}).query_view!
|
80
75
|
end
|
81
76
|
|
82
|
-
it
|
83
|
-
db
|
84
|
-
db.
|
77
|
+
it 'updates a view when the map function has changed' do
|
78
|
+
allow(db).to receive(:get).and_return({'views' => {'view2' => {'map' => '<map_code>', 'reduce' => '<reduce_code>'}}})
|
79
|
+
expect(db).to receive(:save_doc)
|
85
80
|
CouchPotato::View::ViewQuery.new(db, 'design', :view2 => {:map => '<new map_code>', :reduce => '<reduce_code>'}).query_view!
|
86
81
|
end
|
87
82
|
|
88
|
-
it
|
89
|
-
db
|
90
|
-
db.
|
83
|
+
it 'updates a view when the map function has changed' do
|
84
|
+
allow(db).to receive(:get).and_return({'views' => {'view3' => {'map' => '<map_code>'}}})
|
85
|
+
expect(db).to receive(:save_doc)
|
91
86
|
CouchPotato::View::ViewQuery.new(db, 'design', :view3 => {:map => '<new map_code>'}).query_view!
|
92
87
|
end
|
93
88
|
|
94
|
-
it
|
95
|
-
db
|
89
|
+
it 'updates a view when the lib hash has changed' do
|
90
|
+
allow(db).to receive(:get).and_return({'views' => {'view4' => {'map' => '<map_code>'}}}, 'lib' => {'test' => "<test_lib>"})
|
96
91
|
|
97
|
-
db.
|
92
|
+
expect(db).to receive(:save_doc)
|
98
93
|
|
99
94
|
CouchPotato::View::ViewQuery.new(db, 'design', {:view4 => {:map => '<map_code>'}}, nil, {:test => "<test_lib>"}).query_view!
|
100
95
|
end
|
101
96
|
|
102
97
|
it "doesn't override libs with different names" do
|
103
|
-
db
|
104
|
-
db.
|
98
|
+
allow(db).to receive(:get).and_return({'views' => {'view5' => {'map' => '<map_code>'}, 'lib' => {'test' => "<test_lib>"}}})
|
99
|
+
expect(db).to receive(:save_doc).with({
|
105
100
|
'views' => {
|
106
101
|
'view5' => {'map' => '<map_code>'},
|
107
102
|
'lib' => {'test' => '<test_lib>', 'test1' => '<test1_lib>'}
|
@@ -110,10 +105,10 @@ describe CouchPotato::View::ViewQuery, 'query_view!' do
|
|
110
105
|
CouchPotato::View::ViewQuery.new(db, 'design', {:view5 => {:map => '<map_code>'}}, nil, {'test1' => '<test1_lib>'}).query_view!
|
111
106
|
end
|
112
107
|
|
113
|
-
it
|
114
|
-
db
|
108
|
+
it 'overrides libs with the same name' do
|
109
|
+
allow(db).to receive(:get).and_return({'views' => {'view6' => {'map' => '<map_code>'}, 'lib' => {'test' => "<test_lib>"}}})
|
115
110
|
|
116
|
-
db.
|
111
|
+
expect(db).to receive(:save_doc).with({
|
117
112
|
'views' => {
|
118
113
|
'view6' => {'map' => '<map_code>'},
|
119
114
|
'lib' => {'test' => '<test1_lib>'}
|
@@ -123,56 +118,56 @@ describe CouchPotato::View::ViewQuery, 'query_view!' do
|
|
123
118
|
CouchPotato::View::ViewQuery.new(db, 'design', {:view6 => {:map => '<map_code>'}}, nil, {'test' => '<test1_lib>'}).query_view!
|
124
119
|
end
|
125
120
|
|
126
|
-
it
|
127
|
-
db
|
128
|
-
db.
|
121
|
+
it 'does not pass in reduce or lib keys if there is no lib or reduce object' do
|
122
|
+
allow(db).to receive(:get).and_return({'views' => {}})
|
123
|
+
expect(db).to receive(:save_doc).with('views' => {'view7' => {'map' => '<map code>'}})
|
129
124
|
CouchPotato::View::ViewQuery.new(db, 'design', :view7 => {:map => '<map code>', :reduce => nil}).query_view!
|
130
125
|
end
|
131
126
|
|
132
|
-
it
|
133
|
-
db
|
134
|
-
db.
|
127
|
+
it 'updates a view when the reduce function has changed' do
|
128
|
+
allow(db).to receive(:get).and_return({'views' => {'view8' => {'map' => '<map_code>', 'reduce' => '<reduce_code>'}}})
|
129
|
+
expect(db).to receive(:save_doc)
|
135
130
|
CouchPotato::View::ViewQuery.new(db, 'design', :view8 => {:map => '<map_code>', :reduce => '<new reduce_code>'}).query_view!
|
136
131
|
end
|
137
132
|
|
138
|
-
it
|
139
|
-
db
|
133
|
+
it 'updates a view when the list function has changed' do
|
134
|
+
allow(db).to receive(:get).and_return({
|
140
135
|
'views' => {'view9' => {'map' => '<map_code>', 'reduce' => '<reduce_code>'}},
|
141
136
|
'lists' => {'list1' => '<list_code>'}
|
142
|
-
}
|
143
|
-
db.
|
137
|
+
})
|
138
|
+
expect(db).to receive(:save_doc)
|
144
139
|
CouchPotato::View::ViewQuery.new(db, 'design', {:view9 => {:map => '<map_code>', :reduce => '<reduce_code>'}}, :list1 => '<new_list_code>').query_view!
|
145
140
|
end
|
146
141
|
|
147
142
|
it "updates a view when there wasn't a list function but now there is one" do
|
148
|
-
db
|
143
|
+
allow(db).to receive(:get).and_return({
|
149
144
|
'views' => {'view10' => {'map' => '<map_code>', 'reduce' => '<reduce_code>'}}
|
150
|
-
}
|
151
|
-
db.
|
145
|
+
})
|
146
|
+
expect(db).to receive(:save_doc)
|
152
147
|
CouchPotato::View::ViewQuery.new(db, 'design', {:view10 => {:map => '<map_code>', :reduce => '<reduce_code>'}}, :list1 => '<new_list_code>').query_view!
|
153
148
|
end
|
154
149
|
|
155
150
|
it "does not update a view when there is a list function but no list function is passed" do
|
156
|
-
db
|
151
|
+
allow(db).to receive(:get).and_return({
|
157
152
|
'views' => {'view11' => {'map' => '<map_code>', 'reduce' => '<reduce_code>'}},
|
158
153
|
'lists' => {'list1' => '<list_code>'}
|
159
|
-
}
|
160
|
-
db.
|
154
|
+
})
|
155
|
+
expect(db).not_to receive(:save_doc)
|
161
156
|
CouchPotato::View::ViewQuery.new(db, 'design', {:view11 => {:map => '<map_code>', :reduce => '<reduce_code>'}}, {}).query_view!
|
162
157
|
end
|
163
158
|
|
164
159
|
it "does not update a view when there were no lists before and no list function is passed" do
|
165
|
-
db
|
160
|
+
allow(db).to receive(:get).and_return({
|
166
161
|
'views' => {'view12' => {'map' => '<map_code>', 'reduce' => '<reduce_code>'}}
|
167
|
-
}
|
168
|
-
db.
|
162
|
+
})
|
163
|
+
expect(db).not_to receive(:save_doc)
|
169
164
|
CouchPotato::View::ViewQuery.new(db, 'design', {:view12 => {:map => '<map_code>', :reduce => '<reduce_code>'}}, {}).query_view!
|
170
165
|
end
|
171
166
|
|
172
|
-
it "queries
|
173
|
-
db
|
174
|
-
|
167
|
+
it "queries the database directly when querying a list" do
|
168
|
+
allow(db).to receive(:name){'my_database'}
|
169
|
+
|
170
|
+
expect(db.connection).to receive(:get).with('/my_database/_design/my_design/_list/list1/view13?key=1')
|
175
171
|
CouchPotato::View::ViewQuery.new(db, 'my_design', {:view13 => {:map => '<map_code>', :reduce => '<reduce_code>'}}, :list1 => '<new_list_code>').query_view!(:key => 1)
|
176
172
|
end
|
177
|
-
|
178
173
|
end
|
data/spec/update_spec.rb
CHANGED
@@ -14,27 +14,27 @@ describe "create" do
|
|
14
14
|
old_rev = @comment._rev
|
15
15
|
@comment.title = 'xyz'
|
16
16
|
CouchPotato.database.save_document! @comment
|
17
|
-
@comment._rev.
|
18
|
-
@comment._rev.
|
17
|
+
expect(@comment._rev).not_to eq(old_rev)
|
18
|
+
expect(@comment._rev).not_to be_nil
|
19
19
|
end
|
20
20
|
|
21
21
|
it "should not update created at" do
|
22
22
|
old_created_at = @comment.created_at
|
23
23
|
@comment.title = 'xyz'
|
24
24
|
CouchPotato.database.save_document! @comment
|
25
|
-
@comment.created_at.
|
25
|
+
expect(@comment.created_at).to eq(old_created_at)
|
26
26
|
end
|
27
27
|
|
28
28
|
it "should update updated at" do
|
29
29
|
old_updated_at = @comment.updated_at
|
30
30
|
@comment.title = 'xyz'
|
31
31
|
CouchPotato.database.save_document! @comment
|
32
|
-
@comment.updated_at.
|
32
|
+
expect(@comment.updated_at).to be > old_updated_at
|
33
33
|
end
|
34
34
|
|
35
35
|
it "should update the attributes" do
|
36
36
|
@comment.title = 'new title'
|
37
37
|
CouchPotato.database.save_document! @comment
|
38
|
-
CouchPotato.couchrest_database.get("#{@comment.id}").title.
|
38
|
+
expect(CouchPotato.couchrest_database.get("#{@comment.id}").title).to eq('new title')
|
39
39
|
end
|
40
40
|
end
|
data/spec/view_updates_spec.rb
CHANGED
@@ -9,20 +9,20 @@ describe "automatic view updates" do
|
|
9
9
|
it "should update a view that doesn't match the given functions" do
|
10
10
|
CouchPotato::View::ViewQuery.new(@db, 'test_design1', {'test_view' => {:map => 'function(doc) {}', :reduce => 'function() {}'}}, nil).query_view! # create view
|
11
11
|
CouchPotato::View::ViewQuery.new(@db, 'test_design1', {'test_view' => {:map => 'function(doc) {emit(doc.id, null)}', :reduce => 'function(key, values) {return sum(values)}'}}, nil).query_view!
|
12
|
-
CouchPotato.database.load('_design/test_design1')['views']['test_view'].
|
12
|
+
expect(CouchPotato.database.load('_design/test_design1')['views']['test_view']).to eq({
|
13
13
|
'map' => 'function(doc) {emit(doc.id, null)}',
|
14
14
|
'reduce' => 'function(key, values) {return sum(values)}'
|
15
|
-
}
|
15
|
+
})
|
16
16
|
end
|
17
17
|
|
18
18
|
it "should only update a view once to avoid writing the view for every request" do
|
19
19
|
CouchPotato::View::ViewQuery.new(@db, 'test_design2', {'test_view' => {:map => 'function(doc) {}', :reduce => 'function() {}'}}, nil).query_view! # create view
|
20
20
|
CouchPotato::View::ViewQuery.new(@db, 'test_design2', {'test_view' => {:map => 'function(doc) {emit(doc.id, null)}', :reduce => 'function(key, values) {return sum(values)}'}}, nil).query_view!
|
21
21
|
CouchPotato::View::ViewQuery.new(@db, 'test_design2', {'test_view' => {:map => 'function(doc) {}', :reduce => 'function() {}'}}, nil).query_view!
|
22
|
-
CouchPotato.database.load('_design/test_design2')['views']['test_view'].
|
22
|
+
expect(CouchPotato.database.load('_design/test_design2')['views']['test_view']).to eq({
|
23
23
|
'map' => 'function(doc) {emit(doc.id, null)}',
|
24
24
|
'reduce' => 'function(key, values) {return sum(values)}'
|
25
|
-
}
|
25
|
+
})
|
26
26
|
end
|
27
27
|
|
28
28
|
end
|
data/spec/views_spec.rb
CHANGED
@@ -46,7 +46,7 @@ describe 'views' do
|
|
46
46
|
@db.save_document build
|
47
47
|
|
48
48
|
results = @db.view(ErlangBuild.by_name('erlang'))
|
49
|
-
results.
|
49
|
+
expect(results).to eq([build])
|
50
50
|
end
|
51
51
|
|
52
52
|
it 'does not crash couchdb when a document does not have the key' do
|
@@ -54,7 +54,7 @@ describe 'views' do
|
|
54
54
|
@db.couchrest_database.save_doc build
|
55
55
|
|
56
56
|
results = @db.view(ErlangBuild.by_name(:key => nil))
|
57
|
-
results.size.
|
57
|
+
expect(results.size).to eq(1)
|
58
58
|
end
|
59
59
|
|
60
60
|
it 'builds views with composite keys' do
|
@@ -62,7 +62,7 @@ describe 'views' do
|
|
62
62
|
@db.save_document build
|
63
63
|
|
64
64
|
results = @db.view(ErlangBuild.by_name_and_code(['erlang', '123']))
|
65
|
-
results.
|
65
|
+
expect(results).to eq([build])
|
66
66
|
end
|
67
67
|
|
68
68
|
it 'can reduce over erlang views' do
|
@@ -70,72 +70,72 @@ describe 'views' do
|
|
70
70
|
@db.save_document build
|
71
71
|
|
72
72
|
results = @db.view(ErlangBuild.by_name(:reduce => true))
|
73
|
-
results.
|
73
|
+
expect(results).to eq(1)
|
74
74
|
end
|
75
75
|
end
|
76
76
|
|
77
77
|
it "should return instances of the class" do
|
78
78
|
@db.save_document Build.new(:state => 'success', :time => '2008-01-01')
|
79
79
|
results = @db.view(Build.timeline)
|
80
|
-
results.map(&:class).
|
80
|
+
expect(results.map(&:class)).to eq([Build])
|
81
81
|
end
|
82
82
|
|
83
83
|
it "should return the ids if there document was not included" do
|
84
84
|
build = Build.new(:state => 'success', :time => '2008-01-01')
|
85
85
|
@db.save_document build
|
86
86
|
results = @db.view(Build.timeline(:include_docs => false))
|
87
|
-
results.
|
87
|
+
expect(results).to eq([build.id])
|
88
88
|
end
|
89
89
|
|
90
90
|
it "should pass the view options to the view query" do
|
91
|
-
query =
|
92
|
-
CouchPotato::View::ViewQuery.
|
93
|
-
query.
|
91
|
+
query = double 'query'
|
92
|
+
allow(CouchPotato::View::ViewQuery).to receive(:new).and_return(query)
|
93
|
+
expect(query).to receive(:query_view!).with(hash_including(:key => 1)).and_return('rows' => [])
|
94
94
|
@db.view Build.timeline(:key => 1)
|
95
95
|
end
|
96
96
|
|
97
97
|
it "should not return documents that don't have a matching JSON.create_id" do
|
98
98
|
CouchPotato.couchrest_database.save_doc({:time => 'x'})
|
99
|
-
@db.view(Build.timeline).
|
99
|
+
expect(@db.view(Build.timeline)).to eq([])
|
100
100
|
end
|
101
101
|
|
102
102
|
it "should count documents" do
|
103
103
|
@db.save_document! Build.new(:state => 'success', :time => '2008-01-01')
|
104
|
-
@db.view(Build.count(:reduce => true)).
|
104
|
+
expect(@db.view(Build.count(:reduce => true))).to eq(1)
|
105
105
|
end
|
106
106
|
|
107
107
|
it "should count zero documents" do
|
108
|
-
@db.view(Build.count(:reduce => true)).
|
108
|
+
expect(@db.view(Build.count(:reduce => true))).to eq(0)
|
109
109
|
end
|
110
110
|
|
111
111
|
describe "with multiple keys" do
|
112
112
|
it "should return the documents with matching keys" do
|
113
113
|
build = Build.new(:state => 'success', :time => '2008-01-01')
|
114
114
|
@db.save! build
|
115
|
-
@db.view(Build.timeline(:keys => ['2008-01-01'])).
|
115
|
+
expect(@db.view(Build.timeline(:keys => ['2008-01-01']))).to eq([build])
|
116
116
|
end
|
117
117
|
|
118
118
|
it "should not return documents with non-matching keys" do
|
119
119
|
build = Build.new(:state => 'success', :time => '2008-01-01')
|
120
120
|
@db.save! build
|
121
|
-
@db.view(Build.timeline(:keys => ['2008-01-02'])).
|
121
|
+
expect(@db.view(Build.timeline(:keys => ['2008-01-02']))).to be_empty
|
122
122
|
end
|
123
123
|
end
|
124
124
|
|
125
125
|
describe "properties defined" do
|
126
126
|
it "assigns the configured properties" do
|
127
127
|
CouchPotato.couchrest_database.save_doc(:state => 'success', :time => '2008-01-01', JSON.create_id.to_sym => 'Build')
|
128
|
-
@db.view(Build.minimal_timeline).first.state.
|
128
|
+
expect(@db.view(Build.minimal_timeline).first.state).to eql('success')
|
129
129
|
end
|
130
130
|
|
131
131
|
it "does not assign the properties not configured" do
|
132
132
|
CouchPotato.couchrest_database.save_doc(:state => 'success', :time => '2008-01-01', JSON.create_id.to_sym => 'Build')
|
133
|
-
@db.view(Build.minimal_timeline).first.time.
|
133
|
+
expect(@db.view(Build.minimal_timeline).first.time).to be_nil
|
134
134
|
end
|
135
135
|
|
136
136
|
it "assigns the id even if it is not configured" do
|
137
137
|
id = CouchPotato.couchrest_database.save_doc(:state => 'success', :time => '2008-01-01', JSON.create_id.to_sym => 'Build')['id']
|
138
|
-
@db.view(Build.minimal_timeline).first._id.
|
138
|
+
expect(@db.view(Build.minimal_timeline).first._id).to eql(id)
|
139
139
|
end
|
140
140
|
end
|
141
141
|
|
@@ -143,49 +143,49 @@ describe 'views' do
|
|
143
143
|
it "should assign all properties to the objects by default" do
|
144
144
|
id = CouchPotato.couchrest_database.save_doc({:state => 'success', :time => '2008-01-01', JSON.create_id.to_sym => 'Build'})['id']
|
145
145
|
result = @db.view(Build.timeline).first
|
146
|
-
result.state.
|
147
|
-
result.time.
|
148
|
-
result._id.
|
146
|
+
expect(result.state).to eq('success')
|
147
|
+
expect(result.time).to eq('2008-01-01')
|
148
|
+
expect(result._id).to eq(id)
|
149
149
|
end
|
150
150
|
end
|
151
151
|
|
152
152
|
describe "map function given" do
|
153
153
|
it "should still return instances of the class" do
|
154
154
|
CouchPotato.couchrest_database.save_doc({:state => 'success', :time => '2008-01-01'})
|
155
|
-
@db.view(Build.custom_timeline).map(&:class).
|
155
|
+
expect(@db.view(Build.custom_timeline).map(&:class)).to eq([Build])
|
156
156
|
end
|
157
157
|
|
158
158
|
it "should assign the properties from the value" do
|
159
159
|
CouchPotato.couchrest_database.save_doc({:state => 'success', :time => '2008-01-01'})
|
160
|
-
@db.view(Build.custom_timeline).map(&:state).
|
160
|
+
expect(@db.view(Build.custom_timeline).map(&:state)).to eq(['custom_success'])
|
161
161
|
end
|
162
162
|
|
163
163
|
it "should assign the id" do
|
164
164
|
doc = CouchPotato.couchrest_database.save_doc({:state => 'success', :time => '2008-01-01'})
|
165
|
-
@db.view(Build.custom_timeline).map(&:_id).
|
165
|
+
expect(@db.view(Build.custom_timeline).map(&:_id)).to eq([doc['id']])
|
166
166
|
end
|
167
167
|
|
168
168
|
it "should leave the other properties blank" do
|
169
169
|
CouchPotato.couchrest_database.save_doc({:state => 'success', :time => '2008-01-01'})
|
170
|
-
@db.view(Build.custom_timeline).map(&:time).
|
170
|
+
expect(@db.view(Build.custom_timeline).map(&:time)).to eq([nil])
|
171
171
|
end
|
172
172
|
|
173
173
|
describe "that returns null documents" do
|
174
174
|
it "should return instances of the class" do
|
175
175
|
CouchPotato.couchrest_database.save_doc({:state => 'success', :time => '2008-01-01'})
|
176
|
-
@db.view(Build.custom_timeline_returns_docs).map(&:class).
|
176
|
+
expect(@db.view(Build.custom_timeline_returns_docs).map(&:class)).to eq([Build])
|
177
177
|
end
|
178
178
|
|
179
179
|
it "should assign the properties from the value" do
|
180
180
|
CouchPotato.couchrest_database.save_doc({:state => 'success', :time => '2008-01-01'})
|
181
|
-
@db.view(Build.custom_timeline_returns_docs).map(&:state).
|
181
|
+
expect(@db.view(Build.custom_timeline_returns_docs).map(&:state)).to eq(['success'])
|
182
182
|
end
|
183
183
|
|
184
184
|
it "should still return instance of class if document included JSON.create_id" do
|
185
185
|
CouchPotato.couchrest_database.save_doc({:state => 'success', :time => '2008-01-01', JSON.create_id.to_sym => "Build"})
|
186
186
|
view_data = @db.view(Build.custom_timeline_returns_docs)
|
187
|
-
view_data.map(&:class).
|
188
|
-
view_data.map(&:state).
|
187
|
+
expect(view_data.map(&:class)).to eq([Build])
|
188
|
+
expect(view_data.map(&:state)).to eq(['success'])
|
189
189
|
end
|
190
190
|
end
|
191
191
|
|
@@ -193,14 +193,14 @@ describe 'views' do
|
|
193
193
|
it "should still assign the id" do
|
194
194
|
doc = CouchPotato.couchrest_database.save_doc({})
|
195
195
|
CouchPotato.couchrest_database.save_doc({:foreign_key => doc['id']})
|
196
|
-
@db.view(Build.custom_with_reduce).map(&:_id).
|
196
|
+
expect(@db.view(Build.custom_with_reduce).map(&:_id)).to eq([doc['id']])
|
197
197
|
end
|
198
198
|
|
199
199
|
describe "when the additional reduce function is a typical count" do
|
200
200
|
it "should parse the reduce count" do
|
201
201
|
doc = CouchPotato.couchrest_database.save_doc({})
|
202
202
|
CouchPotato.couchrest_database.save_doc({:foreign_key => doc['id']})
|
203
|
-
@db.view(Build.custom_count_with_reduce(:reduce => true)).
|
203
|
+
expect(@db.view(Build.custom_count_with_reduce(:reduce => true))).to eq(2)
|
204
204
|
end
|
205
205
|
end
|
206
206
|
end
|
@@ -208,10 +208,10 @@ describe 'views' do
|
|
208
208
|
|
209
209
|
describe "with array as key" do
|
210
210
|
it "should create a map function with the composite key" do
|
211
|
-
CouchPotato::View::ViewQuery.
|
212
|
-
view['key_array_timeline'][:map].
|
211
|
+
expect(CouchPotato::View::ViewQuery).to receive(:new) do |db, design_name, view, list|
|
212
|
+
expect(view['key_array_timeline'][:map]).to match(/emit\(\[doc\['time'\], doc\['state'\]\]/)
|
213
213
|
|
214
|
-
|
214
|
+
double('view query', :query_view! => {'rows' => []})
|
215
215
|
end
|
216
216
|
@db.view Build.key_array_timeline
|
217
217
|
end
|
@@ -220,18 +220,18 @@ describe 'views' do
|
|
220
220
|
describe "raw view" do
|
221
221
|
it "should return the raw data" do
|
222
222
|
@db.save_document Build.new(:state => 'success', :time => '2008-01-01')
|
223
|
-
@db.view(Build.raw)['rows'][0]['value'].
|
223
|
+
expect(@db.view(Build.raw)['rows'][0]['value']).to eq('success')
|
224
224
|
end
|
225
225
|
|
226
226
|
it "should return filtred raw data" do
|
227
227
|
@db.save_document Build.new(:state => 'success', :time => '2008-01-01')
|
228
|
-
@db.view(Build.filtered_raw).
|
228
|
+
expect(@db.view(Build.filtered_raw)).to eq(['success'])
|
229
229
|
end
|
230
230
|
|
231
231
|
it "should pass view options declared in the view declaration to the query" do
|
232
|
-
view_query =
|
233
|
-
CouchPotato::View::ViewQuery.
|
234
|
-
view_query.
|
232
|
+
view_query = double 'view_query'
|
233
|
+
allow(CouchPotato::View::ViewQuery).to receive(:new).and_return(view_query)
|
234
|
+
expect(view_query).to receive(:query_view!).with(hash_including(:group => true)).and_return({'rows' => []})
|
235
235
|
@db.view(Build.with_view_options)
|
236
236
|
end
|
237
237
|
end
|
@@ -239,15 +239,15 @@ describe 'views' do
|
|
239
239
|
describe "inherited views" do
|
240
240
|
it "should support parent views for objects of the subclass" do
|
241
241
|
@db.save_document CustomBuild.new(:state => 'success', :time => '2008-01-01')
|
242
|
-
@db.view(CustomBuild.timeline).size.
|
243
|
-
@db.view(CustomBuild.timeline).first.
|
242
|
+
expect(@db.view(CustomBuild.timeline).size).to eq(1)
|
243
|
+
expect(@db.view(CustomBuild.timeline).first).to be_kind_of(CustomBuild)
|
244
244
|
end
|
245
245
|
|
246
246
|
it "should return instances of subclasses as well if a special view exists" do
|
247
247
|
@db.save_document Build.new(:state => 'success', :time => '2008-01-01')
|
248
248
|
@db.save_document CustomBuild.new(:state => 'success', :time => '2008-01-01', :server => 'Jenkins')
|
249
249
|
results = @db.view(Build.all)
|
250
|
-
results.map(&:class).
|
250
|
+
expect(results.map(&:class)).to eq([CustomBuild, Build])
|
251
251
|
end
|
252
252
|
end
|
253
253
|
|
@@ -275,12 +275,12 @@ describe 'views' do
|
|
275
275
|
|
276
276
|
it "should use the list function declared at class level" do
|
277
277
|
@db.save! Coworker.new(:name => 'joe')
|
278
|
-
@db.view(Coworker.all_with_list).first.name.
|
278
|
+
expect(@db.view(Coworker.all_with_list).first.name).to eq('joe doe')
|
279
279
|
end
|
280
280
|
|
281
281
|
it "should use the list function passed at runtime" do
|
282
282
|
@db.save! Coworker.new(:name => 'joe')
|
283
|
-
@db.view(Coworker.all(:list => :append_doe)).first.name.
|
283
|
+
expect(@db.view(Coworker.all(:list => :append_doe)).first.name).to eq('joe doe')
|
284
284
|
end
|
285
285
|
end
|
286
286
|
|