bcms_google_mini_search 1.2.2 → 1.3.0

Sign up to get free protection for your applications and to get access to all the features.
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