bento_search 1.7.0.beta.1 → 1.7.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.
- checksums.yaml +4 -4
- data/README.md +16 -7
- data/app/assets/javascripts/bento_search/ajax_load.js +37 -21
- data/app/helpers/bento_search_helper.rb +72 -74
- data/app/models/bento_search/concurrent_searcher.rb +136 -0
- data/app/models/bento_search/multi_searcher.rb +36 -35
- data/app/models/bento_search/search_engine.rb +70 -40
- data/app/search_engines/bento_search/doaj_articles_engine.rb +1 -1
- data/app/search_engines/bento_search/eds_engine.rb +176 -56
- data/app/views/bento_search/_ajax_loading.html.erb +17 -0
- data/app/views/bento_search/_link.html.erb +3 -3
- data/lib/bento_search.rb +12 -0
- data/lib/bento_search/engine.rb +2 -0
- data/lib/bento_search/version.rb +1 -1
- data/test/search_engines/eds_engine_test.rb +91 -59
- data/test/search_engines/search_engine_base_test.rb +11 -0
- data/test/search_engines/search_engine_test.rb +12 -0
- data/test/unit/concurrent_searcher_test.rb +75 -0
- data/test/unit/multi_searcher_test.rb +16 -19
- data/test/vcr_cassettes/eds/FullText_CustomLink.yml +198 -0
- data/test/vcr_cassettes/eds/basic_search_smoke_test.yml +1036 -1729
- data/test/vcr_cassettes/eds/catalog_ebook_query.yml +218 -0
- data/test/vcr_cassettes/eds/catalog_query.yml +255 -0
- data/test/vcr_cassettes/eds/get_auth_token.yml +11 -44
- data/test/vcr_cassettes/eds/get_auth_token_failure.yml +10 -7
- data/test/vcr_cassettes/eds/get_with_auth.yml +144 -153
- data/test/vcr_cassettes/eds/get_with_auth_recovers_from_bad_auth.yml +167 -223
- metadata +15 -5
@@ -0,0 +1,17 @@
|
|
1
|
+
<% # An initially hidden div with loading msg/spinner that will be shown
|
2
|
+
# by js on ajax load
|
3
|
+
%>
|
4
|
+
|
5
|
+
<noscript>
|
6
|
+
<%= I18n.t("bento_search.ajax_noscript") %>
|
7
|
+
</noscript>
|
8
|
+
|
9
|
+
<%=
|
10
|
+
content_tag(:div,
|
11
|
+
:class => "bento_search_ajax_loading",
|
12
|
+
:style => "display:none") do
|
13
|
+
image_tag("bento_search/large_loader.gif",
|
14
|
+
:alt => I18n.translate("bento_search.ajax_loading")
|
15
|
+
)
|
16
|
+
end
|
17
|
+
%>
|
@@ -1,6 +1,6 @@
|
|
1
|
-
<%= link_to(link.label, link.url,
|
2
|
-
:rel => link.rel,
|
1
|
+
<%= link_to(link.label, link.url,
|
2
|
+
:rel => link.rel,
|
3
3
|
:class => (link.style_classes + ["bento_search_link", "btn", "btn-mini", "btn-default", "btn-sm"]),
|
4
|
-
:target => link.target
|
4
|
+
:target => local_assigns[:target] || link.target
|
5
5
|
) %>
|
6
6
|
|
data/lib/bento_search.rb
CHANGED
@@ -47,6 +47,18 @@ module BentoSearch
|
|
47
47
|
# Avoid deprecation warnings in ruby 2.3.0
|
48
48
|
RubyTimeoutClass = (defined?(Timeout::Error) ? Timeout::Error : TimeoutError)
|
49
49
|
|
50
|
+
@@defaults = Confstruct::Configuration.new(
|
51
|
+
error_partial: 'bento_search/search_error',
|
52
|
+
item_partial: 'bento_search/std_item',
|
53
|
+
no_results_partial: 'bento_search/no_results',
|
54
|
+
ajax_loading_partial: 'bento_search/ajax_loading'
|
55
|
+
)
|
56
|
+
def self.set_defaults(hash)
|
57
|
+
@@defaults.merge!(hash)
|
58
|
+
end
|
59
|
+
def self.defaults
|
60
|
+
@@defaults
|
61
|
+
end
|
50
62
|
end
|
51
63
|
|
52
64
|
|
data/lib/bento_search/engine.rb
CHANGED
data/lib/bento_search/version.rb
CHANGED
@@ -2,12 +2,14 @@ require 'test_helper'
|
|
2
2
|
|
3
3
|
class EdsEngineTest < ActiveSupport::TestCase
|
4
4
|
extend TestWithCassette
|
5
|
-
|
5
|
+
|
6
6
|
@@user_id = (ENV['EDS_USER_ID'] || 'DUMMY_USER_ID')
|
7
7
|
@@password = (ENV['EDS_PASSWORD'] || 'DUMMY_PWD')
|
8
|
-
@@profile = (ENV['EDS_PROFILE'] || '
|
9
|
-
|
10
|
-
|
8
|
+
@@profile = (ENV['EDS_PROFILE'] || 'wsapi')
|
9
|
+
# something where the first hit will be from catalog for the profile above
|
10
|
+
@@catalog_result_query = (ENV['EDS_CATALOG_RESULT_QUERY'] || 'New York exposed the gilded age police scandal that launched the progressive era Daniel Czitrom')
|
11
|
+
@@catalog_ebook_result_query = (ENV['EDS_CATALOG_EBOOK_RESULT_QUERY'] || 'Stakeholder forum on federal wetlands mitigation environmental law institute')
|
12
|
+
@@catalog_custom_result_query = (ENV['EDS_CATALOG_CUSTOM_RESULT_QUERY'] || 'Drafting New York Civil-Litigation Documents Part XXIV Summary-Judgment Motions Continued')
|
11
13
|
VCR.configure do |c|
|
12
14
|
c.filter_sensitive_data("DUMMY_USER_ID", :eds) { @@user_id }
|
13
15
|
c.filter_sensitive_data("DUMMY_PWD", :eds) { @@password }
|
@@ -16,140 +18,170 @@ class EdsEngineTest < ActiveSupport::TestCase
|
|
16
18
|
def setup
|
17
19
|
# Class-level remembered auth token messes up our VCR-recording,
|
18
20
|
# since one test will try to use an auth token fetched by a different
|
19
|
-
# test. For testing, blank out the cache before each test.
|
21
|
+
# test. For testing, blank out the cache before each test.
|
20
22
|
BentoSearch::EdsEngine.remembered_auth = nil
|
21
23
|
|
22
24
|
@config = {:user_id => @@user_id, :password => @@password, :profile => @@profile, :auth => true}
|
23
25
|
@engine = BentoSearch::EdsEngine.new(@config)
|
24
26
|
end
|
25
|
-
|
27
|
+
|
26
28
|
test "construct simple search, with comma escaping" do
|
27
29
|
url = @engine.construct_search_url(:query => "foo, bar,baz")
|
28
|
-
|
30
|
+
|
29
31
|
query_params = CGI.parse( URI.parse(url).query )
|
30
32
|
|
31
33
|
assert_equal ["all"], query_params["searchmode"]
|
32
|
-
|
34
|
+
|
33
35
|
assert_equal ["detailed"], query_params["view"]
|
34
|
-
|
35
|
-
assert_equal ["AND,foo bar baz"], query_params["query"]
|
36
|
+
|
37
|
+
assert_equal ["AND,foo bar baz"], query_params["query"]
|
36
38
|
end
|
37
|
-
|
39
|
+
|
38
40
|
test "only_source_types config" do
|
39
41
|
engine = BentoSearch::EdsEngine.new( @config.merge(:only_source_types => [
|
40
42
|
"Academic Journals", "Magazines"
|
41
43
|
]))
|
42
|
-
|
44
|
+
|
43
45
|
url = engine.construct_search_url(:query => "cancer", :per_page => 10)
|
44
|
-
|
46
|
+
|
45
47
|
query_params = CGI.parse( URI.parse(url).query )
|
46
|
-
|
48
|
+
|
47
49
|
# should be
|
48
50
|
# facetfilter=1,SourceType:Academic Journals,SourceType:Magazines
|
49
51
|
# but with value query encoded
|
50
|
-
|
52
|
+
|
51
53
|
assert_equal 1, query_params["facetfilter"].length
|
52
|
-
|
54
|
+
|
53
55
|
facetfilter = query_params["facetfilter"].first
|
54
|
-
|
56
|
+
|
55
57
|
parts = facetfilter.split(",")
|
56
|
-
|
58
|
+
|
57
59
|
assert_equal 3, parts.length
|
58
|
-
|
60
|
+
|
59
61
|
assert_equal "1", parts.first
|
60
|
-
|
62
|
+
|
61
63
|
assert_includes parts, "SourceType:Academic Journals"
|
62
|
-
assert_includes parts, "SourceType:Magazines"
|
64
|
+
assert_includes parts, "SourceType:Magazines"
|
63
65
|
end
|
64
|
-
|
66
|
+
|
65
67
|
def test_has_http_timeout_set
|
66
68
|
assert_equal BentoSearch::EdsEngine::HttpTimeout, @engine.http_client.receive_timeout
|
67
69
|
assert_equal BentoSearch::EdsEngine::HttpTimeout, @engine.http_client.send_timeout
|
68
70
|
assert_equal BentoSearch::EdsEngine::HttpTimeout, @engine.http_client.connect_timeout
|
69
|
-
end
|
71
|
+
end
|
72
|
+
|
70
73
|
|
71
|
-
|
72
74
|
test_with_cassette("get_auth_token failure", :eds) do
|
73
75
|
engine = BentoSearch::EdsEngine.new(:user_id => "bad", :password => "bad", :profile => "bad")
|
74
76
|
exception = assert_raise(BentoSearch::EdsEngine::EdsCommException) do
|
75
77
|
token = engine.get_auth_token
|
76
|
-
end
|
77
|
-
|
78
|
+
end
|
79
|
+
|
78
80
|
assert_present exception.http_status
|
79
|
-
assert_present exception.http_body
|
81
|
+
assert_present exception.http_body
|
80
82
|
end
|
81
|
-
|
83
|
+
|
82
84
|
test_with_cassette("get_auth_token", :eds) do
|
83
85
|
token = @engine.get_auth_token
|
84
|
-
|
86
|
+
|
85
87
|
assert_present token
|
86
88
|
end
|
87
|
-
|
89
|
+
|
88
90
|
# No idea why VCR is having buggy problems with record and playback of this request
|
89
|
-
# We'll emcompass it in the get_with_auth test
|
91
|
+
# We'll emcompass it in the get_with_auth test
|
90
92
|
#
|
91
|
-
#test_with_cassette("with_session", :eds, :match_requests_on => [:method, :uri, :headers, :body]) do
|
93
|
+
#test_with_cassette("with_session", :eds, :match_requests_on => [:method, :uri, :headers, :body]) do
|
92
94
|
# @engine.with_session do |session_token|
|
93
95
|
# assert_present session_token
|
94
|
-
# end
|
96
|
+
# end
|
95
97
|
#end
|
96
|
-
|
98
|
+
|
97
99
|
test_with_cassette("get_with_auth", :eds) do
|
98
100
|
@engine.with_session do |session_token|
|
99
101
|
assert_present session_token
|
100
|
-
|
102
|
+
|
101
103
|
# Coudln't get 'info' request to work even as a test, let's
|
102
|
-
# try a simple search.
|
104
|
+
# try a simple search.
|
103
105
|
url = "#{@engine.configuration.base_url}info"
|
104
106
|
response = @engine.get_with_auth(url, session_token)
|
105
|
-
|
107
|
+
|
106
108
|
assert_present response
|
107
109
|
assert_kind_of Nokogiri::XML::Document, response
|
108
|
-
|
109
|
-
assert_nil response.at_xpath("//ErrorNumber"), "no error report in result"
|
110
|
-
end
|
110
|
+
|
111
|
+
assert_nil response.at_xpath("//ErrorNumber"), "no error report in result"
|
112
|
+
end
|
111
113
|
end
|
112
|
-
|
114
|
+
|
113
115
|
test_with_cassette("get_with_auth recovers from bad auth", :eds) do
|
114
116
|
@engine.with_session do |session_token|
|
115
117
|
BentoSearch::EdsEngine.remembered_auth = "BAD"
|
116
|
-
|
118
|
+
|
117
119
|
url = "#{@engine.configuration.base_url}info"
|
118
120
|
response = @engine.get_with_auth(url, session_token)
|
119
|
-
|
121
|
+
|
120
122
|
assert_present response
|
121
123
|
assert_kind_of Nokogiri::XML::Document, response
|
122
|
-
|
123
|
-
assert_nil response.at_xpath("//ErrorNumber"), "no error report in result"
|
124
|
-
end
|
125
|
-
|
124
|
+
|
125
|
+
assert_nil response.at_xpath("//ErrorNumber"), "no error report in result"
|
126
|
+
end
|
127
|
+
|
126
128
|
BentoSearch::EdsEngine.remembered_auth = nil
|
127
129
|
end
|
128
|
-
|
130
|
+
|
129
131
|
test_with_cassette("basic search smoke test", :eds) do
|
130
|
-
results = @engine.search("cancer")
|
131
|
-
|
132
|
+
results = @engine.search("cancer")
|
133
|
+
|
132
134
|
assert_present results
|
133
|
-
|
135
|
+
|
134
136
|
assert_present results.total_items
|
135
|
-
|
137
|
+
|
136
138
|
first = results.first
|
137
139
|
|
138
140
|
assert_present first.title
|
139
141
|
assert first.title.html_safe? # yeah, for now we use EDS html
|
140
|
-
|
142
|
+
|
141
143
|
assert_present first.abstract
|
142
144
|
assert_present first.abstract.html_safe?
|
143
|
-
|
144
|
-
assert_present first.custom_data["citation_blob"]
|
145
|
-
|
145
|
+
|
146
|
+
assert_present first.custom_data["citation_blob"]
|
147
|
+
|
148
|
+
assert_present first.source_title
|
149
|
+
assert_present first.issn
|
150
|
+
assert_present first.volume
|
151
|
+
assert_present first.issue
|
152
|
+
assert_present first.year
|
153
|
+
assert_present first.publication_date
|
154
|
+
assert_present first.start_page
|
155
|
+
assert_present first.end_page
|
156
|
+
|
157
|
+
assert_present first.doi
|
158
|
+
|
146
159
|
assert_present first.format_str
|
147
|
-
|
160
|
+
|
148
161
|
assert_present first.unique_id
|
149
162
|
# EDS id is db name, colon, accession number
|
150
163
|
assert_match /.+\:.+/, first.unique_id
|
151
164
|
end
|
152
|
-
|
153
|
-
|
165
|
+
|
166
|
+
test_with_cassette("catalog query", :eds) do
|
167
|
+
results = @engine.search(@@catalog_result_query)
|
168
|
+
|
169
|
+
cat_result = results.first
|
170
|
+
|
171
|
+
assert_present cat_result.custom_data[:holdings]
|
172
|
+
assert cat_result.custom_data[:holdings].all? { |h| h.location.present? && h.call_number.present? }
|
173
|
+
end
|
174
|
+
|
175
|
+
test_with_cassette("catalog ebook query", :eds) do
|
176
|
+
result = @engine.search(@@catalog_ebook_result_query).first
|
177
|
+
|
178
|
+
assert_present result.other_links
|
179
|
+
end
|
180
|
+
|
181
|
+
test_with_cassette("FullText CustomLink", :eds) do
|
182
|
+
result = @engine.search(@@catalog_custom_result_query).first
|
183
|
+
assert_present result
|
184
|
+
assert result.other_links.any? { |r| r.label.present? && r.label != "Link" && r.url.present? && URI::regexp =~ r.url && r.rel == "alternate"}
|
185
|
+
end
|
154
186
|
end
|
155
187
|
|
@@ -288,5 +288,16 @@ class ParseSearchArgumentsTest < ActiveSupport::TestCase
|
|
288
288
|
assert_equal "I am a horrible engine", results.error[:exception].message, "results.error has right exception"
|
289
289
|
end
|
290
290
|
|
291
|
+
def test_cover_consistency_api
|
292
|
+
d = Dummy.new()
|
293
|
+
assert_nil d.engine_id
|
294
|
+
assert_equal({}, d.display_configuration)
|
295
|
+
|
296
|
+
d = Dummy.new(id: 'test', for_display: { testkey: 'test' })
|
297
|
+
assert_equal 'test', d.engine_id
|
298
|
+
assert_equal({ testkey: 'test' }, d.display_configuration)
|
299
|
+
|
300
|
+
end
|
301
|
+
|
291
302
|
end
|
292
303
|
|
@@ -132,6 +132,7 @@ class SearchEngineTest < ActiveSupport::TestCase
|
|
132
132
|
|
133
133
|
assert results.failed?, "marked failed"
|
134
134
|
assert_present results.error
|
135
|
+
assert_present results.error[:exception]
|
135
136
|
assert_equal "raises", results.engine_id
|
136
137
|
assert_present results.search_args
|
137
138
|
assert_equal "foo", results.search_args[:query]
|
@@ -139,6 +140,17 @@ class SearchEngineTest < ActiveSupport::TestCase
|
|
139
140
|
assert_equal( {:foo => "foo"}, results.display_configuration )
|
140
141
|
end
|
141
142
|
|
143
|
+
test "can set auto rescued exceptions on instance" do
|
144
|
+
engine = MockEngine.new(:id => "raises", :raise_exception_class => "StandardError", :for_display => {:foo => "foo"})
|
145
|
+
engine.auto_rescued_exceptions = [StandardError]
|
146
|
+
|
147
|
+
results = engine.search("foo", :per_page => 20)
|
148
|
+
|
149
|
+
assert results.failed?, "marked failed"
|
150
|
+
assert_present results.error
|
151
|
+
assert_present results.error[:exception]
|
152
|
+
end
|
153
|
+
|
142
154
|
|
143
155
|
test "has empty :for_display config" do
|
144
156
|
engine = MockEngine.new
|
@@ -0,0 +1,75 @@
|
|
1
|
+
require 'test_helper'
|
2
|
+
|
3
|
+
# Doesn't really test the concurrency, but basic smoke test with fake
|
4
|
+
# searchers.
|
5
|
+
class ConcurrentSearcherTest < ActiveSupport::TestCase
|
6
|
+
setup do
|
7
|
+
BentoSearch.register_engine("one") do |conf|
|
8
|
+
conf.engine = "MockEngine"
|
9
|
+
end
|
10
|
+
BentoSearch.register_engine("two") do |conf|
|
11
|
+
conf.engine = "MockEngine"
|
12
|
+
end
|
13
|
+
BentoSearch.register_engine("three") do |conf|
|
14
|
+
conf.engine = "MockEngine"
|
15
|
+
end
|
16
|
+
|
17
|
+
BentoSearch.register_engine("raiser") do |conf|
|
18
|
+
conf.engine = "MockEngine"
|
19
|
+
conf.raise_exception_class = "StandardError"
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
teardown do
|
24
|
+
BentoSearch.reset_engine_registrations!
|
25
|
+
end
|
26
|
+
|
27
|
+
|
28
|
+
def test_concurrent_search
|
29
|
+
searcher = BentoSearch::ConcurrentSearcher.new(:one, :two, :three)
|
30
|
+
returnval = searcher.search("cancer")
|
31
|
+
|
32
|
+
assert_same searcher, returnval
|
33
|
+
|
34
|
+
results = searcher.results
|
35
|
+
|
36
|
+
assert_kind_of Hash, results
|
37
|
+
assert_equal ["one", "two", "three"].sort, results.keys.sort
|
38
|
+
|
39
|
+
["one", "two", "three"].each do |key|
|
40
|
+
assert_kind_of BentoSearch::Results, results[key]
|
41
|
+
end
|
42
|
+
|
43
|
+
# call results again, we get the exact same hash back.
|
44
|
+
new_results = searcher.results
|
45
|
+
assert_kind_of Hash, new_results
|
46
|
+
assert( results.equal? new_results )
|
47
|
+
end
|
48
|
+
|
49
|
+
def test_results_before_search
|
50
|
+
searcher = BentoSearch::ConcurrentSearcher.new(:one, :two, :three)
|
51
|
+
|
52
|
+
assert_raises(ArgumentError) do
|
53
|
+
results = searcher.results
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
|
58
|
+
def test_concurrent_search_uncaught_exception
|
59
|
+
searcher = BentoSearch::ConcurrentSearcher.new(:one, :raiser, :two)
|
60
|
+
results = searcher.search("cancer").results
|
61
|
+
|
62
|
+
[:one, :two].each do |success_engine_id|
|
63
|
+
assert( results[success_engine_id.to_s].kind_of?(BentoSearch::Results) )
|
64
|
+
assert( !results[success_engine_id.to_s].failed? )
|
65
|
+
end
|
66
|
+
|
67
|
+
|
68
|
+
error_results = results["raiser"]
|
69
|
+
|
70
|
+
assert( error_results.kind_of?(BentoSearch::Results) )
|
71
|
+
assert( error_results.failed? )
|
72
|
+
assert( error_results.error[:exception].present? )
|
73
|
+
assert( error_results.engine_id == "raiser" )
|
74
|
+
end
|
75
|
+
end
|
@@ -21,29 +21,26 @@ class MultiSearcherTest < ActiveSupport::TestCase
|
|
21
21
|
|
22
22
|
|
23
23
|
def test_multisearch
|
24
|
-
|
25
|
-
|
24
|
+
ActiveSupport::Deprecation.silence do
|
25
|
+
searcher = BentoSearch::MultiSearcher.new(:one, :two, :three)
|
26
|
+
start_returnval = searcher.start("cancer")
|
26
27
|
|
27
|
-
|
28
|
+
assert_same searcher, start_returnval
|
28
29
|
|
29
|
-
|
30
|
+
results = searcher.results
|
30
31
|
|
31
|
-
|
32
|
-
|
32
|
+
assert_kind_of Hash, results
|
33
|
+
assert_equal ["one", "two", "three"].sort, results.keys.sort
|
33
34
|
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
# call results again, we get an empty hash, can only call
|
39
|
-
# results once per start.
|
40
|
-
new_results = searcher.results
|
41
|
-
assert_kind_of Hash, new_results
|
42
|
-
assert_empty new_results
|
35
|
+
["one", "two", "three"].each do |key|
|
36
|
+
assert_kind_of BentoSearch::Results, results[key]
|
37
|
+
end
|
43
38
|
|
39
|
+
# call results again, we get an empty hash, can only call
|
40
|
+
# results once per start.
|
41
|
+
new_results = searcher.results
|
42
|
+
assert_kind_of Hash, new_results
|
43
|
+
assert_empty new_results
|
44
|
+
end
|
44
45
|
end
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
46
|
end
|