ap 0.1.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,3 @@
1
+ module AP
2
+ VERSION = '0.1.1'.freeze
3
+ end
@@ -0,0 +1,22 @@
1
+ require 'spec_helper'
2
+
3
+ describe AP::API do
4
+ describe "base_uri" do
5
+ it "should have the correct endpoint" do
6
+ AP::API.base_uri.should == "http://developerapi.ap.org"
7
+ end
8
+ end
9
+
10
+ describe "format" do
11
+ it "should have the custom ap_xml format" do
12
+ AP::API.format.should be(:ap_xml)
13
+ end
14
+ end
15
+
16
+ describe "API key" do
17
+ it "should have a apiKey key in the default params hash" do
18
+ AP::API.new
19
+ AP::API.default_params.keys.should include(:apiKey)
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,83 @@
1
+ require 'spec_helper'
2
+
3
+ describe AP::Article do
4
+ describe "attributes" do
5
+ [:id, :title, :authors, :tags, :link, :content, :updated].each do |e|
6
+ it "should have a #{e} attribute" do
7
+ @article = AP::Article.new
8
+ @article.should respond_to(e)
9
+ end
10
+ end
11
+
12
+ params_hash = {:id => "random", :title => "a title", :authors => "", :tags => ["A tag"], :link => "http://google.com", :content => "<div>content</div>", :updated => Time.now}
13
+ params_hash.each do |e, v|
14
+ it "should have the correct value for #{e}" do
15
+ @article = AP::Article.new(params_hash)
16
+ @article.send(e).should == v
17
+ end
18
+ end
19
+ end
20
+
21
+ describe "creating an object from API data" do
22
+ before do
23
+ @api_data = {
24
+ "id" => "urn:blah:blahblah",
25
+ "title" => "Hello",
26
+ "author" => [],
27
+ "category" => [ {"label" => "Tag 1"}, {"label" => "Tag 2" } ],
28
+ "link" => { "href" => "http://google.com" },
29
+ "content" => "<div>content</div>",
30
+ "updated" => "2011-04-23T06:00:39Z"
31
+ }
32
+ @parsed_data = {
33
+ "id" => "blahblah",
34
+ "title" => "Hello",
35
+ "authors" => [],
36
+ "tags" => ["Tag 1", "Tag 2"],
37
+ "link" => "http://google.com",
38
+ "content" => "<div>content</div>",
39
+ "updated" => Time.parse("2011-04-23T06:00:39Z")
40
+ }
41
+ end
42
+
43
+ describe "should return a proper object" do
44
+ before do
45
+ @article = AP::Article.new_from_api_data(@api_data)
46
+ end
47
+
48
+ [:id, :title, :authors, :tags, :link, :content, :updated].each do |e|
49
+ it "with the correct value for #{e.to_s}" do
50
+ @article.send(e).should == @parsed_data[e.to_s]
51
+ end
52
+ end
53
+ end
54
+
55
+ describe "should properly differentiate between one and multiple authors" do
56
+ before do
57
+ @api_data["author"] = {"name" => "Joe"}
58
+ @parsed_data["authors"] = ["Joe"]
59
+ @article = AP::Article.new_from_api_data(@api_data)
60
+ end
61
+
62
+ [:id, :title, :authors, :tags, :link, :content, :updated].each do |e|
63
+ it "with the correct value for #{e.to_s}" do
64
+ @article.send(e).should == @parsed_data[e.to_s]
65
+ end
66
+ end
67
+ end
68
+
69
+ describe "should support multiple authors" do
70
+ before do
71
+ @api_data["author"] = [{"name" => "Joe"}, {"name" => "Bob"}, {"name" => "Jane"}]
72
+ @parsed_data["authors"] = ["Joe", "Bob", "Jane"]
73
+ @article = AP::Article.new_from_api_data(@api_data)
74
+ end
75
+
76
+ [:id, :title, :authors, :tags, :link, :content, :updated].each do |e|
77
+ it "with the correct value for #{e.to_s}" do
78
+ @article.send(e).should == @parsed_data[e.to_s]
79
+ end
80
+ end
81
+ end
82
+ end
83
+ end
@@ -0,0 +1,50 @@
1
+ require 'spec_helper'
2
+
3
+ describe AP::Category do
4
+ describe "attributes" do
5
+ [:id, :title, :content, :updated].each do |e|
6
+ it "should have a #{e} attribute" do
7
+ @category = AP::Category.new
8
+ @category.should respond_to(e)
9
+ end
10
+ end
11
+
12
+ params_hash = {:id => "random", :title => "a title", :content => "<div>content</div>", :updated => Time.now }
13
+ params_hash.each do |e, v|
14
+ it "should have the correct value for #{e}" do
15
+ @category = AP::Category.new(params_hash)
16
+ @category.send(e).should == v
17
+ end
18
+ end
19
+ end
20
+
21
+ describe "creating an object from API data" do
22
+ before do
23
+ @api_data = {
24
+ "id" => "urn:uuid:31990",
25
+ "title" => "Hello",
26
+ "content" => "<div>content</div>",
27
+ "updated" => "2011-04-23T06:00:39Z"
28
+ }
29
+ @parsed_data = {
30
+ "id" => "31990",
31
+ "title" => "Hello",
32
+ "content" => "<div>content</div>",
33
+ "updated" => Time.parse("2011-04-23T06:00:39Z")
34
+ }
35
+ end
36
+
37
+ describe "should return a proper object" do
38
+ before do
39
+ @category = AP::Category.new_from_api_data(@api_data)
40
+ end
41
+
42
+ [:id, :title, :content, :updated].each do |e|
43
+ it "with the correct value for #{e.to_s}" do
44
+ @category.send(e).should == @parsed_data[e.to_s]
45
+ end
46
+ end
47
+ end
48
+
49
+ end
50
+ end
@@ -0,0 +1,74 @@
1
+ require 'spec_helper'
2
+
3
+ describe AP::Client::Category do
4
+ context "with an API key" do
5
+ before do
6
+ AP.configure do |c|
7
+ c.api_key = "api"
8
+ end
9
+ end
10
+
11
+ describe ".categories" do
12
+ before do
13
+ stub_get("/v2/categories.svc/?apiKey=api").to_return(:body => fixture("categories.xml"), :headers => {:content_type => "application/xml; charset=utf-8"})
14
+ end
15
+
16
+ it "should map API data to objects" do
17
+ AP.categories.size.should == 52
18
+ end
19
+
20
+ {:id => "31990", :content => "AP Online Top General Short Headlines", :title => "AP Online Top General Short Headlines", :updated => Time.parse("2011-04-23T05:55:23Z") }.each do |e, v|
21
+ it "should map the API data to the attribute #{e}" do
22
+ AP.categories.first.send(e).should == v
23
+ end
24
+ end
25
+ end
26
+
27
+ describe ".category(id)" do
28
+ before do
29
+ stub_get("/v2/categories.svc/31990?apiKey=api").to_return(:body => fixture("categories-31990.xml"), :headers => {:content_type => "application/xml; charset=utf-8"})
30
+ end
31
+
32
+ it "should map API data to objects" do
33
+ AP.category(31990).size.should == 10
34
+ end
35
+
36
+ {
37
+ :id => "772cbfbd-eb16-4527-882e-48d4fb21ad35",
38
+ :title => "Tornado causes injuries at St. Louis airport",
39
+ :updated => Time.parse("2011-04-23T05:48:58Z"),
40
+ :authors => ["JIM SALTER", "JIM SUHR"],
41
+ :link => "http://hosted2.ap.org/APDEFAULT/Article_2011-04-23-US-Missouri-Storms/id-p772cbfbdeb164527882e48d4fb21ad35",
42
+ :tags => [ "Property damage", "Tornados", "Power outages", "Storms", "Natural disasters", "Weather", "Air travel disruptions", "Emergency management",
43
+ "Injuries", "General news", "Tornados", "Accidents and disasters", "Transportation", "Government and politics", "Health", "Francis Slay",
44
+ "Jay Nixon", "Maryland", "St. Louis", "Missouri", "United States", "North America"]
45
+ }.each do |e, v|
46
+ it "should map the API data to the attribute #{e}" do
47
+ AP.category(31990).first.send(e).should == v
48
+ end
49
+ end
50
+ end
51
+ end
52
+
53
+ context "without an API key" do
54
+ before do
55
+ AP.configure do |c|
56
+ c.api_key = nil
57
+ end
58
+ end
59
+
60
+ describe ".categories" do
61
+ it "should raise a MissingAPIKeyError" do
62
+ stub_get("/v2/categories.svc/?apiKey=api").to_return(:status => 200, :body => "403 Developer Inactive", :headers => {})
63
+ expect { AP.categories }.to raise_error(AP::API::MissingAPIKeyError)
64
+ end
65
+ end
66
+
67
+ describe ".category(id)" do
68
+ it "should raise a MissingAPIKeyError" do
69
+ stub_get("/v2/categories.svc/5?apiKey=api").to_return(:status => 200, :body => "", :headers => {})
70
+ expect { AP.category(5) }.to raise_error(AP::API::MissingAPIKeyError)
71
+ end
72
+ end
73
+ end
74
+ end
@@ -0,0 +1,15 @@
1
+ require 'spec_helper'
2
+
3
+ describe AP::Client do
4
+ describe "includes AP::Client::Category" do
5
+ before do
6
+ @client = AP::Client.new
7
+ end
8
+
9
+ [:categories, :category].each do |e|
10
+ it "should respond to #{e}" do
11
+ @client.should respond_to(e)
12
+ end
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,14 @@
1
+ require 'spec_helper'
2
+
3
+ describe HTTParty::Parser do
4
+
5
+ it "should add CDATA tags and parse correctly" do
6
+ parsed = HTTParty::Parser.call("<feed xmlns=\"http://www.w3.org/2005/Atom\"><entry><content type=\"xhtml\"><div xmlns=\"http://www.w3.org/1999/xhtml\"><div class=\"hnews hentry item\"></div></div></content></entry></feed>", :ap_xml)
7
+ parsed["feed"]["entry"]["content"].should == "<div xmlns=\"http://www.w3.org/1999/xhtml\"><div class=\"hnews hentry item\"></div></div>"
8
+ end
9
+
10
+ it "shouldn't add CDATA when not needed" do
11
+ parsed = HTTParty::Parser.call("<feed xmlns=\"http://www.w3.org/2005/Atom\"><entry><content type=\"xhtml\"><![CDATA[<div xmlns=\"http://www.w3.org/1999/xhtml\"><div class=\"hnews hentry item\"></div></div>]]></content></entry></feed>", :ap_xml)
12
+ parsed["feed"]["entry"]["content"].should == "<div xmlns=\"http://www.w3.org/1999/xhtml\"><div class=\"hnews hentry item\"></div></div>"
13
+ end
14
+ end
@@ -0,0 +1,453 @@
1
+ require 'spec_helper'
2
+
3
+ describe AP::Search do
4
+ # similar queries
5
+ describe "similar query" do
6
+ before do
7
+ @search = AP::Article.new(:id => "5").similar
8
+ end
9
+
10
+ describe ".clear" do
11
+ before do
12
+ @search.clear
13
+ end
14
+
15
+ it "should reset the search type to request" do
16
+ @search.search_type.should == "request"
17
+ end
18
+
19
+ it "should reset the search terms" do
20
+ @search.query[:searchTerms].should == []
21
+ end
22
+
23
+ it "should reset the start page" do
24
+ @search.query[:startPage].should == 1
25
+ end
26
+
27
+ it "should reset the count" do
28
+ @search.query[:count].should == 20
29
+ end
30
+ end
31
+
32
+ describe ".containing" do
33
+ it "should raise an UnsupportedSearchMethod error" do
34
+ expect { @search.containing("Obama") }.to raise_error(AP::Search::UnsupportedSearchMethod)
35
+ end
36
+ end
37
+
38
+ describe ".exact" do
39
+ it "should raise an UnsupportedSearchMethod error" do
40
+ expect { @search.exact("Obama") }.to raise_error(AP::Search::UnsupportedSearchMethod)
41
+ end
42
+ end
43
+
44
+ describe ".matches" do
45
+ it "should raise an UnsupportedSearchMethod error" do
46
+ expect { @search.matches("Ira") }.to raise_error(AP::Search::UnsupportedSearchMethod)
47
+ end
48
+ end
49
+
50
+ describe ".loose_match" do
51
+ it "should raise an UnsupportedSearchMethod error" do
52
+ expect { @search.loose_match("ira") }.to raise_error(AP::Search::UnsupportedSearchMethod)
53
+ end
54
+ end
55
+
56
+ describe ".geocode" do
57
+ it "should properly set the geocode attributes given lat & long" do
58
+ @search.geocode(50, -125)
59
+ @search.query[:latitude].should == 50
60
+ @search.query[:longitude].should == -125
61
+ @search.query[:radius].should == 50
62
+ end
63
+
64
+ it "should properly set the geocode attributes given lat, long & radius" do
65
+ @search.geocode(50, -125, 35)
66
+ @search.query[:latitude].should == 50
67
+ @search.query[:longitude].should == -125
68
+ @search.query[:radius].should == 35
69
+ end
70
+
71
+ it "should raise a InvalidGeocodinates when latitude is invalid" do
72
+ expect { @search.geocode(100, 0) }.to raise_error(AP::Search::InvalidGeocodinates)
73
+ end
74
+
75
+ it "should raise a InvalidGeocodinates when longitude is invalid" do
76
+ expect { @search.geocode(50, 200) }.to raise_error(AP::Search::InvalidGeocodinates)
77
+ end
78
+
79
+ it "should raise a InvalidGeocodinates when longitude and latitude are invalid" do
80
+ expect { @search.geocode(-95, 200) }.to raise_error(AP::Search::InvalidGeocodinates)
81
+ end
82
+ end
83
+
84
+ describe ".location" do
85
+ it "should set City, State & ZIP code when given" do
86
+ @search.location(:zip_code => 12345, :city => "Albany", :state => "NY")
87
+ @search.query[:location].should == "Albany, NY, 12345"
88
+ end
89
+
90
+ it "should set ZIP code when given" do
91
+ @search.location(:zip_code => 12345)
92
+ @search.query[:location].should == "12345"
93
+ end
94
+
95
+ it "should only set ZIP code if City is also given" do
96
+ @search.location(:zip_code => 12345, :city => "Albany")
97
+ @search.query[:location].should == "12345"
98
+ end
99
+
100
+ it "should only set ZIP code if State is also given" do
101
+ @search.location(:zip_code => 12345, :state => "NY")
102
+ @search.query[:location].should == "12345"
103
+ end
104
+
105
+ it "should set City & State if both are given" do
106
+ @search.location(:city => "Albany", :state => "NY")
107
+ @search.query[:location].should == "Albany, NY"
108
+ end
109
+ end
110
+
111
+ describe ".sort_by_location" do
112
+ it "should default to true" do
113
+ @search.sort_by_location
114
+ @search.query[:sortByLocation].should be(true)
115
+ end
116
+
117
+ it "should take the parameter true" do
118
+ @search.sort_by_location(true)
119
+ @search.query[:sortByLocation].should be(true)
120
+ end
121
+
122
+ it "should take the parameter false" do
123
+ @search.sort_by_location(false)
124
+ @search.query[:sortByLocation].should be(false)
125
+ end
126
+ end
127
+
128
+ describe ".scoped" do
129
+ it "should raise an UnsupportedSearchMethod error" do
130
+ expect { @search.scoped do |c|; end; }.to raise_error(AP::Search::UnsupportedSearchMethod)
131
+ end
132
+ end
133
+
134
+ describe ".and" do
135
+ it "should raise an UnsupportedSearchMethod error" do
136
+ expect { @search.and }.to raise_error(AP::Search::UnsupportedSearchMethod)
137
+ end
138
+ end
139
+
140
+ describe ".or" do
141
+ it "should raise an UnsupportedSearchMethod error" do
142
+ expect { @search.or }.to raise_error(AP::Search::UnsupportedSearchMethod)
143
+ end
144
+ end
145
+
146
+ describe ".and_not" do
147
+ it "should raise an UnsupportedSearchMethod error" do
148
+ expect { @search.and_not }.to raise_error(AP::Search::UnsupportedSearchMethod)
149
+ end
150
+ end
151
+
152
+ describe ".per_page" do
153
+ it "should default to 20" do
154
+ @search.per_page
155
+ @search.query[:count].should == 20
156
+ end
157
+
158
+ it "should set the sent value" do
159
+ @search.per_page(39)
160
+ @search.query[:count].should == 39
161
+ end
162
+ end
163
+
164
+ describe ".page" do
165
+ it "should default to 1" do
166
+ @search.page
167
+ @search.query[:startPage].should == 1
168
+ end
169
+
170
+ it "should move to the sent page" do
171
+ @search.page(5)
172
+ @search.query[:startPage].should == 5
173
+ end
174
+ end
175
+ end
176
+
177
+ # request queries
178
+ describe "request query" do
179
+ before do
180
+ @search = AP::Search.new
181
+ end
182
+
183
+ describe ".clear" do
184
+ before do
185
+ @search.clear
186
+ end
187
+
188
+ it "should keep the search type at request" do
189
+ @search.search_type.should == "request"
190
+ end
191
+
192
+ it "should reset the search terms" do
193
+ @search.query[:searchTerms].should == []
194
+ end
195
+
196
+ it "should reset the start page" do
197
+ @search.query[:startPage].should == 1
198
+ end
199
+
200
+ it "should reset the count" do
201
+ @search.query[:count].should == 20
202
+ end
203
+ end
204
+
205
+ describe ".containing" do
206
+ it "should append the string the the query" do
207
+ @search.containing("Obama")
208
+ @search.query[:searchTerms].first.should == "Obama"
209
+ end
210
+ end
211
+
212
+ describe ".exact" do
213
+ it "should append the string the the query" do
214
+ @search.exact("Obama")
215
+ @search.query[:searchTerms].first.should == "\"Obama\""
216
+ end
217
+ end
218
+
219
+ describe ".matches" do
220
+ it "should append the string the the query" do
221
+ @search.matches("Ira")
222
+ @search.query[:searchTerms].first.should == "Ira?"
223
+ end
224
+ end
225
+
226
+ describe ".loose_match" do
227
+ it "should append the string the the query" do
228
+ @search.loose_match("ira")
229
+ @search.query[:searchTerms].first.should == "ira*"
230
+ end
231
+ end
232
+
233
+ describe ".geocode" do
234
+ it "should properly set the geocode attributes given lat & long" do
235
+ @search.geocode(50, -125)
236
+ @search.query[:latitude].should == 50
237
+ @search.query[:longitude].should == -125
238
+ @search.query[:radius].should == 50
239
+ end
240
+
241
+ it "should properly set the geocode attributes given lat, long & radius" do
242
+ @search.geocode(50, -125, 35)
243
+ @search.query[:latitude].should == 50
244
+ @search.query[:longitude].should == -125
245
+ @search.query[:radius].should == 35
246
+ end
247
+
248
+ it "should raise a InvalidGeocodinates when latitude is invalid" do
249
+ expect { @search.geocode(100, 0) }.to raise_error(AP::Search::InvalidGeocodinates)
250
+ end
251
+
252
+ it "should raise a InvalidGeocodinates when longitude is invalid" do
253
+ expect { @search.geocode(50, 200) }.to raise_error(AP::Search::InvalidGeocodinates)
254
+ end
255
+
256
+ it "should raise a InvalidGeocodinates when longitude and latitude are invalid" do
257
+ expect { @search.geocode(-95, 200) }.to raise_error(AP::Search::InvalidGeocodinates)
258
+ end
259
+ end
260
+
261
+ describe ".location" do
262
+ it "should set City, State & ZIP code when given" do
263
+ @search.location(:zip_code => 12345, :city => "Albany", :state => "NY")
264
+ @search.query[:location].should == "Albany, NY, 12345"
265
+ end
266
+
267
+ it "should set ZIP code when given" do
268
+ @search.location(:zip_code => 12345)
269
+ @search.query[:location].should == "12345"
270
+ end
271
+
272
+ it "should only set ZIP code if City is also given" do
273
+ @search.location(:zip_code => 12345, :city => "Albany")
274
+ @search.query[:location].should == "12345"
275
+ end
276
+
277
+ it "should only set ZIP code if State is also given" do
278
+ @search.location(:zip_code => 12345, :state => "NY")
279
+ @search.query[:location].should == "12345"
280
+ end
281
+
282
+ it "should set City & State if both are given" do
283
+ @search.location(:city => "Albany", :state => "NY")
284
+ @search.query[:location].should == "Albany, NY"
285
+ end
286
+ end
287
+
288
+ describe ".sort_by_location" do
289
+ it "should default to true" do
290
+ @search.sort_by_location
291
+ @search.query[:sortByLocation].should be(true)
292
+ end
293
+
294
+ it "should take the parameter true" do
295
+ @search.sort_by_location(true)
296
+ @search.query[:sortByLocation].should be(true)
297
+ end
298
+
299
+ it "should take the parameter false" do
300
+ @search.sort_by_location(false)
301
+ @search.query[:sortByLocation].should be(false)
302
+ end
303
+ end
304
+
305
+ describe ".and" do
306
+ it "should append AND only if something already is in the query" do
307
+ @search.contains("Obama").and
308
+ @search.query[:searchTerms].last.should == "AND"
309
+ end
310
+
311
+ it "shouldn't append if the query is empty" do
312
+ @search.and
313
+ @search.query[:searchTerms].last.should == nil
314
+ end
315
+
316
+ it "shouldn't append if the last item in the query was AND" do
317
+ @search.contains("Obama").and.and
318
+ @search.query[:searchTerms].first.should == "Obama"
319
+ @search.query[:searchTerms].last.should == "AND"
320
+ @search.query[:searchTerms].size.should == 2
321
+ end
322
+
323
+ it "shouldn't append if the last item in the query was OR" do
324
+ @search.contains("Obama").or.and
325
+ @search.query[:searchTerms].first.should == "Obama"
326
+ @search.query[:searchTerms].last.should == "OR"
327
+ @search.query[:searchTerms].size.should == 2
328
+ end
329
+
330
+ it "shouldn't append if the last item in the query was AND NOT" do
331
+ @search.contains("Obama").and_not.and
332
+ @search.query[:searchTerms].first.should == "Obama"
333
+ @search.query[:searchTerms].last.should == "AND NOT"
334
+ @search.query[:searchTerms].size.should == 2
335
+ end
336
+ end
337
+
338
+ describe ".or" do
339
+ it "should append OR only if something already is in the query" do
340
+ @search.contains("Obama").or
341
+ @search.query[:searchTerms].last.should == "OR"
342
+ end
343
+
344
+ it "shouldn't append if the query is empty" do
345
+ @search.or
346
+ @search.query[:searchTerms].last.should == nil
347
+ end
348
+
349
+ it "shouldn't append if the last item in the query was OR" do
350
+ @search.contains("Obama").or.or
351
+ @search.query[:searchTerms].first.should == "Obama"
352
+ @search.query[:searchTerms].last.should == "OR"
353
+ @search.query[:searchTerms].size.should == 2
354
+ end
355
+ it "shouldn't append if the last item in the query was AND" do
356
+ @search.contains("Obama").and.or
357
+ @search.query[:searchTerms].first.should == "Obama"
358
+ @search.query[:searchTerms].last.should == "AND"
359
+ @search.query[:searchTerms].size.should == 2
360
+ end
361
+
362
+ it "shouldn't append if the last item in the query was AND NOT" do
363
+ @search.contains("Obama").and_not.or
364
+ @search.query[:searchTerms].first.should == "Obama"
365
+ @search.query[:searchTerms].last.should == "AND NOT"
366
+ @search.query[:searchTerms].size.should == 2
367
+ end
368
+ end
369
+
370
+ describe ".and_not" do
371
+ it "should append AND NOT only if something already is in the query" do
372
+ @search.contains("Obama").and_not
373
+ @search.query[:searchTerms].last.should == "AND NOT"
374
+ end
375
+
376
+ it "shouldn't append if the query is empty" do
377
+ @search.and_not
378
+ @search.query[:searchTerms].last.should == nil
379
+ end
380
+
381
+ it "shouldn't append if the last item in the query was AND" do
382
+ @search.contains("Obama").and.and_not
383
+ @search.query[:searchTerms].first.should == "Obama"
384
+ @search.query[:searchTerms].last.should == "AND"
385
+ @search.query[:searchTerms].size.should == 2
386
+ end
387
+
388
+ it "shouldn't append if the last item in the query was OR" do
389
+ @search.contains("Obama").or.and_not
390
+ @search.query[:searchTerms].first.should == "Obama"
391
+ @search.query[:searchTerms].last.should == "OR"
392
+ @search.query[:searchTerms].size.should == 2
393
+ end
394
+
395
+ it "shouldn't append if the last item in the query was AND NOT" do
396
+ @search.contains("Obama").and_not.and_not
397
+ @search.query[:searchTerms].first.should == "Obama"
398
+ @search.query[:searchTerms].last.should == "AND NOT"
399
+ @search.query[:searchTerms].size.should == 2
400
+ end
401
+ end
402
+
403
+ describe ".per_page" do
404
+ it "should default to 20" do
405
+ @search.per_page
406
+ @search.query[:count].should == 20
407
+ end
408
+
409
+ it "should set the sent value" do
410
+ @search.per_page(39)
411
+ @search.query[:count].should == 39
412
+ end
413
+ end
414
+
415
+ describe ".page" do
416
+ it "should default to 1" do
417
+ @search.page
418
+ @search.query[:startPage].should == 1
419
+ end
420
+
421
+ it "should move to the sent page" do
422
+ @search.page(5)
423
+ @search.query[:startPage].should == 5
424
+ end
425
+ end
426
+ end
427
+
428
+ context "without an API key" do
429
+ before do
430
+ @search = AP::Search.new
431
+ end
432
+
433
+ it "should raise a MissingAPIKeyError" do
434
+ @search.contains("Obama")
435
+ expect { @search.fetch }.to raise_error(AP::API::MissingAPIKeyError)
436
+ end
437
+ end
438
+
439
+ context "with an API key" do
440
+ before do
441
+ AP.configure do |c|
442
+ c.api_key = "api"
443
+ end
444
+ @search = AP::Search.new
445
+ stub_get("/v2/search.svc/request/?apiKey=api&count=20&searchTerms=Obama&startPage=1").to_return(:body => fixture("search-obama.xml"), :headers => {:content_type => "application/xml; charset=utf-8"})
446
+ end
447
+
448
+ it "should fetch and return" do
449
+ @search.contains("Obama")
450
+ @search.fetch.size.should == 20
451
+ end
452
+ end
453
+ end