bento_search 0.8.0 → 0.9.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (44) hide show
  1. data/README.md +16 -2
  2. data/app/helpers/bento_search_helper.rb +4 -10
  3. data/app/item_decorators/bento_search/decorator_base.rb +17 -0
  4. data/app/item_decorators/bento_search/standard_decorator.rb +3 -3
  5. data/app/models/bento_search/link.rb +3 -0
  6. data/app/models/bento_search/result_item.rb +17 -1
  7. data/app/models/bento_search/results.rb +5 -0
  8. data/app/models/bento_search/ris_creator.rb +166 -0
  9. data/app/models/bento_search/search_engine.rb +22 -2
  10. data/app/search_engines/bento_search/ebsco_host_engine.rb +54 -6
  11. data/app/search_engines/bento_search/eds_engine.rb +18 -3
  12. data/app/search_engines/bento_search/google_books_engine.rb +81 -54
  13. data/app/search_engines/bento_search/mock_engine.rb +8 -0
  14. data/app/search_engines/bento_search/primo_engine.rb +6 -2
  15. data/app/search_engines/bento_search/scopus_engine.rb +4 -0
  16. data/app/search_engines/bento_search/summon_engine.rb +26 -4
  17. data/app/search_engines/bento_search/worldcat_sru_dc_engine.rb +15 -0
  18. data/app/views/bento_search/_link.html.erb +3 -2
  19. data/lib/bento_search/version.rb +1 -1
  20. data/test/dummy/app/views/_test_custom_item_partial.html.erb +9 -0
  21. data/test/dummy/log/development.log +1 -0
  22. data/test/dummy/log/test.log +84981 -0
  23. data/test/helper/bento_search_helper_test.rb +11 -1
  24. data/test/unit/ebsco_host_engine_test.rb +59 -0
  25. data/test/unit/eds_engine_test.rb +10 -0
  26. data/test/unit/google_books_engine_test.rb +20 -0
  27. data/test/unit/primo_engine_test.rb +1 -1
  28. data/test/unit/ris_creator_test.rb +159 -0
  29. data/test/unit/scopus_engine_test.rb +2 -0
  30. data/test/unit/search_engine_test.rb +37 -0
  31. data/test/unit/summon_engine_test.rb +21 -0
  32. data/test/unit/worldcat_sru_dc_engine_test.rb +151 -0
  33. data/test/vcr_cassettes/ebscohost/live__get_identifier__round_trip.yml +1324 -0
  34. data/test/vcr_cassettes/ebscohost/live_get_id__on_bad_db_raises.yml +45 -0
  35. data/test/vcr_cassettes/ebscohost/live_get_id__with_no_results_raises.yml +45 -0
  36. data/test/vcr_cassettes/gbs/live_get_id_.yml +415 -0
  37. data/test/vcr_cassettes/gbs/live_get_id__with_not_found_id.yml +41 -0
  38. data/test/vcr_cassettes/summon/live__get_id_.yml +313 -0
  39. data/test/vcr_cassettes/summon/live_get_id__on_non-existing_id.yml +54 -0
  40. data/test/vcr_cassettes/worldcat_sru_dc/live_get_id_.yml +769 -0
  41. data/test/vcr_cassettes/worldcat_sru_dc/live_get_id__for_bad_id.yml +68 -0
  42. data/test/view/link_test.rb +21 -0
  43. metadata +31 -6
  44. data/test/vcr_cassettes/max_out_pagination.yml +0 -155
@@ -24,7 +24,15 @@ class BentoSearchHelperTest < ActionView::TestCase
24
24
  results = MockEngine.new.search(:query => "foo")
25
25
  bento_search(results)
26
26
 
27
- assert_select("div.bento_item", 10)
27
+ assert_select("div.bento_item", 10)
28
+ end
29
+
30
+ def test_custom_partial
31
+ results = MockEngine.new(:for_display => {:item_partial => "test_custom_item_partial"})
32
+
33
+ bento_search(results)
34
+
35
+ assert_select("p.custom_item_partial")
28
36
  end
29
37
 
30
38
  def test_with_failed_search
@@ -81,6 +89,8 @@ class BentoSearchHelperTest < ActionView::TestCase
81
89
  assert_raises(ArgumentError) { bento_search(MockEngine.new, :load => :ajax_auto) }
82
90
  end
83
91
 
92
+
93
+
84
94
  def test_ajax_load
85
95
  BentoSearch.register_engine("test_engine") do |conf|
86
96
  conf.engine = "MockEngine"
@@ -88,6 +88,22 @@ class EbscoHostEngineTest < ActiveSupport::TestCase
88
88
 
89
89
  end
90
90
 
91
+ def test_per_search_databases_construction
92
+ url = @engine.query_url(:query => "cancer", :databases => ["aaa", "bbb"])
93
+
94
+ query_params = CGI.parse( URI.parse(url).query )
95
+
96
+ assert_equal ["aaa", "bbb"].to_set, query_params["db"].to_set
97
+ end
98
+
99
+ def test_lookup_by_accession_number_construction
100
+ url = @engine.query_url(:query => "123456", :search_field => "AN")
101
+
102
+ query_params = CGI.parse( URI.parse(url).query )
103
+
104
+ assert_equal ["(AN 123456)"], query_params["query"]
105
+ end
106
+
91
107
 
92
108
  def test_prepare_query
93
109
  query = @engine.ebsco_query_prepare('one :. ; two "three four" and NOT OR five')
@@ -115,6 +131,13 @@ class EbscoHostEngineTest < ActiveSupport::TestCase
115
131
  assert_equal ['"cancer "'], query_params["query"]
116
132
  end
117
133
 
134
+ def test_has_http_timeout_set
135
+ assert_equal BentoSearch::EbscoHostEngine::HttpTimeout, @engine.http_client.receive_timeout
136
+ assert_equal BentoSearch::EbscoHostEngine::HttpTimeout, @engine.http_client.send_timeout
137
+ assert_equal BentoSearch::EbscoHostEngine::HttpTimeout, @engine.http_client.connect_timeout
138
+ end
139
+
140
+
118
141
  test_with_cassette("live search smoke test", :ebscohost) do
119
142
 
120
143
  results = @engine.search(:query => "cancer")
@@ -133,6 +156,10 @@ class EbscoHostEngineTest < ActiveSupport::TestCase
133
156
 
134
157
  assert_present first.language_code
135
158
  assert_present first.language_str
159
+
160
+ assert_present first.unique_id
161
+ # db name, colon, accession number.
162
+ assert_match /.+\:.+/, first.unique_id
136
163
  end
137
164
 
138
165
  test_with_cassette("get_info", :ebscohost) do
@@ -253,4 +280,36 @@ class EbscoHostEngineTest < ActiveSupport::TestCase
253
280
  assert_equal "Machine gun voices: Bandits, favelas, and utopia in Brazilian funk", result.title
254
281
  end
255
282
 
283
+ test_with_cassette("live #get(identifier) round trip", :ebscohost) do
284
+ results = @engine.search("cancer")
285
+
286
+ assert (! results.failed?)
287
+
288
+ item = @engine.get( results.first.unique_id )
289
+
290
+ assert_not_nil item
291
+ assert_kind_of BentoSearch::ResultItem, item
292
+ end
293
+
294
+ test_with_cassette("live get(id) with no results raises", :ebscohost) do
295
+ assert_raise(BentoSearch::NotFound) do
296
+ results = @engine.get("a9h:bar")
297
+ end
298
+ end
299
+
300
+ test_with_cassette("live get(id) on bad db raises", :ebscohost) do
301
+ assert_raise(Exception) do
302
+ results = @engine.get("badbad:bar")
303
+ end
304
+ end
305
+
306
+
307
+ test("illegal arg for get with id with no colon") do
308
+ assert_raise ArgumentError do
309
+ @engine.get("no_colon_in_here")
310
+ end
311
+ end
312
+
313
+
314
+
256
315
  end
@@ -61,6 +61,12 @@ class EdsEngineTest < ActiveSupport::TestCase
61
61
  assert_include parts, "SourceType:Academic Journals"
62
62
  assert_include parts, "SourceType:Magazines"
63
63
  end
64
+
65
+ def test_has_http_timeout_set
66
+ assert_equal BentoSearch::EdsEngine::HttpTimeout, @engine.http_client.receive_timeout
67
+ assert_equal BentoSearch::EdsEngine::HttpTimeout, @engine.http_client.send_timeout
68
+ assert_equal BentoSearch::EdsEngine::HttpTimeout, @engine.http_client.connect_timeout
69
+ end
64
70
 
65
71
 
66
72
  test_with_cassette("get_auth_token failure", :eds) do
@@ -138,6 +144,10 @@ class EdsEngineTest < ActiveSupport::TestCase
138
144
  assert_present first.custom_data["citation_blob"]
139
145
 
140
146
  assert_present first.format_str
147
+
148
+ assert_present first.unique_id
149
+ # EDS id is db name, colon, accession number
150
+ assert_match /.+\:.+/, first.unique_id
141
151
  end
142
152
 
143
153
 
@@ -27,6 +27,8 @@ class GoogleBooksEngineTest < ActiveSupport::TestCase
27
27
 
28
28
  assert_kind_of BentoSearch::ResultItem, first
29
29
 
30
+ assert_not_empty first.unique_id
31
+
30
32
  assert_not_empty first.title
31
33
  assert_not_empty first.publisher
32
34
  assert_not_empty first.link
@@ -81,6 +83,24 @@ class GoogleBooksEngineTest < ActiveSupport::TestCase
81
83
  assert ! results.failed?
82
84
  assert_equal 0, results.total_items
83
85
  end
86
+
87
+ test_with_cassette("live get(id)", :gbs) do
88
+ results = @engine.search 'cancer'
89
+
90
+ assert_present results
91
+
92
+ item = @engine.get(results.first.unique_id)
93
+
94
+ assert_present item
95
+ assert_kind_of BentoSearch::ResultItem, item
96
+ assert_equal results.first.unique_id, item.unique_id
97
+ end
98
+
99
+ test_with_cassette("live get(id) with not found id", :gbs) do
100
+ assert_raise(BentoSearch::NotFound) do
101
+ @engine.get("NOT EXISTING")
102
+ end
103
+ end
84
104
 
85
105
 
86
106
 
@@ -42,7 +42,7 @@ class PrimoEngineTest < ActiveSupport::TestCase
42
42
  # not every result has every field, but at time we recorded
43
43
  # with VCR, this result for this search did. Sorry, a bit fragile.
44
44
  # publisher
45
- %w{format_str format title authors volume issue start_page end_page journal_title issn doi abstract}.each do |attr|
45
+ %w{format_str format title authors volume issue start_page end_page journal_title issn doi abstract unique_id}.each do |attr|
46
46
  assert_present first.send(attr), "must have #{attr}"
47
47
  end
48
48
 
@@ -0,0 +1,159 @@
1
+ require 'test_helper'
2
+
3
+ class RISCreatorTest < ActiveSupport::TestCase
4
+ RISCreator = BentoSearch::RISCreator
5
+ ResultItem = BentoSearch::ResultItem
6
+ Author = BentoSearch::Author
7
+
8
+ # Parses an RIS file into a simpel data structure easier to test:
9
+ # an array of two element arrays, where each two element array is
10
+ # (tag, field). This method MAY also assert that the thing basically
11
+ # looks like a proper RIS file.
12
+ def ris_parse(str)
13
+ assert_match /\A\r\n/, str, "RIS records begin with \r\n seperator"
14
+ str.gsub!(/\A(\r\n)+/, '') # remove any at the beginning, multiple are fine
15
+
16
+ assert_match /\r\n\Z/, str, "Our RIS records end up with \r\n so they are concat-able with blank lines in between"
17
+ str.gsub!(/(\r\n)+\Z/, '') # remove any at the end, multiple are fine
18
+
19
+ lines = str.split("\r\n", -1)
20
+
21
+ assert_present lines, "RIS files are composed of multiple lines seperated by \r\n"
22
+
23
+ # trim blank lines off beginning or end, they're allowed. Also "ER" tag
24
+ # off the end, make sure it's there then trim it.
25
+ assert_equal "ER - ", lines.last, "RIS records end in `ER - `"
26
+ lines.pop # throw it away now.
27
+
28
+ return lines.collect do |line|
29
+ line =~ /^([A-Z][A-Z0-9]) - (.*)$/
30
+ tag = $1 ; value = $2
31
+ assert (tag.present? && value.present?), "Individual RIS lines are composed of `TG - VALUE`, not `#{line}`"
32
+ [tag, value]
33
+ end
34
+ end
35
+
36
+
37
+ @@article = ResultItem.new(
38
+ :format => "Article",
39
+ :title => "Some Article",
40
+ :source_title => "Some Journal",
41
+ :issn => "12345678",
42
+ :volume => "10",
43
+ :issue => "3",
44
+ :start_page => "100",
45
+ :end_page => "110",
46
+ :doi => '10.1000/182',
47
+ :abstract => "This is an abstract",
48
+ :authors => [
49
+ Author.new(:first => "John", :last => "Smith", :middle => "Q"),
50
+ Author.new(:first => "Maria", :last => "Lopez"),
51
+ Author.new(:display => "Some Guy")
52
+ ]
53
+ )
54
+
55
+ @@article_with_full_date = ResultItem.new(
56
+ :format => "Article",
57
+ :title => "Something",
58
+ :source_title => "Some Magazine",
59
+ :start_page => "123",
60
+ :publication_date => Date.new(2011,9,1)
61
+ )
62
+
63
+ @@book = ResultItem.new(
64
+ :format => "Book",
65
+ :title => "Some Book",
66
+ :isbn => "1234567890",
67
+ :publisher => "Some Publisher",
68
+ :year => "1990",
69
+ :authors => [
70
+ Author.new(:first => "John", :last => "Smith", :middle => "Q")
71
+ ]
72
+ )
73
+
74
+ @@book_chapter = ResultItem.new(
75
+ :format => :book_item,
76
+ :title => 'Some Chapter',
77
+ :source_title => "Book Title",
78
+ :year => '1991',
79
+ :publisher => "Some Pub",
80
+ :start_page => '10',
81
+ :authors => [
82
+ Author.new(:first => "John", :last => "Smith", :middle => "Q")
83
+ ]
84
+ )
85
+
86
+ @@dissertation = ResultItem.new(
87
+ :format => :dissertation,
88
+ :title => "Areoformation and the new science",
89
+ :publisher => "University of Mars",
90
+ :year => "2150",
91
+ :authors => [
92
+ Author.new(:display => "mztlbplk q. frakdf")
93
+ ]
94
+ )
95
+
96
+
97
+ def test_article
98
+ lines = ris_parse RISCreator.new(@@article).export
99
+
100
+ assert_include lines, ['TY', 'JOUR']
101
+ assert_include lines, ['TI', @@article.title]
102
+ assert_include lines, ['T2', @@article.source_title]
103
+ assert_include lines, ['SN', @@article.issn]
104
+ assert_include lines, ['VL', @@article.volume]
105
+ assert_include lines, ['IS', @@article.issue]
106
+ assert_include lines, ['SP', @@article.start_page]
107
+ assert_include lines, ['EP', @@article.end_page]
108
+ assert_include lines, ['DO', @@article.doi]
109
+ assert_include lines, ['AB', @@article.abstract]
110
+
111
+ assert_include lines, ['AU', "Smith, John Q."]
112
+ assert_include lines, ['AU', "Lopez, Maria"]
113
+ assert_include lines, ['AU', "Some Guy"]
114
+ end
115
+
116
+ def test_book
117
+ lines = ris_parse RISCreator.new(@@book).export
118
+
119
+ assert_include lines, ['TY', 'BOOK']
120
+ assert_include lines, ['TI', @@book.title]
121
+ assert_include lines, ['PY', @@book.year]
122
+ assert_include lines, ['PB', @@book.publisher]
123
+ assert_include lines, ['SN', @@book.isbn]
124
+
125
+ assert_include lines, ['AU', "Smith, John Q."]
126
+ end
127
+
128
+ def test_book_chapter
129
+ lines = ris_parse RISCreator.new(@@book_chapter).export
130
+
131
+ assert_include lines, ['TY', 'CHAP']
132
+
133
+ assert_include lines, ['TI', @@book_chapter.title]
134
+ assert_include lines, ['T2', @@book_chapter.source_title]
135
+ assert_include lines, ['PY', @@book_chapter.year]
136
+ assert_include lines, ['PB', @@book_chapter.publisher]
137
+ assert_include lines, ['SP', @@book_chapter.start_page]
138
+ end
139
+
140
+ def test_dissertation
141
+ lines = ris_parse RISCreator.new(@@dissertation).export
142
+
143
+ assert_include lines, ['TY', 'THES']
144
+
145
+ assert_include lines, ['TI', @@dissertation.title]
146
+ assert_include lines, ['PB', @@dissertation.publisher]
147
+ assert_include lines, ['PY', @@dissertation.year]
148
+ end
149
+
150
+ def test_article_with_full_date
151
+ lines = ris_parse RISCreator.new(@@article_with_full_date).export
152
+
153
+ assert_include lines, ['TY', 'JOUR']
154
+
155
+ assert_include lines, ['DA', '2011/09/01']
156
+ end
157
+
158
+
159
+ end
@@ -102,6 +102,8 @@ class ScopusEngineTest < ActiveSupport::TestCase
102
102
 
103
103
  assert_present sample_result.format
104
104
 
105
+ assert_present sample_result.unique_id
106
+
105
107
  end
106
108
 
107
109
  test_with_cassette("zero results search", :scopus) do
@@ -103,6 +103,43 @@ class SearchEngineTest < ActiveSupport::TestCase
103
103
 
104
104
  end
105
105
 
106
+ test "sets metadata on items" do
107
+ engine = MockEngine.new(:id => "foo", :for_display => {:key => "value", :decorator => "Foo"})
108
+ results = engine.search(:query => "cancer")
109
+ record = results.first
110
+
111
+ assert_present record.engine_id
112
+ assert_present record.display_configuration
113
+ assert_present record.decorator
114
+ end
115
+
116
+ test "failed sets metadata on results" do
117
+ engine = MockEngine.new(:id => "fail_engine", :error => {:message => "failed"}, :for_display => {:foo => "foo"})
118
+
119
+ results = engine.search(:query => "cancer", :per_page => 20)
120
+
121
+ assert results.failed?
122
+ assert_present results.error
123
+ assert_equal "fail_engine", results.engine_id
124
+ assert_present results.search_args
125
+ assert_equal( {:foo => "foo"}, results.display_configuration )
126
+ end
127
+
128
+ test "auto rescued exception, with proper metadata" do
129
+ engine = MockEngine.new(:id => "raises", :raise_exception_class => 'TimeoutError', :for_display => {:foo => "foo"})
130
+
131
+ results = engine.search("foo", :per_page => 20)
132
+
133
+ assert results.failed?, "marked failed"
134
+ assert_present results.error
135
+ assert_equal "raises", results.engine_id
136
+ assert_present results.search_args
137
+ assert_equal "foo", results.search_args[:query]
138
+
139
+ assert_equal( {:foo => "foo"}, results.display_configuration )
140
+ end
141
+
142
+
106
143
  test "has empty :for_display config" do
107
144
  engine = MockEngine.new
108
145
 
@@ -158,6 +158,8 @@ class SummonEngineTest < ActiveSupport::TestCase
158
158
 
159
159
  # just smoke test to make sure it's set to something
160
160
  assert_not_nil first.link_is_fulltext?
161
+
162
+ assert_present first.unique_id
161
163
  end
162
164
 
163
165
  test_with_cassette("proper tags for snippets", :summon) do
@@ -174,4 +176,23 @@ class SummonEngineTest < ActiveSupport::TestCase
174
176
 
175
177
  end
176
178
 
179
+ test_with_cassette("live #get(id)", :summon) do
180
+ results = @engine.search("cancer")
181
+
182
+ assert_present results
183
+
184
+ item = @engine.get(results.first.unique_id)
185
+
186
+ assert_not_nil item
187
+ assert_kind_of BentoSearch::ResultItem, item
188
+
189
+ assert_equal results.first.unique_id, item.unique_id
190
+ end
191
+
192
+ test_with_cassette("live get(id) on non-existing id", :summon) do
193
+ assert_raise(BentoSearch::NotFound) do
194
+ item = @engine.get("NONE SUCH")
195
+ end
196
+ end
197
+
177
198
  end
@@ -0,0 +1,151 @@
1
+ require 'test_helper'
2
+
3
+ require 'cgi'
4
+ require 'uri'
5
+
6
+ #
7
+ #
8
+ # Using the MARCXML response is way too much work, but the XML 'DC' response
9
+ # is awfully stunted. We do what we can with it, but resulting metadata
10
+ # is weird.
11
+ #
12
+ class WorldcatSruDcEngineTest < ActiveSupport::TestCase
13
+ extend TestWithCassette
14
+
15
+ @@api_key = ENV["WORLDCAT_API_KEY"] || "DUMMY_API_KEY"
16
+
17
+ VCR.configure do |c|
18
+ c.filter_sensitive_data("DUMMY_API_KEY", :worldcat_sru_dc) { @@api_key }
19
+ end
20
+
21
+
22
+ def setup
23
+ @config = {:api_key => @@api_key}
24
+ @engine = BentoSearch::WorldcatSruDcEngine.new(@config)
25
+ end
26
+
27
+ def test_construct_url
28
+ query = 'cancer\'s "one two"'
29
+ url = @engine.construct_query_url(:query => query, :per_page => 10)
30
+
31
+ query_hash = CGI.parse(URI.parse(url).query)
32
+
33
+ assert_equal [@engine.configuration.api_key], query_hash["wskey"]
34
+ assert_equal ['info:srw/schema/1/dc'], query_hash["recordSchema"]
35
+ assert_equal [@engine.construct_cql_query(:query => query)], query_hash["query"]
36
+ end
37
+
38
+ def test_construct_pagination
39
+ url = @engine.construct_query_url(:query => "cancer", :per_page => 20, :start => 20)
40
+
41
+ query_hash = CGI.parse(URI.parse(url).query)
42
+
43
+ assert_equal ["20"], query_hash["maximumRecords"]
44
+ assert_equal ["21"], query_hash["startRecord"]
45
+ end
46
+
47
+ def test_construct_sort
48
+ url = @engine.construct_query_url(:query => "cancer", :sort => "date_desc")
49
+
50
+ query_hash = CGI.parse(URI.parse(url).query)
51
+
52
+ assert_present query_hash["sortKeys"]
53
+ end
54
+
55
+ def test_construct_fielded_search
56
+ cql = @engine.construct_cql_query(:query => "cancer", :search_field => "srw.ti")
57
+
58
+ assert_equal 'srw.ti = "cancer"', cql
59
+ end
60
+
61
+ def test_construct_servicelevel
62
+ url = @engine.construct_query_url(:query => "cancer")
63
+ query_hash = CGI.parse(URI.parse(url).query)
64
+ assert_not_include query_hash["servicelevel"], "full"
65
+
66
+ url = @engine.construct_query_url(:query => "cancer auth", :auth => true)
67
+ query_hash = CGI.parse(URI.parse(url).query)
68
+ assert_include query_hash["servicelevel"], "full"
69
+
70
+ default_on = BentoSearch::WorldcatSruDcEngine.new(@config.merge(:auth => true))
71
+
72
+ url = default_on.construct_query_url(:query => "cancer")
73
+ query_hash = CGI.parse(URI.parse(url).query)
74
+ assert_include query_hash["servicelevel"], "full"
75
+
76
+ url = default_on.construct_query_url(:query => "cancer", :auth => false)
77
+ query_hash = CGI.parse(URI.parse(url).query)
78
+ assert_not_include query_hash["servicelevel"], "full"
79
+ end
80
+
81
+ def test_construct_cql
82
+ # test proper escaping and such
83
+ cql = @engine.construct_cql_query(:query => "alpha's beta \"one two\" thr\"ee")
84
+
85
+ components = cql.split(" AND ")
86
+
87
+ assert_equal 4, components.length
88
+
89
+ ["srw.kw = \"beta\"",
90
+ "srw.kw = \"alpha's\"",
91
+ "srw.kw = \"one two\"",
92
+ "srw.kw = \"thr\\\"ee\""].each do |clause|
93
+ assert_include components, clause
94
+ end
95
+ end
96
+
97
+ test_with_cassette("max_out_pagination", :worldcat_sru_dc) do
98
+ #worldcat maxes out at start 9999, we silently correct
99
+ results = @engine.search("cancer", :start => 100000, :per_page => 10)
100
+
101
+ assert ! results.failed?
102
+ assert_present results
103
+ assert_equal 9999, results.pagination.start_record
104
+ assert_equal 1000, results.pagination.current_page
105
+ end
106
+
107
+ test_with_cassette("smoke test", :worldcat_sru_dc) do
108
+ results = @engine.search("anarchism")
109
+
110
+ assert_present results
111
+
112
+ assert_present results.total_items
113
+
114
+ first = results.first
115
+
116
+ assert_present first.unique_id
117
+
118
+ assert_present first.title
119
+ assert_present first.authors
120
+ assert_present first.publisher
121
+ assert_present first.oclcnum
122
+
123
+ assert_present first.year
124
+
125
+ assert_present first.abstract
126
+
127
+ assert_present first.link
128
+
129
+ assert_present first.language_code
130
+ end
131
+
132
+ test_with_cassette("live get(id)", :worldcat_sru_dc) do
133
+ results = @engine.search("anarchism")
134
+
135
+ assert_present results
136
+
137
+ item = @engine.get( results.first.unique_id)
138
+
139
+ assert_present item
140
+ assert_kind_of BentoSearch::ResultItem, item
141
+ assert_equal results.first.unique_id, item.unique_id
142
+ end
143
+
144
+ test_with_cassette("live get(id) for bad id", :worldcat_sru_dc) do
145
+ assert_raise(BentoSearch::NotFound) do
146
+ @engine.get("NOT EXISTING")
147
+ end
148
+ end
149
+
150
+
151
+ end