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.
- checksums.yaml +5 -5
- data/README.md +27 -24
- data/Rakefile +30 -11
- data/app/assets/javascripts/bento_search/ajax_load.js +54 -22
- data/app/controllers/bento_search/search_controller.rb +31 -30
- data/app/helpers/bento_search_helper.rb +72 -74
- data/app/models/bento_search/concurrent_searcher.rb +136 -0
- data/app/models/bento_search/result_item.rb +15 -12
- data/app/models/bento_search/results/serialization.rb +22 -13
- data/app/models/bento_search/search_engine.rb +170 -140
- data/app/search_engines/bento_search/doaj_articles_engine.rb +20 -20
- data/app/search_engines/bento_search/ebsco_host_engine.rb +3 -3
- data/app/search_engines/bento_search/eds_engine.rb +326 -206
- data/app/search_engines/bento_search/google_books_engine.rb +2 -2
- data/app/search_engines/bento_search/scopus_engine.rb +87 -87
- data/app/search_engines/bento_search/summon_engine.rb +1 -1
- data/app/views/bento_search/_ajax_loading.html.erb +17 -0
- data/app/views/bento_search/_item_title.html.erb +2 -4
- data/app/views/bento_search/_link.html.erb +3 -3
- data/lib/bento_search.rb +24 -9
- data/lib/bento_search/engine.rb +2 -0
- data/lib/bento_search/version.rb +1 -1
- data/lib/generators/bento_search/install/ajax_load_js_generator.rb +15 -0
- data/test/decorator/standard_decorator_test.rb +30 -30
- data/test/dummy/app/assets/config/manifest.js +4 -0
- data/test/dummy/config/application.rb +7 -0
- data/test/dummy/config/boot.rb +4 -9
- data/test/dummy/config/environments/development.rb +2 -0
- data/test/dummy/config/environments/production.rb +7 -1
- data/test/dummy/config/environments/test.rb +10 -3
- data/test/functional/bento_search/search_controller_test.rb +68 -58
- data/test/helper/bento_search_helper_test.rb +103 -103
- data/test/search_engines/doaj_articles_engine_test.rb +9 -9
- data/test/search_engines/eds_engine_test.rb +91 -59
- data/test/search_engines/google_site_search_test.rb +48 -48
- data/test/search_engines/scopus_engine_test.rb +51 -51
- data/test/search_engines/search_engine_base_test.rb +108 -86
- data/test/search_engines/search_engine_test.rb +68 -56
- data/test/support/atom.xsd.xml +3 -3
- data/test/support/xml.xsd +117 -0
- data/test/test_helper.rb +23 -12
- data/test/unit/concurrent_searcher_test.rb +75 -0
- data/test/unit/pagination_test.rb +12 -12
- 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
- data/test/view/atom_results_test.rb +94 -94
- metadata +36 -46
- data/app/assets/javascripts/bento_search.js +0 -3
- data/app/item_decorators/bento_search/ebscohost/conditional_openurl_main_link.rb +0 -36
- data/app/item_decorators/bento_search/only_premade_openurl.rb +0 -20
- data/app/item_decorators/bento_search/openurl_add_other_link.rb +0 -39
- data/app/item_decorators/bento_search/openurl_main_link.rb +0 -34
- data/app/models/bento_search/multi_searcher.rb +0 -131
- data/test/dummy/config/initializers/secret_token.rb +0 -8
- data/test/unit/multi_searcher_test.rb +0 -49
| @@ -7,123 +7,123 @@ require 'cgi' | |
| 7 7 | 
             
            # ENV GOOGLE_SITE_SEARCH_KEY and GOOGLE_SITE_SEARCH_CX
         | 
| 8 8 | 
             
            class GoogleSiteSearchTest < ActiveSupport::TestCase
         | 
| 9 9 | 
             
              extend TestWithCassette
         | 
| 10 | 
            -
             | 
| 10 | 
            +
             | 
| 11 11 | 
             
              @@api_key = ENV["GOOGLE_SITE_SEARCH_KEY"] || "DUMMY_API_KEY"
         | 
| 12 12 | 
             
              @@cx      = ENV["GOOGLE_SITE_SEARCH_CX"] || "DUMMY_CX"
         | 
| 13 | 
            -
             | 
| 13 | 
            +
             | 
| 14 14 | 
             
              VCR.configure do |c|
         | 
| 15 15 | 
             
                c.filter_sensitive_data("DUMMY_API_KEY", :google_site) { @@api_key }
         | 
| 16 16 | 
             
                c.filter_sensitive_data("DUMMY_CX", :google_site) { @@cx }
         | 
| 17 17 | 
             
              end
         | 
| 18 | 
            -
             | 
| 18 | 
            +
             | 
| 19 19 | 
             
              setup do
         | 
| 20 20 | 
             
                @config = {:api_key => @@api_key, :cx => @@cx}
         | 
| 21 21 | 
             
                @engine = BentoSearch::GoogleSiteSearchEngine.new(@config)
         | 
| 22 22 | 
             
              end
         | 
| 23 | 
            -
             | 
| 23 | 
            +
             | 
| 24 24 | 
             
              test("basic query construction") do
         | 
| 25 25 | 
             
                url = @engine.send(:construct_query, {:query => "hours policies"})
         | 
| 26 | 
            -
             | 
| 27 | 
            -
                query_params = CGI.parse( URI.parse(url).query ) | 
| 26 | 
            +
             | 
| 27 | 
            +
                query_params = CGI.parse( URI.parse(url).query )
         | 
| 28 28 |  | 
| 29 29 | 
             
                assert_equal ["hours policies"], query_params["q"]
         | 
| 30 30 | 
             
              end
         | 
| 31 | 
            -
             | 
| 32 | 
            -
              test("pagination construction") do | 
| 31 | 
            +
             | 
| 32 | 
            +
              test("pagination construction") do
         | 
| 33 33 | 
             
                url = @engine.send(:construct_query, {:query => "books", :per_page => 5, :start => 10})
         | 
| 34 | 
            -
             | 
| 34 | 
            +
             | 
| 35 35 | 
             
                query_params = CGI.parse( URI.parse(url).query )
         | 
| 36 | 
            -
             | 
| 36 | 
            +
             | 
| 37 37 | 
             
                assert_equal ["5"], query_params["num"]
         | 
| 38 38 | 
             
                assert_equal ["11"], query_params["start"]
         | 
| 39 39 | 
             
              end
         | 
| 40 | 
            -
             | 
| 40 | 
            +
             | 
| 41 41 | 
             
              test("silently refuses to paginate too far") do
         | 
| 42 42 | 
             
                # google won't let you paginate past ~10 pages, (101 - num). We silently
         | 
| 43 43 | 
             
                # refuse
         | 
| 44 | 
            -
             | 
| 44 | 
            +
             | 
| 45 45 | 
             
                url = @engine.send(:construct_query, {:query => "books", :start => 110})
         | 
| 46 | 
            -
             | 
| 46 | 
            +
             | 
| 47 47 | 
             
                query_params = CGI.parse( URI.parse(url).query )
         | 
| 48 | 
            -
             | 
| 48 | 
            +
             | 
| 49 49 | 
             
                assert_equal ["91"], query_params["start"]
         | 
| 50 50 | 
             
              end
         | 
| 51 | 
            -
             | 
| 51 | 
            +
             | 
| 52 52 | 
             
              test_with_cassette("pagination object is correct for actual page when you ask for too far", :google_site) do
         | 
| 53 53 | 
             
                results = @engine.search("books", :start => 1000)
         | 
| 54 | 
            -
             | 
| 54 | 
            +
             | 
| 55 55 | 
             
                pagination = results.pagination
         | 
| 56 | 
            -
             | 
| 56 | 
            +
             | 
| 57 57 | 
             
                assert_equal 10, pagination.current_page
         | 
| 58 | 
            -
                assert_equal 91, pagination.start_record | 
| 58 | 
            +
                assert_equal 91, pagination.start_record
         | 
| 59 59 | 
             
              end
         | 
| 60 | 
            -
             | 
| 60 | 
            +
             | 
| 61 61 | 
             
              test("sort query construction") do
         | 
| 62 62 | 
             
                url = @engine.send(:construct_query, {:query => "books", :sort => "date_desc"})
         | 
| 63 | 
            -
             | 
| 63 | 
            +
             | 
| 64 64 | 
             
                query_params = CGI.parse( URI.parse(url).query )
         | 
| 65 | 
            -
             | 
| 65 | 
            +
             | 
| 66 66 | 
             
                assert_equal ["date"], query_params["sort"]
         | 
| 67 67 | 
             
              end
         | 
| 68 | 
            -
             | 
| 69 | 
            -
              test_with_cassette("basic smoke test", :google_site) do | 
| 68 | 
            +
             | 
| 69 | 
            +
              test_with_cassette("basic smoke test", :google_site) do
         | 
| 70 70 | 
             
                results = @engine.search("books")
         | 
| 71 | 
            -
             | 
| 71 | 
            +
             | 
| 72 72 | 
             
                assert_present results
         | 
| 73 73 | 
             
                assert_present results.total_items
         | 
| 74 | 
            -
                assert_kind_of  | 
| 75 | 
            -
             | 
| 74 | 
            +
                assert_kind_of 1.class, results.total_items
         | 
| 75 | 
            +
             | 
| 76 76 | 
             
                first = results.first
         | 
| 77 | 
            -
             | 
| 77 | 
            +
             | 
| 78 78 | 
             
                assert_present first.title
         | 
| 79 79 | 
             
                assert_present first.link
         | 
| 80 80 | 
             
                assert_present first.abstract
         | 
| 81 | 
            -
                assert_present first.journal_title # used as source_title for display url | 
| 82 | 
            -
             | 
| 81 | 
            +
                assert_present first.journal_title # used as source_title for display url
         | 
| 82 | 
            +
             | 
| 83 83 | 
             
                # no openurls for google, we decided
         | 
| 84 84 | 
             
                assert_nil     BentoSearch::StandardDecorator.new(first, nil).to_openurl
         | 
| 85 85 | 
             
              end
         | 
| 86 | 
            -
             | 
| 86 | 
            +
             | 
| 87 87 | 
             
              test_with_cassette("with highlighting", :google_site) do
         | 
| 88 88 | 
             
                engine = BentoSearch::GoogleSiteSearchEngine.new(@config.merge(:highlighting => true))
         | 
| 89 | 
            -
             | 
| 89 | 
            +
             | 
| 90 90 | 
             
                results = engine.search("books")
         | 
| 91 | 
            -
             | 
| 91 | 
            +
             | 
| 92 92 | 
             
                first = results.first
         | 
| 93 93 |  | 
| 94 | 
            -
                assert first.title.html_safe? | 
| 94 | 
            +
                assert first.title.html_safe?
         | 
| 95 95 | 
             
                assert first.abstract.html_safe?
         | 
| 96 | 
            -
                assert first.journal_title.html_safe? | 
| 96 | 
            +
                assert first.journal_title.html_safe?
         | 
| 97 97 | 
             
              end
         | 
| 98 | 
            -
             | 
| 98 | 
            +
             | 
| 99 99 | 
             
              test_with_cassette("without highlighting", :google_site) do
         | 
| 100 100 | 
             
                engine = BentoSearch::GoogleSiteSearchEngine.new(@config.merge(:highlighting => false))
         | 
| 101 | 
            -
             | 
| 101 | 
            +
             | 
| 102 102 | 
             
                results = engine.search("books")
         | 
| 103 | 
            -
             | 
| 103 | 
            +
             | 
| 104 104 | 
             
                first = results.first
         | 
| 105 | 
            -
             | 
| 106 | 
            -
                assert ! first.title.html_safe? | 
| 105 | 
            +
             | 
| 106 | 
            +
                assert ! first.title.html_safe?
         | 
| 107 107 | 
             
                assert ! first.abstract.html_safe?
         | 
| 108 | 
            -
                assert ! first.journal_title.html_safe? | 
| 108 | 
            +
                assert ! first.journal_title.html_safe?
         | 
| 109 109 | 
             
              end
         | 
| 110 | 
            -
             | 
| 110 | 
            +
             | 
| 111 111 | 
             
              test_with_cassette("empty result set", :google_site) do
         | 
| 112 112 | 
             
                results = nil
         | 
| 113 113 | 
             
                assert_nothing_raised { results = @engine.search('"adfa lakjdr xavier aldkfj 92323kjadf"') }
         | 
| 114 | 
            -
             | 
| 114 | 
            +
             | 
| 115 115 | 
             
                assert ! results.failed?
         | 
| 116 | 
            -
             | 
| 117 | 
            -
                assert results.empty? | 
| 116 | 
            +
             | 
| 117 | 
            +
                assert results.empty?
         | 
| 118 118 | 
             
              end
         | 
| 119 | 
            -
             | 
| 119 | 
            +
             | 
| 120 120 | 
             
              test_with_cassette("gets format string", :google_site) do
         | 
| 121 121 | 
             
                results = @engine.search("PDF")
         | 
| 122 122 |  | 
| 123 123 | 
             
                # assume at least one result had a PDF format, which it does
         | 
| 124 124 | 
             
                # in our current VCR capture. For a new one, find a search where
         | 
| 125 | 
            -
                # it does. | 
| 126 | 
            -
                assert_present(results.find_all {|i| i.format_str =~ /PDF/ }, "At least one result has PDF in format_str") | 
| 125 | 
            +
                # it does.
         | 
| 126 | 
            +
                assert_present(results.find_all {|i| i.format_str =~ /PDF/ }, "At least one result has PDF in format_str")
         | 
| 127 127 | 
             
              end
         | 
| 128 | 
            -
             | 
| 128 | 
            +
             | 
| 129 129 | 
             
            end
         | 
| @@ -4,32 +4,32 @@ require 'cgi' | |
| 4 4 | 
             
            require 'uri'
         | 
| 5 5 |  | 
| 6 6 | 
             
            # Set shell env SCOPUS_KEY to your api key to test fresh http
         | 
| 7 | 
            -
            # connections, if you can't use the ones cached by VCR. | 
| 7 | 
            +
            # connections, if you can't use the ones cached by VCR.
         | 
| 8 8 |  | 
| 9 9 | 
             
            class ScopusEngineTest < ActiveSupport::TestCase
         | 
| 10 10 | 
             
              extend TestWithCassette
         | 
| 11 | 
            -
             | 
| 11 | 
            +
             | 
| 12 12 | 
             
              # Filter API key out of VCR cache for tag :scopus, which we'll use
         | 
| 13 | 
            -
              # in this test. | 
| 13 | 
            +
              # in this test.
         | 
| 14 14 | 
             
              @@api_key = (ENV["SCOPUS_KEY"] || "DUMMY_API_KEY")
         | 
| 15 15 | 
             
              VCR.configure do |c|
         | 
| 16 16 | 
             
                c.filter_sensitive_data("DUMMY_API_KEY", :scopus) { @@api_key }
         | 
| 17 17 | 
             
              end
         | 
| 18 | 
            -
             | 
| 18 | 
            +
             | 
| 19 19 | 
             
              def setup
         | 
| 20 20 | 
             
                @engine = BentoSearch::ScopusEngine.new(:api_key => @@api_key)
         | 
| 21 21 | 
             
              end
         | 
| 22 | 
            -
             | 
| 23 | 
            -
             | 
| 22 | 
            +
             | 
| 23 | 
            +
             | 
| 24 24 | 
             
              def test_construct_search_url
         | 
| 25 25 | 
             
                url = @engine.send(:scopus_url, :query => "one two")
         | 
| 26 | 
            -
             | 
| 26 | 
            +
             | 
| 27 27 | 
             
                assert_equal "http://api.elsevier.com/content/search/index:SCOPUS?query=one+two&sort=refeid", url
         | 
| 28 28 | 
             
              end
         | 
| 29 | 
            -
             | 
| 29 | 
            +
             | 
| 30 30 | 
             
              def test_construct_fielded_search_url
         | 
| 31 31 | 
             
                url = @engine.send(:scopus_url, :query => "one two", :search_field => "AUTH")
         | 
| 32 | 
            -
             | 
| 32 | 
            +
             | 
| 33 33 | 
             
                assert_equal "http://api.elsevier.com/content/search/index:SCOPUS?query=AUTH%28one+two%29&sort=refeid", url
         | 
| 34 34 | 
             
              end
         | 
| 35 35 |  | 
| @@ -46,66 +46,66 @@ class ScopusEngineTest < ActiveSupport::TestCase | |
| 46 46 | 
             
                assert_includes query_components, "AUTH(John Smith)"
         | 
| 47 47 | 
             
                assert_includes query_components, "TITLE(Terrible Diseases)"
         | 
| 48 48 | 
             
              end
         | 
| 49 | 
            -
             | 
| 49 | 
            +
             | 
| 50 50 | 
             
              def test_construct_search_with_per_page
         | 
| 51 51 | 
             
                url = @engine.send(:scopus_url, :query => "one two", :per_page => 30)
         | 
| 52 | 
            -
             | 
| 52 | 
            +
             | 
| 53 53 | 
             
                assert_equal "http://api.elsevier.com/content/search/index:SCOPUS?query=one+two&count=30&sort=refeid", url
         | 
| 54 54 | 
             
              end
         | 
| 55 | 
            -
             | 
| 55 | 
            +
             | 
| 56 56 | 
             
              def test_construct_search_with_sort
         | 
| 57 57 | 
             
                url = @engine.send(:scopus_url, :query => "one two", :sort => "date_desc")
         | 
| 58 | 
            -
             | 
| 58 | 
            +
             | 
| 59 59 | 
             
                assert_equal "http://api.elsevier.com/content/search/index:SCOPUS?query=one+two&sort=-datesort%2C%2Bauth", url
         | 
| 60 | 
            -
             | 
| 60 | 
            +
             | 
| 61 61 | 
             
                url = @engine.send(:scopus_url, :query => "one two", :sort => "relevance")
         | 
| 62 | 
            -
             | 
| 62 | 
            +
             | 
| 63 63 | 
             
                assert_equal "http://api.elsevier.com/content/search/index:SCOPUS?query=one+two&sort=refeid", url
         | 
| 64 | 
            -
             | 
| 64 | 
            +
             | 
| 65 65 | 
             
              end
         | 
| 66 | 
            -
             | 
| 66 | 
            +
             | 
| 67 67 | 
             
              def test_construct_default_relevance_sort
         | 
| 68 68 | 
             
                url_implicit = @engine.send(:scopus_url, :query => "one two")
         | 
| 69 69 | 
             
                url_explicit = @engine.send(:scopus_url, :query => "one two", :sort => "relevance")
         | 
| 70 | 
            -
             | 
| 70 | 
            +
             | 
| 71 71 | 
             
                assert_equal url_explicit, url_implicit
         | 
| 72 72 | 
             
              end
         | 
| 73 | 
            -
             | 
| 74 | 
            -
             | 
| 73 | 
            +
             | 
| 74 | 
            +
             | 
| 75 75 | 
             
              def test_construct_with_pagination
         | 
| 76 76 | 
             
                url = @engine.send(:scopus_url, :query => "one two", :start => 20, :per_page => 10)
         | 
| 77 | 
            -
             | 
| 77 | 
            +
             | 
| 78 78 | 
             
                query_hash = CGI.parse(URI.parse(url).query)
         | 
| 79 | 
            -
             | 
| 79 | 
            +
             | 
| 80 80 | 
             
                assert_equal ["20"], query_hash["start"]
         | 
| 81 | 
            -
                assert_equal ["10"], query_hash["count"] | 
| 81 | 
            +
                assert_equal ["10"], query_hash["count"]
         | 
| 82 82 | 
             
              end
         | 
| 83 | 
            -
             | 
| 84 | 
            -
             | 
| 83 | 
            +
             | 
| 84 | 
            +
             | 
| 85 85 | 
             
              test_with_cassette("bad api key should return error response", :scopus) do
         | 
| 86 86 | 
             
                @engine = BentoSearch::ScopusEngine.new(:api_key => "BAD_KEY_ERROR")
         | 
| 87 | 
            -
             | 
| 87 | 
            +
             | 
| 88 88 | 
             
                results = @engine.search(:query => "cancer")
         | 
| 89 89 |  | 
| 90 | 
            -
                assert results.failed?, "response.failed? should be" | 
| 90 | 
            +
                assert results.failed?, "response.failed? should be"
         | 
| 91 91 |  | 
| 92 92 | 
             
                assert_present results.error[:error_info]
         | 
| 93 93 | 
             
                assert_includes results.error[:error_info], "AUTHORIZATION_ERROR"
         | 
| 94 94 | 
             
              end
         | 
| 95 | 
            -
             | 
| 95 | 
            +
             | 
| 96 96 | 
             
              test_with_cassette("simple search", :scopus) do
         | 
| 97 97 | 
             
                results = @engine.search(:query => "cancer")
         | 
| 98 | 
            -
             | 
| 98 | 
            +
             | 
| 99 99 | 
             
                assert_not_nil results.total_items, "total_items not nil"
         | 
| 100 | 
            -
                assert_kind_of  | 
| 101 | 
            -
             | 
| 100 | 
            +
                assert_kind_of 1.class, results.total_items
         | 
| 101 | 
            +
             | 
| 102 102 | 
             
                assert_not_nil results.start, "start not nil"
         | 
| 103 103 | 
             
                assert_not_nil results.per_page, "per_page not nil"
         | 
| 104 | 
            -
             | 
| 104 | 
            +
             | 
| 105 105 | 
             
                assert_equal 10, results.length
         | 
| 106 | 
            -
             | 
| 106 | 
            +
             | 
| 107 107 | 
             
                sample_result = results.first
         | 
| 108 | 
            -
             | 
| 108 | 
            +
             | 
| 109 109 | 
             
                assert_present sample_result.title
         | 
| 110 110 | 
             
                assert_present sample_result.link
         | 
| 111 111 | 
             
                assert_present sample_result.journal_title
         | 
| @@ -114,37 +114,37 @@ class ScopusEngineTest < ActiveSupport::TestCase | |
| 114 114 | 
             
                assert_present sample_result.volume
         | 
| 115 115 | 
             
                assert_present sample_result.issue
         | 
| 116 116 | 
             
                assert_present sample_result.start_page
         | 
| 117 | 
            -
             | 
| 118 | 
            -
                assert_present sample_result.authors | 
| 119 | 
            -
             | 
| 117 | 
            +
             | 
| 118 | 
            +
                assert_present sample_result.authors
         | 
| 119 | 
            +
             | 
| 120 120 | 
             
                assert_present sample_result.format
         | 
| 121 | 
            -
             | 
| 121 | 
            +
             | 
| 122 122 | 
             
                assert_present sample_result.unique_id
         | 
| 123 | 
            -
             | 
| 123 | 
            +
             | 
| 124 124 | 
             
              end
         | 
| 125 | 
            -
             | 
| 125 | 
            +
             | 
| 126 126 | 
             
              test_with_cassette("zero results search", :scopus) do
         | 
| 127 127 | 
             
                results = @engine.search(:query => "aldfjkadf lakdj zdfzzzz")
         | 
| 128 128 | 
             
                assert ! results.failed?, "results not marked failed"
         | 
| 129 129 | 
             
                assert_equal 0, results.size
         | 
| 130 130 | 
             
              end
         | 
| 131 | 
            -
             | 
| 131 | 
            +
             | 
| 132 132 | 
             
              test_with_cassette("escaped chars", :scopus) do
         | 
| 133 133 | 
             
                results = @engine.search(:query => "monkey:(brain)")
         | 
| 134 | 
            -
             | 
| 134 | 
            +
             | 
| 135 135 | 
             
                assert ! results.failed?, "results not marked failed"
         | 
| 136 136 | 
             
              end
         | 
| 137 | 
            -
             | 
| 138 | 
            -
             | 
| 139 | 
            -
             | 
| 137 | 
            +
             | 
| 138 | 
            +
             | 
| 139 | 
            +
             | 
| 140 140 | 
             
              test_with_cassette("fielded search", :scopus) do
         | 
| 141 141 | 
             
                results = @engine.search(:query => "cancer", :semantic_search_field => :title)
         | 
| 142 142 |  | 
| 143 | 
            -
                assert results.first.title.downcase.include?("cancer"), "Title includes query term" | 
| 143 | 
            +
                assert results.first.title.downcase.include?("cancer"), "Title includes query term"
         | 
| 144 144 | 
             
              end
         | 
| 145 | 
            -
             | 
| 145 | 
            +
             | 
| 146 146 | 
             
              test_with_cassette("multi-field search", :scopus) do
         | 
| 147 | 
            -
                results = @engine.search(:query => | 
| 147 | 
            +
                results = @engine.search(:query =>
         | 
| 148 148 | 
             
                  { :title => "Protein measurement with the folin phenol reagent",
         | 
| 149 149 | 
             
                    :author => "Lowry",
         | 
| 150 150 | 
             
                    :issn => "0021-9258"
         | 
| @@ -168,12 +168,12 @@ class ScopusEngineTest < ActiveSupport::TestCase | |
| 168 168 | 
             
                })
         | 
| 169 169 |  | 
| 170 170 | 
             
                assert ! results.failed?
         | 
| 171 | 
            -
                assert_equal 1, results.total_items | 
| 171 | 
            +
                assert_equal 1, results.total_items
         | 
| 172 172 |  | 
| 173 173 | 
             
                item = results.first
         | 
| 174 174 |  | 
| 175 175 | 
             
                assert item.title.start_with?("Architects and planners in the middle of a road war")
         | 
| 176 176 | 
             
              end
         | 
| 177 | 
            -
             | 
| 178 | 
            -
             | 
| 177 | 
            +
             | 
| 178 | 
            +
             | 
| 179 179 | 
             
            end
         | 
| @@ -5,22 +5,22 @@ class ParseSearchArgumentsTest < ActiveSupport::TestCase | |
| 5 5 |  | 
| 6 6 | 
             
              class Dummy
         | 
| 7 7 | 
             
                include BentoSearch::SearchEngine
         | 
| 8 | 
            -
             | 
| 8 | 
            +
             | 
| 9 9 | 
             
                def search_implementation(args)
         | 
| 10 10 | 
             
                  # no-op for now
         | 
| 11 11 | 
             
                  BentoSearch::Results.new
         | 
| 12 12 | 
             
                end
         | 
| 13 | 
            -
             | 
| 13 | 
            +
             | 
| 14 14 | 
             
                def test_parse(*args)
         | 
| 15 15 | 
             
                  # original method is protected, this is a lame way
         | 
| 16 | 
            -
                  # to expose it. | 
| 16 | 
            +
                  # to expose it.
         | 
| 17 17 | 
             
                  parse_search_arguments(*args)
         | 
| 18 18 | 
             
                end
         | 
| 19 | 
            -
             | 
| 19 | 
            +
             | 
| 20 20 | 
             
                def max_per_page
         | 
| 21 21 | 
             
                  40
         | 
| 22 22 | 
             
                end
         | 
| 23 | 
            -
             | 
| 23 | 
            +
             | 
| 24 24 | 
             
                def search_field_definitions
         | 
| 25 25 | 
             
                  {
         | 
| 26 26 | 
             
                    "my_title" => {:semantic => :title},
         | 
| @@ -28,114 +28,125 @@ class ParseSearchArgumentsTest < ActiveSupport::TestCase | |
| 28 28 | 
             
                    "my_other" => nil
         | 
| 29 29 | 
             
                  }
         | 
| 30 30 | 
             
                end
         | 
| 31 | 
            -
             | 
| 32 | 
            -
              end | 
| 33 | 
            -
             | 
| 34 | 
            -
             | 
| 31 | 
            +
             | 
| 32 | 
            +
              end
         | 
| 33 | 
            +
             | 
| 34 | 
            +
             | 
| 35 35 | 
             
              def test_single_arg
         | 
| 36 36 | 
             
                d = Dummy.new
         | 
| 37 | 
            -
             | 
| 37 | 
            +
             | 
| 38 38 | 
             
                args = d.test_parse("query")
         | 
| 39 | 
            -
             | 
| 40 | 
            -
                assert_equal( {:query => "query", :per_page => BentoSearch::SearchEngine::DefaultPerPage }, args ) | 
| 39 | 
            +
             | 
| 40 | 
            +
                assert_equal( {:query => "query", :per_page => BentoSearch::SearchEngine::DefaultPerPage }, args )
         | 
| 41 41 | 
             
              end
         | 
| 42 | 
            -
             | 
| 42 | 
            +
             | 
| 43 43 | 
             
              def test_two_arg
         | 
| 44 44 | 
             
                d = Dummy.new
         | 
| 45 | 
            -
             | 
| 45 | 
            +
             | 
| 46 46 | 
             
                args = d.test_parse("query", :arg => "1")
         | 
| 47 | 
            -
             | 
| 47 | 
            +
             | 
| 48 48 | 
             
                assert_equal( {:query => "query", :arg => "1", :per_page => BentoSearch::SearchEngine::DefaultPerPage }, args )
         | 
| 49 49 | 
             
              end
         | 
| 50 | 
            -
             | 
| 51 | 
            -
             | 
| 52 | 
            -
             | 
| 50 | 
            +
             | 
| 51 | 
            +
             | 
| 52 | 
            +
             | 
| 53 53 | 
             
              def test_convert_page_to_start
         | 
| 54 54 | 
             
                d = Dummy.new
         | 
| 55 | 
            -
             | 
| 55 | 
            +
             | 
| 56 56 | 
             
                args = d.test_parse(:query => "query", :page => 1, :per_page => 20)
         | 
| 57 | 
            -
             | 
| 57 | 
            +
             | 
| 58 58 | 
             
                assert_equal 0, args[:start]
         | 
| 59 59 | 
             
                assert_equal 1, args[:page]
         | 
| 60 60 | 
             
                assert_equal 20, args[:per_page]
         | 
| 61 | 
            -
             | 
| 61 | 
            +
             | 
| 62 62 | 
             
                args = d.test_parse(:query => "query", :page => 3, :per_page => 20)
         | 
| 63 63 |  | 
| 64 64 | 
             
                assert_equal 40, args[:start]
         | 
| 65 65 | 
             
                assert_equal 3, args[:page]
         | 
| 66 | 
            -
                assert_equal 20, args[:per_page] | 
| 66 | 
            +
                assert_equal 20, args[:per_page]
         | 
| 67 67 | 
             
              end
         | 
| 68 | 
            -
             | 
| 68 | 
            +
             | 
| 69 69 | 
             
              def test_convert_start_to_page
         | 
| 70 70 | 
             
                d = Dummy.new
         | 
| 71 | 
            -
             | 
| 72 | 
            -
                # rounds down to get closest 'page' if need be. | 
| 71 | 
            +
             | 
| 72 | 
            +
                # rounds down to get closest 'page' if need be.
         | 
| 73 73 | 
             
                args = d.test_parse(:query => "query", :start => '19', :per_page => '20')
         | 
| 74 | 
            -
             | 
| 74 | 
            +
             | 
| 75 75 | 
             
                assert_equal 19, args[:start]
         | 
| 76 76 | 
             
                assert_equal 1,  args[:page]
         | 
| 77 | 
            -
             | 
| 77 | 
            +
             | 
| 78 78 | 
             
                args = d.test_parse(:query => "query", :start => '20', :per_page => '20')
         | 
| 79 79 | 
             
                assert_equal 2,  args[:page]
         | 
| 80 80 | 
             
              end
         | 
| 81 | 
            -
             | 
| 82 | 
            -
             | 
| 81 | 
            +
             | 
| 82 | 
            +
             | 
| 83 83 | 
             
              def test_pagination_to_integer
         | 
| 84 84 | 
             
                d = Dummy.new
         | 
| 85 | 
            -
             | 
| 85 | 
            +
             | 
| 86 86 | 
             
                args = d.test_parse(:query => "query", :page => "1", :per_page => "20")
         | 
| 87 87 | 
             
                assert_equal 0, args[:start]
         | 
| 88 88 | 
             
                assert_equal 1, args[:page]
         | 
| 89 89 | 
             
                assert_equal 20, args[:per_page]
         | 
| 90 | 
            -
             | 
| 90 | 
            +
             | 
| 91 91 | 
             
                args = d.test_parse(:query => "query", :start => "20", :per_page => "20")
         | 
| 92 | 
            -
                assert_equal 20, args[:start] | 
| 92 | 
            +
                assert_equal 20, args[:start]
         | 
| 93 93 | 
             
                assert_equal 20, args[:per_page]
         | 
| 94 | 
            -
             | 
| 94 | 
            +
             | 
| 95 95 | 
             
              end
         | 
| 96 | 
            -
             | 
| 96 | 
            +
             | 
| 97 97 | 
             
              def test_ignore_blank_pagination_args
         | 
| 98 98 | 
             
                d = Dummy.new
         | 
| 99 | 
            -
             | 
| 99 | 
            +
             | 
| 100 100 | 
             
                args = d.test_parse(:query => "query", :page => "", :per_page => "", :start => "")
         | 
| 101 | 
            -
             | 
| 101 | 
            +
             | 
| 102 102 | 
             
                assert ! (args.has_key? :page)
         | 
| 103 103 | 
             
                assert ! (args.has_key? :start)
         | 
| 104 | 
            -
                assert  (args.has_key? :per_page) # default per page always provided | 
| 104 | 
            +
                assert  (args.has_key? :per_page) # default per page always provided
         | 
| 105 105 | 
             
              end
         | 
| 106 | 
            -
             | 
| 106 | 
            +
             | 
| 107 107 | 
             
              def test_enforce_max_per_page
         | 
| 108 108 | 
             
                d = Dummy.new
         | 
| 109 | 
            -
             | 
| 110 | 
            -
                assert_raise(ArgumentError) { d.test_parse(:query => "query", :per_page => 1000) } | 
| 109 | 
            +
             | 
| 110 | 
            +
                assert_raise(ArgumentError) { d.test_parse(:query => "query", :per_page => 1000) }
         | 
| 111 | 
            +
              end
         | 
| 112 | 
            +
             | 
| 113 | 
            +
              def test_default_per_page
         | 
| 114 | 
            +
                d = Dummy.new
         | 
| 115 | 
            +
             | 
| 116 | 
            +
                args = d.test_parse(:query => "query")
         | 
| 117 | 
            +
                assert_equal(Dummy::DefaultPerPage, args[:per_page])
         | 
| 118 | 
            +
             | 
| 119 | 
            +
                d.configuration[:default_per_page] = 2
         | 
| 120 | 
            +
                args = d.test_parse(:query => "query")
         | 
| 121 | 
            +
                assert_equal(2, args[:per_page])
         | 
| 111 122 | 
             
              end
         | 
| 112 | 
            -
             | 
| 113 | 
            -
              def test_search_field_keys | 
| 123 | 
            +
             | 
| 124 | 
            +
              def test_search_field_keys
         | 
| 114 125 | 
             
                assert_equal ["my_title", "my_author", "my_other"], Dummy.new.search_keys
         | 
| 115 126 | 
             
                assert_equal ["title", "author"], Dummy.new.semantic_search_keys
         | 
| 116 127 | 
             
              end
         | 
| 117 | 
            -
             | 
| 128 | 
            +
             | 
| 118 129 | 
             
              def test_semantic_search_map
         | 
| 119 | 
            -
                assert_equal( {"title" => "my_title", "author" => "my_author"}, | 
| 130 | 
            +
                assert_equal( {"title" => "my_title", "author" => "my_author"},
         | 
| 120 131 | 
             
                  Dummy.new.semantic_search_map)
         | 
| 121 132 | 
             
              end
         | 
| 122 | 
            -
             | 
| 133 | 
            +
             | 
| 123 134 | 
             
              def test_translate_search_field_semantics
         | 
| 124 135 | 
             
                d = Dummy.new
         | 
| 125 | 
            -
             | 
| 136 | 
            +
             | 
| 126 137 | 
             
                args = d.test_parse(:query => "query", :semantic_search_field => :title)
         | 
| 127 | 
            -
             | 
| 138 | 
            +
             | 
| 128 139 | 
             
                assert ! (args.has_key? :semantic_search_field), "translates semantic_search_field to search_field"
         | 
| 129 140 | 
             
                assert_equal "my_title", args[:search_field]
         | 
| 130 | 
            -
             | 
| 141 | 
            +
             | 
| 131 142 | 
             
                assert_raise(ArgumentError, "Raises for undefined semantic_search_field when asked") do
         | 
| 132 143 | 
             
                  d.test_parse(:query => "query", :semantic_search_field => :subject, :unrecognized_search_field => :raise)
         | 
| 133 144 | 
             
                end
         | 
| 134 145 | 
             
                # without the :unrecognized_search_field => :raise, ignore
         | 
| 135 146 | 
             
                args = d.test_parse(:query => "query", :semantic_search_field => :subject)
         | 
| 136 | 
            -
                assert_nil args[:search_field] | 
| 147 | 
            +
                assert_nil args[:search_field]
         | 
| 137 148 | 
             
              end
         | 
| 138 | 
            -
             | 
| 149 | 
            +
             | 
| 139 150 | 
             
              def test_unrecognized_search_field
         | 
| 140 151 | 
             
                d = Dummy.new
         | 
| 141 152 | 
             
                assert_raise(ArgumentError, "Raises for undefined search field when asked") do
         | 
| @@ -144,7 +155,7 @@ class ParseSearchArgumentsTest < ActiveSupport::TestCase | |
| 144 155 | 
             
                assert_nothing_raised do
         | 
| 145 156 | 
             
                  d.test_parse(:query => "query", :search_field => "I_made_this_up")
         | 
| 146 157 | 
             
                end
         | 
| 147 | 
            -
             | 
| 158 | 
            +
             | 
| 148 159 | 
             
                # combine config and args
         | 
| 149 160 | 
             
                engine = BentoSearch::MockEngine.new(:unrecognized_search_field => :raise)
         | 
| 150 161 | 
             
                assert_raise(ArgumentError, "Raises for undefined search field when asked") do
         | 
| @@ -153,7 +164,7 @@ class ParseSearchArgumentsTest < ActiveSupport::TestCase | |
| 153 164 | 
             
                assert_nothing_raised do
         | 
| 154 165 | 
             
                  engine.normalized_search_arguments(:query => "query", :search_field => "I_made_this_up", :unrecognized_search_field => :ignore)
         | 
| 155 166 | 
             
                end
         | 
| 156 | 
            -
             | 
| 167 | 
            +
             | 
| 157 168 | 
             
              end
         | 
| 158 169 |  | 
| 159 170 |  | 
| @@ -170,26 +181,26 @@ class ParseSearchArgumentsTest < ActiveSupport::TestCase | |
| 170 181 | 
             
                end
         | 
| 171 182 |  | 
| 172 183 | 
             
                it "converts semantic search fields" do
         | 
| 173 | 
            -
                  engine = MockEngine.new(:multi_field_search => true, | 
| 184 | 
            +
                  engine = MockEngine.new(:multi_field_search => true,
         | 
| 174 185 | 
             
                    :search_field_definitions => {
         | 
| 175 186 | 
             
                      "internal_title_field"  => {:semantic => :title},
         | 
| 176 | 
            -
                      "internal_author_field" => {:semantic => :author} | 
| 187 | 
            +
                      "internal_author_field" => {:semantic => :author}
         | 
| 177 188 | 
             
                    })
         | 
| 178 189 |  | 
| 179 190 | 
             
                  engine.search(:query => {:title => "title query", :author => "author query"})
         | 
| 180 191 |  | 
| 181 192 | 
             
                  assert_equal(
         | 
| 182 | 
            -
                    { "internal_title_field"  => "title query", | 
| 193 | 
            +
                    { "internal_title_field"  => "title query",
         | 
| 183 194 | 
             
                      "internal_author_field" => "author query"},
         | 
| 184 195 | 
             
                    engine.last_args[:query]
         | 
| 185 196 | 
             
                  )
         | 
| 186 197 | 
             
                end
         | 
| 187 198 |  | 
| 188 199 | 
             
                it "passes through other fields" do
         | 
| 189 | 
            -
                  engine = MockEngine.new(:multi_field_search => true, | 
| 200 | 
            +
                  engine = MockEngine.new(:multi_field_search => true,
         | 
| 190 201 | 
             
                    :search_field_definitions => {
         | 
| 191 202 | 
             
                      "internal_title_field"  => {:semantic => :title},
         | 
| 192 | 
            -
                      "internal_author_field" => {:semantic => :author} | 
| 203 | 
            +
                      "internal_author_field" => {:semantic => :author}
         | 
| 193 204 | 
             
                    })
         | 
| 194 205 |  | 
| 195 206 | 
             
                  engine.search(:query => {"internal_title_field" => "query", "other field" => "query"})
         | 
| @@ -201,81 +212,92 @@ class ParseSearchArgumentsTest < ActiveSupport::TestCase | |
| 201 212 | 
             
                end
         | 
| 202 213 |  | 
| 203 214 | 
             
                it "complains on unrecognized field if configured" do
         | 
| 204 | 
            -
                  engine = MockEngine.new(:multi_field_search => true, | 
| 215 | 
            +
                  engine = MockEngine.new(:multi_field_search => true,
         | 
| 205 216 | 
             
                    :unrecognized_search_field => "raise",
         | 
| 206 217 | 
             
                    :search_field_definitions => {
         | 
| 207 218 | 
             
                      "internal_title_field"  => {:semantic => :title},
         | 
| 208 | 
            -
                      "internal_author_field" => {:semantic => :author} | 
| 209 | 
            -
                    }) | 
| 219 | 
            +
                      "internal_author_field" => {:semantic => :author}
         | 
| 220 | 
            +
                    })
         | 
| 210 221 | 
             
                  assert_raises(ArgumentError) do
         | 
| 211 222 | 
             
                    engine.search(:query => {"internal_title_field" => "query", "other field" => "query"})
         | 
| 212 223 | 
             
                  end
         | 
| 213 224 | 
             
                end
         | 
| 214 225 | 
             
              end
         | 
| 215 | 
            -
             | 
| 226 | 
            +
             | 
| 216 227 | 
             
              def test_semantic_blank_ignored
         | 
| 217 228 | 
             
                d = Dummy.new
         | 
| 218 | 
            -
             | 
| 229 | 
            +
             | 
| 219 230 | 
             
                args1 = d.test_parse(:query => "query", :semantic_search_field => nil)
         | 
| 220 231 | 
             
                args2 = d.test_parse(:query => "query", :semantic_search_field => nil)
         | 
| 221 | 
            -
             | 
| 232 | 
            +
             | 
| 222 233 | 
             
                assert_nil args1[:search_field]
         | 
| 223 234 | 
             
                assert_nil args2[:search_field]
         | 
| 224 235 | 
             
              end
         | 
| 225 | 
            -
             | 
| 236 | 
            +
             | 
| 226 237 | 
             
              def test_semantic_string_or_symbol
         | 
| 227 238 | 
             
                d = Dummy.new
         | 
| 228 | 
            -
             | 
| 239 | 
            +
             | 
| 229 240 | 
             
                args1 = d.test_parse(:query => "query", :semantic_search_field => :title)
         | 
| 230 241 | 
             
                args2 = d.test_parse(:query => "query", :semantic_search_field => "title")
         | 
| 231 | 
            -
             | 
| 232 | 
            -
                assert_equal args1, args2 | 
| 242 | 
            +
             | 
| 243 | 
            +
                assert_equal args1, args2
         | 
| 233 244 | 
             
              end
         | 
| 234 | 
            -
             | 
| 245 | 
            +
             | 
| 235 246 | 
             
              def test_converts_sort_to_string
         | 
| 236 247 | 
             
                d = Dummy.new
         | 
| 237 | 
            -
             | 
| 248 | 
            +
             | 
| 238 249 | 
             
                args = d.test_parse(:query => "query", :sort => :title_asc)
         | 
| 239 | 
            -
             | 
| 250 | 
            +
             | 
| 240 251 | 
             
                assert_equal "title_asc", args[:sort]
         | 
| 241 252 | 
             
              end
         | 
| 242 | 
            -
             | 
| 253 | 
            +
             | 
| 243 254 | 
             
              def test_sets_timing
         | 
| 244 255 | 
             
                d = Dummy.new
         | 
| 245 256 | 
             
                results = d.search("foo")
         | 
| 246 | 
            -
             | 
| 257 | 
            +
             | 
| 247 258 | 
             
                assert_not_nil results.timing
         | 
| 248 | 
            -
                assert_not_nil results.timing_ms | 
| 259 | 
            +
                assert_not_nil results.timing_ms
         | 
| 249 260 | 
             
              end
         | 
| 250 | 
            -
             | 
| 261 | 
            +
             | 
| 251 262 | 
             
              def test_passes_arbitrary_keys
         | 
| 252 263 | 
             
                d = Dummy.new
         | 
| 253 264 | 
             
                args = d.test_parse(:query => "foo", :custom_auth => true)
         | 
| 254 | 
            -
             | 
| 265 | 
            +
             | 
| 255 266 | 
             
                assert_present args[:custom_auth]
         | 
| 256 267 | 
             
                assert_equal true, args[:custom_auth]
         | 
| 257 | 
            -
             | 
| 268 | 
            +
             | 
| 258 269 | 
             
              end
         | 
| 259 | 
            -
             | 
| 270 | 
            +
             | 
| 260 271 | 
             
              def test_rescues_exceptions
         | 
| 261 272 | 
             
                horrible_engine = Class.new do
         | 
| 262 273 | 
             
                  include BentoSearch::SearchEngine
         | 
| 263 | 
            -
             | 
| 274 | 
            +
             | 
| 264 275 | 
             
                  def search_implementation(args)
         | 
| 265 | 
            -
                    raise  | 
| 276 | 
            +
                    raise BentoSearch::RubyTimeoutClass.new("I am a horrible engine")
         | 
| 266 277 | 
             
                  end
         | 
| 267 278 | 
             
                end
         | 
| 268 | 
            -
             | 
| 279 | 
            +
             | 
| 269 280 | 
             
                engine = horrible_engine.new
         | 
| 270 | 
            -
             | 
| 271 | 
            -
                results =  engine.search("cancer") | 
| 272 | 
            -
             | 
| 281 | 
            +
             | 
| 282 | 
            +
                results =  engine.search("cancer")
         | 
| 283 | 
            +
             | 
| 273 284 | 
             
                assert_not_nil results
         | 
| 274 285 | 
             
                assert results.failed?, "results marked failed"
         | 
| 275 286 | 
             
                assert_not_nil results.error[:exception], "results.error has exception"
         | 
| 276 | 
            -
             | 
| 277 | 
            -
                assert_equal "I am a horrible engine", results.error[:exception].message, "results.error has right exception" | 
| 287 | 
            +
             | 
| 288 | 
            +
                assert_equal "I am a horrible engine", results.error[:exception].message, "results.error has right exception"
         | 
| 278 289 | 
             
              end
         | 
| 279 | 
            -
             | 
| 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 | 
            +
             | 
| 280 302 | 
             
            end
         | 
| 281 303 |  |