pose 1.2.0 → 1.2.1

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.
@@ -0,0 +1,279 @@
1
+ # encoding: utf-8
2
+
3
+ require "spec_helper"
4
+
5
+ describe Pose do
6
+ subject { PosableOne.new }
7
+
8
+ describe 'associations' do
9
+ it 'allows to access the associated words of a posable object directly' do
10
+ subject.should have(0).pose_words
11
+ subject.pose_words << PoseWord.new(text: 'one')
12
+ subject.should have_pose_words(['one'])
13
+ end
14
+ end
15
+
16
+ describe '#update_pose_index' do
17
+
18
+ context "in the 'test' environment" do
19
+ # Set global env configuration.
20
+ before :each do
21
+ Pose::CONFIGURATION[:search_in_tests] = search_in_tests
22
+ end
23
+
24
+ # Restores global configuration to default.
25
+ after :each do
26
+ Pose::CONFIGURATION[:search_in_tests] = true
27
+ end
28
+
29
+ context "search_in_tests flag is not enabled" do
30
+ let(:search_in_tests) { false }
31
+
32
+ it "doesn't call update_pose_words" do
33
+ subject.should_not_receive :update_pose_words
34
+ subject.update_pose_index
35
+ end
36
+ end
37
+
38
+ context "search_in_tests flag is enabled" do
39
+ let(:search_in_tests) { true }
40
+
41
+ it "calls update_pose_words" do
42
+ subject.should_receive :update_pose_words
43
+ subject.update_pose_index
44
+ end
45
+ end
46
+ end
47
+
48
+ # TODO(REMOVE).
49
+ context "in the 'production' environment' do" do
50
+ before :each do
51
+ @old_env = Rails.env
52
+ Rails.env = 'production'
53
+ Pose::CONFIGURATION[:search_in_tests] = false
54
+ end
55
+
56
+ after :each do
57
+ Rails.env = @old_env
58
+ Pose::CONFIGURATION[:search_in_tests] = true
59
+ end
60
+
61
+ it "always calls update_pose_words, even when search_in_tests is disabled" do
62
+ subject.should_receive :update_pose_words
63
+ subject.update_pose_index
64
+ end
65
+ end
66
+ end
67
+
68
+
69
+ describe '#update_pose_words' do
70
+
71
+ it 'saves the words for search' do
72
+ subject.text = 'foo bar'
73
+ subject.update_pose_words
74
+ subject.should have_pose_words ['foo', 'bar']
75
+ end
76
+
77
+ it 'updates the search index when the text is changed' do
78
+ subject.text = 'foo'
79
+ subject.save!
80
+
81
+ subject.text = 'other text'
82
+ subject.update_pose_words
83
+
84
+ subject.should have_pose_words ['other', 'text']
85
+ end
86
+
87
+ it "doesn't create duplicate words" do
88
+ subject.text = 'foo foo'
89
+ subject.save!
90
+ subject.should have(1).pose_words
91
+ end
92
+ end
93
+
94
+
95
+ describe 'search' do
96
+
97
+ it 'works' do
98
+ pos = PosableOne.create text: 'foo'
99
+ result = Pose.search 'foo', PosableOne
100
+ result.should == { PosableOne => [pos] }
101
+ end
102
+
103
+ describe 'classes parameter' do
104
+
105
+ before :each do
106
+ @pos1 = PosableOne.create text: 'foo'
107
+ @pos2 = PosableTwo.create text: 'foo'
108
+ end
109
+
110
+ it 'returns all requested classes' do
111
+ result = Pose.search 'foo', [PosableOne, PosableTwo]
112
+
113
+ result.keys.should have(2).items
114
+ result.keys.should include PosableOne
115
+ result.keys.should include PosableTwo
116
+ end
117
+
118
+ it 'returns all matching instances of each requested class' do
119
+ result = Pose.search 'foo', [PosableOne, PosableTwo]
120
+
121
+ result[PosableOne].should == [@pos1]
122
+ result[PosableTwo].should == [@pos2]
123
+ end
124
+
125
+ it 'returns only instances of the given classes' do
126
+ result = Pose.search 'foo', PosableOne
127
+ result.keys.should include PosableOne
128
+ result.keys.should_not include PosableTwo
129
+ end
130
+ end
131
+
132
+ describe 'query parameter' do
133
+
134
+ it 'returns an empty array if nothing matches' do
135
+ pos1 = PosableOne.create text: 'one'
136
+ result = Pose.search 'two', PosableOne
137
+ result[PosableOne].should be_empty
138
+ end
139
+
140
+ it 'returns only objects that match all given query words' do
141
+ pos1 = PosableOne.create text: 'one two'
142
+ pos2 = PosableOne.create text: 'one three'
143
+ pos3 = PosableOne.create text: 'two three'
144
+
145
+ result = Pose.search 'two one', PosableOne
146
+
147
+ result[PosableOne].should == [pos1]
148
+ end
149
+
150
+ it 'returns nothing if searching for a non-existing word' do
151
+ pos1 = PosableOne.create text: 'one two'
152
+ result = Pose.search 'one zonk', PosableOne
153
+ result[PosableOne].should be_empty
154
+ end
155
+
156
+ it 'works if the query is given in uppercase' do
157
+ pos1 = PosableOne.create text: 'one two'
158
+ result = Pose.search 'OnE TwO', PosableOne
159
+ result[PosableOne].should == [pos1]
160
+ end
161
+ end
162
+
163
+
164
+ describe "'limit' parameter" do
165
+
166
+ it 'works' do
167
+ FactoryGirl.create :posable_one, text: 'foo one'
168
+ FactoryGirl.create :posable_one, text: 'foo two'
169
+ FactoryGirl.create :posable_one, text: 'foo three'
170
+
171
+ result = Pose.search 'foo', PosableOne, limit: 2
172
+
173
+ result[PosableOne].should have(2).items
174
+ end
175
+ end
176
+
177
+
178
+ describe "'result_type' parameter" do
179
+
180
+ before :each do
181
+ @foo_one = FactoryGirl.create :posable_one, text: 'foo one'
182
+ end
183
+
184
+ describe 'default behavior' do
185
+ it 'returns full objects' do
186
+ result = Pose.search 'foo', PosableOne
187
+ result[PosableOne].first.should == @foo_one
188
+ end
189
+ end
190
+
191
+ context ':ids given' do
192
+ it 'returns ids instead of objects' do
193
+ result = Pose.search 'foo', PosableOne, result_type: :ids
194
+ result[PosableOne].first.should == @foo_one.id
195
+ end
196
+ end
197
+ end
198
+
199
+
200
+ describe "'scopes' parameter" do
201
+
202
+ before :each do
203
+ @one = FactoryGirl.create :posable_one, text: 'foo one', private: true
204
+ @bar = FactoryGirl.create :posable_one, text: 'bar one', private: true
205
+ @two = FactoryGirl.create :posable_one, text: 'foo two', private: false
206
+ end
207
+
208
+ context 'with result type :classes' do
209
+
210
+ it 'limits the result set by the given scope' do
211
+ result = Pose.search 'foo', PosableOne, scope: [ private: true ]
212
+ result[PosableOne].should have(1).item
213
+ result[PosableOne].should include @one
214
+ end
215
+
216
+ it 'allows to use the hash syntax for queries' do
217
+ result = Pose.search 'foo', PosableOne, scope: [ private: true ]
218
+ result[PosableOne].should have(1).item
219
+ result[PosableOne].should include @one
220
+ end
221
+
222
+ it 'allows to use the string syntax for queries' do
223
+ result = Pose.search 'foo', PosableOne, scope: [ ['private = ?', true] ]
224
+ result[PosableOne].should have(1).item
225
+ result[PosableOne].should include @one
226
+ end
227
+
228
+ it 'allows to combine several scopes' do
229
+ @three = FactoryGirl.create :posable_one, text: 'foo two', private: true
230
+ result = Pose.search 'foo', PosableOne, scope: [ {private: true}, ['text = ?', 'foo two'] ]
231
+ result[PosableOne].should have(1).item
232
+ result[PosableOne].should include @three
233
+ end
234
+ end
235
+
236
+ context 'with result type :ids' do
237
+
238
+ it 'limits the result set by the given scope' do
239
+ result = Pose.search 'foo', PosableOne, result_type: :ids, scope: [ private: true ]
240
+ result[PosableOne].should have(1).item
241
+ result[PosableOne].should include @one.id
242
+ end
243
+ end
244
+ end
245
+ end
246
+
247
+
248
+ describe 'autocomplete_words' do
249
+
250
+ it 'returns words that start with the given phrase' do
251
+ PosableOne.create text: 'great green pine tree'
252
+
253
+ result = Pose::Helpers.autocomplete_words 'gr'
254
+
255
+ result.should have(2).words
256
+ result.should include 'great'
257
+ result.should include 'green'
258
+ end
259
+
260
+ it 'returns words that match the given phrase exactly' do
261
+ PoseWord.create text: 'cat'
262
+ result = Pose::Helpers.autocomplete_words 'cat'
263
+ result.should == ['cat']
264
+ end
265
+
266
+ it 'stems the search query' do
267
+ PosableOne.create text: 'car'
268
+ result = Pose::Helpers.autocomplete_words 'cars'
269
+ result.should have(1).words
270
+ result[0].should == 'car'
271
+ end
272
+
273
+ it 'returns nothing if the search query is empty' do
274
+ PosableOne.create text: 'foo bar'
275
+ result = Pose::Helpers.autocomplete_words ''
276
+ result.should be_empty
277
+ end
278
+ end
279
+ end
@@ -2,47 +2,44 @@ require 'spec_helper'
2
2
 
3
3
  describe PoseAssignment do
4
4
 
5
- before :each do
6
- PoseAssignment.delete_all
7
- end
8
-
9
5
  describe "delete_class_index" do
10
-
6
+
11
7
  before :each do
12
8
  FactoryGirl.create :pose_assignment, posable_id: 1, posable_type: 'PosableOne'
13
9
  FactoryGirl.create :pose_assignment, posable_id: 2, posable_type: 'PosableTwo'
14
10
  PoseAssignment.delete_class_index PosableOne
15
11
  end
16
-
12
+
17
13
  it "deletes all PoseAssignments for the given class" do
18
14
  PoseAssignment.where(posable_type: 'PosableOne').should have(0).items
19
15
  end
20
-
16
+
21
17
  it "doesn't delete PoseAssignments for other classes" do
22
18
  PoseAssignment.where(posable_type: 'PosableTwo').should have(1).items
23
19
  end
24
20
  end
25
-
21
+
22
+
26
23
  describe "cleanup_orphaned_pose_assignments" do
27
-
24
+
28
25
  it "deletes the assignment if the posable object doesn't exist" do
29
26
  FactoryGirl.create :pose_assignment, posable_id: 2, posable_type: 'PosableOne'
30
27
  PoseAssignment.count.should > 0
31
28
  PoseAssignment.cleanup_orphaned_pose_assignments
32
- PoseAssignment.should have(0).items
29
+ PoseAssignment.count.should == 0
33
30
  end
34
-
31
+
35
32
  it "deletes the assignment if the pose_word doesn't exist" do
36
33
  assignment = FactoryGirl.create :pose_assignment, pose_word: nil, pose_word_id: 27
37
34
  PoseAssignment.cleanup_orphaned_pose_assignments
38
35
  PoseAssignment.find_by_id(assignment.id).should be_nil
39
36
  end
40
-
37
+
41
38
  it "doesn't delete the assignment if it is still used" do
42
39
  assignment = FactoryGirl.create :pose_assignment
43
40
  PoseAssignment.cleanup_orphaned_pose_assignments
44
41
  PoseAssignment.find_by_id(assignment.id).should_not be_nil
45
42
  end
46
43
  end
47
-
44
+
48
45
  end
@@ -1,23 +1,26 @@
1
1
  require 'spec_helper'
2
2
 
3
3
  describe PoseWord do
4
-
5
- before :all do
6
- PoseWord.delete_all
7
- end
8
-
9
- describe 'remove_unused_words' do
10
4
 
11
- it 'removes unused words' do
12
- FactoryGirl.create :pose_word
13
- PoseWord.remove_unused_words
14
- PoseWord.count.should == 0
15
- end
16
-
17
- it "doesn't remove used words" do
18
- snippet = FactoryGirl.create :posable_one
19
- PoseWord.remove_unused_words
20
- PoseWord.count.should > 0
5
+ describe 'class methods' do
6
+ subject { PoseWord }
7
+
8
+ describe '::remove_unused_words' do
9
+
10
+ before :each do
11
+ instantiate_objects
12
+ PoseWord.remove_unused_words
13
+ end
14
+
15
+ context 'having unused words' do
16
+ let(:instantiate_objects) { FactoryGirl.create :pose_word }
17
+ its(:count) { should == 0 }
18
+ end
19
+
20
+ context 'having used words' do
21
+ let(:instantiate_objects) { FactoryGirl.create :posable_one }
22
+ its(:count) { should > 0 }
23
+ end
21
24
  end
22
25
  end
23
26
  end
data/spec/spec_helper.rb CHANGED
@@ -9,6 +9,8 @@ require 'active_support/core_ext/string'
9
9
  require 'pose'
10
10
  require 'faker'
11
11
  require 'factory_girl'
12
+ require 'database_cleaner'
13
+
12
14
  FactoryGirl.find_definitions
13
15
 
14
16
  # Configure Rails Environment
@@ -16,7 +18,7 @@ ENV["RAILS_ENV"] = "test"
16
18
  Rails = Hashie::Mash.new({env: 'test'})
17
19
 
18
20
  # We have no Railtie in these tests --> load Pose manually.
19
- ActiveRecord::Base.send :extend, Pose::BaseAdditions
21
+ ActiveRecord::Base.send :extend, Pose::ActiveRecordBaseAdditions
20
22
 
21
23
  # Load support files
22
24
  Dir["#{File.dirname(__FILE__)}/support/**/*.rb"].each { |f| require f }
@@ -35,51 +37,21 @@ RSpec.configure do |config|
35
37
  # If you're not using ActiveRecord, or you'd prefer not to run each of your
36
38
  # examples within a transaction, remove the following line or assign false
37
39
  # instead of true.
38
- # config.use_transactional_fixtures = true
40
+ # config.use_transactional_fixtures = true
39
41
 
40
42
  config.before :suite do
41
43
  setup_db
42
44
  Pose::CONFIGURATION[:search_in_tests] = true
45
+ DatabaseCleaner.strategy = :deletion
43
46
  end
44
-
45
- config.after :suite do
46
- teardown_db
47
- end
48
- end
49
47
 
50
-
51
- #####################
52
- # MATCHERS
53
- #
54
-
55
- # Verifies that a taggable object has the given tags.
56
- RSpec::Matchers.define :have_pose_words do |expected|
57
- match do |actual|
58
- actual.should have(expected.size).pose_words
59
- texts = actual.pose_words.map &:text
60
- expected.each do |expected_word|
61
- # Note (KG): Can't use text.should include(expected_word) here
62
- # because Ruby thinks I want to include a Module for some reason.
63
- texts.include?(expected_word).should be_true
64
- end
65
- end
66
- failure_message_for_should do |actual|
67
- texts = actual.pose_words.map &:text
68
- "expected that subject would have pose words [#{expected.join ', '}], but it has [#{texts.join ', '}]"
48
+ config.before :each do
49
+ DatabaseCleaner.start
69
50
  end
70
- end
71
-
72
51
 
73
- #####################
74
- # TEST CLASSES
75
- #
76
-
77
- class PosableOne < ActiveRecord::Base
78
- posify { text }
79
- end
80
-
81
- class PosableTwo < ActiveRecord::Base
82
- posify { text }
52
+ config.after :each do
53
+ DatabaseCleaner.clean
54
+ end
83
55
  end
84
56
 
85
57
 
@@ -88,32 +60,37 @@ end
88
60
  #
89
61
 
90
62
  def setup_db
91
- ActiveRecord::Schema.define(version: 1) do
63
+ ActiveRecord::Base.establish_connection adapter: 'postgresql',
64
+ database: 'pose_test',
65
+ min_messages: 'INFO'
92
66
 
93
- create_table 'posable_ones' do |t|
94
- t.string 'text'
95
- t.boolean 'private'
67
+ ActiveRecord::Schema.define(version: 1) do
68
+ unless table_exists? 'posable_ones'
69
+ create_table 'posable_ones' do |t|
70
+ t.string 'text'
71
+ t.boolean 'private'
72
+ end
96
73
  end
97
74
 
98
- create_table 'posable_twos' do |t|
99
- t.string 'text'
100
- t.boolean 'private'
75
+ unless table_exists? 'posable_twos'
76
+ create_table 'posable_twos' do |t|
77
+ t.string 'text'
78
+ t.boolean 'private'
79
+ end
101
80
  end
102
81
 
103
- create_table "pose_assignments" do |t|
104
- t.integer "pose_word_id", null: false
105
- t.integer "posable_id", null: false
106
- t.string "posable_type", limit: 20, null: false
82
+ unless table_exists? 'pose_assignments'
83
+ create_table "pose_assignments" do |t|
84
+ t.integer "pose_word_id", null: false
85
+ t.integer "posable_id", null: false
86
+ t.string "posable_type", limit: 20, null: false
87
+ end
107
88
  end
108
89
 
109
- create_table "pose_words" do |t|
110
- t.string "text", limit: 80, null: false
90
+ unless table_exists? 'pose_words'
91
+ create_table "pose_words" do |t|
92
+ t.string "text", limit: 80, null: false
93
+ end
111
94
  end
112
95
  end
113
96
  end
114
-
115
- def teardown_db
116
- ActiveRecord::Base.connection.tables.each do |table|
117
- ActiveRecord::Base.connection.drop_table(table)
118
- end
119
- end