bento_search 0.5.0 → 0.6.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.
- data/README.md +6 -5
- data/app/assets/javascripts/bento_search/ajax_load.js +42 -16
- data/app/assets/stylesheets/bento_search/suggested_styles.css +9 -0
- data/app/controllers/bento_search/search_controller.rb +15 -6
- data/app/helpers/bento_search_helper.rb +24 -8
- data/app/item_decorators/bento_search/no_links.rb +13 -0
- data/app/models/bento_search/openurl_creator.rb +18 -8
- data/app/models/bento_search/registrar.rb +2 -6
- data/app/models/bento_search/result_item.rb +43 -3
- data/app/models/bento_search/results.rb +4 -0
- data/app/models/bento_search/search_engine.rb +25 -23
- data/app/search_engines/bento_search/ebsco_host_engine.rb +42 -17
- data/app/search_engines/bento_search/google_books_engine.rb +2 -0
- data/app/search_engines/bento_search/google_site_search_engine.rb +177 -0
- data/app/search_engines/bento_search/mock_engine.rb +5 -0
- data/app/search_engines/bento_search/primo_engine.rb +23 -2
- data/app/search_engines/bento_search/scopus_engine.rb +4 -1
- data/app/search_engines/bento_search/summon_engine.rb +4 -14
- data/app/search_engines/bento_search/worldcat_sru_dc_engine.rb +293 -0
- data/app/views/bento_search/_std_item.html.erb +4 -5
- data/app/views/bento_search/_wrap_with_count.html.erb +20 -0
- data/app/views/bento_search/search/search.html.erb +15 -1
- data/config/locales/en.yml +6 -4
- data/lib/bento_search/util.rb +13 -0
- data/lib/bento_search/version.rb +1 -1
- data/test/dummy/log/development.log +1 -0
- data/test/dummy/log/test.log +24357 -0
- data/test/functional/bento_search/search_controller_test.rb +39 -0
- data/test/helper/bento_search_helper_test.rb +47 -5
- data/test/unit/ebsco_host_engine_test.rb +15 -0
- data/test/unit/google_books_engine_test.rb +1 -0
- data/test/unit/google_site_search_test.rb +122 -0
- data/test/unit/item_decorators_test.rb +12 -1
- data/test/unit/openurl_creator_test.rb +19 -3
- data/test/unit/primo_engine_test.rb +5 -3
- data/test/unit/result_item_test.rb +36 -1
- data/test/unit/search_engine_test.rb +27 -4
- data/test/unit/worldcat_sru_dc_engine_test.rb +120 -0
- data/test/vcr_cassettes/google_site/basic_smoke_test.yml +254 -0
- data/test/vcr_cassettes/google_site/empty_result_set.yml +53 -0
- data/test/vcr_cassettes/google_site/pagination_object_is_correct_for_actual_page_when_you_ask_for_too_far.yml +260 -0
- data/test/vcr_cassettes/google_site/with_highlighting.yml +265 -0
- data/test/vcr_cassettes/google_site/without_highlighting.yml +267 -0
- data/test/vcr_cassettes/primo/proper_tags_for_snippets.yml +517 -502
- data/test/vcr_cassettes/primo/search_smoke_test.yml +1 -1
- data/test/vcr_cassettes/worldcat_sru_dc/smoke_test.yml +628 -0
- metadata +40 -4
@@ -13,6 +13,17 @@ module BentoSearch
|
|
13
13
|
# no allow_routable_results
|
14
14
|
end
|
15
15
|
|
16
|
+
BentoSearch.register_engine("with_layout_config") do |config|
|
17
|
+
config.engine = "MockEngine"
|
18
|
+
|
19
|
+
config.allow_routable_results = true
|
20
|
+
|
21
|
+
config.for_display do |display|
|
22
|
+
display.ajax do |ajax|
|
23
|
+
ajax.wrapper_template = "bento_search/wrap_with_count"
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
16
27
|
end
|
17
28
|
|
18
29
|
def teardown
|
@@ -28,6 +39,17 @@ module BentoSearch
|
|
28
39
|
assert_template "bento_search/search"
|
29
40
|
end
|
30
41
|
|
42
|
+
test "custom layout config" do
|
43
|
+
get :search, {:engine_id => "with_layout_config", :query => "my search"}
|
44
|
+
|
45
|
+
assert_response :success
|
46
|
+
|
47
|
+
assert_not_nil assigns(:partial_wrapper)
|
48
|
+
|
49
|
+
assert_template "bento_search/_wrap_with_count"
|
50
|
+
assert_template "bento_search/search"
|
51
|
+
end
|
52
|
+
|
31
53
|
test "non-routable engine" do
|
32
54
|
get :search, {:engine_id => "not_routable", :query => "my search"}
|
33
55
|
|
@@ -40,6 +62,22 @@ module BentoSearch
|
|
40
62
|
assert_response 404
|
41
63
|
end
|
42
64
|
|
65
|
+
|
66
|
+
test "respects public_settable_search_args" do
|
67
|
+
get :search, {:engine_id => "mock",
|
68
|
+
'query' => "query", 'sort' => "sort", 'per_page' => "15",
|
69
|
+
'page' => "6", 'search_field' => "title", 'not_allowed' => "not allowed"}
|
70
|
+
|
71
|
+
|
72
|
+
search_args = assigns[:engine].last_args
|
73
|
+
|
74
|
+
[:query, :sort, :per_page, :page, :search_field].each do |allowed_key|
|
75
|
+
assert search_args.has_key?(allowed_key)
|
76
|
+
end
|
77
|
+
assert ! search_args.has_key?(:not_allowed)
|
78
|
+
assert ! search_args.has_key?("not_allowed")
|
79
|
+
end
|
80
|
+
|
43
81
|
test "custom before filter" do
|
44
82
|
# Okay, we're going to do a weird thing with a custom controller subclass
|
45
83
|
# we can add a custom before filter like a local app might.
|
@@ -74,6 +112,7 @@ module BentoSearch
|
|
74
112
|
|
75
113
|
end
|
76
114
|
|
115
|
+
|
77
116
|
|
78
117
|
|
79
118
|
|
@@ -1,5 +1,8 @@
|
|
1
1
|
require 'test_helper'
|
2
2
|
|
3
|
+
# this seems to work? Rails view testing is a mess.
|
4
|
+
require 'sprockets/helpers/rails_helper'
|
5
|
+
|
3
6
|
class BentoSearchHelperTest < ActionView::TestCase
|
4
7
|
include BentoSearchHelper
|
5
8
|
|
@@ -8,13 +11,11 @@ class BentoSearchHelperTest < ActionView::TestCase
|
|
8
11
|
def teardown
|
9
12
|
BentoSearch.reset_engine_registrations!
|
10
13
|
end
|
11
|
-
|
12
|
-
|
13
|
-
|
14
14
|
|
15
15
|
def setup
|
16
16
|
# Make routing work
|
17
|
-
@routes = Rails.application.routes
|
17
|
+
@routes = Rails.application.routes
|
18
|
+
|
18
19
|
end
|
19
20
|
|
20
21
|
def test_with_results_arg
|
@@ -89,6 +90,8 @@ class BentoSearchHelperTest < ActionView::TestCase
|
|
89
90
|
|
90
91
|
div = results.find(:attributes => {:class => "bento_search_ajax_wait"})
|
91
92
|
assert div, "produces div.bento_search_ajax_wait"
|
93
|
+
assert_equal "ajax_auto", div["data-bento-search-load"], "has data-bento-search-load attribute"
|
94
|
+
|
92
95
|
|
93
96
|
assert_present div.attributes["data-bento-ajax-url"]
|
94
97
|
url = URI.parse(div.attributes["data-bento-ajax-url"])
|
@@ -97,12 +100,35 @@ class BentoSearchHelperTest < ActionView::TestCase
|
|
97
100
|
query = CGI.parse(url.query.gsub("&", "&")) # gsub weirdness of HTML::Tag
|
98
101
|
assert_equal ["QUERY"], query["query"]
|
99
102
|
assert_empty query["load"]
|
103
|
+
|
104
|
+
# hidden loading msg
|
105
|
+
loading_msg = div.find(:attributes => {:class => "bento_search_ajax_loading"})
|
106
|
+
assert_present loading_msg, "bento_search_ajax_loading present"
|
107
|
+
assert_match /display\:none/, loading_msg["style"], "loading has CSS style hidden"
|
100
108
|
|
101
109
|
assert div.find(:tag => "noscript"), "has <noscript> tag"
|
102
110
|
|
103
|
-
assert (img =
|
111
|
+
assert (img = loading_msg.find(:tag => "img")), "Has spinner gif"
|
104
112
|
assert_equal I18n.translate("bento_search.ajax_loading"), img.attributes["alt"]
|
105
113
|
end
|
114
|
+
|
115
|
+
def test_ajax_triggered_load
|
116
|
+
BentoSearch.register_engine("test_engine") do |conf|
|
117
|
+
conf.engine = "MockEngine"
|
118
|
+
end
|
119
|
+
|
120
|
+
results = bento_search("test_engine", :query => "QUERY", :load => :ajax_triggered)
|
121
|
+
results = HTML::Document.new(results)
|
122
|
+
|
123
|
+
div = results.find(:attributes => {:class => "bento_search_ajax_wait"})
|
124
|
+
assert div, "produces div.bento_search_ajax_wait"
|
125
|
+
assert_equal "ajax_triggered", div["data-bento-search-load"], "has data-bento-search-load attribute"
|
126
|
+
|
127
|
+
# hidden loading msg
|
128
|
+
loading_msg = div.find(:attributes => {:class => "bento_search_ajax_loading"})
|
129
|
+
assert_present loading_msg, "bento_search_ajax_loading present"
|
130
|
+
assert_match /display\:none/, loading_msg["style"], "loading has CSS style hidden"
|
131
|
+
end
|
106
132
|
|
107
133
|
|
108
134
|
def test_sort_hash_for
|
@@ -121,6 +147,22 @@ class BentoSearchHelperTest < ActionView::TestCase
|
|
121
147
|
assert_equal key, hash[ I18n.translate(key, :scope => "bento_search.sort_keys") ]
|
122
148
|
end
|
123
149
|
end
|
150
|
+
|
151
|
+
def test_sort_hash_for_no_i18n
|
152
|
+
# If there's no 18n key available, use reasonable humanized approximation
|
153
|
+
|
154
|
+
engine = MockEngine.new(:sort_definitions => {"no_key_test" => {}})
|
155
|
+
|
156
|
+
hash = bento_sort_hash_for(engine)
|
157
|
+
|
158
|
+
assert_present hash
|
159
|
+
|
160
|
+
key = hash.key("no_key_test")
|
161
|
+
|
162
|
+
assert_no_match /translation missing/, key
|
163
|
+
|
164
|
+
assert_equal "No Key Test", key
|
165
|
+
end
|
124
166
|
|
125
167
|
|
126
168
|
end
|
@@ -80,6 +80,18 @@ class EbscoHostEngineTest < ActiveSupport::TestCase
|
|
80
80
|
assert_equal ["cancer "], query_params["query"]
|
81
81
|
end
|
82
82
|
|
83
|
+
def test_removes_question_marks
|
84
|
+
# who knows why, ebsco doesn't like question marks even inside
|
85
|
+
# quoted phrases, some special char to ebsco.
|
86
|
+
url = @engine.query_url(:query => "cancer?", :sort => "date_desc")
|
87
|
+
query_params = CGI.parse( URI.parse(url).query )
|
88
|
+
assert_equal ["cancer "], query_params["query"]
|
89
|
+
|
90
|
+
url = @engine.query_url(:query => '"cancer?"', :sort => "date_desc")
|
91
|
+
query_params = CGI.parse( URI.parse(url).query )
|
92
|
+
assert_equal ['"cancer "'], query_params["query"]
|
93
|
+
end
|
94
|
+
|
83
95
|
test_with_cassette("live search smoke test", :ebscohost) do
|
84
96
|
|
85
97
|
results = @engine.search(:query => "cancer")
|
@@ -95,6 +107,9 @@ class EbscoHostEngineTest < ActiveSupport::TestCase
|
|
95
107
|
|
96
108
|
assert_present first.format
|
97
109
|
assert_present first.format_str
|
110
|
+
|
111
|
+
assert_present first.language_code
|
112
|
+
assert_present first.language_str
|
98
113
|
end
|
99
114
|
|
100
115
|
test_with_cassette("get_info", :ebscohost) do
|
@@ -0,0 +1,122 @@
|
|
1
|
+
require 'test_helper'
|
2
|
+
|
3
|
+
require 'uri'
|
4
|
+
require 'cgi'
|
5
|
+
|
6
|
+
# To run these tests without VCR cassettes, need
|
7
|
+
# ENV GOOGLE_SITE_SEARCH_KEY and GOOGLE_SITE_SEARCH_CX
|
8
|
+
class GoogleSiteSearchTest < ActiveSupport::TestCase
|
9
|
+
extend TestWithCassette
|
10
|
+
|
11
|
+
@@api_key = ENV["GOOGLE_SITE_SEARCH_KEY"] || "DUMMY_API_KEY"
|
12
|
+
@@cx = ENV["GOOGLE_SITE_SEARCH_CX"] || "DUMMY_CX"
|
13
|
+
|
14
|
+
VCR.configure do |c|
|
15
|
+
c.filter_sensitive_data("DUMMY_API_KEY", :google_site) { @@api_key }
|
16
|
+
c.filter_sensitive_data("DUMMY_CX", :google_site) { @@cx }
|
17
|
+
end
|
18
|
+
|
19
|
+
setup do
|
20
|
+
@config = {:api_key => @@api_key, :cx => @@cx}
|
21
|
+
@engine = BentoSearch::GoogleSiteSearchEngine.new(@config)
|
22
|
+
end
|
23
|
+
|
24
|
+
test("basic query construction") do
|
25
|
+
url = @engine.send(:construct_query, {:query => "hours policies"})
|
26
|
+
|
27
|
+
query_params = CGI.parse( URI.parse(url).query )
|
28
|
+
|
29
|
+
assert_equal ["hours policies"], query_params["q"]
|
30
|
+
end
|
31
|
+
|
32
|
+
test("pagination construction") do
|
33
|
+
url = @engine.send(:construct_query, {:query => "books", :per_page => 5, :start => 10})
|
34
|
+
|
35
|
+
query_params = CGI.parse( URI.parse(url).query )
|
36
|
+
|
37
|
+
assert_equal ["5"], query_params["num"]
|
38
|
+
assert_equal ["11"], query_params["start"]
|
39
|
+
end
|
40
|
+
|
41
|
+
test("silently refuses to paginate too far") do
|
42
|
+
# google won't let you paginate past ~10 pages, (101 - num). We silently
|
43
|
+
# refuse
|
44
|
+
|
45
|
+
url = @engine.send(:construct_query, {:query => "books", :start => 110})
|
46
|
+
|
47
|
+
query_params = CGI.parse( URI.parse(url).query )
|
48
|
+
|
49
|
+
assert_equal ["91"], query_params["start"]
|
50
|
+
end
|
51
|
+
|
52
|
+
test_with_cassette("pagination object is correct for actual page when you ask for too far", :google_site) do
|
53
|
+
results = @engine.search("books", :start => 1000)
|
54
|
+
|
55
|
+
pagination = results.pagination
|
56
|
+
|
57
|
+
assert_equal 10, pagination.current_page
|
58
|
+
assert_equal 91, pagination.start_record
|
59
|
+
end
|
60
|
+
|
61
|
+
test("sort query construction") do
|
62
|
+
url = @engine.send(:construct_query, {:query => "books", :sort => "date_desc"})
|
63
|
+
|
64
|
+
query_params = CGI.parse( URI.parse(url).query )
|
65
|
+
|
66
|
+
assert_equal ["date"], query_params["sort"]
|
67
|
+
end
|
68
|
+
|
69
|
+
test_with_cassette("basic smoke test", :google_site) do
|
70
|
+
results = @engine.search("books")
|
71
|
+
|
72
|
+
assert_present results
|
73
|
+
assert_present results.total_items
|
74
|
+
assert_kind_of Fixnum, results.total_items
|
75
|
+
|
76
|
+
first = results.first
|
77
|
+
|
78
|
+
assert_present first.title
|
79
|
+
assert_present first.link
|
80
|
+
assert_present first.abstract
|
81
|
+
assert_present first.journal_title # used as source_title for display url
|
82
|
+
|
83
|
+
# no openurls for google, we decided
|
84
|
+
assert_nil first.to_openurl
|
85
|
+
end
|
86
|
+
|
87
|
+
test_with_cassette("with highlighting", :google_site) do
|
88
|
+
engine = BentoSearch::GoogleSiteSearchEngine.new(@config.merge(:highlighting => true))
|
89
|
+
|
90
|
+
results = engine.search("books")
|
91
|
+
|
92
|
+
first = results.first
|
93
|
+
|
94
|
+
assert first.title.html_safe?
|
95
|
+
assert first.abstract.html_safe?
|
96
|
+
assert first.journal_title.html_safe?
|
97
|
+
|
98
|
+
assert first.published_in.html_safe?
|
99
|
+
end
|
100
|
+
|
101
|
+
test_with_cassette("without highlighting", :google_site) do
|
102
|
+
engine = BentoSearch::GoogleSiteSearchEngine.new(@config.merge(:highlighting => false))
|
103
|
+
|
104
|
+
results = engine.search("books")
|
105
|
+
|
106
|
+
first = results.first
|
107
|
+
|
108
|
+
assert ! first.title.html_safe?
|
109
|
+
assert ! first.abstract.html_safe?
|
110
|
+
assert ! first.journal_title.html_safe?
|
111
|
+
end
|
112
|
+
|
113
|
+
test_with_cassette("empty result set", :google_site) do
|
114
|
+
results = nil
|
115
|
+
assert_nothing_raised { results = @engine.search('"adfa lakjdr xavier aldkfj 92323kjadf"') }
|
116
|
+
|
117
|
+
assert ! results.failed?
|
118
|
+
|
119
|
+
assert results.empty?
|
120
|
+
end
|
121
|
+
|
122
|
+
end
|
@@ -1,6 +1,6 @@
|
|
1
1
|
require 'test_helper'
|
2
2
|
|
3
|
-
class
|
3
|
+
class ItemDecoratorsTest < ActiveSupport::TestCase
|
4
4
|
MockEngine = BentoSearch::MockEngine
|
5
5
|
|
6
6
|
# simple decorator that replaces main link
|
@@ -35,6 +35,17 @@ class LinkDecoratorsTest < ActiveSupport::TestCase
|
|
35
35
|
end
|
36
36
|
end
|
37
37
|
|
38
|
+
test "decorator as string" do
|
39
|
+
@engine = MockEngine.new(:item_decorators => ["::ItemDecoratorsTest::Decorator"])
|
40
|
+
|
41
|
+
results = @engine.search(:query => "Query")
|
42
|
+
|
43
|
+
results.each do |result|
|
44
|
+
assert_kind_of Decorator, result
|
45
|
+
end
|
46
|
+
|
47
|
+
end
|
48
|
+
|
38
49
|
# Is it a good idea to have a decorator that mutates on 'extend'?
|
39
50
|
# I'm not sure, I think probably not, but it is possible.
|
40
51
|
# Here we'll use it to move an original link to other links
|
@@ -1,3 +1,5 @@
|
|
1
|
+
require 'test_helper'
|
2
|
+
|
1
3
|
class OpenurlCreatorTest < ActiveSupport::TestCase
|
2
4
|
|
3
5
|
def test_create_article
|
@@ -80,7 +82,7 @@ class OpenurlCreatorTest < ActiveSupport::TestCase
|
|
80
82
|
|
81
83
|
end
|
82
84
|
|
83
|
-
def
|
85
|
+
def test_create_hardcoded_kev
|
84
86
|
item = BentoSearch::ResultItem.new(
|
85
87
|
:format => "Book",
|
86
88
|
:title => "Something",
|
@@ -89,13 +91,13 @@ class OpenurlCreatorTest < ActiveSupport::TestCase
|
|
89
91
|
|
90
92
|
r = BentoSearch::OpenurlCreator.new(item).to_openurl.referent
|
91
93
|
|
92
|
-
assert_equal "
|
94
|
+
assert_equal "journal", r.format
|
93
95
|
assert_equal "Foo Bar", r.metadata["title"]
|
94
96
|
assert_equal "Smith", r.metadata["au"]
|
95
97
|
|
96
98
|
end
|
97
99
|
|
98
|
-
def
|
100
|
+
def test_result_item_to_openurl
|
99
101
|
item = BentoSearch::ResultItem.new(
|
100
102
|
:format => "Book",
|
101
103
|
:title => "Something",
|
@@ -107,5 +109,19 @@ class OpenurlCreatorTest < ActiveSupport::TestCase
|
|
107
109
|
assert_kind_of OpenURL::ContextObject, openurl
|
108
110
|
end
|
109
111
|
|
112
|
+
def test_strip_tags
|
113
|
+
item = BentoSearch::ResultItem.new(
|
114
|
+
:title => "<b>My Title</b>".html_safe,
|
115
|
+
:year => 2012,
|
116
|
+
:isbn => "XXXX",
|
117
|
+
)
|
118
|
+
|
119
|
+
openurl = item.to_openurl
|
120
|
+
|
121
|
+
assert_equal "My Title", openurl.referent.metadata["title"]
|
122
|
+
end
|
123
|
+
|
124
|
+
|
125
|
+
|
110
126
|
|
111
127
|
end
|
@@ -2,12 +2,14 @@ require 'test_helper'
|
|
2
2
|
|
3
3
|
class PrimoEngineTest < ActiveSupport::TestCase
|
4
4
|
extend TestWithCassette
|
5
|
-
|
6
|
-
|
5
|
+
|
6
|
+
# dummy host needs to be in all lowercase, and not explicitly
|
7
|
+
# say '80' to work right with VCR
|
8
|
+
@@host_port = (ENV['PRIMO_HOST_PORT'] || 'example.org' )
|
7
9
|
@@institution = (ENV['PRIMO_INSTITUTION'] || 'DUMMY_INSTITUTION')
|
8
10
|
|
9
11
|
VCR.configure do |c|
|
10
|
-
c.filter_sensitive_data("
|
12
|
+
c.filter_sensitive_data("example.org", :primo) { @@host_port }
|
11
13
|
c.filter_sensitive_data("DUMMY_INSTITUTION", :primo) { @@institution }
|
12
14
|
end
|
13
15
|
|
@@ -27,10 +27,45 @@ class ResultItemTest < ActiveSupport::TestCase
|
|
27
27
|
assert_equal "new", dup.title
|
28
28
|
assert_equal "original", r.title
|
29
29
|
|
30
|
-
assert_not_same dup, r
|
30
|
+
assert_not_same dup, r
|
31
|
+
end
|
32
|
+
|
33
|
+
def test_openurl_disabled
|
34
|
+
r = ResultItem.new(:title => "original")
|
35
|
+
|
36
|
+
assert_present r.to_openurl
|
37
|
+
|
38
|
+
r.openurl_disabled = true
|
39
|
+
|
40
|
+
assert_nil r.to_openurl
|
41
|
+
end
|
42
|
+
|
43
|
+
def test_language
|
44
|
+
r = ResultItem.new(:title => "something", :language_code => "en")
|
45
|
+
assert_equal "en", r.language_code
|
46
|
+
assert_equal "English", r.language_str
|
47
|
+
|
48
|
+
r = ResultItem.new(:title => "something", :language_code => "eng")
|
49
|
+
assert_equal "eng", r.language_code
|
50
|
+
assert_equal "English", r.language_str
|
31
51
|
|
52
|
+
# language_str override
|
53
|
+
r = ResultItem.new(:title => "something", :language_code => "en", :language_str => "Weird English")
|
54
|
+
assert_equal "en", r.language_code
|
55
|
+
assert_equal "Weird English", r.language_str
|
56
|
+
|
57
|
+
# language_str only
|
58
|
+
r = ResultItem.new(:title => "something", :language_str => "English")
|
59
|
+
assert_nil r.language_code
|
60
|
+
assert_equal "English", r.language_str
|
32
61
|
|
33
62
|
end
|
34
63
|
|
64
|
+
def test_bad_language_code
|
65
|
+
r = ResultItem.new(:title => "something", :language_code => "not_valid")
|
66
|
+
|
67
|
+
assert_equal "not_valid", r.language_code
|
68
|
+
assert_nil r.language_str
|
69
|
+
end
|
35
70
|
|
36
71
|
end
|