@@ -1,52 +1,52 | |||||
1 | <h2><%= l(:label_search) %></h2> |
|
1 | <h2><%= l(:label_search) %></h2> | |
2 |
|
2 | |||
3 | <div class="box"> |
|
3 | <div class="box"> | |
4 | <%= form_tag({}, :method => :get) do %> |
|
4 | <%= form_tag({}, :method => :get) do %> | |
5 | <%= label_tag "search-input", l(:description_search), :class => "hidden-for-sighted" %> |
|
5 | <%= label_tag "search-input", l(:description_search), :class => "hidden-for-sighted" %> | |
6 | <p><%= text_field_tag 'q', @question, :size => 60, :id => 'search-input' %> |
|
6 | <p><%= text_field_tag 'q', @question, :size => 60, :id => 'search-input' %> | |
7 | <%= javascript_tag "$('#search-input').focus()" %> |
|
7 | <%= javascript_tag "$('#search-input').focus()" %> | |
8 | <%= project_select_tag %> |
|
8 | <%= project_select_tag %> | |
9 | <%= hidden_field_tag 'all_words', '', :id => nil %> |
|
9 | <%= hidden_field_tag 'all_words', '', :id => nil %> | |
10 | <label><%= check_box_tag 'all_words', 1, @all_words %> <%= l(:label_all_words) %></label> |
|
10 | <label><%= check_box_tag 'all_words', 1, @all_words %> <%= l(:label_all_words) %></label> | |
11 | <%= hidden_field_tag 'titles_only', '', :id => nil %> |
|
11 | <%= hidden_field_tag 'titles_only', '', :id => nil %> | |
12 | <label><%= check_box_tag 'titles_only', 1, @titles_only %> <%= l(:label_search_titles_only) %></label> |
|
12 | <label><%= check_box_tag 'titles_only', 1, @titles_only %> <%= l(:label_search_titles_only) %></label> | |
13 | </p> |
|
13 | </p> | |
14 | <p> |
|
14 | <p> | |
15 | <% @object_types.each do |t| %> |
|
15 | <% @object_types.each do |t| %> | |
16 | <label><%= check_box_tag t, 1, @scope.include?(t) %> <%= type_label(t) %></label> |
|
16 | <label><%= check_box_tag t, 1, @scope.include?(t) %> <%= type_label(t) %></label> | |
17 | <% end %> |
|
17 | <% end %> | |
18 | </p> |
|
18 | </p> | |
19 |
|
19 | |||
20 | <p><%= submit_tag l(:button_submit), :name => 'submit' %></p> |
|
20 | <p><%= submit_tag l(:button_submit), :name => 'submit' %></p> | |
21 | <% end %> |
|
21 | <% end %> | |
22 | </div> |
|
22 | </div> | |
23 |
|
23 | |||
24 | <% if @results %> |
|
24 | <% if @results %> | |
25 | <div id="search-results-counts"> |
|
25 | <div id="search-results-counts"> | |
26 | <%= render_results_by_type(@results_by_type) unless @scope.size == 1 %> |
|
26 | <%= render_results_by_type(@results_by_type) unless @scope.size == 1 %> | |
27 | </div> |
|
27 | </div> | |
28 |
|
28 | |||
29 | <h3><%= l(:label_result_plural) %> (<%= @results_by_type.values.sum %>)</h3> |
|
29 | <h3><%= l(:label_result_plural) %> (<%= @results_by_type.values.sum %>)</h3> | |
30 | <dl id="search-results"> |
|
30 | <dl id="search-results"> | |
31 | <% @results.each do |e| %> |
|
31 | <% @results.each do |e| %> | |
32 |
<dt class="<%= e.event_type %>"><%= content_tag('span', h(e.project), :class => 'project') unless @project == e.project %> <%= link_to highlight_tokens(truncate( |
|
32 | <dt class="<%= e.event_type %>"><%= content_tag('span', h(e.project), :class => 'project') unless @project == e.project %> <%= link_to highlight_tokens(truncate(e.event_title, :length => 255), @tokens), e.event_url %></dt> | |
33 |
<dd><span class="description"><%= highlight_tokens( |
|
33 | <dd><span class="description"><%= highlight_tokens(e.event_description, @tokens) %></span> | |
34 | <span class="author"><%= format_time(e.event_datetime) %></span></dd> |
|
34 | <span class="author"><%= format_time(e.event_datetime) %></span></dd> | |
35 | <% end %> |
|
35 | <% end %> | |
36 | </dl> |
|
36 | </dl> | |
37 | <% end %> |
|
37 | <% end %> | |
38 |
|
38 | |||
39 | <p><center> |
|
39 | <p><center> | |
40 | <% if @pagination_previous_date %> |
|
40 | <% if @pagination_previous_date %> | |
41 | <%= link_to_content_update("\xc2\xab " + l(:label_previous), |
|
41 | <%= link_to_content_update("\xc2\xab " + l(:label_previous), | |
42 | params.merge(:previous => 1, |
|
42 | params.merge(:previous => 1, | |
43 | :offset => @pagination_previous_date.strftime("%Y%m%d%H%M%S"))) %> |
|
43 | :offset => @pagination_previous_date.strftime("%Y%m%d%H%M%S"))) %> | |
44 | <% end %> |
|
44 | <% end %> | |
45 | <% if @pagination_next_date %> |
|
45 | <% if @pagination_next_date %> | |
46 | <%= link_to_content_update(l(:label_next) + " \xc2\xbb", |
|
46 | <%= link_to_content_update(l(:label_next) + " \xc2\xbb", | |
47 | params.merge(:previous => nil, |
|
47 | params.merge(:previous => nil, | |
48 | :offset => @pagination_next_date.strftime("%Y%m%d%H%M%S"))) %> |
|
48 | :offset => @pagination_next_date.strftime("%Y%m%d%H%M%S"))) %> | |
49 | <% end %> |
|
49 | <% end %> | |
50 | </center></p> |
|
50 | </center></p> | |
51 |
|
51 | |||
52 | <% html_title(l(:label_search)) -%> |
|
52 | <% html_title(l(:label_search)) -%> |
@@ -1,202 +1,222 | |||||
1 | require File.expand_path('../../test_helper', __FILE__) |
|
1 | require File.expand_path('../../test_helper', __FILE__) | |
2 | require 'search_controller' |
|
2 | require 'search_controller' | |
3 |
|
3 | |||
4 | # Re-raise errors caught by the controller. |
|
4 | # Re-raise errors caught by the controller. | |
5 | class SearchController; def rescue_action(e) raise e end; end |
|
5 | class SearchController; def rescue_action(e) raise e end; end | |
6 |
|
6 | |||
7 | class SearchControllerTest < ActionController::TestCase |
|
7 | class SearchControllerTest < ActionController::TestCase | |
8 | fixtures :projects, :enabled_modules, :roles, :users, :members, :member_roles, |
|
8 | fixtures :projects, :enabled_modules, :roles, :users, :members, :member_roles, | |
9 | :issues, :trackers, :issue_statuses, |
|
9 | :issues, :trackers, :issue_statuses, | |
10 | :custom_fields, :custom_values, |
|
10 | :custom_fields, :custom_values, | |
11 | :repositories, :changesets |
|
11 | :repositories, :changesets | |
12 |
|
12 | |||
13 | def setup |
|
13 | def setup | |
14 | @controller = SearchController.new |
|
14 | @controller = SearchController.new | |
15 | @request = ActionController::TestRequest.new |
|
15 | @request = ActionController::TestRequest.new | |
16 | @response = ActionController::TestResponse.new |
|
16 | @response = ActionController::TestResponse.new | |
17 | User.current = nil |
|
17 | User.current = nil | |
18 | end |
|
18 | end | |
19 |
|
19 | |||
20 | def test_search_for_projects |
|
20 | def test_search_for_projects | |
21 | get :index |
|
21 | get :index | |
22 | assert_response :success |
|
22 | assert_response :success | |
23 | assert_template 'index' |
|
23 | assert_template 'index' | |
24 |
|
24 | |||
25 | get :index, :q => "cook" |
|
25 | get :index, :q => "cook" | |
26 | assert_response :success |
|
26 | assert_response :success | |
27 | assert_template 'index' |
|
27 | assert_template 'index' | |
28 | assert assigns(:results).include?(Project.find(1)) |
|
28 | assert assigns(:results).include?(Project.find(1)) | |
29 | end |
|
29 | end | |
30 |
|
30 | |||
31 | def test_search_all_projects |
|
31 | def test_search_all_projects | |
32 | get :index, :q => 'recipe subproject commit', :all_words => '' |
|
32 | get :index, :q => 'recipe subproject commit', :all_words => '' | |
33 | assert_response :success |
|
33 | assert_response :success | |
34 | assert_template 'index' |
|
34 | assert_template 'index' | |
35 |
|
35 | |||
36 | assert assigns(:results).include?(Issue.find(2)) |
|
36 | assert assigns(:results).include?(Issue.find(2)) | |
37 | assert assigns(:results).include?(Issue.find(5)) |
|
37 | assert assigns(:results).include?(Issue.find(5)) | |
38 | assert assigns(:results).include?(Changeset.find(101)) |
|
38 | assert assigns(:results).include?(Changeset.find(101)) | |
39 | assert_tag :dt, :attributes => { :class => /issue/ }, |
|
39 | assert_tag :dt, :attributes => { :class => /issue/ }, | |
40 | :child => { :tag => 'a', :content => /Add ingredients categories/ }, |
|
40 | :child => { :tag => 'a', :content => /Add ingredients categories/ }, | |
41 | :sibling => { :tag => 'dd', :content => /should be classified by categories/ } |
|
41 | :sibling => { :tag => 'dd', :content => /should be classified by categories/ } | |
42 |
|
42 | |||
43 | assert assigns(:results_by_type).is_a?(Hash) |
|
43 | assert assigns(:results_by_type).is_a?(Hash) | |
44 | assert_equal 5, assigns(:results_by_type)['changesets'] |
|
44 | assert_equal 5, assigns(:results_by_type)['changesets'] | |
45 | assert_tag :a, :content => 'Changesets (5)' |
|
45 | assert_tag :a, :content => 'Changesets (5)' | |
46 | end |
|
46 | end | |
47 |
|
47 | |||
48 | def test_search_issues |
|
48 | def test_search_issues | |
49 | get :index, :q => 'issue', :issues => 1 |
|
49 | get :index, :q => 'issue', :issues => 1 | |
50 | assert_response :success |
|
50 | assert_response :success | |
51 | assert_template 'index' |
|
51 | assert_template 'index' | |
52 |
|
52 | |||
53 | assert_equal true, assigns(:all_words) |
|
53 | assert_equal true, assigns(:all_words) | |
54 | assert_equal false, assigns(:titles_only) |
|
54 | assert_equal false, assigns(:titles_only) | |
55 | assert assigns(:results).include?(Issue.find(8)) |
|
55 | assert assigns(:results).include?(Issue.find(8)) | |
56 | assert assigns(:results).include?(Issue.find(5)) |
|
56 | assert assigns(:results).include?(Issue.find(5)) | |
57 | assert_tag :dt, :attributes => { :class => /issue closed/ }, |
|
57 | assert_tag :dt, :attributes => { :class => /issue closed/ }, | |
58 | :child => { :tag => 'a', :content => /Closed/ } |
|
58 | :child => { :tag => 'a', :content => /Closed/ } | |
59 | end |
|
59 | end | |
60 |
|
60 | |||
61 | def test_search_all_projects_with_scope_param |
|
61 | def test_search_all_projects_with_scope_param | |
62 | get :index, :q => 'issue', :scope => 'all' |
|
62 | get :index, :q => 'issue', :scope => 'all' | |
63 | assert_response :success |
|
63 | assert_response :success | |
64 | assert_template 'index' |
|
64 | assert_template 'index' | |
65 | assert assigns(:results).present? |
|
65 | assert assigns(:results).present? | |
66 | end |
|
66 | end | |
67 |
|
67 | |||
68 | def test_search_my_projects |
|
68 | def test_search_my_projects | |
69 | @request.session[:user_id] = 2 |
|
69 | @request.session[:user_id] = 2 | |
70 | get :index, :id => 1, :q => 'recipe subproject', :scope => 'my_projects', :all_words => '' |
|
70 | get :index, :id => 1, :q => 'recipe subproject', :scope => 'my_projects', :all_words => '' | |
71 | assert_response :success |
|
71 | assert_response :success | |
72 | assert_template 'index' |
|
72 | assert_template 'index' | |
73 | assert assigns(:results).include?(Issue.find(1)) |
|
73 | assert assigns(:results).include?(Issue.find(1)) | |
74 | assert !assigns(:results).include?(Issue.find(5)) |
|
74 | assert !assigns(:results).include?(Issue.find(5)) | |
75 | end |
|
75 | end | |
76 |
|
76 | |||
77 | def test_search_my_projects_without_memberships |
|
77 | def test_search_my_projects_without_memberships | |
78 | # anonymous user has no memberships |
|
78 | # anonymous user has no memberships | |
79 | get :index, :id => 1, :q => 'recipe subproject', :scope => 'my_projects', :all_words => '' |
|
79 | get :index, :id => 1, :q => 'recipe subproject', :scope => 'my_projects', :all_words => '' | |
80 | assert_response :success |
|
80 | assert_response :success | |
81 | assert_template 'index' |
|
81 | assert_template 'index' | |
82 | assert assigns(:results).empty? |
|
82 | assert assigns(:results).empty? | |
83 | end |
|
83 | end | |
84 |
|
84 | |||
85 | def test_search_project_and_subprojects |
|
85 | def test_search_project_and_subprojects | |
86 | get :index, :id => 1, :q => 'recipe subproject', :scope => 'subprojects', :all_words => '' |
|
86 | get :index, :id => 1, :q => 'recipe subproject', :scope => 'subprojects', :all_words => '' | |
87 | assert_response :success |
|
87 | assert_response :success | |
88 | assert_template 'index' |
|
88 | assert_template 'index' | |
89 | assert assigns(:results).include?(Issue.find(1)) |
|
89 | assert assigns(:results).include?(Issue.find(1)) | |
90 | assert assigns(:results).include?(Issue.find(5)) |
|
90 | assert assigns(:results).include?(Issue.find(5)) | |
91 | end |
|
91 | end | |
92 |
|
92 | |||
93 | def test_search_without_searchable_custom_fields |
|
93 | def test_search_without_searchable_custom_fields | |
94 | CustomField.update_all "searchable = #{ActiveRecord::Base.connection.quoted_false}" |
|
94 | CustomField.update_all "searchable = #{ActiveRecord::Base.connection.quoted_false}" | |
95 |
|
95 | |||
96 | get :index, :id => 1 |
|
96 | get :index, :id => 1 | |
97 | assert_response :success |
|
97 | assert_response :success | |
98 | assert_template 'index' |
|
98 | assert_template 'index' | |
99 | assert_not_nil assigns(:project) |
|
99 | assert_not_nil assigns(:project) | |
100 |
|
100 | |||
101 | get :index, :id => 1, :q => "can" |
|
101 | get :index, :id => 1, :q => "can" | |
102 | assert_response :success |
|
102 | assert_response :success | |
103 | assert_template 'index' |
|
103 | assert_template 'index' | |
104 | end |
|
104 | end | |
105 |
|
105 | |||
106 | def test_search_with_searchable_custom_fields |
|
106 | def test_search_with_searchable_custom_fields | |
107 | get :index, :id => 1, :q => "stringforcustomfield" |
|
107 | get :index, :id => 1, :q => "stringforcustomfield" | |
108 | assert_response :success |
|
108 | assert_response :success | |
109 | results = assigns(:results) |
|
109 | results = assigns(:results) | |
110 | assert_not_nil results |
|
110 | assert_not_nil results | |
111 | assert_equal 1, results.size |
|
111 | assert_equal 1, results.size | |
112 | assert results.include?(Issue.find(7)) |
|
112 | assert results.include?(Issue.find(7)) | |
113 | end |
|
113 | end | |
114 |
|
114 | |||
115 | def test_search_all_words |
|
115 | def test_search_all_words | |
116 | # 'all words' is on by default |
|
116 | # 'all words' is on by default | |
117 | get :index, :id => 1, :q => 'recipe updating saving', :all_words => '1' |
|
117 | get :index, :id => 1, :q => 'recipe updating saving', :all_words => '1' | |
118 | assert_equal true, assigns(:all_words) |
|
118 | assert_equal true, assigns(:all_words) | |
119 | results = assigns(:results) |
|
119 | results = assigns(:results) | |
120 | assert_not_nil results |
|
120 | assert_not_nil results | |
121 | assert_equal 1, results.size |
|
121 | assert_equal 1, results.size | |
122 | assert results.include?(Issue.find(3)) |
|
122 | assert results.include?(Issue.find(3)) | |
123 | end |
|
123 | end | |
124 |
|
124 | |||
125 | def test_search_one_of_the_words |
|
125 | def test_search_one_of_the_words | |
126 | get :index, :id => 1, :q => 'recipe updating saving', :all_words => '' |
|
126 | get :index, :id => 1, :q => 'recipe updating saving', :all_words => '' | |
127 | assert_equal false, assigns(:all_words) |
|
127 | assert_equal false, assigns(:all_words) | |
128 | results = assigns(:results) |
|
128 | results = assigns(:results) | |
129 | assert_not_nil results |
|
129 | assert_not_nil results | |
130 | assert_equal 3, results.size |
|
130 | assert_equal 3, results.size | |
131 | assert results.include?(Issue.find(3)) |
|
131 | assert results.include?(Issue.find(3)) | |
132 | end |
|
132 | end | |
133 |
|
133 | |||
134 | def test_search_titles_only_without_result |
|
134 | def test_search_titles_only_without_result | |
135 | get :index, :id => 1, :q => 'recipe updating saving', :titles_only => '1' |
|
135 | get :index, :id => 1, :q => 'recipe updating saving', :titles_only => '1' | |
136 | results = assigns(:results) |
|
136 | results = assigns(:results) | |
137 | assert_not_nil results |
|
137 | assert_not_nil results | |
138 | assert_equal 0, results.size |
|
138 | assert_equal 0, results.size | |
139 | end |
|
139 | end | |
140 |
|
140 | |||
141 | def test_search_titles_only |
|
141 | def test_search_titles_only | |
142 | get :index, :id => 1, :q => 'recipe', :titles_only => '1' |
|
142 | get :index, :id => 1, :q => 'recipe', :titles_only => '1' | |
143 | assert_equal true, assigns(:titles_only) |
|
143 | assert_equal true, assigns(:titles_only) | |
144 | results = assigns(:results) |
|
144 | results = assigns(:results) | |
145 | assert_not_nil results |
|
145 | assert_not_nil results | |
146 | assert_equal 2, results.size |
|
146 | assert_equal 2, results.size | |
147 | end |
|
147 | end | |
148 |
|
148 | |||
149 | def test_search_content |
|
149 | def test_search_content | |
150 | Issue.update_all("description = 'This is a searchkeywordinthecontent'", "id=1") |
|
150 | Issue.update_all("description = 'This is a searchkeywordinthecontent'", "id=1") | |
151 |
|
151 | |||
152 | get :index, :id => 1, :q => 'searchkeywordinthecontent', :titles_only => '' |
|
152 | get :index, :id => 1, :q => 'searchkeywordinthecontent', :titles_only => '' | |
153 | assert_equal false, assigns(:titles_only) |
|
153 | assert_equal false, assigns(:titles_only) | |
154 | results = assigns(:results) |
|
154 | results = assigns(:results) | |
155 | assert_not_nil results |
|
155 | assert_not_nil results | |
156 | assert_equal 1, results.size |
|
156 | assert_equal 1, results.size | |
157 | end |
|
157 | end | |
158 |
|
158 | |||
159 | def test_search_with_offset |
|
159 | def test_search_with_offset | |
160 | get :index, :q => 'coo', :offset => '20080806073000' |
|
160 | get :index, :q => 'coo', :offset => '20080806073000' | |
161 | assert_response :success |
|
161 | assert_response :success | |
162 | results = assigns(:results) |
|
162 | results = assigns(:results) | |
163 | assert results.any? |
|
163 | assert results.any? | |
164 | assert results.map(&:event_datetime).max < '20080806T073000'.to_time |
|
164 | assert results.map(&:event_datetime).max < '20080806T073000'.to_time | |
165 | end |
|
165 | end | |
166 |
|
166 | |||
167 | def test_search_previous_with_offset |
|
167 | def test_search_previous_with_offset | |
168 | get :index, :q => 'coo', :offset => '20080806073000', :previous => '1' |
|
168 | get :index, :q => 'coo', :offset => '20080806073000', :previous => '1' | |
169 | assert_response :success |
|
169 | assert_response :success | |
170 | results = assigns(:results) |
|
170 | results = assigns(:results) | |
171 | assert results.any? |
|
171 | assert results.any? | |
172 | assert results.map(&:event_datetime).min >= '20080806T073000'.to_time |
|
172 | assert results.map(&:event_datetime).min >= '20080806T073000'.to_time | |
173 | end |
|
173 | end | |
174 |
|
174 | |||
175 | def test_search_with_invalid_project_id |
|
175 | def test_search_with_invalid_project_id | |
176 | get :index, :id => 195, :q => 'recipe' |
|
176 | get :index, :id => 195, :q => 'recipe' | |
177 | assert_response 404 |
|
177 | assert_response 404 | |
178 | assert_nil assigns(:results) |
|
178 | assert_nil assigns(:results) | |
179 | end |
|
179 | end | |
180 |
|
180 | |||
181 | def test_quick_jump_to_issue |
|
181 | def test_quick_jump_to_issue | |
182 | # issue of a public project |
|
182 | # issue of a public project | |
183 | get :index, :q => "3" |
|
183 | get :index, :q => "3" | |
184 | assert_redirected_to '/issues/3' |
|
184 | assert_redirected_to '/issues/3' | |
185 |
|
185 | |||
186 | # issue of a private project |
|
186 | # issue of a private project | |
187 | get :index, :q => "4" |
|
187 | get :index, :q => "4" | |
188 | assert_response :success |
|
188 | assert_response :success | |
189 | assert_template 'index' |
|
189 | assert_template 'index' | |
190 | end |
|
190 | end | |
191 |
|
191 | |||
192 | def test_large_integer |
|
192 | def test_large_integer | |
193 | get :index, :q => '4615713488' |
|
193 | get :index, :q => '4615713488' | |
194 | assert_response :success |
|
194 | assert_response :success | |
195 | assert_template 'index' |
|
195 | assert_template 'index' | |
196 | end |
|
196 | end | |
197 |
|
197 | |||
198 | def test_tokens_with_quotes |
|
198 | def test_tokens_with_quotes | |
199 | get :index, :id => 1, :q => '"good bye" hello "bye bye"' |
|
199 | get :index, :id => 1, :q => '"good bye" hello "bye bye"' | |
200 | assert_equal ["good bye", "hello", "bye bye"], assigns(:tokens) |
|
200 | assert_equal ["good bye", "hello", "bye bye"], assigns(:tokens) | |
201 | end |
|
201 | end | |
|
202 | ||||
|
203 | def test_results_should_be_escaped_once | |||
|
204 | assert Issue.find(1).update_attributes(:subject => '<subject> escaped_once', :description => '<description> escaped_once') | |||
|
205 | get :index, :q => 'escaped_once' | |||
|
206 | assert_response :success | |||
|
207 | assert_select '#search-results' do | |||
|
208 | assert_select 'dt.issue a', :text => /<subject>/ | |||
|
209 | assert_select 'dd', :text => /<description>/ | |||
|
210 | end | |||
|
211 | end | |||
|
212 | ||||
|
213 | def test_keywords_should_be_highlighted | |||
|
214 | assert Issue.find(1).update_attributes(:subject => 'subject highlighted', :description => 'description highlighted') | |||
|
215 | get :index, :q => 'highlighted' | |||
|
216 | assert_response :success | |||
|
217 | assert_select '#search-results' do | |||
|
218 | assert_select 'dt.issue a span.highlight', :text => 'highlighted' | |||
|
219 | assert_select 'dd span.highlight', :text => 'highlighted' | |||
|
220 | end | |||
|
221 | end | |||
202 | end |
|
222 | end |
General Comments 0
You need to be logged in to leave comments.
Login now