lucid_works 0.7.18 → 0.9.4

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.
Files changed (68) hide show
  1. data/.rvmrc +2 -3
  2. data/Gemfile +2 -8
  3. data/Gemfile.lock +45 -53
  4. data/README.rdoc +2 -6
  5. data/Rakefile +1 -1
  6. data/config/locales/en.yml +221 -239
  7. data/lib/lucid_works/activity.rb +8 -5
  8. data/lib/lucid_works/base.rb +27 -16
  9. data/lib/lucid_works/cache.rb +13 -0
  10. data/lib/lucid_works/cluster.rb +84 -0
  11. data/lib/lucid_works/collection/settings.rb +15 -6
  12. data/lib/lucid_works/collection.rb +62 -92
  13. data/lib/lucid_works/datasource/history.rb +2 -1
  14. data/lib/lucid_works/datasource/mapping.rb +12 -0
  15. data/lib/lucid_works/datasource/schedule.rb +5 -2
  16. data/lib/lucid_works/datasource/status.rb +3 -2
  17. data/lib/lucid_works/datasource.rb +31 -48
  18. data/lib/lucid_works/datasource_property.rb +2 -1
  19. data/lib/lucid_works/datasource_type.rb +14 -0
  20. data/lib/lucid_works/dynamicfield.rb +12 -0
  21. data/lib/lucid_works/elevation.rb +93 -0
  22. data/lib/lucid_works/exceptions.rb +0 -4
  23. data/lib/lucid_works/field.rb +31 -111
  24. data/lib/lucid_works/field_commons.rb +133 -0
  25. data/lib/lucid_works/gem_version.rb +1 -1
  26. data/lib/lucid_works/inflections.rb +3 -0
  27. data/lib/lucid_works/patch_time.rb +4 -0
  28. data/lib/lucid_works/request_handler.rb +16 -0
  29. data/lib/lucid_works/role.rb +23 -8
  30. data/lib/lucid_works/schema/attribute.rb +1 -1
  31. data/lib/lucid_works/schema/boolean_attribute.rb +1 -1
  32. data/lib/lucid_works/schema/integer_attribute.rb +3 -4
  33. data/lib/lucid_works/server/crawlers_status.rb +15 -0
  34. data/lib/lucid_works/server.rb +35 -14
  35. data/lib/lucid_works/simple_naming.rb +1 -7
  36. data/lib/lucid_works/synonym.rb +1 -1
  37. data/lib/lucid_works/version.rb +1 -0
  38. data/lib/lucid_works.rb +8 -1
  39. data/lucid_works.gemspec +8 -9
  40. data/spec/fixtures/zookeeper/clusterstate.json +30 -0
  41. data/spec/fixtures/zookeeper/clusterstate_broken_shard.json +29 -0
  42. data/spec/fixtures/zookeeper/live_nodes.json +28 -0
  43. data/spec/fixtures/zookeeper/live_nodes_no_children.json +26 -0
  44. data/spec/fixtures/zookeeper/live_nodes_one_child.json +36 -0
  45. data/spec/lib/lucid_works/base_spec.rb +33 -24
  46. data/spec/lib/lucid_works/cache_spec.rb +44 -0
  47. data/spec/lib/lucid_works/cluster_spec.rb +109 -0
  48. data/spec/lib/lucid_works/collection/activity_spec.rb +29 -0
  49. data/spec/lib/lucid_works/collection/prime_activities_spec.rb +1 -1
  50. data/spec/lib/lucid_works/collection/settings_spec.rb +31 -0
  51. data/spec/lib/lucid_works/collection_spec.rb +166 -107
  52. data/spec/lib/lucid_works/datasource/schedule_spec.rb +75 -46
  53. data/spec/lib/lucid_works/datasource/status_spec.rb +5 -5
  54. data/spec/lib/lucid_works/datasource_property_spec.rb +41 -0
  55. data/spec/lib/lucid_works/datasource_spec.rb +40 -12
  56. data/spec/lib/lucid_works/datasource_type_spec.rb +31 -0
  57. data/spec/lib/lucid_works/dynamicfield_spec.rb +214 -0
  58. data/spec/lib/lucid_works/elevation_spec.rb +175 -0
  59. data/spec/lib/lucid_works/field_spec.rb +52 -21
  60. data/spec/lib/lucid_works/fieldtype_spec.rb +0 -1
  61. data/spec/lib/lucid_works/request_handler_spec.rb +11 -0
  62. data/spec/lib/lucid_works/role_spec.rb +77 -0
  63. data/spec/lib/lucid_works/server/crawlers_status_spec.rb +21 -0
  64. data/spec/lib/lucid_works/server_spec.rb +123 -22
  65. data/spec/lib/lucid_works/{collection/synonym_spec.rb → synonym_spec.rb} +23 -22
  66. data/spec/lib/lucid_works/version_spec.rb +6 -0
  67. metadata +132 -64
  68. data/spec/lib/lucid_works/collection/acl_config_spec.rb +0 -212
@@ -0,0 +1,41 @@
1
+ require 'spec_helper'
2
+
3
+ describe LucidWorks::DatasourceProperty do
4
+
5
+ it "exposes the 'name' attribute" do
6
+ LucidWorks::DatasourceProperty.new('name' => 'foo').name.should == 'foo'
7
+ end
8
+
9
+ it "exposes the 'description' attribute" do
10
+ LucidWorks::DatasourceProperty.new('description' => 'my description').
11
+ description.should == 'my description'
12
+ end
13
+
14
+ it "exposes the 'type' attribute" do
15
+ LucidWorks::DatasourceProperty.new('type' => 'boolean').type.should == 'boolean'
16
+ end
17
+
18
+ it "exposes the 'default_value' attribute" do
19
+ LucidWorks::DatasourceProperty.new('default_value' => -1).default_value.should == -1
20
+ end
21
+
22
+ it "exposes the 'allowed_values' attribute" do
23
+ LucidWorks::DatasourceProperty.new('allowed_values' => ['tree', 'host', 'domain', 'none']).
24
+ allowed_values.should == ['tree', 'host', 'domain', 'none']
25
+ end
26
+
27
+ it "exposes the 'read_only' attribute" do
28
+ LucidWorks::DatasourceProperty.new('read_only' => false).should_not be_read_only
29
+ LucidWorks::DatasourceProperty.new('read_only' => true).should be_read_only
30
+ end
31
+
32
+ it "exposes the 'required' attribute" do
33
+ LucidWorks::DatasourceProperty.new('required' => false).should_not be_required
34
+ LucidWorks::DatasourceProperty.new('required' => true).should be_required
35
+ end
36
+
37
+ it "exposes the 'advanced' attribute" do
38
+ LucidWorks::DatasourceProperty.new.should_not be_advanced
39
+ LucidWorks::DatasourceProperty.new('hints' => ['advanced']).should be_advanced
40
+ end
41
+ end
@@ -7,6 +7,34 @@ describe LucidWorks::Datasource do
7
7
  @collection = @server.collection('collection1')
8
8
  end
9
9
 
10
+ describe "virtual attributes" do
11
+ let(:datasource) do
12
+ LucidWorks::Datasource.new(
13
+ :parent => @collection,
14
+ :commit_within => 10000, # 10 seconds
15
+ :delete_after => 86400000 # 1 day
16
+ )
17
+ end
18
+
19
+ it "allows retrieving 'commit_within' in seconds" do
20
+ datasource.commit_within_sec.should == 10
21
+ end
22
+
23
+ it "allows setting 'commit_within' in seconds" do
24
+ datasource.commit_within_sec = 20
25
+ datasource.commit_within.should == 20000
26
+ end
27
+
28
+ it "allows retrieving 'delete_after' in days" do
29
+ datasource.delete_after_days.should == 1
30
+ end
31
+
32
+ it "allows setting 'delete_after' in days" do
33
+ datasource.delete_after_days = 2
34
+ datasource.delete_after.should == 172800000
35
+ end
36
+ end
37
+
10
38
  describe "CRUD" do
11
39
 
12
40
  def datasource_count
@@ -57,7 +85,7 @@ describe LucidWorks::Datasource do
57
85
  @parameters = {
58
86
  :collection => @collection,
59
87
  :name => "foo",
60
- :crawler => LucidWorks::Datasource::CRAWLERS['web'],
88
+ :crawler => 'lucid.aperture',
61
89
  :type => 'web',
62
90
  :url => "invalid url",
63
91
  :crawl_depth => 1
@@ -78,7 +106,7 @@ describe LucidWorks::Datasource do
78
106
  before do
79
107
  @parameters = {
80
108
  :collection => @collection,
81
- :crawler => LucidWorks::Datasource::CRAWLERS['web'],
109
+ :crawler => 'lucid.aperture',
82
110
  :type => 'web',
83
111
  :name => "Lucid Imagination Website",
84
112
  :url => "http://www.lucidimagination.com/",
@@ -108,7 +136,7 @@ describe LucidWorks::Datasource do
108
136
  before do
109
137
  @datasource = LucidWorks::Datasource.create(
110
138
  :collection => @collection,
111
- :crawler => LucidWorks::Datasource::CRAWLERS['file'],
139
+ :crawler => 'lucid.aperture',
112
140
  :type => 'file',
113
141
  :name => "slash_temp",
114
142
  :path => "/tmp",
@@ -130,7 +158,7 @@ describe LucidWorks::Datasource do
130
158
  before do
131
159
  @datasource = LucidWorks::Datasource.create(
132
160
  :collection => @collection,
133
- :crawler => LucidWorks::Datasource::CRAWLERS['file'],
161
+ :crawler => 'lucid.aperture',
134
162
  :type => 'file',
135
163
  :name => "datasource we are going to update",
136
164
  :path => fixture_path("fake_file_ds_to_be_updated"),
@@ -152,7 +180,7 @@ describe LucidWorks::Datasource do
152
180
  before do
153
181
  @datasource = LucidWorks::Datasource.create(
154
182
  :collection => @collection,
155
- :crawler => LucidWorks::Datasource::CRAWLERS['file'],
183
+ :crawler => 'lucid.aperture',
156
184
  :type => 'file',
157
185
  :name => "datasource we are going to delete",
158
186
  :path => fixture_path("fake_file_ds_to_be_deleted"),
@@ -177,7 +205,7 @@ describe LucidWorks::Datasource do
177
205
  before :all do
178
206
  @datasource = LucidWorks::Datasource.create(
179
207
  :collection => @collection,
180
- :crawler => LucidWorks::Datasource::CRAWLERS['file'],
208
+ :crawler => 'lucid.aperture',
181
209
  :type => 'file',
182
210
  :name => "datasource we are going to get a status of",
183
211
  :path => fixture_path("fake_file_ds_to_get_status_of"),
@@ -203,7 +231,7 @@ describe LucidWorks::Datasource do
203
231
  it "should retrieve the datasource's schedule" do
204
232
  @datasource = LucidWorks::Datasource.create(
205
233
  :collection => @collection,
206
- :crawler => LucidWorks::Datasource::CRAWLERS['file'],
234
+ :crawler => 'lucid.aperture',
207
235
  :type => 'file',
208
236
  :name => "datasource we are going to get a schedule of",
209
237
  :path => fixture_path("fake_file_ds_to_get_schedule_of"),
@@ -216,7 +244,7 @@ describe LucidWorks::Datasource do
216
244
  schedule.should be_a(LucidWorks::Datasource::Schedule)
217
245
  schedule.should be_persisted
218
246
  schedule.datasource.should == @datasource
219
- schedule.type.should == "index"
247
+ schedule.type.should == 'crawl'
220
248
  schedule.period.should == 0
221
249
  schedule.active.should == false
222
250
  end
@@ -226,7 +254,7 @@ describe LucidWorks::Datasource do
226
254
  it "should return a new LucidWorks::Datasource::Index for this datasource" do
227
255
  @datasource = LucidWorks::Datasource.create(
228
256
  :collection => @collection,
229
- :crawler => LucidWorks::Datasource::CRAWLERS['file'],
257
+ :crawler => 'lucid.aperture',
230
258
  :type => 'file',
231
259
  :name => "datasource we are going to get a index of",
232
260
  :path => fixture_path("fake_file_ds_to_get_index_of"),
@@ -244,7 +272,7 @@ describe LucidWorks::Datasource do
244
272
  before :all do
245
273
  @datasource = LucidWorks::Datasource.create(
246
274
  :collection => @collection,
247
- :crawler => LucidWorks::Datasource::CRAWLERS['file'],
275
+ :crawler => 'lucid.aperture',
248
276
  :type => 'file',
249
277
  :name => "datasource we are going to mess with job of",
250
278
  :path => fixture_path("fake_file_ds_to_mess_with_job_of"),
@@ -280,7 +308,7 @@ describe LucidWorks::Datasource do
280
308
  before do
281
309
  @datasource = LucidWorks::Datasource.create(
282
310
  :collection => @collection,
283
- :crawler => LucidWorks::Datasource::CRAWLERS['file'],
311
+ :crawler => 'lucid.aperture',
284
312
  :type => 'file',
285
313
  :name => "datasource we are going to empty",
286
314
  :path => "/fake_ds_to_empty",
@@ -300,7 +328,7 @@ describe LucidWorks::Datasource do
300
328
  before do
301
329
  @datasource = LucidWorks::Datasource.create(
302
330
  :collection => @collection,
303
- :crawler => LucidWorks::Datasource::CRAWLERS['file'],
331
+ :crawler => 'lucid.aperture',
304
332
  :type => 'file',
305
333
  :name => "datasource we are going to get progress of",
306
334
  :path => fixture_path("fake_file_ds_to_test_progress"),
@@ -0,0 +1,31 @@
1
+ require 'spec_helper'
2
+
3
+ describe LucidWorks::DatasourceType do
4
+ subject {
5
+ LucidWorks::DatasourceType.new(
6
+ mock(LucidWorks::Crawler),
7
+ {
8
+ 'type' => 'file',
9
+ 'category' => 'FileSystem',
10
+ 'props' => [
11
+ {'name' => 'regular1', 'decription' => 'blah', 'type' => 'boolean', 'hints' => []},
12
+ {'name' => 'advanced1', 'decription' => 'blah', 'type' => 'boolean', 'hints' => ['advanced']},
13
+ {'name' => 'regular2', 'decription' => 'blah', 'type' => 'boolean', 'hints' => []},
14
+ {'name' => 'advanced2', 'decription' => 'blah', 'type' => 'boolean', 'hints' => ['advanced']}
15
+ ]
16
+ }
17
+ )
18
+ }
19
+
20
+ it { should have(4).properties }
21
+
22
+ it "finds regular properties" do
23
+ subject.properties.regular.should have(2).properties
24
+ subject.properties.regular.map(&:name).should == %w(regular1 regular2)
25
+ end
26
+
27
+ it "finds advanced properties" do
28
+ subject.properties.advanced.should have(2).properties
29
+ subject.properties.advanced.map(&:name).should == %w(advanced1 advanced2)
30
+ end
31
+ end
@@ -0,0 +1,214 @@
1
+ require 'spec_helper'
2
+
3
+ describe LucidWorks::Dynamicfield do
4
+ before :all do
5
+ @server = connect_to_live_server
6
+ @server.reset_collections!
7
+ @collection = @server.collection('collection1')
8
+ end
9
+
10
+ it "should use the ORM" do
11
+ LucidWorks::Dynamicfield.new(:parent => @collection).should be_a(LucidWorks::Base)
12
+ end
13
+
14
+ describe "default attribute values" do
15
+ context "for a new dynamic field" do
16
+ subject { LucidWorks::Dynamicfield.new(:parent => @collection) }
17
+
18
+ it { subject.omit_tf.should be_false }
19
+ end
20
+
21
+ context "on update" do
22
+ before(:each) do
23
+ subject.persisted = true
24
+ subject.stub(:save)
25
+ end
26
+
27
+ subject {
28
+ LucidWorks::Dynamicfield.new(
29
+ :parent => @collection, :field_type => 'string', :indexed => true, :omit_tf => true, :short_field_boost => true, :stored => true
30
+ )
31
+ }
32
+
33
+ context "when indexed is set to false" do
34
+ before(:each) do
35
+ subject.update_attributes(:indexed => false)
36
+ end
37
+
38
+ it { subject.omit_positions.should be_false }
39
+ it { subject.omit_tf.should be_false }
40
+ end
41
+ end
42
+ end
43
+
44
+ describe "validations" do
45
+ context "for a new dynamic field" do
46
+ context :name do
47
+ it "is required" do
48
+ field = LucidWorks::Dynamicfield.new(:field_type => 'string', :parent => @collection)
49
+ field.should_not be_valid
50
+ field.errors[:name].should == ["can't be blank"]
51
+ end
52
+
53
+ it "needs to be unique" do
54
+ field = LucidWorks::Dynamicfield.new(:parent => @collection, :name => '*_t')
55
+ field.should_not be_valid
56
+ field.errors[:name].should == ["must be unique"]
57
+ end
58
+ end
59
+
60
+ it "requires a field type" do
61
+ field = LucidWorks::Dynamicfield.new(:parent => @collection, :name => '*_foo')
62
+ field.should_not be_valid
63
+ field.errors[:field_type].should == ["can't be blank"]
64
+ end
65
+ end
66
+
67
+ context "for an existing dynamic field" do
68
+ it "doesn't validate the name's uniqueness" do
69
+ field = LucidWorks::Dynamicfield.find('*_t', :parent => @collection)
70
+ field.should be_valid
71
+ end
72
+ end
73
+ end
74
+
75
+ describe "indexing options" do
76
+ DYNAMICFIELD_INDEXING_OPTIONS_TRUTH_TABLE = [
77
+ { :indexed => true, :indexing_options => :document_termfreq_termpos, :omit_tf => false, :omit_positions => false },
78
+ { :indexed => true, :indexing_options => :document_termfreq, :omit_tf => false, :omit_positions => true },
79
+ { :indexed => true, :indexing_options => :document_only, :omit_tf => true, :omit_positions => true },
80
+ { :indexed => false, :indexing_options => :document_termfreq_termpos, :omit_tf => true, :omit_positions => true },
81
+ { :indexed => false, :indexing_options => :document_termfreq_termpos, :omit_tf => true, :omit_positions => true },
82
+ { :indexed => false, :indexing_options => :document_termfreq_termpos, :omit_tf => true, :omit_positions => true },
83
+ ]
84
+
85
+ context "when neither the setter nor getter have been accessed" do
86
+ context "for an object with indexed = false" do
87
+ before do
88
+ @field = LucidWorks::Dynamicfield.create(:name => '*_indexed', :field_type => 'string', :indexed => false, :parent => @collection)
89
+ end
90
+
91
+ it "should ignore indexing_options and validate okay" do
92
+ @field.should be_valid
93
+ end
94
+
95
+ it "should save omit_tf and omit_positions as true" do
96
+ @field.omit_positions.should be_true
97
+ @field.omit_tf.should be_true
98
+ end
99
+ end
100
+
101
+ context "for an object with indexed = true" do
102
+ before do
103
+ @field = LucidWorks::Dynamicfield.find('*_t', :parent => @collection)
104
+ end
105
+
106
+ it "should validate correctly" do
107
+ @field.should be_valid
108
+ end
109
+ end
110
+ end
111
+
112
+ describe "getter" do
113
+ context "when indexed is false" do
114
+ before do
115
+ @field = LucidWorks::Dynamicfield.new(:parent => @collection, :name => '*_foo', :field_type => 'string', :indexed => false)
116
+ end
117
+
118
+ describe "it should always return :document_termfreq_termpos" do
119
+ DYNAMICFIELD_INDEXING_OPTIONS_TRUTH_TABLE.select{ |x| x[:indexed] == 'false'}.each do |settings|
120
+ it "should return :document_termfreq_termpos if omit_tf=#{settings[:omit_tf]} and omit_positions=#{settings[:omit_positions]}" do
121
+ settings.each { |k,v| @field.send("#{k}=", v) }
122
+ @field.indexing_options.should == :document_termfreq_termpos
123
+ end
124
+ end
125
+
126
+ end
127
+ end
128
+
129
+ context "when indexed is true" do
130
+ before do
131
+ @field = LucidWorks::Dynamicfield.new(:parent => @collection, :name => '*_foo', :field_type => 'string', :indexed => true)
132
+ end
133
+
134
+ DYNAMICFIELD_INDEXING_OPTIONS_TRUTH_TABLE.select { |x| x[:indexed] == true }.each do |data|
135
+ it "should return #{data[:indexing_options]} if omit_tf=#{data[:omit_tf]} and omit_positions=#{data[:omit_positions]}" do
136
+ @field.omit_tf = data[:omit_tf]
137
+ @field.omit_positions = data[:omit_positions]
138
+ @field.indexing_options.should == data[:indexing_options]
139
+ end
140
+ end
141
+ end
142
+ end
143
+
144
+ describe "setter" do
145
+ before do
146
+ @field = LucidWorks::Dynamicfield.new(:parent => @collection, :name => 'my_field', :field_type => 'string')
147
+ end
148
+
149
+ DYNAMICFIELD_INDEXING_OPTIONS_TRUTH_TABLE.each do |data|
150
+
151
+ context "when indexed is set to #{data[:indexed]} BEFORE indexing options is set to #{data[:indexing_options]}" do
152
+ before do
153
+ @field.indexed = data[:indexed]
154
+ @field.indexing_options = data[:indexing_options]
155
+ end
156
+
157
+ it "should set omit_tf=#{data[:omit_tf]} and omit_positions=#{data[:omit_positions]} before save" do
158
+ RestClient.stub(:send) do |method, url, payload, options|
159
+ method.should == :post
160
+ hash = JSON.parse(payload)
161
+ hash['omit_tf'].should == data[:omit_tf]
162
+ hash['omit_positions'].should == data[:omit_positions]
163
+ end
164
+ @field.save
165
+ end
166
+
167
+ it "should not pass indexing_options on to the rest api" do
168
+ RestClient.stub(:send) do |method, url, payload, options|
169
+ method.should == :post
170
+ hash = JSON.parse(payload)
171
+ hash.keys.should_not include('indexing_options')
172
+ end
173
+ @field.save
174
+ end
175
+ end
176
+
177
+ context "when indexed is set to #{data[:indexed]} AFTER indexing options is set to #{data[:indexing_options]}" do
178
+ before do
179
+ @field.indexing_options = data[:indexing_options]
180
+ @field.indexed = data[:indexed]
181
+ end
182
+
183
+ it "should set omit_tf=#{data[:omit_tf]} and omit_positions=#{data[:omit_positions]} before save" do
184
+ RestClient.stub(:send) do |method, url, payload, options|
185
+ method.should == :post
186
+ hash = JSON.parse(payload)
187
+ hash['omit_tf'].should == data[:omit_tf]
188
+ hash['omit_positions'].should == data[:omit_positions]
189
+ end
190
+ @field.save
191
+ end
192
+
193
+ it "should not pass indexing_options on to the rest api" do
194
+ RestClient.stub(:send) do |method, url, payload, options|
195
+ method.should == :post
196
+ hash = JSON.parse(payload)
197
+ hash.keys.should_not include('indexing_options')
198
+ end
199
+ @field.save
200
+ end
201
+ end
202
+ end
203
+ end
204
+ end
205
+
206
+ describe "CRUD" do
207
+ describe "find" do
208
+ it "should retrieve a dynamic field" do
209
+ field = LucidWorks::Dynamicfield.find('*_t', :parent => @collection)
210
+ field.should be_a(LucidWorks::Dynamicfield)
211
+ end
212
+ end
213
+ end
214
+ end
@@ -0,0 +1,175 @@
1
+ require 'spec_helper'
2
+
3
+ describe LucidWorks::Elevation do
4
+ let(:server) { connect_to_live_server.tap {|server| server.reset_collections! } }
5
+
6
+ let(:collection) { server.collection('collection1') }
7
+
8
+ describe "naming support" do
9
+ it "demodularizes names" do
10
+ LucidWorks::Elevation.model_name.singular.should == "elevation"
11
+ LucidWorks::Elevation.model_name.plural.should == "elevations"
12
+ LucidWorks::Elevation.model_name.collection.should == "elevations"
13
+ end
14
+ end
15
+
16
+ describe "conversion support" do
17
+ it "can be converted to a key" do
18
+ elevation = LucidWorks::Elevation.new(:collection => collection, :query => 'blue jeans', :doc_id => 'http://mystore.com/products/123')
19
+ elevation.save
20
+ elevation.to_key.should == ['blue+jeans~~http://mystore.com/products/123']
21
+ end
22
+ end
23
+
24
+ describe "attributes" do
25
+ subject { LucidWorks::Elevation.new(:collection => collection, :query => 'blue jeans', :doc_id => 'http://mystore.com/products/123', :excluded => true) }
26
+
27
+ its(:id) { should == 'blue+jeans~~http://mystore.com/products/123' }
28
+ its(:persisted?) { should be_false }
29
+ its(:collection) { should == collection }
30
+ its(:query) { should == 'blue jeans' }
31
+ its(:excluded?) { should be_true }
32
+ end
33
+
34
+ describe :save do
35
+ subject { LucidWorks::Elevation.new(:collection => collection, :query => 'blue jeans', :doc_id => 'http://mystore.com/products/123', :excluded => true) }
36
+
37
+ it "gets saved as collection settings" do
38
+ subject.save
39
+ collection.settings!.elevations.should == {'blue jeans' => ['doc' => 'http://mystore.com/products/123', 'exclude' => true]}
40
+ end
41
+
42
+ it "only updates the 'elevations' setting" do
43
+ RestClient.should_receive(:put) do |url, data, headers|
44
+ JSON.parse(data).keys.should == ["elevations"]
45
+ end
46
+ subject.save
47
+ end
48
+
49
+ it "returns true to indicate success" do
50
+ subject.save.should be(true)
51
+ end
52
+
53
+ it "marks the elevation as persisted" do
54
+ subject.save
55
+ subject.should be_persisted
56
+ end
57
+ end
58
+
59
+ describe :destroy do
60
+ before(:each) do
61
+ collection.settings.elevations['blue jeans'] = ['doc' => 'http://mystore.com/products/123']
62
+ collection.settings.save
63
+ end
64
+
65
+ it "removes the elevation from the collection settings" do
66
+ LucidWorks::Elevation.new(:collection => collection, :query => 'blue jeans', :doc_id => 'http://mystore.com/products/123', :persisted => true).destroy
67
+ collection.settings!.elevations.should be_empty
68
+ end
69
+ end
70
+
71
+ describe "position helpers for true elevations" do
72
+ before(:all) do
73
+ collection.settings.elevations['blue jeans'] = [
74
+ {'doc' => 'item_1', 'exclude' => true},
75
+ {'doc' => 'item_2'},
76
+ {'doc' => 'item_3', 'exclude' => true},
77
+ {'doc' => 'item_4'},
78
+ {'doc' => 'item_5', 'exclude' => true}
79
+ ]
80
+ collection.settings.save
81
+ end
82
+
83
+ it "detects the first elevation" do
84
+ LucidWorks::Elevation.new(:collection => collection, :query => 'blue jeans', :doc_id => 'item_1').should_not be_first
85
+ LucidWorks::Elevation.new(:collection => collection, :query => 'blue jeans', :doc_id => 'item_2').should be_first
86
+ end
87
+
88
+ it "detects the last elevation" do
89
+ LucidWorks::Elevation.new(:collection => collection, :query => 'blue jeans', :doc_id => 'item_4').should be_last
90
+ LucidWorks::Elevation.new(:collection => collection, :query => 'blue jeans', :doc_id => 'item_5').should_not be_last
91
+ end
92
+ end
93
+
94
+ describe "reordering" do
95
+ before(:each) do
96
+ collection.settings.elevations['blue jeans'] = [
97
+ {'doc' => 'item_1', 'exclude' => true},
98
+ {'doc' => 'item_2'},
99
+ {'doc' => 'item_3'},
100
+ {'doc' => 'item_4', 'exclude' => true},
101
+ {'doc' => 'item_5'},
102
+ {'doc' => 'item_6', 'exclude' => true}
103
+ ]
104
+ collection.settings.save
105
+ end
106
+
107
+ describe "moving up" do
108
+ context "when the elevation is not yet at the top" do
109
+ subject { LucidWorks::Elevation.new(:collection => collection, :query => 'blue jeans', :doc_id => 'item_5') }
110
+
111
+ it "moves it up" do
112
+ subject.move_up
113
+ collection.settings!.elevations['blue jeans'].should == [
114
+ {'doc' => 'item_1', 'exclude' => true},
115
+ {'doc' => 'item_2'},
116
+ {'doc' => 'item_5'},
117
+ {'doc' => 'item_3'},
118
+ {'doc' => 'item_4', 'exclude' => true},
119
+ {'doc' => 'item_6', 'exclude' => true}
120
+ ]
121
+ end
122
+ end
123
+
124
+ context "when the elevation is already at the top" do
125
+ subject { LucidWorks::Elevation.new(:collection => collection, :query => 'blue jeans', :doc_id => 'item_2') }
126
+
127
+ it "doesn't move anything" do
128
+ subject.move_up
129
+ collection.settings!.elevations['blue jeans'].should == [
130
+ {'doc' => 'item_1', 'exclude' => true},
131
+ {'doc' => 'item_2'},
132
+ {'doc' => 'item_3'},
133
+ {'doc' => 'item_4', 'exclude' => true},
134
+ {'doc' => 'item_5'},
135
+ {'doc' => 'item_6', 'exclude' => true}
136
+ ]
137
+ end
138
+ end
139
+ end
140
+
141
+ describe "moving down" do
142
+ context "when the elevation is not yet at the end" do
143
+ subject { LucidWorks::Elevation.new(:collection => collection, :query => 'blue jeans', :doc_id => 'item_3') }
144
+
145
+ it "moves it down" do
146
+ subject.move_down
147
+ collection.settings!.elevations['blue jeans'].should == [
148
+ {'doc' => 'item_1', 'exclude' => true},
149
+ {'doc' => 'item_2'},
150
+ {'doc' => 'item_4', 'exclude' => true},
151
+ {'doc' => 'item_5'},
152
+ {'doc' => 'item_3'},
153
+ {'doc' => 'item_6', 'exclude' => true}
154
+ ]
155
+ end
156
+ end
157
+
158
+ context "when the elevation is already at the end" do
159
+ subject { LucidWorks::Elevation.new(:collection => collection, :query => 'blue jeans', :doc_id => 'item_5') }
160
+
161
+ it "doesn't move anything" do
162
+ subject.move_down
163
+ collection.settings!.elevations['blue jeans'].should == [
164
+ {'doc' => 'item_1', 'exclude' => true},
165
+ {'doc' => 'item_2'},
166
+ {'doc' => 'item_3'},
167
+ {'doc' => 'item_4', 'exclude' => true},
168
+ {'doc' => 'item_5'},
169
+ {'doc' => 'item_6', 'exclude' => true}
170
+ ]
171
+ end
172
+ end
173
+ end
174
+ end
175
+ end