bcms_google_mini_search 1.2.2 → 1.3.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.
Files changed (35) hide show
  1. data/.gitignore +12 -0
  2. data/.rvmrc +1 -0
  3. data/COPYRIGHT.txt +23 -0
  4. data/GPL.txt +674 -0
  5. data/Gemfile +7 -0
  6. data/LICENSE.txt +165 -0
  7. data/README.markdown +3 -7
  8. data/Rakefile +10 -0
  9. data/app/models/search_result.rb +34 -104
  10. data/app/portlets/google_mini_search_engine_portlet.rb +4 -20
  11. data/app/views/layouts/templates/{default.html.erb.html.erb → default.html.erb} +0 -0
  12. data/app/views/portlets/google_mini_search_engine/_form.html.erb +0 -2
  13. data/app/views/portlets/google_mini_search_engine/render.html.erb +17 -39
  14. data/bcms_google_mini_search.gemspec +35 -0
  15. data/doc/README_FOR_APP +2 -0
  16. data/lib/bcms_google_mini_search.rb +1 -2
  17. data/lib/bcms_google_mini_search/engine.rb +7 -0
  18. data/lib/bcms_google_mini_search/routes.rb +3 -3
  19. data/lib/bcms_google_mini_search/version.rb +3 -0
  20. data/lib/generators/bcms_google_mini_search/install/USAGE +10 -0
  21. data/lib/generators/bcms_google_mini_search/install/install_generator.rb +9 -0
  22. data/lib/tasks/.gitkeep +0 -0
  23. data/public/stylesheets/.gitkeep +0 -0
  24. data/test/performance/browsing_test.rb +9 -0
  25. data/test/test_helper.rb +18 -0
  26. data/test/unit/helpers/search_engine_helper_test.rb +4 -0
  27. data/test/unit/portlets/google_mini_search_engine_portlet_test.rb +15 -0
  28. data/test/unit/portlets/search_box_portlet_test.rb +9 -0
  29. data/test/unit/search_result_test.rb +474 -0
  30. data/vendor/plugins/.gitkeep +0 -0
  31. metadata +70 -48
  32. data/app/controllers/application_controller.rb +0 -10
  33. data/app/helpers/application_helper.rb +0 -3
  34. data/lib/bcms_google_mini_search/gsa.rb +0 -144
  35. data/rails/init.rb +0 -3
@@ -1,55 +1,33 @@
1
-
2
1
  <h2>Search Results</h2>
3
- For '<%= @results.query %>', found <%= @results.results_count %> results. <br/>
4
- <%= link_to_unless @results.sorting_by_date?(params), "Sort by Date", @results.sort_by_date_path %> /
5
- <%= link_to_if @results.sorting_by_date?(params), "Sort by Relevance", @results.sort_by_relevance_path %> <br/>
6
- <% if @results.previous_page? %><%= link_to h("< Back"), @results.previous_page_path %>
7
- <% end %>
8
- <% if @results.next_page? %><%= link_to h("Next >"), @results.next_page_path %>
9
- <% end %>
2
+ For '<%= @results.query %>', found <%= @results.results_count %> results. <br />
3
+ <% if @results.previous_page? %><%= link_to h("< Back"), @results.previous_page_path %><% end %>
4
+ <% if @results.next_page? %><%= link_to h("Next >"), @results.next_page_path %><% end %>
10
5
  <% if @results.key_matches? %>
11
6
  <ul class="key_matches">
12
- <% @results.key_matches.each do |match| %>
13
- <li><%= link_to match.title, match.url %></li>
14
- <% end %>
7
+ <% @results.key_matches.each do |match| %>
8
+ <li><%= link_to match.title, match.url %></li>
9
+ <% end %>
15
10
  </ul>
16
11
  <% end %>
17
12
  <% if @results.synonyms? %>
18
13
  <span class="synonyms">You could also try:
19
- <% @results.synonyms.each do |synonym| %>
14
+ <% @results.synonyms.each do |synonym| %>
20
15
  <%= link_to synonym.label, synonym.url %>
21
16
  <% end %>
22
17
  </span>
23
18
  <% end %>
24
19
  <ul class="search_results">
25
- <% @results.each do |result| %>
26
- <li>
27
- <%= result.number %> <%= link_to result.title, result.url, :class=>"search_result_title" %>
28
- <br/>
29
- <span class="search_result_description"><%= result.description %></span> <br/>
30
- <span class="search_result_url"><%= result.url %></span> -
20
+ <% @results.each do |result|%>
21
+ <li>
22
+ <%= result.number %> <%= link_to result.title, result.url, :class=>"search_result_title" %><br />
23
+ <span class="search_result_description"><%= result.description.html_safe %></span> <br />
24
+ <span class="search_result_url"><%= result.url %></span> -
31
25
  <span class="search_result_size"><%= result.size %></span>
32
- <span class="search_result_cached"><%= link_to "Cached", result.cached_document_url(@query) %></span>
33
-
34
- </li>
26
+ </li>
35
27
  <% end %>
36
28
  </ul>
37
-
38
- <% if @portlet.narrow_your_search? %>
39
- <div id="clustering">
40
- <h3>Narrow your search</h3>
41
- <ul>
42
- <% @suggested_queries.each_with_index do |suggestion, i| %>
43
- <li id="cluster_label<%= i %>"><%= link_to suggestion.query, @results.path_for(suggestion.query) %></li>
44
- <% end %>
45
- </ul>
46
- </div>
47
- <% end %>
48
-
49
- <% if @results.previous_page? %><%= link_to h("< Back"), @results.previous_page_path %>
50
- <% end %>
51
- <% @results.pages.each do |p| %>
52
- <%= link_to_unless @results.current_page?(p), p, @results.page_path(p) %>
53
- <% end %>
54
- <% if @results.next_page? %><%= link_to h("Next >"), @results.next_page_path %>
29
+ <% if @results.previous_page? %><%= link_to h("< Back"), @results.previous_page_path %><% end %>
30
+ <% @results.pages.each do |p| %>
31
+ <%= link_to_unless @results.current_page?(p), p, @results.page_path(p) %>
55
32
  <% end %>
33
+ <% if @results.next_page? %><%= link_to h("Next >"), @results.next_page_path %><% end %>
@@ -0,0 +1,35 @@
1
+ # -*- encoding: utf-8 -*-
2
+ $:.push File.expand_path("../lib", __FILE__)
3
+ require "bcms_google_mini_search/version"
4
+
5
+ Gem::Specification.new do |s|
6
+ s.name = "bcms_google_mini_search"
7
+ s.version = BcmsGoogleMiniSearch::VERSION
8
+ s.authors = ["BrowserMedia"]
9
+ s.email = %q{github@browsermedia.com}
10
+ s.homepage = %q{http://github.com/browsermedia/bcms_google_mini_search}
11
+ s.description = %q{A Google Appliance modules for BrowserCMS. Used to display search results from a Google Mini/Search Appliance on a site.}
12
+ s.summary = %q{A Google Mini Search Module for BrowserCMS}
13
+ s.extra_rdoc_files = [
14
+ "README.markdown"
15
+ ]
16
+ s.rdoc_options = ["--charset=UTF-8"]
17
+
18
+ s.rubyforge_project = "bcms_google_mini_search"
19
+
20
+ s.files = `git ls-files`.split("\n")
21
+ # Exclude files required for the 'dummy' Rails app
22
+ s.files -= Dir['config/**/*', 'public/**/*', 'config.ru', 'db/**/*', 'script/**/*',
23
+ 'app/controllers/application_controller.rb',
24
+ 'app/helpers/application_helper.rb',
25
+ 'app/layouts/templates/**/*'
26
+
27
+ ]
28
+ s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
29
+ s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
30
+ s.require_paths = ["lib"]
31
+
32
+ s.add_dependency(%q<browsercms>, ["~> 3.3.0"])
33
+ end
34
+
35
+
@@ -0,0 +1,2 @@
1
+ Use this README file to introduce your application and point to useful places in the API for learning more.
2
+ Run "rake doc:app" to generate API documentation for your models, controllers, helpers, and libraries.
@@ -1,3 +1,2 @@
1
- require 'rexml/document'
1
+ require 'bcms_google_mini_search/engine'
2
2
  require 'bcms_google_mini_search/routes'
3
- require 'bcms_google_mini_search/gsa'
@@ -0,0 +1,7 @@
1
+ require 'browsercms'
2
+
3
+ module BcmsGoogleMiniSearch
4
+ class Engine < Rails::Engine
5
+ include Cms::Module
6
+ end
7
+ end
@@ -1,7 +1,7 @@
1
1
  module Cms::Routes
2
2
  def routes_for_bcms_google_mini_search
3
- namespace(:cms) do |cms|
4
- #cms.content_blocks :google_mini_searches
5
- end
3
+ namespace(:cms) do
4
+ #content_blocks :news_articles
5
+ end
6
6
  end
7
7
  end
@@ -0,0 +1,3 @@
1
+ module BcmsGoogleMiniSearch
2
+ VERSION = "1.3.0"
3
+ end
@@ -0,0 +1,10 @@
1
+ Description:
2
+ Installs the bcms_google_mini_search module.
3
+
4
+ Example:
5
+ rails generate bcms_google_mini_search:install
6
+
7
+ This will:
8
+ 1. Copy any migrations from the gem into the project.
9
+ 2. Add the routes to the config/routes.rb
10
+
@@ -0,0 +1,9 @@
1
+ require 'cms/module_installation'
2
+
3
+ class BcmsGoogleMiniSearch::InstallGenerator < Cms::ModuleInstallation
4
+ add_migrations_directory_to_source_root __FILE__
5
+
6
+ # Add migrations to be copied, by uncommenting the following file and editing as needed.
7
+ # copy_migration_file 'DATESTAMP_create_name_of_content_block.rb'
8
+
9
+ end
File without changes
File without changes
@@ -0,0 +1,9 @@
1
+ require 'test_helper'
2
+ require 'rails/performance_test_help'
3
+
4
+ # Profiling results for each test method are written to tmp/performance.
5
+ class BrowsingTest < ActionDispatch::PerformanceTest
6
+ def test_homepage
7
+ get '/'
8
+ end
9
+ end
@@ -0,0 +1,18 @@
1
+ ENV["RAILS_ENV"] = "test"
2
+ require File.expand_path('../../config/environment', __FILE__)
3
+ # require 'test/unit'
4
+ require 'rails/test_help'
5
+
6
+ require "rexml/document"
7
+
8
+ class ActiveSupport::TestCase
9
+ # Setup all fixtures in test/fixtures/*.(yml|csv) for all tests in alphabetical order.
10
+ #
11
+ # Note: You'll currently still have to declare fixtures explicitly in integration tests
12
+ # -- they do not yet inherit this setting
13
+ fixtures :all
14
+
15
+ # Add more helper methods to be used by all tests here...
16
+ end
17
+ require 'mocha'
18
+
@@ -0,0 +1,4 @@
1
+ require 'test_helper'
2
+
3
+ class SearchEngineHelperTest < ActionView::TestCase
4
+ end
@@ -0,0 +1,15 @@
1
+ require 'test_helper'
2
+
3
+ class GoogleMiniSearchEngineTest < ActiveSupport::TestCase
4
+
5
+ test "Should be able to create new instance of a portlet" do
6
+ assert GoogleMiniSearchEnginePortlet.create!(:name => "New Portlet")
7
+ end
8
+
9
+
10
+
11
+ test "Path attribute can be set in constructor" do
12
+ portlet = GoogleMiniSearchEnginePortlet.create!(:name=>"Engine", :path => "/engine")
13
+ assert_equal "/engine", portlet.path
14
+ end
15
+ end
@@ -0,0 +1,9 @@
1
+ require 'test_helper'
2
+
3
+ class SearchBoxTest < ActiveSupport::TestCase
4
+
5
+ test "Should be able to create new instance of a portlet" do
6
+ assert SearchBoxPortlet.create!(:name => "New Portlet")
7
+ end
8
+
9
+ end
@@ -0,0 +1,474 @@
1
+ require 'test_helper'
2
+
3
+ class SearchResultTest < ActiveSupport::TestCase
4
+
5
+ def setup
6
+ @xml_string = <<EOF
7
+ <GSP>
8
+ <RES>
9
+ <M>2</M>
10
+ <R N="1">
11
+ <U>http://someurl.com</U>
12
+ <T>TITLE</T>
13
+ <S>BLURB</S>
14
+ <HAS>
15
+ <C SZ="1k" />
16
+ </HAS>
17
+ </R>
18
+ <R N="2">
19
+ <U>http://someurl2.com</U>
20
+ <T>TITLE 2</T>
21
+ <S>BLURB 2</S>
22
+ <HAS>
23
+ <C SZ="2k"/>
24
+ </HAS>
25
+ </R>
26
+ </RES>
27
+ </GSP>
28
+ EOF
29
+ @xml_doc = REXML::Document.new @xml_string
30
+
31
+ @large_results_set = <<EOF
32
+ <GSP>
33
+ <RES>
34
+ <M>35</M>
35
+ <R N="1">
36
+ <U>http://someurl.com</U>
37
+ <T>TITLE</T>
38
+ <S>BLURB</S>
39
+ <HAS>
40
+ <C SZ="1k" />
41
+ </HAS>
42
+ </R>
43
+ <R N="2">
44
+ <U>http://someurl2.com</U>
45
+ <T>TITLE 2</T>
46
+ <S>BLURB 2</S>
47
+ <HAS>
48
+ <C SZ="2k"/>
49
+ </HAS>
50
+ </R>
51
+ </RES>
52
+ </GSP>
53
+ EOF
54
+ @large_xml_doc = REXML::Document.new(@large_results_set)
55
+
56
+ end
57
+
58
+ test "fetch_xml_doc should download and parse the xml results from the GSA" do
59
+ SearchResult.expects(:build_mini_url).returns("http://example.com")
60
+ REXML::Document.expects(:new).returns("EXPECTED_RESULTS")
61
+ assert_equal "EXPECTED_RESULTS", SearchResult.fetch_xml_doc("")
62
+ end
63
+
64
+ test "Parse result count from google mini results xml." do
65
+
66
+ xml = <<EOF
67
+ <GSP>
68
+ <RES>
69
+ <M>35</M>
70
+ </RES>
71
+ </GSP>
72
+ EOF
73
+ empty_doc = REXML::Document.new xml
74
+ assert_equal 35, SearchResult.parse_results_count(empty_doc)
75
+ assert_equal 35, SearchResult.parse_xml(empty_doc).results_count
76
+ assert_equal 4, SearchResult.parse_xml(empty_doc).num_pages
77
+
78
+ end
79
+
80
+ test "Default result count is zero." do
81
+
82
+ xml = <<EOF
83
+ <GSP>
84
+ <RES>
85
+ </RES>
86
+ </GSP>
87
+ EOF
88
+ empty_doc = REXML::Document.new xml
89
+ assert_equal 0, SearchResult.parse_results_count(empty_doc)
90
+
91
+ end
92
+
93
+ test "Empty xml gives empty results" do
94
+ xml = <<EOF
95
+ <GSP>
96
+ <RES>
97
+ </RES>
98
+ </GSP>
99
+ EOF
100
+ empty_doc = REXML::Document.new xml
101
+ SearchResult.expects(:fetch_xml_doc).with("therapy", {}).returns(empty_doc)
102
+
103
+ assert_equal [], SearchResult.find("therapy", {})
104
+ end
105
+
106
+ test "Parse result set" do
107
+
108
+ results = SearchResult.parse_hits(@xml_doc)
109
+ assert_equal 2, results.size
110
+
111
+ assert_equal "1", results[0].number
112
+ assert_equal "http://someurl.com", results[0].url
113
+ assert_equal "TITLE", results[0].title
114
+ assert_equal "BLURB", results[0].description
115
+ assert_equal "1k", results[0].size
116
+
117
+ assert_equal "2", results[1].number
118
+ assert_equal "http://someurl2.com", results[1].url
119
+ assert_equal "TITLE 2", results[1].title
120
+ assert_equal "BLURB 2", results[1].description
121
+ assert_equal "2k", results[1].size
122
+ end
123
+
124
+
125
+ test "Calculates the results pages" do
126
+ assert_equal 1, SearchResult.calculate_results_pages(9)
127
+ assert_equal 1, SearchResult.calculate_results_pages(10)
128
+ assert_equal 2, SearchResult.calculate_results_pages(19)
129
+ assert_equal 2, SearchResult.calculate_results_pages(20)
130
+ assert_equal 3, SearchResult.calculate_results_pages(21)
131
+ assert_equal 4, SearchResult.calculate_results_pages(40)
132
+ assert_equal 0, SearchResult.calculate_results_pages(0)
133
+
134
+ end
135
+
136
+ test "Calculates current page based on total results and start" do
137
+ results = SearchResult::QueryResult.new
138
+ results.start = 0
139
+ assert_equal 1, results.current_page
140
+
141
+ results.start = 10
142
+ assert_equal 2, results.current_page
143
+
144
+ results.start = 20
145
+ assert_equal 3, results.current_page
146
+
147
+ results.start = 30
148
+ assert_equal 4, results.current_page
149
+ end
150
+
151
+ test "Next start" do
152
+ r = SearchResult::QueryResult.new
153
+ r.start = 0
154
+ assert_equal 10, r.next_start
155
+ r.start = 10
156
+ assert_equal 20, r.next_start
157
+ r.start = 20
158
+ assert_equal 30, r.next_start
159
+ end
160
+
161
+ test "Find results should return a paging list of documents with no start" do
162
+ SearchResult.expects(:fetch_xml_doc).with("therapy", {}).returns(@large_xml_doc)
163
+
164
+ results = SearchResult.find("therapy")
165
+ assert_equal "therapy", results.query
166
+ assert_equal 35, results.results_count
167
+ assert_equal 4, results.num_pages
168
+ assert_equal 0, results.start
169
+ assert_equal 2, results.size
170
+ assert_equal 1, results.current_page
171
+ assert_equal 10, results.next_start
172
+ assert results.next_page?
173
+ assert_equal -10, results.previous_start
174
+ assert_equal false, results.previous_page?
175
+ assert_equal (1..4), results.pages
176
+
177
+ end
178
+
179
+
180
+ test "Find results starts on page 2, if a start is specified" do
181
+ SearchResult.expects(:fetch_xml_doc).with("therapy", :start=>10).returns(@large_xml_doc)
182
+
183
+ results = SearchResult.find("therapy", :start => 10)
184
+ assert_equal 35, results.results_count
185
+ assert_equal 4, results.num_pages
186
+ assert_equal 10, results.start
187
+ assert_equal 2, results.size
188
+ assert_equal 2, results.current_page
189
+ assert_equal 20, results.next_start
190
+ assert results.next_page?
191
+ assert_equal 0, results.previous_start
192
+ assert_equal true, results.previous_page?
193
+ end
194
+
195
+ test "No next start when on the last page" do
196
+ SearchResult.expects(:fetch_xml_doc).with("therapy", {:start => 30}).returns(@large_xml_doc)
197
+
198
+ results = SearchResult.find("therapy", :start => 30)
199
+ assert_equal 40, results.next_start
200
+ assert_equal false, results.next_page?
201
+ assert_equal 20, results.previous_start
202
+ assert_equal true, results.previous_page?
203
+ end
204
+
205
+ test "Should be no previous or next for a single page of results" do
206
+ SearchResult.expects(:fetch_xml_doc).with("therapy", {}).returns(@xml_doc)
207
+
208
+ results = SearchResult.find("therapy")
209
+ assert_equal false, results.next_page?
210
+ assert_equal false, results.previous_page?
211
+ assert_equal [], results.pages
212
+ end
213
+
214
+ test "Behavior of ranges" do
215
+ c = 0
216
+ (1..4).each_with_index do |i, count|
217
+ assert_equal count + 1, i
218
+ c = count
219
+ end
220
+ assert_equal 3, c
221
+ end
222
+
223
+ test "current_page should check to see if the current page matches" do
224
+ results = SearchResult::QueryResult.new
225
+ results.start = 0
226
+
227
+ assert_equal true, results.current_page?(1)
228
+ assert_equal false, results.current_page?(2)
229
+ assert_equal false, results.current_page?(3)
230
+ assert_equal false, results.current_page?(4)
231
+
232
+ end
233
+
234
+ test "Path to next page" do
235
+ results = SearchResult::QueryResult.new
236
+ results.start = 0
237
+ results.path = "/search/search-results"
238
+ results.query = "X"
239
+
240
+ assert_equal "/search/search-results?query=X&start=10", results.next_page_path
241
+ end
242
+
243
+ test "Path to previous page" do
244
+ results = SearchResult::QueryResult.new
245
+ results.start = 20
246
+ results.path = "/search/search-results"
247
+ results.query = "X"
248
+
249
+ assert_equal "/search/search-results?query=X&start=10", results.previous_page_path
250
+ end
251
+
252
+ test "Sets path to default search-results" do
253
+ results = SearchResult::QueryResult.new
254
+ assert_equal "/search/search-results", results.path
255
+ end
256
+
257
+ test "Setting path overrides the defaults" do
258
+ results = SearchResult::QueryResult.new
259
+ results.path = "/other"
260
+ assert_equal "/other", results.path
261
+ end
262
+
263
+ test "page_path" do
264
+ results = SearchResult::QueryResult.new
265
+ results.query = "X"
266
+
267
+ assert_equal "/search/search-results?query=X&start=0", results.page_path(1)
268
+ assert_equal "/search/search-results?query=X&start=10", results.page_path(2)
269
+ assert_equal "/search/search-results?query=X&start=20", results.page_path(3)
270
+ assert_equal "/search/search-results?query=X&start=30", results.page_path(4)
271
+
272
+ end
273
+
274
+ test "Portlet attributes are used to look up path" do
275
+ portlet = GoogleMiniSearchEnginePortlet.new(:name=>"Engine", :path => "/engine")
276
+ SearchResult.expects(:fetch_xml_doc).with("therapy", {:portlet=> portlet}).returns(@xml_doc)
277
+
278
+ results = SearchResult.find("therapy", {:portlet=> portlet})
279
+
280
+ assert_equal "/engine", results.path
281
+ end
282
+
283
+ test "Default path is used if no portlet specified" do
284
+ SearchResult.expects(:fetch_xml_doc).with("therapy", {}).returns(@xml_doc)
285
+ results = SearchResult.find("therapy", {})
286
+ assert_equal "/search/search-results", results.path
287
+ end
288
+
289
+ test "Uses service URL from portlet" do
290
+ portlet = GoogleMiniSearchEnginePortlet.new(
291
+ :name=>"Engine", :path => "/engine", :service_url => "http://mini.someurl.com",
292
+ :collection_name => "COLLECT", :front_end_name => "FRONT_END")
293
+
294
+ url = SearchResult.build_mini_url({:portlet => portlet}, "STUFF")
295
+ assert_equal "http://mini.someurl.com/search?q=STUFF&output=xml_no_dtd&client=FRONT_END&site=COLLECT&filter=0", url
296
+
297
+ url = SearchResult.build_mini_url({:portlet => portlet, :start=>100}, "STUFF")
298
+ assert_equal "http://mini.someurl.com/search?q=STUFF&output=xml_no_dtd&client=FRONT_END&site=COLLECT&filter=0&start=100", url
299
+
300
+ end
301
+
302
+ test "Explicitly passing a collection in will query with that rather than a default collection" do
303
+ portlet = GoogleMiniSearchEnginePortlet.new(
304
+ :name=>"Engine", :path => "/engine", :service_url => "http://mini.someurl.com",
305
+ :collection_name => "COLLECT", :front_end_name => "FRONT_END")
306
+
307
+ url = SearchResult.build_mini_url({:portlet => portlet, :site=>"ANOTHER_COLLECTION"}, "STUFF")
308
+ assert_equal "http://mini.someurl.com/search?q=STUFF&output=xml_no_dtd&client=FRONT_END&site=ANOTHER_COLLECTION&filter=0", url
309
+ end
310
+
311
+ test "Handles multiword queries" do
312
+ url = SearchResult.build_mini_url({}, "One Two")
313
+ assert_equal "/search?q=One+Two&output=xml_no_dtd&client=&site=&filter=0", url
314
+ end
315
+
316
+ test "Handles keymatches in results" do
317
+ @xml_with_keymatches = <<XML
318
+ <GSP>
319
+ <GM>
320
+ <GL>http://url1.org</GL>
321
+ <GD>URL 1</GD>
322
+ </GM>
323
+ <GM>
324
+ <GL>http://url2.org</GL>
325
+ <GD>URL 2</GD>
326
+ </GM>
327
+ <RES>
328
+ <M>35</M>
329
+ <R N="1">
330
+ <U>http://someurl.com</U>
331
+ <T>TITLE</T>
332
+ <S>BLURB</S>
333
+ <HAS>
334
+ <C SZ="1k" />
335
+ </HAS>
336
+ </R>
337
+ <R N="2">
338
+ <U>http://someurl2.com</U>
339
+ <T>TITLE 2</T>
340
+ <S>BLURB 2</S>
341
+ <HAS>
342
+ <C SZ="2k"/>
343
+ </HAS>
344
+ </R>
345
+ </RES>
346
+ </GSP>
347
+ XML
348
+ @results_with_keymatches = REXML::Document.new @xml_with_keymatches
349
+
350
+ result = SearchResult.parse_xml @results_with_keymatches
351
+
352
+ assert_equal true, result.key_matches?
353
+ assert_equal 2, result.key_matches.size
354
+ assert_equal "http://url1.org", result.key_matches[0].url
355
+ assert_equal "URL 1", result.key_matches[0].title
356
+ assert_equal "http://url2.org", result.key_matches[1].url
357
+ assert_equal "URL 2", result.key_matches[1].title
358
+ end
359
+
360
+ test "Handles results with no keymatches" do
361
+ result = SearchResult.parse_xml @xml_doc
362
+ assert_equal false, result.key_matches?
363
+ end
364
+
365
+ test "Handle Synonyms / Related Queries" do
366
+ xml_with_synonyms = <<XML
367
+ <GSP>
368
+ <Synonyms>
369
+ <OneSynonym q="Query 1">Label 1</OneSynonym>
370
+ <OneSynonym q="Query 2">Label 2</OneSynonym>
371
+ </Synonyms>
372
+ <RES>
373
+ <M>35</M>
374
+ <R N="1">
375
+ <U>http://someurl.com</U>
376
+ <T>TITLE</T>
377
+ <S>BLURB</S>
378
+ <HAS>
379
+ <C SZ="1k" />
380
+ </HAS>
381
+ </R>
382
+ <R N="2">
383
+ <U>http://someurl2.com</U>
384
+ <T>TITLE 2</T>
385
+ <S>BLURB 2</S>
386
+ <HAS>
387
+ <C SZ="2k"/>
388
+ </HAS>
389
+ </R>
390
+ </RES>
391
+ </GSP>
392
+ XML
393
+ xml_doc_with_synonyms = REXML::Document.new xml_with_synonyms
394
+
395
+ result = SearchResult.parse_xml xml_doc_with_synonyms
396
+
397
+ result.expects(:path).returns("/search").twice
398
+ assert_equal true, result.synonyms?
399
+ assert_equal 2, result.synonyms.size
400
+ assert_equal "Label 1", result.synonyms[0].label
401
+ assert_equal "Query 1", result.synonyms[0].query
402
+ assert_equal "/search?query=Query 1", result.synonyms[0].url
403
+ assert_equal "Label 2", result.synonyms[1].label
404
+ assert_equal "Query 2", result.synonyms[1].query
405
+ assert_equal "/search?query=Query 2", result.synonyms[1].url
406
+
407
+ end
408
+
409
+ test "Handles results with no Synonyms" do
410
+ result = SearchResult.parse_xml @xml_doc
411
+ assert_equal false, result.synonyms?
412
+ end
413
+
414
+ test "Calculate URL for Related Queries/Synonyms" do
415
+ syn = SearchResult::Synonym.new
416
+ syn.query = "Testing"
417
+ mock_result = mock()
418
+ mock_result.expects(:path).returns("/random")
419
+ syn.query_result = mock_result
420
+ assert_equal "/random?query=Testing", syn.url
421
+ end
422
+
423
+ test "No query = empty results" do
424
+ result = SearchResult.find(nil)
425
+ assert_equal 0, result.size
426
+ assert_equal 0, result.start
427
+ assert_equal false, result.next_page?
428
+ assert_equal false, result.previous_page?
429
+ assert_equal false, result.key_matches?
430
+ assert_equal false, result.synonyms?
431
+ assert_equal [], result.pages
432
+ end
433
+
434
+ test "Search results for PDF's that have no size" do
435
+ pdf_results = <<EOF
436
+ <GSP>
437
+ <RES>
438
+ <M>35</M>
439
+ <R N="1">
440
+ <U>http://someurl.com</U>
441
+ <T>TITLE</T>
442
+ <S>BLURB</S>
443
+ <HAS>
444
+ <C SZ="1k" />
445
+ </HAS>
446
+ </R>
447
+ <R N="2">
448
+ <U>http://someurl2.com</U>
449
+ <T>TITLE 2</T>
450
+ <S>BLURB 2</S>
451
+ <HAS>
452
+ <L/>
453
+ </HAS>
454
+ </R>
455
+ </RES>
456
+ </GSP>
457
+ EOF
458
+ xml_doc = REXML::Document.new(pdf_results)
459
+ results = SearchResult.parse_xml xml_doc
460
+ assert_equal 2, results.size
461
+
462
+ assert_equal "1", results[0].number
463
+ assert_equal "http://someurl.com", results[0].url
464
+ assert_equal "TITLE", results[0].title
465
+ assert_equal "BLURB", results[0].description
466
+ assert_equal "1k", results[0].size
467
+
468
+ assert_equal "2", results[1].number
469
+ assert_equal "http://someurl2.com", results[1].url
470
+ assert_equal "TITLE 2", results[1].title
471
+ assert_equal "BLURB 2", results[1].description
472
+ assert_equal "", results[1].size
473
+ end
474
+ end