active_force 0.15.1 → 0.17.0

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.
@@ -9,7 +9,7 @@ describe ActiveForce::ActiveQuery do
9
9
  })
10
10
  end
11
11
  let(:mappings){ { id: "Id", field: "Field__c", other_field: "Other_Field" } }
12
- let(:client){ double("client") }
12
+ let(:client) { double('client', query: nil) }
13
13
  let(:active_query){ described_class.new(sobject) }
14
14
  let(:api_result) do
15
15
  [
@@ -42,48 +42,45 @@ describe ActiveForce::ActiveQuery do
42
42
 
43
43
  describe "select only some field using mappings" do
44
44
  it "should return a query only with selected field" do
45
- active_query.select(:field)
46
- expect(active_query.to_s).to eq("SELECT Field__c FROM table_name")
45
+ new_query = active_query.select(:field)
46
+ expect(new_query.to_s).to eq("SELECT Field__c FROM table_name")
47
47
  end
48
48
  end
49
49
 
50
50
  describe "condition mapping" do
51
51
  it "maps conditions for a .where" do
52
- active_query.where(field: 123)
53
- expect(active_query.to_s).to eq("SELECT Id FROM table_name WHERE (Field__c = 123)")
52
+ new_query = active_query.where(field: 123)
53
+ expect(new_query.to_s).to eq("SELECT Id FROM table_name WHERE (Field__c = 123)")
54
54
  end
55
55
 
56
56
  it 'transforms an array to a WHERE/IN clause' do
57
- active_query.where(field: ['foo', 'bar'])
58
- expect(active_query.to_s).to eq("SELECT Id FROM table_name WHERE (Field__c IN ('foo','bar'))")
57
+ new_query = active_query.where(field: ['foo', 'bar'])
58
+ expect(new_query.to_s).to eq("SELECT Id FROM table_name WHERE (Field__c IN ('foo','bar'))")
59
59
  end
60
60
 
61
61
  it "encloses the value in quotes if it's a string" do
62
- active_query.where field: "hello"
63
- expect(active_query.to_s).to end_with("(Field__c = 'hello')")
62
+ new_query = active_query.where field: "hello"
63
+ expect(new_query.to_s).to end_with("(Field__c = 'hello')")
64
64
  end
65
65
 
66
66
  it "formats as YYYY-MM-DDThh:mm:ss-hh:mm and does not enclose in quotes if it's a DateTime" do
67
67
  value = DateTime.now
68
- active_query.where(field: value)
69
- expect(active_query.to_s).to end_with("(Field__c = #{value.iso8601})")
68
+ expect(active_query.where(field: value).to_s).to end_with("(Field__c = #{value.iso8601})")
70
69
  end
71
70
 
72
71
  it "formats as YYYY-MM-DDThh:mm:ss-hh:mm and does not enclose in quotes if it's a Time" do
73
72
  value = Time.now
74
- active_query.where(field: value)
75
- expect(active_query.to_s).to end_with("(Field__c = #{value.iso8601})")
73
+ expect(active_query.where(field: value).to_s).to end_with("(Field__c = #{value.iso8601})")
76
74
  end
77
75
 
78
76
  it "formats as YYYY-MM-DD and does not enclose in quotes if it's a Date" do
79
77
  value = Date.today
80
- active_query.where(field: value)
81
- expect(active_query.to_s).to end_with("(Field__c = #{value.iso8601})")
78
+ expect(active_query.where(field: value).to_s).to end_with("(Field__c = #{value.iso8601})")
82
79
  end
83
80
 
84
81
  it "puts NULL when a field is set as nil" do
85
- active_query.where field: nil
86
- expect(active_query.to_s).to end_with("(Field__c = NULL)")
82
+ new_query = active_query.where field: nil
83
+ expect(new_query.to_s).to end_with("(Field__c = NULL)")
87
84
  end
88
85
 
89
86
  describe 'bind parameters' do
@@ -95,36 +92,33 @@ describe ActiveForce::ActiveQuery do
95
92
  end
96
93
 
97
94
  it 'accepts bind parameters' do
98
- active_query.where('Field__c = ?', 123)
99
- expect(active_query.to_s).to eq("SELECT Id FROM table_name WHERE (Field__c = 123)")
95
+ new_query = active_query.where('Field__c = ?', 123)
96
+ expect(new_query.to_s).to eq("SELECT Id FROM table_name WHERE (Field__c = 123)")
100
97
  end
101
98
 
102
99
  it 'accepts nil bind parameters' do
103
- active_query.where('Field__c = ?', nil)
104
- expect(active_query.to_s).to eq("SELECT Id FROM table_name WHERE (Field__c = NULL)")
100
+ new_query = active_query.where('Field__c = ?', nil)
101
+ expect(new_query.to_s).to eq("SELECT Id FROM table_name WHERE (Field__c = NULL)")
105
102
  end
106
103
 
107
104
  it 'accepts multiple bind parameters' do
108
- active_query.where('Field__c = ? AND Other_Field__c = ? AND Name = ?', 123, 321, 'Bob')
109
- expect(active_query.to_s).to eq("SELECT Id FROM table_name WHERE (Field__c = 123 AND Other_Field__c = 321 AND Name = 'Bob')")
105
+ new_query = active_query.where('Field__c = ? AND Other_Field__c = ? AND Name = ?', 123, 321, 'Bob')
106
+ expect(new_query.to_s).to eq("SELECT Id FROM table_name WHERE (Field__c = 123 AND Other_Field__c = 321 AND Name = 'Bob')")
110
107
  end
111
108
 
112
109
  it 'formats as YYYY-MM-DDThh:mm:ss-hh:mm and does not enclose in quotes if value is a DateTime' do
113
110
  value = DateTime.now
114
- active_query.where('Field__c > ?', value)
115
- expect(active_query.to_s).to end_with("(Field__c > #{value.iso8601})")
111
+ expect(active_query.where('Field__c > ?', value).to_s).to end_with("(Field__c > #{value.iso8601})")
116
112
  end
117
113
 
118
114
  it 'formats as YYYY-MM-DDThh:mm:ss-hh:mm and does not enclose in quotes if value is a Time' do
119
115
  value = Time.now
120
- active_query.where('Field__c > ?', value)
121
- expect(active_query.to_s).to end_with("(Field__c > #{value.iso8601})")
116
+ expect(active_query.where('Field__c > ?', value).to_s).to end_with("(Field__c > #{value.iso8601})")
122
117
  end
123
118
 
124
119
  it 'formats as YYYY-MM-DD and does not enclose in quotes if value is a Date' do
125
120
  value = Date.today
126
- active_query.where('Field__c > ?', value)
127
- expect(active_query.to_s).to end_with("(Field__c > #{value.iso8601})")
121
+ expect(active_query.where('Field__c > ?', value).to_s).to end_with("(Field__c > #{value.iso8601})")
128
122
  end
129
123
 
130
124
  it 'complains when there given an incorrect number of bind parameters' do
@@ -135,41 +129,41 @@ describe ActiveForce::ActiveQuery do
135
129
 
136
130
  context 'named bind parameters' do
137
131
  it 'accepts bind parameters' do
138
- active_query.where('Field__c = :field', field: 123)
139
- expect(active_query.to_s).to eq("SELECT Id FROM table_name WHERE (Field__c = 123)")
132
+ new_query = active_query.where('Field__c = :field', field: 123)
133
+ expect(new_query.to_s).to eq("SELECT Id FROM table_name WHERE (Field__c = 123)")
140
134
  end
141
135
 
142
136
  it 'accepts nil bind parameters' do
143
- active_query.where('Field__c = :field', field: nil)
144
- expect(active_query.to_s).to eq("SELECT Id FROM table_name WHERE (Field__c = NULL)")
137
+ new_query = active_query.where('Field__c = :field', field: nil)
138
+ expect(new_query.to_s).to eq("SELECT Id FROM table_name WHERE (Field__c = NULL)")
145
139
  end
146
140
 
147
141
  it 'formats as YYYY-MM-DDThh:mm:ss-hh:mm and does not enclose in quotes if value is a DateTime' do
148
142
  value = DateTime.now
149
- active_query.where('Field__c < :field', field: value)
150
- expect(active_query.to_s).to end_with("(Field__c < #{value.iso8601})")
143
+ new_query = active_query.where('Field__c < :field', field: value)
144
+ expect(new_query.to_s).to end_with("(Field__c < #{value.iso8601})")
151
145
  end
152
146
 
153
147
  it 'formats as YYYY-MM-DDThh:mm:ss-hh:mm and does not enclose in quotes if value is a Time' do
154
148
  value = Time.now
155
- active_query.where('Field__c < :field', field: value)
156
- expect(active_query.to_s).to end_with("(Field__c < #{value.iso8601})")
149
+ new_query = active_query.where('Field__c < :field', field: value)
150
+ expect(new_query.to_s).to end_with("(Field__c < #{value.iso8601})")
157
151
  end
158
152
 
159
153
  it 'formats as YYYY-MM-DD and does not enclose in quotes if value is a Date' do
160
154
  value = Date.today
161
- active_query.where('Field__c < :field', field: value)
162
- expect(active_query.to_s).to end_with("(Field__c < #{value.iso8601})")
155
+ new_query = active_query.where('Field__c < :field', field: value)
156
+ expect(new_query.to_s).to end_with("(Field__c < #{value.iso8601})")
163
157
  end
164
158
 
165
159
  it 'accepts multiple bind parameters' do
166
- active_query.where('Field__c = :field AND Other_Field__c = :other_field AND Name = :name', field: 123, other_field: 321, name: 'Bob')
167
- expect(active_query.to_s).to eq("SELECT Id FROM table_name WHERE (Field__c = 123 AND Other_Field__c = 321 AND Name = 'Bob')")
160
+ new_query = active_query.where('Field__c = :field AND Other_Field__c = :other_field AND Name = :name', field: 123, other_field: 321, name: 'Bob')
161
+ expect(new_query.to_s).to eq("SELECT Id FROM table_name WHERE (Field__c = 123 AND Other_Field__c = 321 AND Name = 'Bob')")
168
162
  end
169
163
 
170
164
  it 'accepts multiple bind parameters orderless' do
171
- active_query.where('Field__c = :field AND Other_Field__c = :other_field AND Name = :name', name: 'Bob', other_field: 321, field: 123)
172
- expect(active_query.to_s).to eq("SELECT Id FROM table_name WHERE (Field__c = 123 AND Other_Field__c = 321 AND Name = 'Bob')")
165
+ new_query = active_query.where('Field__c = :field AND Other_Field__c = :other_field AND Name = :name', name: 'Bob', other_field: 321, field: 123)
166
+ expect(new_query.to_s).to eq("SELECT Id FROM table_name WHERE (Field__c = 123 AND Other_Field__c = 321 AND Name = 'Bob')")
173
167
  end
174
168
 
175
169
  it 'complains when there given an incorrect number of bind parameters' do
@@ -198,29 +192,77 @@ describe ActiveForce::ActiveQuery do
198
192
  {"Id" => "0000000000EEEEEFFF"}
199
193
  ]
200
194
  end
195
+
201
196
  it 'allows method chaining' do
202
197
  result = active_query.where("Text_Label = 'foo'").where("Checkbox_Label = true")
203
198
  expect(result).to be_a described_class
204
199
  end
205
200
 
201
+ it 'does not execute a query' do
202
+ active_query.where('x')
203
+ expect(client).not_to have_received(:query)
204
+ end
205
+
206
+ context 'when calling `where` on an ActiveQuery object that already has records' do
207
+ context 'after the query result has been decorated' do
208
+ it 'returns a new ActiveQuery object' do
209
+ first_active_query = active_query.where("Text_Label = 'foo'")
210
+ first_active_query.to_a # decorates the results
211
+ second_active_query = first_active_query.where("Checkbox_Label = true")
212
+ second_active_query.to_a
213
+ expect(second_active_query).to be_a described_class
214
+ expect(second_active_query).not_to eq first_active_query
215
+ expect(second_active_query.to_s).not_to eq first_active_query.to_s
216
+ expect(second_active_query.to_a.size).to eq(1)
217
+ end
218
+ end
219
+ end
220
+
206
221
  context 'when calling `where` on an ActiveQuery object that already has records' do
207
- it 'returns a new ActiveQuery object' do
208
- first_active_query = active_query.where("Text_Label = 'foo'")
209
- first_active_query.inspect # so the query is executed
210
- second_active_query = first_active_query.where("Checkbox_Label = true")
211
- second_active_query.inspect
212
- expect(second_active_query).to be_a described_class
213
- expect(second_active_query).not_to eq first_active_query
222
+ context 'without the query result being decorated' do
223
+
224
+ it 'returns a new ActiveQuery object' do
225
+ first_active_query = active_query.where("Text_Label = 'foo'")
226
+ second_active_query = first_active_query.where("Checkbox_Label = true")
227
+ expect(second_active_query).to be_a described_class
228
+ expect(second_active_query).not_to eq first_active_query
229
+ expect(second_active_query.to_s).not_to eq first_active_query.to_s
230
+ expect(second_active_query.to_a.size).to eq(1)
231
+ end
214
232
  end
215
233
  end
234
+ end
216
235
 
236
+ describe '#not' do
237
+ it 'adds a not condition' do
238
+ expect(active_query.not(field: 'x').to_s).to end_with("WHERE (NOT ((Field__c = 'x')))")
239
+ end
240
+
241
+ it 'allows chaining' do
242
+ expect(active_query.where(field: 'x').not(field: 'y').where(field: 'z')).to be_a(described_class)
243
+ end
244
+
245
+ it 'does not mutate the original query' do
246
+ original = active_query.to_s
247
+ active_query.not(field: 'x')
248
+ expect(active_query.to_s).to eq(original)
249
+ end
250
+
251
+ it 'returns the original query if not given a condition' do
252
+ expect(active_query.not).to be(active_query)
253
+ end
254
+
255
+ it 'does not execute a query' do
256
+ active_query.not(field: 'x')
257
+ expect(client).not_to have_received(:query)
258
+ end
217
259
  end
218
260
 
219
261
  describe "#find_by" do
220
262
  it "should query the client, with the SFDC field names and correctly enclosed values" do
221
- expect(client).to receive :query
222
- active_query.find_by field: 123
223
- expect(active_query.to_s).to eq "SELECT Id FROM table_name WHERE (Field__c = 123) LIMIT 1"
263
+ expect(client).to receive(:query).with("SELECT Id FROM table_name WHERE (Field__c = 123) LIMIT 1")
264
+ new_query = active_query.find_by field: 123
265
+ expect(new_query).to be_nil
224
266
  end
225
267
  end
226
268
 
@@ -290,18 +332,18 @@ describe ActiveForce::ActiveQuery do
290
332
  let(:expected_query){ "SELECT Id FROM table_name WHERE (Backslash_Field__c = '\\\\' AND NumberField = 123 AND QuoteField = '\\' OR Id!=NULL OR Id=\\'')" }
291
333
 
292
334
  it 'escapes quotes and backslashes in bind parameters' do
293
- active_query.where('Backslash_Field__c = :backslash_field AND NumberField = :number_field AND QuoteField = :quote_field', number_field: number_input, backslash_field: backslash_input, quote_field: quote_input)
294
- expect(active_query.to_s).to eq(expected_query)
335
+ new_query = active_query.where('Backslash_Field__c = :backslash_field AND NumberField = :number_field AND QuoteField = :quote_field', number_field: number_input, backslash_field: backslash_input, quote_field: quote_input)
336
+ expect(new_query.to_s).to eq(expected_query)
295
337
  end
296
338
 
297
339
  it 'escapes quotes and backslashes in named bind parameters' do
298
- active_query.where('Backslash_Field__c = ? AND NumberField = ? AND QuoteField = ?', backslash_input, number_input, quote_input)
299
- expect(active_query.to_s).to eq(expected_query)
340
+ new_query = active_query.where('Backslash_Field__c = ? AND NumberField = ? AND QuoteField = ?', backslash_input, number_input, quote_input)
341
+ expect(new_query.to_s).to eq(expected_query)
300
342
  end
301
343
 
302
344
  it 'escapes quotes and backslashes in hash conditions' do
303
- active_query.where(backslash_field: backslash_input, number_field: number_input, quote_field: quote_input)
304
- expect(active_query.to_s).to eq("SELECT Id FROM table_name WHERE (Backslash_Field__c = '\\\\') AND (NumberField = 123) AND (QuoteField = '\\' OR Id!=NULL OR Id=\\'')")
345
+ new_query = active_query.where(backslash_field: backslash_input, number_field: number_input, quote_field: quote_input)
346
+ expect(new_query.to_s).to eq("SELECT Id FROM table_name WHERE (Backslash_Field__c = '\\\\') AND (NumberField = 123) AND (QuoteField = '\\' OR Id!=NULL OR Id=\\'')")
305
347
  end
306
348
  end
307
349
 
@@ -40,6 +40,16 @@ describe ActiveForce::SObject do
40
40
  post.comments.to_a
41
41
  end
42
42
 
43
+ it 'is not mutated by #where' do
44
+ post.comments.where(body: 'test').to_a
45
+ expect(post.comments.to_s).to end_with("FROM Comment__c WHERE (PostId = '1')")
46
+ end
47
+
48
+ it 'is not mutated by #none' do
49
+ post.comments.none.to_a
50
+ expect(post.comments.to_s).to end_with("FROM Comment__c WHERE (PostId = '1')")
51
+ end
52
+
43
53
  describe 'to_s' do
44
54
  it "should return a SOQL statment" do
45
55
  soql = "SELECT Id, PostId, PosterId__c, FancyPostId, Body__c FROM Comment__c WHERE (PostId = '1')"
@@ -376,7 +386,7 @@ describe ActiveForce::SObject do
376
386
  it 'allows passing a foreign key' do
377
387
  Comment.belongs_to :post, foreign_key: :fancy_post_id
378
388
  allow(comment).to receive(:fancy_post_id).and_return "2"
379
- expect(client).to receive(:query).with("SELECT Id, Title__c FROM Post__c WHERE (Id = '2') LIMIT 1")
389
+ expect(client).to receive(:query).with("SELECT Id, Title__c, BlogId FROM Post__c WHERE (Id = '2') LIMIT 1")
380
390
  comment.post
381
391
  Comment.belongs_to :post # reset association to original value
382
392
  end
@@ -32,7 +32,7 @@ describe ActiveForce::Query do
32
32
  expect(query.all.to_s).to eq "SELECT Id, name, etc FROM table_name"
33
33
  end
34
34
 
35
- it "should ignore dupicated attributes in select statment" do
35
+ it "should ignore duplicated attributes in select statment" do
36
36
  query.fields ['Id', 'name', 'etc']
37
37
  expect(query.all.to_s).to eq "SELECT Id, name, etc FROM table_name"
38
38
  end
@@ -46,6 +46,19 @@ describe ActiveForce::Query do
46
46
  it "should add multiples conditions to a query with parentheses" do
47
47
  expect(query.where("condition1 = 1").where("condition2 = 2 OR condition3 = 3").to_s).to eq "SELECT Id, name, etc FROM table_name WHERE (condition1 = 1) AND (condition2 = 2 OR condition3 = 3)"
48
48
  end
49
+
50
+ it "should not duplicate conditions" do
51
+ first_query = query.where("name = 'cool'").where("foo = 'baz'")
52
+ second_query = first_query.where("name = 'cool'")
53
+ expect(first_query.to_s).to eq(second_query.to_s)
54
+ expect(first_query.object_id).to eq(second_query.object_id)
55
+ end
56
+
57
+ it "should not update the original query" do
58
+ new_query = query.where("name = 'cool'")
59
+ expect(query.to_s).to eq "SELECT Id, name, etc FROM table_name"
60
+ expect(new_query.to_s).to eq "SELECT Id, name, etc FROM table_name WHERE (name = 'cool')"
61
+ end
49
62
  end
50
63
 
51
64
  describe ".not" do
@@ -68,12 +81,18 @@ describe ActiveForce::Query do
68
81
  it "should add a limit to a query" do
69
82
  expect(query.limit("25").to_s).to eq "SELECT Id, name, etc FROM table_name LIMIT 25"
70
83
  end
84
+
85
+ it "should not update the original query" do
86
+ new_query = query.limit("25")
87
+ expect(query.to_s).to eq "SELECT Id, name, etc FROM table_name"
88
+ expect(new_query.to_s).to eq "SELECT Id, name, etc FROM table_name LIMIT 25"
89
+ end
71
90
  end
72
91
 
73
92
  describe ".limit_value" do
74
93
  it "should return the limit value" do
75
- query.limit(4)
76
- expect(query.limit_value).to eq 4
94
+ new_query = query.limit(4)
95
+ expect(new_query.limit_value).to eq 4
77
96
  end
78
97
  end
79
98
 
@@ -81,12 +100,18 @@ describe ActiveForce::Query do
81
100
  it "should add an offset to a query" do
82
101
  expect(query.offset(4).to_s).to eq "SELECT Id, name, etc FROM table_name OFFSET 4"
83
102
  end
103
+
104
+ it "should not update the original query" do
105
+ new_query = query.offset(4)
106
+ expect(query.to_s).to eq "SELECT Id, name, etc FROM table_name"
107
+ expect(new_query.to_s).to eq "SELECT Id, name, etc FROM table_name OFFSET 4"
108
+ end
84
109
  end
85
110
 
86
111
  describe ".offset_value" do
87
112
  it "should return the offset value" do
88
- query.offset(4)
89
- expect(query.offset_value).to eq 4
113
+ new_query = query.offset(4)
114
+ expect(new_query.offset_value).to eq 4
90
115
  end
91
116
  end
92
117
 
@@ -104,6 +129,12 @@ describe ActiveForce::Query do
104
129
  it "should add a order condition in the statment with WHERE and LIMIT" do
105
130
  expect(query.where("condition1 = 1").order("name desc").limit(1).to_s).to eq "SELECT Id, name, etc FROM table_name WHERE (condition1 = 1) ORDER BY name desc LIMIT 1"
106
131
  end
132
+
133
+ it "should not update the original query" do
134
+ ordered_query = query.order("name desc")
135
+ expect(query.to_s).to eq "SELECT Id, name, etc FROM table_name"
136
+ expect(ordered_query.to_s).to eq "SELECT Id, name, etc FROM table_name ORDER BY name desc"
137
+ end
107
138
  end
108
139
 
109
140
  describe '.join' do
@@ -116,18 +147,36 @@ describe ActiveForce::Query do
116
147
  it 'should add another select statment on the current select' do
117
148
  expect(query.join(join_query).to_s).to eq 'SELECT Id, name, etc, (SELECT Id, name, etc FROM join_table_name) FROM table_name'
118
149
  end
150
+
151
+ it "should not update the original query" do
152
+ new_query = query.join(join_query)
153
+ expect(query.to_s).to eq "SELECT Id, name, etc FROM table_name"
154
+ expect(new_query.to_s).to eq 'SELECT Id, name, etc, (SELECT Id, name, etc FROM join_table_name) FROM table_name'
155
+ end
119
156
  end
120
157
 
121
158
  describe '.first' do
122
159
  it 'should return the query for the first record' do
123
160
  expect(query.first.to_s).to eq 'SELECT Id, name, etc FROM table_name LIMIT 1'
124
161
  end
162
+
163
+ it "should not update the original query" do
164
+ new_query = query.first
165
+ expect(query.to_s).to eq "SELECT Id, name, etc FROM table_name"
166
+ expect(new_query.to_s).to eq 'SELECT Id, name, etc FROM table_name LIMIT 1'
167
+ end
125
168
  end
126
169
 
127
170
  describe '.last' do
128
171
  it 'should return the query for the last record' do
129
172
  expect(query.last.to_s).to eq 'SELECT Id, name, etc FROM table_name ORDER BY Id DESC LIMIT 1'
130
173
  end
174
+
175
+ it "should not update the original query" do
176
+ new_query = query.last
177
+ expect(query.to_s).to eq "SELECT Id, name, etc FROM table_name"
178
+ expect(new_query.to_s).to eq 'SELECT Id, name, etc FROM table_name ORDER BY Id DESC LIMIT 1'
179
+ end
131
180
  end
132
181
 
133
182
  describe ".count" do
@@ -138,6 +187,12 @@ describe ActiveForce::Query do
138
187
  it "should work with a condition" do
139
188
  expect(query.where("name = 'cool'").count.to_s).to eq "SELECT count(Id) FROM table_name WHERE (name = 'cool')"
140
189
  end
190
+
191
+ it "should not update the original query" do
192
+ query_with_count = query.where("name = 'cool'").count
193
+ expect(query.to_s).to eq "SELECT Id, name, etc FROM table_name"
194
+ expect(query_with_count.to_s).to eq "SELECT count(Id) FROM table_name WHERE (name = 'cool')"
195
+ end
141
196
  end
142
197
 
143
198
  describe ".sum" do