bento_search 1.5.0 → 2.0.0.rc1

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.
Files changed (61) hide show
  1. checksums.yaml +5 -5
  2. data/README.md +27 -24
  3. data/Rakefile +30 -11
  4. data/app/assets/javascripts/bento_search/ajax_load.js +54 -22
  5. data/app/controllers/bento_search/search_controller.rb +31 -30
  6. data/app/helpers/bento_search_helper.rb +72 -74
  7. data/app/models/bento_search/concurrent_searcher.rb +136 -0
  8. data/app/models/bento_search/result_item.rb +15 -12
  9. data/app/models/bento_search/results/serialization.rb +22 -13
  10. data/app/models/bento_search/search_engine.rb +170 -140
  11. data/app/search_engines/bento_search/doaj_articles_engine.rb +20 -20
  12. data/app/search_engines/bento_search/ebsco_host_engine.rb +3 -3
  13. data/app/search_engines/bento_search/eds_engine.rb +326 -206
  14. data/app/search_engines/bento_search/google_books_engine.rb +2 -2
  15. data/app/search_engines/bento_search/scopus_engine.rb +87 -87
  16. data/app/search_engines/bento_search/summon_engine.rb +1 -1
  17. data/app/views/bento_search/_ajax_loading.html.erb +17 -0
  18. data/app/views/bento_search/_item_title.html.erb +2 -4
  19. data/app/views/bento_search/_link.html.erb +3 -3
  20. data/lib/bento_search.rb +24 -9
  21. data/lib/bento_search/engine.rb +2 -0
  22. data/lib/bento_search/version.rb +1 -1
  23. data/lib/generators/bento_search/install/ajax_load_js_generator.rb +15 -0
  24. data/test/decorator/standard_decorator_test.rb +30 -30
  25. data/test/dummy/app/assets/config/manifest.js +4 -0
  26. data/test/dummy/config/application.rb +7 -0
  27. data/test/dummy/config/boot.rb +4 -9
  28. data/test/dummy/config/environments/development.rb +2 -0
  29. data/test/dummy/config/environments/production.rb +7 -1
  30. data/test/dummy/config/environments/test.rb +10 -3
  31. data/test/functional/bento_search/search_controller_test.rb +68 -58
  32. data/test/helper/bento_search_helper_test.rb +103 -103
  33. data/test/search_engines/doaj_articles_engine_test.rb +9 -9
  34. data/test/search_engines/eds_engine_test.rb +91 -59
  35. data/test/search_engines/google_site_search_test.rb +48 -48
  36. data/test/search_engines/scopus_engine_test.rb +51 -51
  37. data/test/search_engines/search_engine_base_test.rb +108 -86
  38. data/test/search_engines/search_engine_test.rb +68 -56
  39. data/test/support/atom.xsd.xml +3 -3
  40. data/test/support/xml.xsd +117 -0
  41. data/test/test_helper.rb +23 -12
  42. data/test/unit/concurrent_searcher_test.rb +75 -0
  43. data/test/unit/pagination_test.rb +12 -12
  44. data/test/vcr_cassettes/eds/FullText_CustomLink.yml +198 -0
  45. data/test/vcr_cassettes/eds/basic_search_smoke_test.yml +1036 -1729
  46. data/test/vcr_cassettes/eds/catalog_ebook_query.yml +218 -0
  47. data/test/vcr_cassettes/eds/catalog_query.yml +255 -0
  48. data/test/vcr_cassettes/eds/get_auth_token.yml +11 -44
  49. data/test/vcr_cassettes/eds/get_auth_token_failure.yml +10 -7
  50. data/test/vcr_cassettes/eds/get_with_auth.yml +144 -153
  51. data/test/vcr_cassettes/eds/get_with_auth_recovers_from_bad_auth.yml +167 -223
  52. data/test/view/atom_results_test.rb +94 -94
  53. metadata +36 -46
  54. data/app/assets/javascripts/bento_search.js +0 -3
  55. data/app/item_decorators/bento_search/ebscohost/conditional_openurl_main_link.rb +0 -36
  56. data/app/item_decorators/bento_search/only_premade_openurl.rb +0 -20
  57. data/app/item_decorators/bento_search/openurl_add_other_link.rb +0 -39
  58. data/app/item_decorators/bento_search/openurl_main_link.rb +0 -34
  59. data/app/models/bento_search/multi_searcher.rb +0 -131
  60. data/test/dummy/config/initializers/secret_token.rb +0 -8
  61. data/test/unit/multi_searcher_test.rb +0 -49
data/lib/bento_search.rb CHANGED
@@ -2,7 +2,7 @@ require 'confstruct'
2
2
 
3
3
  module BentoSearch
4
4
  class Error < ::StandardError ; end
5
- end
5
+ end
6
6
 
7
7
  require "bento_search/engine"
8
8
  require 'bento_search/routes'
@@ -14,36 +14,51 @@ require File.dirname(__FILE__) + '/../app/models/bento_search/registrar'
14
14
 
15
15
  # Crazy workaround to the fact that some versions of Hashie::Mash,
16
16
  # when used with SafeAssignment as Confstruct does, don't let
17
- # you use :id as a key.
17
+ # you use :id as a key.
18
18
  # https://github.com/intridea/hashie/issues/290
19
19
  # We fix by removing the unused method with vary hacky meta programming
20
- # sorry.
20
+ # sorry.
21
21
  require 'hashie/mash'
22
22
  if Hashie::Mash.instance_methods(false).include?(:id)
23
23
  Hashie::Mash.send(:remove_method, :id)
24
24
  end
25
25
 
26
26
 
27
- module BentoSearch
27
+ module BentoSearch
28
28
  def self.global_registrar
29
29
  @@global_registrar ||= BentoSearch::Registrar.new
30
30
  end
31
-
31
+
32
32
  # See BentoSearch::Registrar#register_engine, this is a
33
- # default global registrar.
33
+ # default global registrar.
34
34
  def self.register_engine(id, data = nil, &block)
35
- global_registrar.register_engine(id, data, &block)
35
+ global_registrar.register_engine(id, data, &block)
36
36
  end
37
-
37
+
38
38
  def self.get_engine(id)
39
39
  global_registrar.get_engine(id)
40
40
  end
41
-
41
+
42
42
  # Mostly just used for testing
43
43
  def self.reset_engine_registrations!
44
44
  global_registrar.reset_engine_registrations!
45
45
  end
46
46
 
47
+ # Avoid deprecation warnings in ruby 2.3.0
48
+ RubyTimeoutClass = (defined?(Timeout::Error) ? Timeout::Error : TimeoutError)
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
47
62
  end
48
63
 
49
64
 
@@ -1,5 +1,7 @@
1
1
  module BentoSearch
2
2
  class Engine < ::Rails::Engine
3
3
  #isolate_namespace BentoSearch
4
+
5
+ config.assets.precompile += %w( bento_search/large_loader.gif )
4
6
  end
5
7
  end
@@ -1,3 +1,3 @@
1
1
  module BentoSearch
2
- VERSION = "1.5.0"
2
+ VERSION = "2.0.0.rc1"
3
3
  end
@@ -0,0 +1,15 @@
1
+ require 'rails/generators'
2
+ module BentoSearch
3
+ module Install
4
+ class AjaxLoadJsGenerator < ::Rails::Generators::Base
5
+ source_root BentoSearch::Engine.root.to_s
6
+
7
+ desc "Copy ajax_load.js file to local .app/javascript/src/js/"
8
+
9
+ def generate
10
+ copy_file 'app/assets/javascripts/bento_search/ajax_load.js',
11
+ (Rails.root + "app/javascript/src/js/bento_search_ajax_load.js")
12
+ end
13
+ end
14
+ end
15
+ end
@@ -4,74 +4,74 @@ require 'test_helper'
4
4
 
5
5
  class StandardDecoratorTest < ActionView::TestCase
6
6
  include BentoSearch
7
-
8
- def decorator(hash = {})
7
+
8
+ def decorator(hash = {})
9
9
  StandardDecorator.new(
10
10
  ResultItem.new(hash), view
11
11
  )
12
12
  end
13
-
14
-
13
+
14
+
15
15
  test "author with first and last" do
16
16
  author = Author.new(:last => "Smith", :first => "John")
17
-
17
+
18
18
  str = decorator.author_display(author)
19
-
20
- assert_equal "Smith, J", str
19
+
20
+ assert_equal "Smith, J", str
21
21
  end
22
-
22
+
23
23
  test "author with display form and just last" do
24
24
  author = Author.new(:last => "Smith", :display => "Display Form")
25
-
25
+
26
26
  str = decorator.author_display(author)
27
-
27
+
28
28
  assert_equal "Display Form", str
29
29
  end
30
-
30
+
31
31
  test "Author with just last" do
32
32
  author = Author.new(:last => "Johnson")
33
-
33
+
34
34
  str = decorator.author_display(author)
35
-
35
+
36
36
  assert_equal "Johnson", str
37
-
37
+
38
38
  end
39
-
39
+
40
40
  test "Missing title" do
41
41
  assert_equal I18n.translate("bento_search.missing_title"), decorator.complete_title
42
42
  end
43
-
43
+
44
44
  test "language label nil if default" do
45
45
  I18n.with_locale(:'en-GB') do
46
- item = decorator(:language_code => 'en')
46
+ item = decorator(:language_code => 'en')
47
47
  assert_nil item.display_language
48
-
48
+
49
49
  item = decorator(:language_code => 'es')
50
- assert_equal "Spanish", item.display_language
50
+ assert_equal "Spanish", item.display_language
51
51
  end
52
52
  end
53
53
 
54
54
  test "display_language works with just langauge_str" do
55
- item = decorator(:language_str => 'German')
55
+ item = decorator(:language_str => 'German')
56
56
  assert_equal "German", item.display_language
57
57
  end
58
-
58
+
59
59
  test "display_format with nil format" do
60
60
  item = decorator(:format => nil, :format_str => nil)
61
-
61
+
62
62
  display_format = item.display_format
63
-
64
- assert_nil display_format
63
+
64
+ assert_nil display_format
65
65
  end
66
-
66
+
67
67
  test "display_date" do
68
- item = decorator(:year => 1900)
68
+ item = decorator(:year => 1900)
69
69
  assert_equal "1900", item.display_date
70
-
70
+
71
71
  d = Date.new(2010, 5, 5)
72
72
  item = decorator(:publication_date => d)
73
73
  assert_equal I18n.l(d, :format => "%d %b %Y"), item.display_date
74
-
74
+
75
75
  # if volume and issue, only prints out year
76
76
  item = decorator(:publication_date => d, :volume => "101", :issue => "2")
77
77
  assert_equal I18n.l(d, :format => "%Y"), item.display_date
@@ -112,7 +112,7 @@ class StandardDecoratorTest < ActionView::TestCase
112
112
  assert_equal "snippet", item.render_summary, "use snippet if that's all that's there, even when configured for abstract"
113
113
 
114
114
  item = decorator()
115
- assert_equal nil, item.render_summary, "Okay with no snippet or abstract"
115
+ assert_nil item.render_summary, "Okay with no snippet or abstract"
116
116
  end
117
-
117
+
118
118
  end
@@ -0,0 +1,4 @@
1
+ // See: https://github.com/rails/sprockets/blob/c4b191e70d89e9d70f19ade5faf0692054a3bd1b/UPGRADING.md
2
+ //
3
+ //= link_directory ../javascripts .js
4
+ //= link_directory ../stylesheets .css
@@ -46,6 +46,13 @@ module Dummy
46
46
 
47
47
  # Version of your assets, change this if you want to expire all your assets
48
48
  config.assets.version = '1.0'
49
+
50
+ # Avoid Rails deprecation warning
51
+ if Gem::Version.new(Rails.version).release >= Gem::Version.new("5.2.0") && Gem::Version.new(Rails.version).release < Gem::Version.new("6.0.0")
52
+ config.active_record.sqlite3.represent_boolean_as_integer = true
53
+ end
54
+
55
+ config.secret_key_base = '60f73d25f61301b1ea3119011efb9fd9a741fcc010757599341d45765fbda7676daf5d602fb17bb5085c3163a04e20c0750ad02562ee9cb7f03f813d1b62c639'
49
56
  end
50
57
  end
51
58
 
@@ -1,10 +1,5 @@
1
- require 'rubygems'
2
- gemfile = File.expand_path('../../../../Gemfile', __FILE__)
1
+ # Set up gems listed in the Gemfile.
2
+ ENV['BUNDLE_GEMFILE'] ||= File.expand_path('../../../../Gemfile', __FILE__)
3
3
 
4
- if File.exist?(gemfile)
5
- ENV['BUNDLE_GEMFILE'] = gemfile
6
- require 'bundler'
7
- Bundler.setup
8
- end
9
-
10
- $:.unshift File.expand_path('../../../../lib', __FILE__)
4
+ require 'bundler/setup' if File.exist?(ENV['BUNDLE_GEMFILE'])
5
+ $LOAD_PATH.unshift File.expand_path('../../../../lib', __FILE__)
@@ -27,4 +27,6 @@ Dummy::Application.configure do
27
27
 
28
28
  # Expands the lines which load the assets
29
29
  config.assets.debug = true
30
+
31
+ config.eager_load = false
30
32
  end
@@ -9,7 +9,11 @@ Dummy::Application.configure do
9
9
  config.action_controller.perform_caching = true
10
10
 
11
11
  # Disable Rails's static asset server (Apache or nginx will already do this)
12
- config.serve_static_files = false
12
+ if Rails::VERSION::MAJOR < 5
13
+ config.serve_static_files = false
14
+ else
15
+ config.public_file_server.enabled = false
16
+ end
13
17
 
14
18
  # Compress JavaScripts and CSS
15
19
  config.assets.compress = true
@@ -60,4 +64,6 @@ Dummy::Application.configure do
60
64
 
61
65
  # Send deprecation notices to registered listeners
62
66
  config.active_support.deprecation = :notify
67
+
68
+ config.eager_load = true
63
69
  end
@@ -8,11 +8,16 @@ Dummy::Application.configure do
8
8
  config.cache_classes = true
9
9
 
10
10
  # Configure static asset server for tests with Cache-Control for performance
11
- config.serve_static_files = true
12
- config.static_cache_control = "public, max-age=3600"
11
+ if Rails::VERSION::MAJOR < 5
12
+ config.serve_static_files = true
13
+ config.static_cache_control = "public, max-age=3600"
14
+ else
15
+ config.public_file_server.enabled = true
16
+ config.public_file_server.headers = { 'Cache-Control' => 'public, max-age=3600' }
17
+ end
13
18
 
14
19
  config.eager_load = false
15
-
20
+
16
21
  # Show full error reports and disable caching
17
22
  config.consider_all_requests_local = true
18
23
  config.action_controller.perform_caching = false
@@ -32,4 +37,6 @@ Dummy::Application.configure do
32
37
  config.active_support.deprecation = :stderr
33
38
 
34
39
  config.active_support.test_order = :random
40
+
41
+ config.eager_load = false
35
42
  end
@@ -7,23 +7,23 @@ module BentoSearch
7
7
  config.engine = "MockEngine"
8
8
  config.allow_routable_results = true
9
9
  end
10
-
10
+
11
11
  BentoSearch.register_engine("failed_response") do |config|
12
12
  config.engine = "MockEngine"
13
13
  config.allow_routable_results = true
14
14
  config.error = {:message => "faked error"}
15
15
  end
16
-
16
+
17
17
  BentoSearch.register_engine("not_routable") do |config|
18
18
  config.engine = "MockEngine"
19
19
  # no allow_routable_results
20
20
  end
21
-
21
+
22
22
  BentoSearch.register_engine("with_layout_config") do |config|
23
23
  config.engine = "MockEngine"
24
-
24
+
25
25
  config.allow_routable_results = true
26
-
26
+
27
27
  config.for_display do |display|
28
28
  display.ajax do |ajax|
29
29
  ajax.wrapper_template = "bento_search/wrap_with_count"
@@ -31,119 +31,129 @@ module BentoSearch
31
31
  end
32
32
  end
33
33
  end
34
-
35
- def teardown
34
+
35
+ def teardown
36
36
  BentoSearch.reset_engine_registrations!
37
37
  end
38
-
39
-
38
+
39
+
40
40
  test "search" do
41
- get :search, {:engine_id => "mock", :query => "my search"}
41
+ get_search_with_params :engine_id => "mock", :query => "my search"
42
42
  assert_response :success
43
43
  assert_not_nil assigns(:results)
44
-
44
+
45
45
  assert_template "bento_search/search/search"
46
-
46
+
47
47
  # meta tag with count
48
48
  meta_tag = assert_select("meta[itemprop=total_items][content]", :count => 1 )
49
- assert_match /^\d+$/, meta_tag.attribute("content").text
49
+ assert_match(/^\d+$/, meta_tag.attribute("content").text)
50
50
  end
51
-
51
+
52
52
  test "failed search" do
53
- get :search, {:engine_id => "failed_response", :query => "my search"}
54
-
53
+ get_search_with_params :engine_id => "failed_response", :query => "my search"
54
+
55
55
  # should this really be a success? Yes, I think so, we don't
56
56
  # want to stop ajax from getting it, it'll just have an error
57
57
  # message in the HTML. Should it maybe have an html5 meta microdata
58
58
  # warning?
59
59
  assert_response :success
60
-
60
+
61
61
  assert_template "bento_search/search/search"
62
62
  assert_template "bento_search/_search_error"
63
-
63
+
64
64
  assert_select("meta[itemprop=total_items]", :count => 0)
65
65
  end
66
-
67
-
68
-
69
-
70
-
66
+
67
+
68
+
69
+
70
+
71
71
  test "custom layout config" do
72
- get :search, {:engine_id => "with_layout_config", :query => "my search"}
73
-
72
+ get_search_with_params :engine_id => "with_layout_config", :query => "my search"
73
+
74
74
  assert_response :success
75
-
75
+
76
76
  assert_not_nil assigns(:partial_wrapper)
77
-
77
+
78
78
  assert_template "bento_search/_wrap_with_count"
79
79
  assert_template "bento_search/search/search"
80
80
  end
81
-
81
+
82
82
  test "non-routable engine" do
83
- get :search, {:engine_id => "not_routable", :query => "my search"}
84
-
83
+ get_search_with_params :engine_id => "not_routable", :query => "my search"
84
+
85
85
  assert_response 403
86
86
  end
87
-
87
+
88
88
  test "non-existent engine" do
89
- get :search, {:engine_id => "not_existing", :query => "my search"}
90
-
89
+ get_search_with_params :engine_id => "not_existing", :query => "my search"
90
+
91
91
  assert_response 404
92
92
  end
93
-
94
-
93
+
94
+
95
95
  test "respects public_settable_search_args" do
96
- get :search, {:engine_id => "mock",
97
- 'query' => "query", 'sort' => "sort", 'per_page' => "15",
98
- 'page' => "6", 'search_field' => "title", 'not_allowed' => "not allowed"}
99
-
100
-
96
+ get_search_with_params :engine_id => "mock",
97
+ 'query' => "query", 'sort' => "sort", 'per_page' => "15",
98
+ 'page' => "6", 'search_field' => "title", 'not_allowed' => "not allowed"
99
+
100
+
101
101
  search_args = assigns[:engine].last_args
102
-
102
+
103
103
  [:query, :sort, :per_page, :page, :search_field].each do |allowed_key|
104
104
  assert search_args.has_key?(allowed_key)
105
105
  end
106
106
  assert ! search_args.has_key?(:not_allowed)
107
107
  assert ! search_args.has_key?("not_allowed")
108
108
  end
109
-
109
+
110
110
  test "custom before filter" do
111
111
  # Okay, we're going to do a weird thing with a custom controller subclass
112
- # we can add a custom before filter like a local app might.
112
+ # we can add a custom before filter like a local app might.
113
113
  #
114
- # SUPER HACKY, but I dunno what else to do.
115
-
114
+ # SUPER HACKY, but I dunno what else to do.
115
+
116
116
  class CustomSearchController < BentoSearch::SearchController
117
- before_filter :deny_everyone
118
-
117
+ if respond_to?(:before_action)
118
+ before_action :deny_everyone
119
+ else
120
+ before_filter :deny_everyone
121
+ end
122
+
119
123
  def deny_everyone
120
124
  raise BentoSearch::SearchController::AccessDenied
121
125
  end
122
126
  end
123
-
124
127
 
125
-
128
+
129
+
126
130
  orig_controller = @controller
127
-
131
+
128
132
  begin
129
133
  Rails.application.routes.draw do
130
134
  get "/custom_search" => "bento_search/search_controller_test/custom_search#search"
131
135
  end
132
136
  @controller = CustomSearchController.new
133
-
134
- get :search, {:engine_id => "mock", :query => "my search"}
135
-
137
+
138
+ get_search_with_params :engine_id => "mock", :query => "my search"
139
+
136
140
  assert_response 403
137
141
  ensure
138
142
  @controller = orig_controller
139
143
  Rails.application.reload_routes!
140
144
  end
141
-
145
+
146
+ end
147
+
148
+
149
+ # Do rails4 or rails5
150
+ def get_search_with_params(params)
151
+ if Gem::Version.new(Rails.version) >= Gem::Version.new(5.0)
152
+ get :search, params: params
153
+ else
154
+ get :search, params
155
+ end
142
156
  end
143
-
144
157
 
145
-
146
-
147
-
148
158
  end
149
159
  end