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
@@ -8,7 +8,7 @@ end
|
|
8
8
|
|
9
9
|
describe 'dirty attribute tracking' do
|
10
10
|
before(:each) do
|
11
|
-
@couchrest_db =
|
11
|
+
@couchrest_db = double('database', :save_doc => {'id' => '1', 'rev' => '2'}, :info => nil)
|
12
12
|
@db = CouchPotato::Database.new(@couchrest_db)
|
13
13
|
end
|
14
14
|
|
@@ -16,21 +16,21 @@ describe 'dirty attribute tracking' do
|
|
16
16
|
it "should not save when nothing dirty" do
|
17
17
|
plate = Plate.new :food => 'sushi'
|
18
18
|
@db.save_document!(plate)
|
19
|
-
@couchrest_db.
|
19
|
+
expect(@couchrest_db).not_to receive(:save_doc)
|
20
20
|
@db.save_document(plate)
|
21
21
|
end
|
22
22
|
|
23
23
|
it "should return true when not dirty" do
|
24
24
|
plate = Plate.new :food => 'sushi'
|
25
25
|
@db.save_document!(plate)
|
26
|
-
@db.save_document(plate).
|
26
|
+
expect(@db.save_document(plate)).to be_truthy
|
27
27
|
end
|
28
28
|
|
29
29
|
it "should save when there are dirty attributes" do
|
30
30
|
plate = Plate.new :food => 'sushi'
|
31
31
|
@db.save_document!(plate)
|
32
32
|
plate.food = 'burger'
|
33
|
-
@couchrest_db.
|
33
|
+
expect(@couchrest_db).to receive(:save_doc)
|
34
34
|
@db.save_document(plate)
|
35
35
|
end
|
36
36
|
end
|
@@ -44,7 +44,7 @@ describe 'dirty attribute tracking' do
|
|
44
44
|
describe "access old values" do
|
45
45
|
it "should return the old value" do
|
46
46
|
@plate.food = 'burger'
|
47
|
-
@plate.food_was.
|
47
|
+
expect(@plate.food_was).to eq('sushi')
|
48
48
|
end
|
49
49
|
|
50
50
|
describe "with type BigDecimal" do
|
@@ -56,15 +56,15 @@ describe 'dirty attribute tracking' do
|
|
56
56
|
end
|
57
57
|
it "should not dup BigDecimal" do
|
58
58
|
|
59
|
-
|
59
|
+
expect {
|
60
60
|
Bowl.new :price => BigDecimal.new("5.23")
|
61
|
-
}.
|
61
|
+
}.not_to raise_error
|
62
62
|
end
|
63
63
|
|
64
64
|
it "should return the old value" do
|
65
65
|
bowl = Bowl.new :price => BigDecimal.new("5.23")
|
66
66
|
bowl.price = BigDecimal.new("2.23")
|
67
|
-
bowl.price_was.
|
67
|
+
expect(bowl.price_was).to eq(5.23)
|
68
68
|
end
|
69
69
|
|
70
70
|
end
|
@@ -73,41 +73,41 @@ describe 'dirty attribute tracking' do
|
|
73
73
|
describe "check for dirty" do
|
74
74
|
it "should return true if attribute changed" do
|
75
75
|
@plate.food = 'burger'
|
76
|
-
@plate.
|
76
|
+
expect(@plate).to be_food_changed
|
77
77
|
end
|
78
78
|
|
79
79
|
it "should return false if attribute not changed" do
|
80
|
-
Plate.new.
|
80
|
+
expect(Plate.new).not_to be_food_changed
|
81
81
|
end
|
82
82
|
|
83
83
|
it "should return true if forced dirty" do
|
84
84
|
@plate.is_dirty
|
85
|
-
@plate.
|
85
|
+
expect(@plate).to be_dirty
|
86
86
|
end
|
87
87
|
end
|
88
88
|
end
|
89
89
|
|
90
90
|
describe "object loaded from database" do
|
91
91
|
before(:each) do
|
92
|
-
couchrest_db =
|
92
|
+
couchrest_db = double('database', :get => Plate.json_create({'_id' => '1', '_rev' => '2', 'food' => 'sushi', JSON.create_id => 'Plate'}), :info => nil)
|
93
93
|
@plate = CouchPotato::Database.new(couchrest_db).load_document '1'
|
94
94
|
end
|
95
95
|
|
96
96
|
describe "access old values" do
|
97
97
|
it "should return the old value" do
|
98
98
|
@plate.food = 'burger'
|
99
|
-
@plate.food_was.
|
99
|
+
expect(@plate.food_was).to eq('sushi')
|
100
100
|
end
|
101
101
|
end
|
102
102
|
|
103
103
|
describe "check for dirty" do
|
104
104
|
it "should return true if attribute changed" do
|
105
105
|
@plate.food = 'burger'
|
106
|
-
@plate.
|
106
|
+
expect(@plate).to be_food_changed
|
107
107
|
end
|
108
108
|
|
109
109
|
it "should return false if attribute not changed" do
|
110
|
-
@plate.
|
110
|
+
expect(@plate).not_to be_food_changed
|
111
111
|
end
|
112
112
|
end
|
113
113
|
end
|
@@ -115,21 +115,21 @@ describe 'dirty attribute tracking' do
|
|
115
115
|
|
116
116
|
describe "after save" do
|
117
117
|
it "should reset all attributes to not dirty" do
|
118
|
-
couchrest_db =
|
118
|
+
couchrest_db = double('database', :get => Plate.json_create({'_id' => '1', '_rev' => '2', 'food' => 'sushi', JSON.create_id => 'Plate'}), :info => nil, :save_doc => {})
|
119
119
|
db = CouchPotato::Database.new(couchrest_db)
|
120
120
|
@plate = db.load_document '1'
|
121
121
|
@plate.food = 'burger'
|
122
122
|
db.save! @plate
|
123
|
-
@plate.
|
123
|
+
expect(@plate).not_to be_food_changed
|
124
124
|
end
|
125
125
|
|
126
126
|
it "should reset a forced dirty state" do
|
127
|
-
couchrest_db =
|
127
|
+
couchrest_db = double('database', :get => Plate.json_create({'_id' => '1', '_rev' => '2', 'food' => 'sushi', JSON.create_id => 'Plate'}), :info => nil, :save_doc => {'rev' => '3'})
|
128
128
|
db = CouchPotato::Database.new(couchrest_db)
|
129
129
|
@plate = db.load_document '1'
|
130
130
|
@plate.is_dirty
|
131
131
|
db.save! @plate
|
132
|
-
@plate.
|
132
|
+
expect(@plate).not_to be_dirty
|
133
133
|
end
|
134
134
|
end
|
135
135
|
|
@@ -16,13 +16,13 @@ begin
|
|
16
16
|
it 'raises no error when passing permitted attributes' do
|
17
17
|
expect {
|
18
18
|
Child.new ActionController::Parameters.new(:text => 'xx').permit!
|
19
|
-
}.to_not raise_error
|
19
|
+
}.to_not raise_error
|
20
20
|
end
|
21
21
|
|
22
22
|
it "raises no error when passing attributes that don't respond to permitted?" do
|
23
23
|
expect {
|
24
24
|
Child.new :text => 'xx'
|
25
|
-
}.to_not raise_error
|
25
|
+
}.to_not raise_error
|
26
26
|
end
|
27
27
|
end
|
28
28
|
|
@@ -38,13 +38,13 @@ begin
|
|
38
38
|
it 'raises no error when passing permitted attributes' do
|
39
39
|
expect {
|
40
40
|
subject.attributes = ActionController::Parameters.new(:text => 'xx').permit!
|
41
|
-
}.to_not raise_error
|
41
|
+
}.to_not raise_error
|
42
42
|
end
|
43
43
|
|
44
44
|
it "raises no error when passing attributes that don't respond to permitted?" do
|
45
45
|
expect {
|
46
46
|
subject.attributes = {:text => 'xx'}
|
47
|
-
}.to_not raise_error
|
47
|
+
}.to_not raise_error
|
48
48
|
end
|
49
49
|
end
|
50
50
|
end
|
@@ -2,37 +2,55 @@ require 'spec_helper'
|
|
2
2
|
|
3
3
|
class Document
|
4
4
|
include CouchPotato::Persistence
|
5
|
-
|
5
|
+
|
6
6
|
property :title
|
7
7
|
property :content
|
8
8
|
end
|
9
9
|
|
10
|
-
describe
|
11
|
-
context
|
10
|
+
describe 'new' do
|
11
|
+
context 'without arguments' do
|
12
12
|
subject { Document.new }
|
13
13
|
|
14
|
-
it {
|
15
|
-
|
16
|
-
|
14
|
+
it { is_expected.to be_a(Document) }
|
15
|
+
|
16
|
+
it 'has no title' do
|
17
|
+
expect(subject.title).to be_nil
|
18
|
+
end
|
19
|
+
|
20
|
+
it 'has no content' do
|
21
|
+
expect(subject.content).to be_nil
|
22
|
+
end
|
17
23
|
end
|
18
24
|
|
19
|
-
context
|
20
|
-
subject { Document.new(:
|
25
|
+
context 'with an argument hash' do
|
26
|
+
subject { Document.new(title: 'My Title') }
|
27
|
+
|
28
|
+
it { is_expected.to be_a(Document) }
|
21
29
|
|
22
|
-
it
|
23
|
-
|
24
|
-
|
30
|
+
it 'has a title' do
|
31
|
+
expect(subject.title).to eql('My Title')
|
32
|
+
end
|
33
|
+
|
34
|
+
it 'has no content' do
|
35
|
+
expect(subject.content).to be_nil
|
36
|
+
end
|
25
37
|
end
|
26
38
|
|
27
|
-
context
|
28
|
-
subject
|
29
|
-
Document.new(:
|
39
|
+
context 'yielding to a block' do
|
40
|
+
subject do
|
41
|
+
Document.new(title: 'My Title') do |doc|
|
30
42
|
doc.content = 'My Content'
|
31
43
|
end
|
32
|
-
|
44
|
+
end
|
45
|
+
|
46
|
+
it { is_expected.to be_a(Document) }
|
33
47
|
|
34
|
-
it
|
35
|
-
|
36
|
-
|
48
|
+
it 'has a title' do
|
49
|
+
expect(subject.title).to eql('My Title')
|
50
|
+
end
|
51
|
+
|
52
|
+
it 'has a content' do
|
53
|
+
expect(subject.content).to eql('My Content')
|
54
|
+
end
|
37
55
|
end
|
38
|
-
end
|
56
|
+
end
|
data/spec/unit/json_spec.rb
CHANGED
@@ -10,12 +10,12 @@ describe CouchPotato::Persistence::Json do
|
|
10
10
|
context '#to_hash' do
|
11
11
|
it "should inject JSON.create_id into the hash representation of a persistent object" do
|
12
12
|
sake = Drink.new(:alcohol => "18%")
|
13
|
-
sake.to_hash[JSON.create_id].
|
13
|
+
expect(sake.to_hash[JSON.create_id]).to eql("Drink")
|
14
14
|
end
|
15
15
|
|
16
16
|
it "should not include _attachments if there are none" do
|
17
17
|
sake = Drink.new(:alcohol => "18%")
|
18
|
-
sake.to_hash.keys.
|
18
|
+
expect(sake.to_hash.keys).not_to include('_attachments')
|
19
19
|
end
|
20
20
|
|
21
21
|
end
|
@@ -23,8 +23,8 @@ describe CouchPotato::Persistence::Json do
|
|
23
23
|
context '.json_create' do
|
24
24
|
it 'should assign the _document' do
|
25
25
|
sake = Drink.json_create({"alcohol" => "18%"})
|
26
|
-
sake._document.
|
26
|
+
expect(sake._document).to eq({"alcohol" => "18%"})
|
27
27
|
end
|
28
28
|
end
|
29
29
|
|
30
|
-
end
|
30
|
+
end
|
data/spec/unit/lists_spec.rb
CHANGED
@@ -1,20 +1,20 @@
|
|
1
1
|
require 'spec_helper'
|
2
2
|
|
3
3
|
describe CouchPotato::View::Lists, '.list' do
|
4
|
-
it
|
4
|
+
it 'should make the list function available via .lists' do
|
5
5
|
clazz = Class.new
|
6
6
|
clazz.send :include, CouchPotato::View::Lists
|
7
7
|
clazz.list 'my_list', '<list_code>'
|
8
|
-
|
9
|
-
clazz.lists('my_list').
|
8
|
+
|
9
|
+
expect(clazz.lists('my_list')).to eq('<list_code>')
|
10
10
|
end
|
11
|
-
|
12
|
-
it
|
11
|
+
|
12
|
+
it 'should make the list available to subclasses' do
|
13
13
|
clazz = Class.new
|
14
14
|
clazz.send :include, CouchPotato::View::Lists
|
15
15
|
clazz.list 'my_list', '<list_code>'
|
16
16
|
sub_clazz = Class.new clazz
|
17
|
-
|
18
|
-
sub_clazz.lists('my_list').
|
17
|
+
|
18
|
+
expect(sub_clazz.lists('my_list')).to eq('<list_code>')
|
19
19
|
end
|
20
|
-
end
|
20
|
+
end
|
@@ -26,12 +26,12 @@ end
|
|
26
26
|
describe CouchPotato::View::ModelViewSpec, '#map_function' do
|
27
27
|
it "should include conditions" do
|
28
28
|
spec = CouchPotato::View::ModelViewSpec.new Object, 'all', {:conditions => 'doc.closed = true'}, {}
|
29
|
-
spec.map_function.
|
29
|
+
expect(spec.map_function).to include('if(doc.ruby_class && doc.ruby_class == \'Object\' && (doc.closed = true))')
|
30
30
|
end
|
31
31
|
|
32
32
|
it 'generates an erlang map function with a single key if the language is erlang' do
|
33
33
|
spec = CouchPotato::View::ModelViewSpec.new Object, 'all', {:key => :name, :language => :erlang}, {}
|
34
|
-
spec.map_function.
|
34
|
+
expect(spec.map_function).to eql_ignoring_indentation(<<-ERL
|
35
35
|
fun({Doc}) ->
|
36
36
|
case proplists:get_value(<<"ruby_class">>, Doc) of
|
37
37
|
<<"Object">> ->
|
@@ -47,7 +47,7 @@ describe CouchPotato::View::ModelViewSpec, '#map_function' do
|
|
47
47
|
|
48
48
|
it 'generates an erlang map function with a composite key if the language is erlang' do
|
49
49
|
spec = CouchPotato::View::ModelViewSpec.new Object, 'all', {:key => [:code, :name], :language => :erlang}, {}
|
50
|
-
spec.map_function.
|
50
|
+
expect(spec.map_function).to eql_ignoring_indentation(<<-ERL
|
51
51
|
fun({Doc}) ->
|
52
52
|
case proplists:get_value(<<"ruby_class">>, Doc) of
|
53
53
|
<<"Object">> ->
|
@@ -64,50 +64,50 @@ describe CouchPotato::View::ModelViewSpec, '#map_function' do
|
|
64
64
|
|
65
65
|
it 'does not support conditions in erlang' do
|
66
66
|
spec = CouchPotato::View::ModelViewSpec.new Object, 'all', {:language => :erlang, :conditions => 'abc'}, {}
|
67
|
-
|
67
|
+
expect {
|
68
68
|
spec.map_function
|
69
|
-
}.
|
69
|
+
}.to raise_error(NotImplementedError)
|
70
70
|
end
|
71
71
|
|
72
72
|
it 'does not support a custom emit value in erlang' do
|
73
73
|
spec = CouchPotato::View::ModelViewSpec.new Object, 'all', {:language => :erlang, :emit_value => :count}, {}
|
74
|
-
|
74
|
+
expect {
|
75
75
|
spec.map_function
|
76
|
-
}.
|
76
|
+
}.to raise_error(NotImplementedError)
|
77
77
|
end
|
78
78
|
|
79
79
|
it "should not include conditions when they are nil" do
|
80
80
|
spec = CouchPotato::View::ModelViewSpec.new Object, 'all', {}, {}
|
81
|
-
spec.map_function.
|
81
|
+
expect(spec.map_function).to include('if(doc.ruby_class && doc.ruby_class == \'Object\')')
|
82
82
|
end
|
83
83
|
|
84
84
|
it "should have a custom emit value when specified as symbol" do
|
85
85
|
spec = CouchPotato::View::ModelViewSpec.new Object, 'all', {:emit_value => :count}, {}
|
86
|
-
spec.map_function.
|
86
|
+
expect(spec.map_function).to include(%{emit(doc[''], doc['count'])})
|
87
87
|
end
|
88
88
|
|
89
89
|
it "should have a custom emit value when specified as string" do
|
90
90
|
spec = CouchPotato::View::ModelViewSpec.new Object, 'all', {:emit_value => "doc['a'] + doc['b']"}, {}
|
91
|
-
spec.map_function.
|
91
|
+
expect(spec.map_function).to include("emit(doc[''], doc['a'] + doc['b'])")
|
92
92
|
end
|
93
93
|
|
94
94
|
it "should have a custom emit value when specified as integer" do
|
95
95
|
spec = CouchPotato::View::ModelViewSpec.new Object, 'all', {:emit_value => 7}, {}
|
96
|
-
spec.map_function.
|
96
|
+
expect(spec.map_function).to include("emit(doc[''], 7)")
|
97
97
|
end
|
98
98
|
|
99
99
|
it "should have a custom emit value when specified as float" do
|
100
100
|
spec = CouchPotato::View::ModelViewSpec.new Object, 'all', {:emit_value => 7.2}, {}
|
101
|
-
spec.map_function.
|
101
|
+
expect(spec.map_function).to include("emit(doc[''], 7.2")
|
102
102
|
end
|
103
103
|
|
104
104
|
it "should have a emit value of 1 when nothing is specified" do
|
105
105
|
spec = CouchPotato::View::ModelViewSpec.new Object, 'all', {}, {}
|
106
|
-
spec.map_function.
|
106
|
+
expect(spec.map_function).to include("emit(doc[''], 1")
|
107
107
|
end
|
108
108
|
|
109
109
|
it "should raise exception when emit value cannot be handled" do
|
110
110
|
spec = CouchPotato::View::ModelViewSpec.new Object, 'all', {:emit_value => []}, {}
|
111
|
-
|
111
|
+
expect { spec.map_function }.to raise_error
|
112
112
|
end
|
113
113
|
end
|
@@ -18,23 +18,23 @@ describe "persistence" do
|
|
18
18
|
|
19
19
|
none_dude22 = NoneDude.new(:id => "22", :name => "foo")
|
20
20
|
|
21
|
-
dude22.
|
22
|
-
dude22.
|
23
|
-
dude22.
|
21
|
+
expect(dude22).to eql(dude22)
|
22
|
+
expect(dude22).not_to eql(none_dude22)
|
23
|
+
expect(dude22).not_to eql(dude11)
|
24
24
|
end
|
25
25
|
|
26
26
|
it "should handle new objects without id to be never equal" do
|
27
27
|
dude = Dude.new(:name => "foo")
|
28
28
|
dude22 = Dude.new(:id => "22", :name => "foo")
|
29
29
|
|
30
|
-
dude.
|
31
|
-
dude22.
|
30
|
+
expect(dude).not_to eql(Dude.new(:name => "foo"))
|
31
|
+
expect(dude22).not_to eql(Dude.new(:name => "foo"))
|
32
32
|
end
|
33
33
|
|
34
34
|
it "should handle same object references to be equal" do
|
35
35
|
dude = Dude.new(:name => "foo")
|
36
36
|
|
37
|
-
dude.
|
37
|
+
expect(dude).to eql(dude)
|
38
38
|
end
|
39
39
|
end
|
40
40
|
end
|
@@ -20,25 +20,25 @@ describe CouchPotato::View::PropertiesViewSpec do
|
|
20
20
|
end
|
21
21
|
|
22
22
|
it "should map the given properties" do
|
23
|
-
Contract.by_date.
|
23
|
+
expect(Contract.by_date).to map(
|
24
24
|
Contract.new(:date => '2010-01-01', :_id => '1')
|
25
25
|
).to(['1', {"date" => "2010-01-01"}])
|
26
26
|
end
|
27
27
|
|
28
28
|
it "should reduce to the number of documents" do
|
29
|
-
Contract.by_date.
|
29
|
+
expect(Contract.by_date).to reduce(
|
30
30
|
['1', {"date" => "2010-01-01"}], ['2', {"date" => "2010-01-02"}]
|
31
31
|
).to(2)
|
32
32
|
end
|
33
33
|
|
34
34
|
it "should rereduce the number of documents" do
|
35
|
-
Contract.by_date.
|
35
|
+
expect(Contract.by_date).to rereduce(
|
36
36
|
nil, [12, 13]
|
37
37
|
).to(25)
|
38
38
|
end
|
39
39
|
|
40
40
|
it 'always uses javascript' do
|
41
41
|
CouchPotato::Config.default_language = :erlang
|
42
|
-
CouchPotato::View::PropertiesViewSpec.new(Contract, 'all', {}, {}).language.
|
42
|
+
expect(CouchPotato::View::PropertiesViewSpec.new(Contract, 'all', {}, {}).language).to eq(:javascript)
|
43
43
|
end
|
44
44
|
end
|
@@ -1,79 +1,79 @@
|
|
1
1
|
require 'spec_helper'
|
2
|
-
require 'couch_potato
|
2
|
+
require 'couch_potato-rspec'
|
3
3
|
|
4
4
|
describe CouchPotato::RSpec::MapToMatcher do
|
5
5
|
|
6
6
|
describe "basic map function" do
|
7
7
|
before(:each) do
|
8
|
-
@view_spec =
|
8
|
+
@view_spec = double(:map_function => "function(doc) {emit(doc.name, doc.tags.length);}")
|
9
9
|
end
|
10
10
|
|
11
11
|
it "should pass if the given function emits the expected javascript" do
|
12
|
-
@view_spec.
|
12
|
+
expect(@view_spec).to map({:name => 'horst', :tags => ['person', 'male']}).to(['horst', 2])
|
13
13
|
end
|
14
14
|
|
15
15
|
it "should not pass if the given function emits different javascript" do
|
16
|
-
@view_spec.
|
16
|
+
expect(@view_spec).not_to map({:name => 'horst', :tags => ['person', 'male']}).to(['horst', 3])
|
17
17
|
end
|
18
18
|
end
|
19
19
|
|
20
20
|
describe "functions emitting multiple times" do
|
21
21
|
before(:each) do
|
22
|
-
@view_spec =
|
22
|
+
@view_spec = double(:map_function => "function(doc) {emit(doc.name, doc.tags.length); emit(doc.tags[0], doc.tags[1])};")
|
23
23
|
end
|
24
24
|
|
25
25
|
it "should pass if the given function emits the expected javascript" do
|
26
|
-
@view_spec.
|
26
|
+
expect(@view_spec).to map({:name => 'horst', :tags => ['person', 'male']}).to(['horst', 2], ['person', 'male'])
|
27
27
|
end
|
28
28
|
|
29
29
|
it "should return false if the given function emits different javascript" do
|
30
|
-
@view_spec.
|
30
|
+
expect(@view_spec).not_to map({:name => 'horst', :tags => ['person', 'male']}).to(['horst', 2], ['male', 'person'])
|
31
31
|
end
|
32
32
|
end
|
33
33
|
|
34
34
|
it "should work with date emit values" do
|
35
|
-
spec =
|
36
|
-
spec.
|
35
|
+
spec = double(:map_function => "function(doc) { emit(null, new Date(1368802800000)); }")
|
36
|
+
expect(spec).to map({}).to([nil, "2013-05-17T15:00:00.000Z"])
|
37
37
|
end
|
38
38
|
|
39
39
|
it "should work with commonJS modules that use 'exports'" do
|
40
|
-
spec =
|
40
|
+
spec = double(
|
41
41
|
:map_function => "function(doc) { var test = require('views/lib/test'); emit(null, test.test); }",
|
42
42
|
:lib => {:test => "exports.test = 'test';"}
|
43
43
|
)
|
44
|
-
spec.
|
44
|
+
expect(spec).to map({}).to([nil, "test"])
|
45
45
|
end
|
46
46
|
|
47
47
|
it "should work with commonJS modules that use 'module.exports'" do
|
48
|
-
spec =
|
48
|
+
spec = double(
|
49
49
|
:map_function => "function(doc) { var test = require('views/lib/test'); emit(null, test.test); }",
|
50
50
|
:lib => {:test => "module.exports.test = 'test';"}
|
51
51
|
)
|
52
|
-
spec.
|
52
|
+
expect(spec).to map({}).to([nil, "test"])
|
53
53
|
end
|
54
54
|
|
55
55
|
describe "failing specs" do
|
56
56
|
before(:each) do
|
57
|
-
@view_spec =
|
57
|
+
@view_spec = double(:map_function => "function(doc) {emit(doc.name, null)}")
|
58
58
|
end
|
59
59
|
|
60
60
|
it "should have a nice error message for failing should" do
|
61
|
-
|
62
|
-
@view_spec.
|
63
|
-
}.
|
61
|
+
expect {
|
62
|
+
expect(@view_spec).to map({:name => 'bill'}).to(['linus', nil])
|
63
|
+
}.to raise_error('Expected to map to [["linus", nil]] but got [["bill", nil]].')
|
64
64
|
end
|
65
65
|
|
66
66
|
it "should have a nice error message for failing should not" do
|
67
|
-
|
68
|
-
@view_spec.
|
69
|
-
}.
|
67
|
+
expect {
|
68
|
+
expect(@view_spec).not_to map({:name => 'bill'}).to(['bill', nil])
|
69
|
+
}.to raise_error('Expected not to map to [["bill", nil]] but did.')
|
70
70
|
end
|
71
71
|
end
|
72
72
|
end
|
73
73
|
|
74
74
|
describe CouchPotato::RSpec::ReduceToMatcher do
|
75
75
|
before(:each) do
|
76
|
-
@view_spec =
|
76
|
+
@view_spec = double(:reduce_function => "function(keys, values, rereduce) {
|
77
77
|
if(rereduce) {
|
78
78
|
return(sum(values) * 2);
|
79
79
|
} else {
|
@@ -83,47 +83,47 @@ describe CouchPotato::RSpec::ReduceToMatcher do
|
|
83
83
|
end
|
84
84
|
|
85
85
|
it "should pass if the given function return the expected javascript" do
|
86
|
-
@view_spec.
|
86
|
+
expect(@view_spec).to reduce([], [1, 2, 3]).to(6)
|
87
87
|
end
|
88
88
|
|
89
89
|
it "should not pass if the given function returns different javascript" do
|
90
|
-
@view_spec.
|
90
|
+
expect(@view_spec).not_to reduce([], [1, 2, 3]).to(7)
|
91
91
|
end
|
92
92
|
|
93
93
|
it "should work with date return values" do
|
94
|
-
spec =
|
95
|
-
spec.
|
94
|
+
spec = double(:reduce_function => "function() { return new Date(1368802800000); }")
|
95
|
+
expect(spec).to reduce([], []).to("2013-05-17T15:00:00.000Z")
|
96
96
|
end
|
97
97
|
|
98
98
|
describe "rereduce" do
|
99
99
|
it "should pass if the given function return the expected javascript" do
|
100
|
-
@view_spec.
|
100
|
+
expect(@view_spec).to rereduce([], [1, 2, 3]).to(12)
|
101
101
|
end
|
102
102
|
|
103
103
|
it "should not pass if the given function returns different javascript" do
|
104
|
-
@view_spec.
|
104
|
+
expect(@view_spec).not_to rereduce([], [1, 2, 3]).to(13)
|
105
105
|
end
|
106
106
|
end
|
107
107
|
|
108
108
|
describe 'failing specs' do
|
109
109
|
|
110
110
|
it "should have a nice error message for failing should" do
|
111
|
-
|
112
|
-
@view_spec.
|
113
|
-
}.
|
111
|
+
expect {
|
112
|
+
expect(@view_spec).to reduce([], [1, 2, 3]).to(7)
|
113
|
+
}.to raise_error('Expected to reduce to 7 but got 6.')
|
114
114
|
end
|
115
115
|
|
116
116
|
it "should have a nice error message for failing should not" do
|
117
|
-
|
118
|
-
@view_spec.
|
119
|
-
}.
|
117
|
+
expect {
|
118
|
+
expect(@view_spec).not_to reduce([], [1, 2, 3]).to(6)
|
119
|
+
}.to raise_error('Expected not to reduce to 6 but did.')
|
120
120
|
end
|
121
121
|
end
|
122
122
|
end
|
123
123
|
|
124
124
|
describe CouchPotato::RSpec::MapReduceToMatcher do
|
125
125
|
before(:each) do
|
126
|
-
@view_spec =
|
126
|
+
@view_spec = double(
|
127
127
|
:map_function => "function(doc) {
|
128
128
|
for (var i in doc.numbers)
|
129
129
|
emit([doc.age, doc.name], doc.numbers[i]);
|
@@ -140,48 +140,48 @@ describe CouchPotato::RSpec::MapReduceToMatcher do
|
|
140
140
|
end
|
141
141
|
|
142
142
|
it "should handle date return values" do
|
143
|
-
spec =
|
143
|
+
spec = double(:map_function => "function() { emit(null, null); }",
|
144
144
|
:reduce_function => "function() { return new Date(1368802800000); }")
|
145
|
-
spec.
|
145
|
+
expect(spec).to map_reduce({}).to({"key" => nil, "value" => "2013-05-17T15:00:00.000Z"})
|
146
146
|
end
|
147
147
|
|
148
148
|
it "should handle CommonJS requires for modules that use 'exports'" do
|
149
|
-
spec =
|
149
|
+
spec = double(
|
150
150
|
:map_function => "function() { var test = require('views/lib/test'); emit(null, test.test); }",
|
151
151
|
:reduce_function => "function(keys, values) { return 'test' }",
|
152
152
|
:lib => {:test => "exports.test = 'test'"})
|
153
|
-
spec.
|
153
|
+
expect(spec).to map_reduce({}).to({"key" => nil, "value" => "test"})
|
154
154
|
end
|
155
155
|
|
156
156
|
it "should handle CommonJS requires for modules that use 'module.exports'" do
|
157
|
-
spec =
|
157
|
+
spec = double(
|
158
158
|
:map_function => "function() { var test = require('views/lib/test'); emit(null, test.test); }",
|
159
159
|
:reduce_function => "function(keys, values) { return 'test' }",
|
160
160
|
:lib => {:test => "module.exports.test = 'test'"})
|
161
|
-
spec.
|
161
|
+
expect(spec).to map_reduce({}).to({"key" => nil, "value" => "test"})
|
162
162
|
end
|
163
163
|
|
164
164
|
it "should handle sum function" do
|
165
|
-
spec =
|
165
|
+
spec = double(
|
166
166
|
:map_function => "function(doc) { emit(null, doc.age); }",
|
167
167
|
:reduce_function => "function(keys, values) { return sum(values); }")
|
168
|
-
spec.
|
168
|
+
expect(spec).to map_reduce(@docs).to({"key" => nil, "value" => 103})
|
169
169
|
end
|
170
170
|
|
171
171
|
context "without grouping" do
|
172
172
|
it "should not group by key by default" do
|
173
|
-
@view_spec.
|
173
|
+
expect(@view_spec).to map_reduce(@docs).to({"key" => nil, "value" => 8})
|
174
174
|
end
|
175
175
|
|
176
176
|
it "should group by key with :group => false" do
|
177
|
-
@view_spec.
|
177
|
+
expect(@view_spec).to map_reduce(@docs).with_options(:group => false).to({"key" => nil, "value" => 8})
|
178
178
|
end
|
179
179
|
end
|
180
180
|
|
181
181
|
context "with grouping" do
|
182
182
|
[true, "exact"].each do |group_value|
|
183
183
|
it "should group by the full key with option :group => #{group_value}" do
|
184
|
-
@view_spec.
|
184
|
+
expect(@view_spec).to map_reduce(@docs).with_options(:group => group_value).to(
|
185
185
|
{"key" => [25, "a"], "value" => 2},
|
186
186
|
{"key" => [25, "b"], "value" => 4},
|
187
187
|
{"key" => [26, "c"], "value" => 6},
|
@@ -190,7 +190,7 @@ describe CouchPotato::RSpec::MapReduceToMatcher do
|
|
190
190
|
end
|
191
191
|
|
192
192
|
it "should group by parts of the keys based on the :group_level option" do
|
193
|
-
@view_spec.
|
193
|
+
expect(@view_spec).to map_reduce(@docs).with_options(:group_level => 1).to(
|
194
194
|
{"key" => [25], "value" => 4},
|
195
195
|
{"key" => [26], "value" => 6},
|
196
196
|
{"key" => [27], "value" => 8})
|
@@ -199,7 +199,7 @@ describe CouchPotato::RSpec::MapReduceToMatcher do
|
|
199
199
|
|
200
200
|
describe "rereducing" do
|
201
201
|
before :each do
|
202
|
-
@view_spec =
|
202
|
+
@view_spec = double(:map_function => "function(doc) {
|
203
203
|
emit(doc.name, doc.number);
|
204
204
|
}",
|
205
205
|
:reduce_function => "function (keys, values, rereduce) {
|
@@ -215,7 +215,7 @@ describe CouchPotato::RSpec::MapReduceToMatcher do
|
|
215
215
|
end
|
216
216
|
|
217
217
|
it "should reduce and rereduce for a single emit" do
|
218
|
-
@view_spec.
|
218
|
+
expect(@view_spec).to map_reduce({:name => "a", :number => 1}).to({"key" => nil, "value" => {"rereduce_values" => [[1]]}})
|
219
219
|
end
|
220
220
|
|
221
221
|
it "should split and reduce each half of emitted values separately and rereduce the results" do
|
@@ -224,7 +224,7 @@ describe CouchPotato::RSpec::MapReduceToMatcher do
|
|
224
224
|
{:name => "a", :number => 2},
|
225
225
|
{:name => "a", :number => 3},
|
226
226
|
{:name => "a", :number => 4}]
|
227
|
-
@view_spec.
|
227
|
+
expect(@view_spec).to map_reduce(docs).to({"key" => nil, "value" => {"rereduce_values" => [[1, 2], [3, 4]]}})
|
228
228
|
end
|
229
229
|
|
230
230
|
it "should correctly split and rereduce with an odd number of emits" do
|
@@ -232,43 +232,43 @@ describe CouchPotato::RSpec::MapReduceToMatcher do
|
|
232
232
|
{:name => "a", :number => 1},
|
233
233
|
{:name => "a", :number => 2},
|
234
234
|
{:name => "a", :number => 3}]
|
235
|
-
@view_spec.
|
235
|
+
expect(@view_spec).to map_reduce(docs).to({"key" => nil, "value" => {"rereduce_values" => [[1], [2, 3]]}})
|
236
236
|
end
|
237
237
|
end
|
238
238
|
|
239
239
|
describe "failing specs" do
|
240
240
|
it "should have a nice error message for failing should" do
|
241
|
-
|
242
|
-
@view_spec.
|
243
|
-
}.
|
241
|
+
expect {
|
242
|
+
expect(@view_spec).to map_reduce(@docs).with_options(:group => false).to({"key" => nil, "value" => 9})
|
243
|
+
}.to raise_error('Expected to map/reduce to [{"key"=>nil, "value"=>9}] but got [{"key"=>nil, "value"=>8}].')
|
244
244
|
end
|
245
245
|
|
246
246
|
it "should have a nice error message for failing should not" do
|
247
|
-
|
248
|
-
@view_spec.
|
249
|
-
}.
|
247
|
+
expect {
|
248
|
+
expect(@view_spec).not_to map_reduce(@docs).with_options(:group => false).to({"key" => nil, "value" => 8})
|
249
|
+
}.to raise_error('Expected not to map/reduce to [{"key"=>nil, "value"=>8}] but did.')
|
250
250
|
end
|
251
251
|
end
|
252
252
|
|
253
253
|
describe "couchdb built-in reduce functions" do
|
254
254
|
describe "_sum" do
|
255
255
|
it "should return the sum of emitted values" do
|
256
|
-
spec =
|
257
|
-
spec.
|
256
|
+
spec = double(:map_function => @view_spec.map_function, :reduce_function => "_sum")
|
257
|
+
expect(spec).to map_reduce(@docs).to({"key" => nil, "value" => 36})
|
258
258
|
end
|
259
259
|
end
|
260
260
|
|
261
261
|
describe "_count" do
|
262
262
|
it "should return the count of emitted values" do
|
263
|
-
spec =
|
264
|
-
spec.
|
263
|
+
spec = double(:map_function => @view_spec.map_function, :reduce_function => "_count")
|
264
|
+
expect(spec).to map_reduce(@docs).to({"key" => nil, "value" => 8})
|
265
265
|
end
|
266
266
|
end
|
267
267
|
|
268
268
|
describe "_stats" do
|
269
269
|
it "should return the numerical statistics of emitted values" do
|
270
|
-
spec =
|
271
|
-
spec.
|
270
|
+
spec = double(:map_function => @view_spec.map_function, :reduce_function => "_stats")
|
271
|
+
expect(spec).to map_reduce(@docs).to({
|
272
272
|
"key" => nil,
|
273
273
|
"value" => {
|
274
274
|
"sum" => 36,
|
@@ -285,33 +285,33 @@ end
|
|
285
285
|
|
286
286
|
describe CouchPotato::RSpec::ListAsMatcher do
|
287
287
|
before(:each) do
|
288
|
-
@view_spec =
|
288
|
+
@view_spec = double(:list_function => "function() {var row = getRow(); send(JSON.stringify([{text: row.text + ' world'}]));}")
|
289
289
|
end
|
290
290
|
|
291
291
|
it "should pass if the function return the expected json" do
|
292
|
-
@view_spec.
|
292
|
+
expect(@view_spec).to list({'rows' => [{:text => 'hello'}]}).as([{'text' => 'hello world'}])
|
293
293
|
end
|
294
294
|
|
295
295
|
it "should not pass if the function does not return the expected json" do
|
296
|
-
@view_spec.
|
296
|
+
expect(@view_spec).not_to list({'rows' => [{:text => 'hello'}]}).as([{'text' => 'hello there'}])
|
297
297
|
end
|
298
298
|
|
299
299
|
it "should work with date values" do
|
300
|
-
spec =
|
301
|
-
spec.
|
300
|
+
spec = double(:list_function => "function() { send(JSON.stringify([{date: new Date(1368802800000)}])); }")
|
301
|
+
expect(spec).to list({"rows" => [{}]}).as([{"date" => "2013-05-17T15:00:00.000Z"}])
|
302
302
|
end
|
303
303
|
|
304
304
|
describe "failing specs" do
|
305
305
|
it "should have a nice error message for failing should" do
|
306
|
-
|
307
|
-
@view_spec.
|
308
|
-
}.
|
306
|
+
expect {
|
307
|
+
expect(@view_spec).to list({'rows' => [{:text => 'hello'}]}).as([{'text' => 'hello there'}])
|
308
|
+
}.to raise_error('Expected to list as [{"text"=>"hello there"}] but got [{"text"=>"hello world"}].')
|
309
309
|
end
|
310
310
|
|
311
311
|
it "should have a nice error message for failing should not" do
|
312
|
-
|
313
|
-
@view_spec.
|
314
|
-
}.
|
312
|
+
expect {
|
313
|
+
expect(@view_spec).not_to list({'rows' => [{:text => 'hello'}]}).as([{'text' => 'hello world'}])
|
314
|
+
}.to raise_error('Expected to not list as [{"text"=>"hello world"}] but did.')
|
315
315
|
end
|
316
316
|
end
|
317
317
|
end
|