##// END OF EJS Templates
Inline images alt attribute set to the attachment description....
Jean-Philippe Lang -
r1313:c37abb64151e
parent child
Show More
@@ -1,504 +1,506
1 # redMine - project management software
1 # redMine - project management software
2 # Copyright (C) 2006-2007 Jean-Philippe Lang
2 # Copyright (C) 2006-2007 Jean-Philippe Lang
3 #
3 #
4 # This program is free software; you can redistribute it and/or
4 # This program is free software; you can redistribute it and/or
5 # modify it under the terms of the GNU General Public License
5 # modify it under the terms of the GNU General Public License
6 # as published by the Free Software Foundation; either version 2
6 # as published by the Free Software Foundation; either version 2
7 # of the License, or (at your option) any later version.
7 # of the License, or (at your option) any later version.
8 #
8 #
9 # This program is distributed in the hope that it will be useful,
9 # This program is distributed in the hope that it will be useful,
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 # GNU General Public License for more details.
12 # GNU General Public License for more details.
13 #
13 #
14 # You should have received a copy of the GNU General Public License
14 # You should have received a copy of the GNU General Public License
15 # along with this program; if not, write to the Free Software
15 # along with this program; if not, write to the Free Software
16 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
16 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17
17
18 module ApplicationHelper
18 module ApplicationHelper
19 include Redmine::WikiFormatting::Macros::Definitions
19 include Redmine::WikiFormatting::Macros::Definitions
20
20
21 def current_role
21 def current_role
22 @current_role ||= User.current.role_for_project(@project)
22 @current_role ||= User.current.role_for_project(@project)
23 end
23 end
24
24
25 # Return true if user is authorized for controller/action, otherwise false
25 # Return true if user is authorized for controller/action, otherwise false
26 def authorize_for(controller, action)
26 def authorize_for(controller, action)
27 User.current.allowed_to?({:controller => controller, :action => action}, @project)
27 User.current.allowed_to?({:controller => controller, :action => action}, @project)
28 end
28 end
29
29
30 # Display a link if user is authorized
30 # Display a link if user is authorized
31 def link_to_if_authorized(name, options = {}, html_options = nil, *parameters_for_method_reference)
31 def link_to_if_authorized(name, options = {}, html_options = nil, *parameters_for_method_reference)
32 link_to(name, options, html_options, *parameters_for_method_reference) if authorize_for(options[:controller] || params[:controller], options[:action])
32 link_to(name, options, html_options, *parameters_for_method_reference) if authorize_for(options[:controller] || params[:controller], options[:action])
33 end
33 end
34
34
35 # Display a link to user's account page
35 # Display a link to user's account page
36 def link_to_user(user)
36 def link_to_user(user)
37 user ? link_to(user, :controller => 'account', :action => 'show', :id => user) : 'Anonymous'
37 user ? link_to(user, :controller => 'account', :action => 'show', :id => user) : 'Anonymous'
38 end
38 end
39
39
40 def link_to_issue(issue, options={})
40 def link_to_issue(issue, options={})
41 link_to "#{issue.tracker.name} ##{issue.id}", {:controller => "issues", :action => "show", :id => issue}, options
41 link_to "#{issue.tracker.name} ##{issue.id}", {:controller => "issues", :action => "show", :id => issue}, options
42 end
42 end
43
43
44 def toggle_link(name, id, options={})
44 def toggle_link(name, id, options={})
45 onclick = "Element.toggle('#{id}'); "
45 onclick = "Element.toggle('#{id}'); "
46 onclick << (options[:focus] ? "Form.Element.focus('#{options[:focus]}'); " : "this.blur(); ")
46 onclick << (options[:focus] ? "Form.Element.focus('#{options[:focus]}'); " : "this.blur(); ")
47 onclick << "return false;"
47 onclick << "return false;"
48 link_to(name, "#", :onclick => onclick)
48 link_to(name, "#", :onclick => onclick)
49 end
49 end
50
50
51 def show_and_goto_link(name, id, options={})
51 def show_and_goto_link(name, id, options={})
52 onclick = "Element.show('#{id}'); "
52 onclick = "Element.show('#{id}'); "
53 onclick << (options[:focus] ? "Form.Element.focus('#{options[:focus]}'); " : "this.blur(); ")
53 onclick << (options[:focus] ? "Form.Element.focus('#{options[:focus]}'); " : "this.blur(); ")
54 onclick << "Element.scrollTo('#{id}'); "
54 onclick << "Element.scrollTo('#{id}'); "
55 onclick << "return false;"
55 onclick << "return false;"
56 link_to(name, "#", options.merge(:onclick => onclick))
56 link_to(name, "#", options.merge(:onclick => onclick))
57 end
57 end
58
58
59 def image_to_function(name, function, html_options = {})
59 def image_to_function(name, function, html_options = {})
60 html_options.symbolize_keys!
60 html_options.symbolize_keys!
61 tag(:input, html_options.merge({
61 tag(:input, html_options.merge({
62 :type => "image", :src => image_path(name),
62 :type => "image", :src => image_path(name),
63 :onclick => (html_options[:onclick] ? "#{html_options[:onclick]}; " : "") + "#{function};"
63 :onclick => (html_options[:onclick] ? "#{html_options[:onclick]}; " : "") + "#{function};"
64 }))
64 }))
65 end
65 end
66
66
67 def prompt_to_remote(name, text, param, url, html_options = {})
67 def prompt_to_remote(name, text, param, url, html_options = {})
68 html_options[:onclick] = "promptToRemote('#{text}', '#{param}', '#{url_for(url)}'); return false;"
68 html_options[:onclick] = "promptToRemote('#{text}', '#{param}', '#{url_for(url)}'); return false;"
69 link_to name, {}, html_options
69 link_to name, {}, html_options
70 end
70 end
71
71
72 def format_date(date)
72 def format_date(date)
73 return nil unless date
73 return nil unless date
74 # "Setting.date_format.size < 2" is a temporary fix (content of date_format setting changed)
74 # "Setting.date_format.size < 2" is a temporary fix (content of date_format setting changed)
75 @date_format ||= (Setting.date_format.blank? || Setting.date_format.size < 2 ? l(:general_fmt_date) : Setting.date_format)
75 @date_format ||= (Setting.date_format.blank? || Setting.date_format.size < 2 ? l(:general_fmt_date) : Setting.date_format)
76 date.strftime(@date_format)
76 date.strftime(@date_format)
77 end
77 end
78
78
79 def format_time(time, include_date = true)
79 def format_time(time, include_date = true)
80 return nil unless time
80 return nil unless time
81 time = time.to_time if time.is_a?(String)
81 time = time.to_time if time.is_a?(String)
82 zone = User.current.time_zone
82 zone = User.current.time_zone
83 if time.utc?
83 if time.utc?
84 local = zone ? zone.adjust(time) : time.getlocal
84 local = zone ? zone.adjust(time) : time.getlocal
85 else
85 else
86 local = zone ? zone.adjust(time.getutc) : time
86 local = zone ? zone.adjust(time.getutc) : time
87 end
87 end
88 @date_format ||= (Setting.date_format.blank? || Setting.date_format.size < 2 ? l(:general_fmt_date) : Setting.date_format)
88 @date_format ||= (Setting.date_format.blank? || Setting.date_format.size < 2 ? l(:general_fmt_date) : Setting.date_format)
89 @time_format ||= (Setting.time_format.blank? ? l(:general_fmt_time) : Setting.time_format)
89 @time_format ||= (Setting.time_format.blank? ? l(:general_fmt_time) : Setting.time_format)
90 include_date ? local.strftime("#{@date_format} #{@time_format}") : local.strftime(@time_format)
90 include_date ? local.strftime("#{@date_format} #{@time_format}") : local.strftime(@time_format)
91 end
91 end
92
92
93 def html_hours(text)
93 def html_hours(text)
94 text.gsub(%r{(\d+)\.(\d+)}, '<span class="hours hours-int">\1</span><span class="hours hours-dec">.\2</span>')
94 text.gsub(%r{(\d+)\.(\d+)}, '<span class="hours hours-int">\1</span><span class="hours hours-dec">.\2</span>')
95 end
95 end
96
96
97 def authoring(created, author)
97 def authoring(created, author)
98 time_tag = content_tag('acronym', distance_of_time_in_words(Time.now, created), :title => format_time(created))
98 time_tag = content_tag('acronym', distance_of_time_in_words(Time.now, created), :title => format_time(created))
99 l(:label_added_time_by, author || 'Anonymous', time_tag)
99 l(:label_added_time_by, author || 'Anonymous', time_tag)
100 end
100 end
101
101
102 def l_or_humanize(s)
102 def l_or_humanize(s)
103 l_has_string?("label_#{s}".to_sym) ? l("label_#{s}".to_sym) : s.to_s.humanize
103 l_has_string?("label_#{s}".to_sym) ? l("label_#{s}".to_sym) : s.to_s.humanize
104 end
104 end
105
105
106 def day_name(day)
106 def day_name(day)
107 l(:general_day_names).split(',')[day-1]
107 l(:general_day_names).split(',')[day-1]
108 end
108 end
109
109
110 def month_name(month)
110 def month_name(month)
111 l(:actionview_datehelper_select_month_names).split(',')[month-1]
111 l(:actionview_datehelper_select_month_names).split(',')[month-1]
112 end
112 end
113
113
114 def pagination_links_full(paginator, count=nil, options={})
114 def pagination_links_full(paginator, count=nil, options={})
115 page_param = options.delete(:page_param) || :page
115 page_param = options.delete(:page_param) || :page
116 url_param = params.dup
116 url_param = params.dup
117 # don't reuse params if filters are present
117 # don't reuse params if filters are present
118 url_param.clear if url_param.has_key?(:set_filter)
118 url_param.clear if url_param.has_key?(:set_filter)
119
119
120 html = ''
120 html = ''
121 html << link_to_remote(('&#171; ' + l(:label_previous)),
121 html << link_to_remote(('&#171; ' + l(:label_previous)),
122 {:update => 'content',
122 {:update => 'content',
123 :url => url_param.merge(page_param => paginator.current.previous),
123 :url => url_param.merge(page_param => paginator.current.previous),
124 :complete => 'window.scrollTo(0,0)'},
124 :complete => 'window.scrollTo(0,0)'},
125 {:href => url_for(:params => url_param.merge(page_param => paginator.current.previous))}) + ' ' if paginator.current.previous
125 {:href => url_for(:params => url_param.merge(page_param => paginator.current.previous))}) + ' ' if paginator.current.previous
126
126
127 html << (pagination_links_each(paginator, options) do |n|
127 html << (pagination_links_each(paginator, options) do |n|
128 link_to_remote(n.to_s,
128 link_to_remote(n.to_s,
129 {:url => {:params => url_param.merge(page_param => n)},
129 {:url => {:params => url_param.merge(page_param => n)},
130 :update => 'content',
130 :update => 'content',
131 :complete => 'window.scrollTo(0,0)'},
131 :complete => 'window.scrollTo(0,0)'},
132 {:href => url_for(:params => url_param.merge(page_param => n))})
132 {:href => url_for(:params => url_param.merge(page_param => n))})
133 end || '')
133 end || '')
134
134
135 html << ' ' + link_to_remote((l(:label_next) + ' &#187;'),
135 html << ' ' + link_to_remote((l(:label_next) + ' &#187;'),
136 {:update => 'content',
136 {:update => 'content',
137 :url => url_param.merge(page_param => paginator.current.next),
137 :url => url_param.merge(page_param => paginator.current.next),
138 :complete => 'window.scrollTo(0,0)'},
138 :complete => 'window.scrollTo(0,0)'},
139 {:href => url_for(:params => url_param.merge(page_param => paginator.current.next))}) if paginator.current.next
139 {:href => url_for(:params => url_param.merge(page_param => paginator.current.next))}) if paginator.current.next
140
140
141 unless count.nil?
141 unless count.nil?
142 html << [" (#{paginator.current.first_item}-#{paginator.current.last_item}/#{count})", per_page_links(paginator.items_per_page)].compact.join(' | ')
142 html << [" (#{paginator.current.first_item}-#{paginator.current.last_item}/#{count})", per_page_links(paginator.items_per_page)].compact.join(' | ')
143 end
143 end
144
144
145 html
145 html
146 end
146 end
147
147
148 def per_page_links(selected=nil)
148 def per_page_links(selected=nil)
149 url_param = params.dup
149 url_param = params.dup
150 url_param.clear if url_param.has_key?(:set_filter)
150 url_param.clear if url_param.has_key?(:set_filter)
151
151
152 links = Setting.per_page_options_array.collect do |n|
152 links = Setting.per_page_options_array.collect do |n|
153 n == selected ? n : link_to_remote(n, {:update => "content", :url => params.dup.merge(:per_page => n)},
153 n == selected ? n : link_to_remote(n, {:update => "content", :url => params.dup.merge(:per_page => n)},
154 {:href => url_for(url_param.merge(:per_page => n))})
154 {:href => url_for(url_param.merge(:per_page => n))})
155 end
155 end
156 links.size > 1 ? l(:label_display_per_page, links.join(', ')) : nil
156 links.size > 1 ? l(:label_display_per_page, links.join(', ')) : nil
157 end
157 end
158
158
159 def breadcrumb(*args)
159 def breadcrumb(*args)
160 content_tag('p', args.join(' &#187; ') + ' &#187; ', :class => 'breadcrumb')
160 content_tag('p', args.join(' &#187; ') + ' &#187; ', :class => 'breadcrumb')
161 end
161 end
162
162
163 def html_title(*args)
163 def html_title(*args)
164 if args.empty?
164 if args.empty?
165 title = []
165 title = []
166 title << @project.name if @project
166 title << @project.name if @project
167 title += @html_title if @html_title
167 title += @html_title if @html_title
168 title << Setting.app_title
168 title << Setting.app_title
169 title.compact.join(' - ')
169 title.compact.join(' - ')
170 else
170 else
171 @html_title ||= []
171 @html_title ||= []
172 @html_title += args
172 @html_title += args
173 end
173 end
174 end
174 end
175
175
176 def accesskey(s)
176 def accesskey(s)
177 Redmine::AccessKeys.key_for s
177 Redmine::AccessKeys.key_for s
178 end
178 end
179
179
180 # Formats text according to system settings.
180 # Formats text according to system settings.
181 # 2 ways to call this method:
181 # 2 ways to call this method:
182 # * with a String: textilizable(text, options)
182 # * with a String: textilizable(text, options)
183 # * with an object and one of its attribute: textilizable(issue, :description, options)
183 # * with an object and one of its attribute: textilizable(issue, :description, options)
184 def textilizable(*args)
184 def textilizable(*args)
185 options = args.last.is_a?(Hash) ? args.pop : {}
185 options = args.last.is_a?(Hash) ? args.pop : {}
186 case args.size
186 case args.size
187 when 1
187 when 1
188 obj = nil
188 obj = nil
189 text = args.shift
189 text = args.shift
190 when 2
190 when 2
191 obj = args.shift
191 obj = args.shift
192 text = obj.send(args.shift).to_s
192 text = obj.send(args.shift).to_s
193 else
193 else
194 raise ArgumentError, 'invalid arguments to textilizable'
194 raise ArgumentError, 'invalid arguments to textilizable'
195 end
195 end
196 return '' if text.blank?
196 return '' if text.blank?
197
197
198 only_path = options.delete(:only_path) == false ? false : true
198 only_path = options.delete(:only_path) == false ? false : true
199
199
200 # when using an image link, try to use an attachment, if possible
200 # when using an image link, try to use an attachment, if possible
201 attachments = options[:attachments] || (obj && obj.respond_to?(:attachments) ? obj.attachments : nil)
201 attachments = options[:attachments] || (obj && obj.respond_to?(:attachments) ? obj.attachments : nil)
202
202
203 if attachments
203 if attachments
204 text = text.gsub(/!((\<|\=|\>)?(\([^\)]+\))?(\[[^\]]+\])?(\{[^\}]+\})?)(\S+\.(gif|jpg|jpeg|png))!/) do |m|
204 text = text.gsub(/!((\<|\=|\>)?(\([^\)]+\))?(\[[^\]]+\])?(\{[^\}]+\})?)(\S+\.(gif|jpg|jpeg|png))!/) do |m|
205 style = $1
205 style = $1
206 filename = $6
206 filename = $6
207 rf = Regexp.new(filename, Regexp::IGNORECASE)
207 rf = Regexp.new(filename, Regexp::IGNORECASE)
208 # search for the picture in attachments
208 # search for the picture in attachments
209 if found = attachments.detect { |att| att.filename =~ rf }
209 if found = attachments.detect { |att| att.filename =~ rf }
210 image_url = url_for :only_path => only_path, :controller => 'attachments', :action => 'download', :id => found.id
210 image_url = url_for :only_path => only_path, :controller => 'attachments', :action => 'download', :id => found
211 "!#{style}#{image_url}!"
211 desc = found.description.to_s.gsub(/^([^\(\)]*).*$/, "\\1")
212 alt = desc.blank? ? nil : "(#{desc})"
213 "!#{style}#{image_url}#{alt}!"
212 else
214 else
213 "!#{style}#{filename}!"
215 "!#{style}#{filename}!"
214 end
216 end
215 end
217 end
216 end
218 end
217
219
218 text = (Setting.text_formatting == 'textile') ?
220 text = (Setting.text_formatting == 'textile') ?
219 Redmine::WikiFormatting.to_html(text) { |macro, args| exec_macro(macro, obj, args) } :
221 Redmine::WikiFormatting.to_html(text) { |macro, args| exec_macro(macro, obj, args) } :
220 simple_format(auto_link(h(text)))
222 simple_format(auto_link(h(text)))
221
223
222 # different methods for formatting wiki links
224 # different methods for formatting wiki links
223 case options[:wiki_links]
225 case options[:wiki_links]
224 when :local
226 when :local
225 # used for local links to html files
227 # used for local links to html files
226 format_wiki_link = Proc.new {|project, title| "#{title}.html" }
228 format_wiki_link = Proc.new {|project, title| "#{title}.html" }
227 when :anchor
229 when :anchor
228 # used for single-file wiki export
230 # used for single-file wiki export
229 format_wiki_link = Proc.new {|project, title| "##{title}" }
231 format_wiki_link = Proc.new {|project, title| "##{title}" }
230 else
232 else
231 format_wiki_link = Proc.new {|project, title| url_for(:only_path => only_path, :controller => 'wiki', :action => 'index', :id => project, :page => title) }
233 format_wiki_link = Proc.new {|project, title| url_for(:only_path => only_path, :controller => 'wiki', :action => 'index', :id => project, :page => title) }
232 end
234 end
233
235
234 project = options[:project] || @project || (obj && obj.respond_to?(:project) ? obj.project : nil)
236 project = options[:project] || @project || (obj && obj.respond_to?(:project) ? obj.project : nil)
235
237
236 # Wiki links
238 # Wiki links
237 #
239 #
238 # Examples:
240 # Examples:
239 # [[mypage]]
241 # [[mypage]]
240 # [[mypage|mytext]]
242 # [[mypage|mytext]]
241 # wiki links can refer other project wikis, using project name or identifier:
243 # wiki links can refer other project wikis, using project name or identifier:
242 # [[project:]] -> wiki starting page
244 # [[project:]] -> wiki starting page
243 # [[project:|mytext]]
245 # [[project:|mytext]]
244 # [[project:mypage]]
246 # [[project:mypage]]
245 # [[project:mypage|mytext]]
247 # [[project:mypage|mytext]]
246 text = text.gsub(/(!)?(\[\[([^\]\n\|]+)(\|([^\]\n\|]+))?\]\])/) do |m|
248 text = text.gsub(/(!)?(\[\[([^\]\n\|]+)(\|([^\]\n\|]+))?\]\])/) do |m|
247 link_project = project
249 link_project = project
248 esc, all, page, title = $1, $2, $3, $5
250 esc, all, page, title = $1, $2, $3, $5
249 if esc.nil?
251 if esc.nil?
250 if page =~ /^([^\:]+)\:(.*)$/
252 if page =~ /^([^\:]+)\:(.*)$/
251 link_project = Project.find_by_name($1) || Project.find_by_identifier($1)
253 link_project = Project.find_by_name($1) || Project.find_by_identifier($1)
252 page = $2
254 page = $2
253 title ||= $1 if page.blank?
255 title ||= $1 if page.blank?
254 end
256 end
255
257
256 if link_project && link_project.wiki
258 if link_project && link_project.wiki
257 # check if page exists
259 # check if page exists
258 wiki_page = link_project.wiki.find_page(page)
260 wiki_page = link_project.wiki.find_page(page)
259 link_to((title || page), format_wiki_link.call(link_project, Wiki.titleize(page)),
261 link_to((title || page), format_wiki_link.call(link_project, Wiki.titleize(page)),
260 :class => ('wiki-page' + (wiki_page ? '' : ' new')))
262 :class => ('wiki-page' + (wiki_page ? '' : ' new')))
261 else
263 else
262 # project or wiki doesn't exist
264 # project or wiki doesn't exist
263 title || page
265 title || page
264 end
266 end
265 else
267 else
266 all
268 all
267 end
269 end
268 end
270 end
269
271
270 # Redmine links
272 # Redmine links
271 #
273 #
272 # Examples:
274 # Examples:
273 # Issues:
275 # Issues:
274 # #52 -> Link to issue #52
276 # #52 -> Link to issue #52
275 # Changesets:
277 # Changesets:
276 # r52 -> Link to revision 52
278 # r52 -> Link to revision 52
277 # commit:a85130f -> Link to scmid starting with a85130f
279 # commit:a85130f -> Link to scmid starting with a85130f
278 # Documents:
280 # Documents:
279 # document#17 -> Link to document with id 17
281 # document#17 -> Link to document with id 17
280 # document:Greetings -> Link to the document with title "Greetings"
282 # document:Greetings -> Link to the document with title "Greetings"
281 # document:"Some document" -> Link to the document with title "Some document"
283 # document:"Some document" -> Link to the document with title "Some document"
282 # Versions:
284 # Versions:
283 # version#3 -> Link to version with id 3
285 # version#3 -> Link to version with id 3
284 # version:1.0.0 -> Link to version named "1.0.0"
286 # version:1.0.0 -> Link to version named "1.0.0"
285 # version:"1.0 beta 2" -> Link to version named "1.0 beta 2"
287 # version:"1.0 beta 2" -> Link to version named "1.0 beta 2"
286 # Attachments:
288 # Attachments:
287 # attachment:file.zip -> Link to the attachment of the current object named file.zip
289 # attachment:file.zip -> Link to the attachment of the current object named file.zip
288 # Source files:
290 # Source files:
289 # source:some/file -> Link to the file located at /some/file in the project's repository
291 # source:some/file -> Link to the file located at /some/file in the project's repository
290 # source:some/file@52 -> Link to the file's revision 52
292 # source:some/file@52 -> Link to the file's revision 52
291 # source:some/file#L120 -> Link to line 120 of the file
293 # source:some/file#L120 -> Link to line 120 of the file
292 # source:some/file@52#L120 -> Link to line 120 of the file's revision 52
294 # source:some/file@52#L120 -> Link to line 120 of the file's revision 52
293 # export:some/file -> Force the download of the file
295 # export:some/file -> Force the download of the file
294 text = text.gsub(%r{([\s\(,-^])(!)?(attachment|document|version|commit|source|export)?((#|r)(\d+)|(:)([^"\s<>][^\s<>]*|"[^"]+"))(?=[[:punct:]]|\s|<|$)}) do |m|
296 text = text.gsub(%r{([\s\(,-^])(!)?(attachment|document|version|commit|source|export)?((#|r)(\d+)|(:)([^"\s<>][^\s<>]*|"[^"]+"))(?=[[:punct:]]|\s|<|$)}) do |m|
295 leading, esc, prefix, sep, oid = $1, $2, $3, $5 || $7, $6 || $8
297 leading, esc, prefix, sep, oid = $1, $2, $3, $5 || $7, $6 || $8
296 link = nil
298 link = nil
297 if esc.nil?
299 if esc.nil?
298 if prefix.nil? && sep == 'r'
300 if prefix.nil? && sep == 'r'
299 if project && (changeset = project.changesets.find_by_revision(oid))
301 if project && (changeset = project.changesets.find_by_revision(oid))
300 link = link_to("r#{oid}", {:only_path => only_path, :controller => 'repositories', :action => 'revision', :id => project, :rev => oid},
302 link = link_to("r#{oid}", {:only_path => only_path, :controller => 'repositories', :action => 'revision', :id => project, :rev => oid},
301 :class => 'changeset',
303 :class => 'changeset',
302 :title => truncate(changeset.comments, 100))
304 :title => truncate(changeset.comments, 100))
303 end
305 end
304 elsif sep == '#'
306 elsif sep == '#'
305 oid = oid.to_i
307 oid = oid.to_i
306 case prefix
308 case prefix
307 when nil
309 when nil
308 if issue = Issue.find_by_id(oid, :include => [:project, :status], :conditions => Project.visible_by(User.current))
310 if issue = Issue.find_by_id(oid, :include => [:project, :status], :conditions => Project.visible_by(User.current))
309 link = link_to("##{oid}", {:only_path => only_path, :controller => 'issues', :action => 'show', :id => oid},
311 link = link_to("##{oid}", {:only_path => only_path, :controller => 'issues', :action => 'show', :id => oid},
310 :class => (issue.closed? ? 'issue closed' : 'issue'),
312 :class => (issue.closed? ? 'issue closed' : 'issue'),
311 :title => "#{truncate(issue.subject, 100)} (#{issue.status.name})")
313 :title => "#{truncate(issue.subject, 100)} (#{issue.status.name})")
312 link = content_tag('del', link) if issue.closed?
314 link = content_tag('del', link) if issue.closed?
313 end
315 end
314 when 'document'
316 when 'document'
315 if document = Document.find_by_id(oid, :include => [:project], :conditions => Project.visible_by(User.current))
317 if document = Document.find_by_id(oid, :include => [:project], :conditions => Project.visible_by(User.current))
316 link = link_to h(document.title), {:only_path => only_path, :controller => 'documents', :action => 'show', :id => document},
318 link = link_to h(document.title), {:only_path => only_path, :controller => 'documents', :action => 'show', :id => document},
317 :class => 'document'
319 :class => 'document'
318 end
320 end
319 when 'version'
321 when 'version'
320 if version = Version.find_by_id(oid, :include => [:project], :conditions => Project.visible_by(User.current))
322 if version = Version.find_by_id(oid, :include => [:project], :conditions => Project.visible_by(User.current))
321 link = link_to h(version.name), {:only_path => only_path, :controller => 'versions', :action => 'show', :id => version},
323 link = link_to h(version.name), {:only_path => only_path, :controller => 'versions', :action => 'show', :id => version},
322 :class => 'version'
324 :class => 'version'
323 end
325 end
324 end
326 end
325 elsif sep == ':'
327 elsif sep == ':'
326 # removes the double quotes if any
328 # removes the double quotes if any
327 name = oid.gsub(%r{^"(.*)"$}, "\\1")
329 name = oid.gsub(%r{^"(.*)"$}, "\\1")
328 case prefix
330 case prefix
329 when 'document'
331 when 'document'
330 if project && document = project.documents.find_by_title(name)
332 if project && document = project.documents.find_by_title(name)
331 link = link_to h(document.title), {:only_path => only_path, :controller => 'documents', :action => 'show', :id => document},
333 link = link_to h(document.title), {:only_path => only_path, :controller => 'documents', :action => 'show', :id => document},
332 :class => 'document'
334 :class => 'document'
333 end
335 end
334 when 'version'
336 when 'version'
335 if project && version = project.versions.find_by_name(name)
337 if project && version = project.versions.find_by_name(name)
336 link = link_to h(version.name), {:only_path => only_path, :controller => 'versions', :action => 'show', :id => version},
338 link = link_to h(version.name), {:only_path => only_path, :controller => 'versions', :action => 'show', :id => version},
337 :class => 'version'
339 :class => 'version'
338 end
340 end
339 when 'commit'
341 when 'commit'
340 if project && (changeset = project.changesets.find(:first, :conditions => ["scmid LIKE ?", "#{name}%"]))
342 if project && (changeset = project.changesets.find(:first, :conditions => ["scmid LIKE ?", "#{name}%"]))
341 link = link_to h("#{name}"), {:only_path => only_path, :controller => 'repositories', :action => 'revision', :id => project, :rev => changeset.revision}, :class => 'changeset', :title => truncate(changeset.comments, 100)
343 link = link_to h("#{name}"), {:only_path => only_path, :controller => 'repositories', :action => 'revision', :id => project, :rev => changeset.revision}, :class => 'changeset', :title => truncate(changeset.comments, 100)
342 end
344 end
343 when 'source', 'export'
345 when 'source', 'export'
344 if project && project.repository
346 if project && project.repository
345 name =~ %r{^[/\\]*(.*?)(@([0-9a-f]+))?(#(L\d+))?$}
347 name =~ %r{^[/\\]*(.*?)(@([0-9a-f]+))?(#(L\d+))?$}
346 path, rev, anchor = $1, $3, $5
348 path, rev, anchor = $1, $3, $5
347 link = link_to h("#{prefix}:#{name}"), {:controller => 'repositories', :action => 'entry', :id => project, :path => path,
349 link = link_to h("#{prefix}:#{name}"), {:controller => 'repositories', :action => 'entry', :id => project, :path => path,
348 :rev => rev,
350 :rev => rev,
349 :anchor => anchor,
351 :anchor => anchor,
350 :format => (prefix == 'export' ? 'raw' : nil)},
352 :format => (prefix == 'export' ? 'raw' : nil)},
351 :class => (prefix == 'export' ? 'source download' : 'source')
353 :class => (prefix == 'export' ? 'source download' : 'source')
352 end
354 end
353 when 'attachment'
355 when 'attachment'
354 if attachments && attachment = attachments.detect {|a| a.filename == name }
356 if attachments && attachment = attachments.detect {|a| a.filename == name }
355 link = link_to h(attachment.filename), {:only_path => only_path, :controller => 'attachments', :action => 'download', :id => attachment},
357 link = link_to h(attachment.filename), {:only_path => only_path, :controller => 'attachments', :action => 'download', :id => attachment},
356 :class => 'attachment'
358 :class => 'attachment'
357 end
359 end
358 end
360 end
359 end
361 end
360 end
362 end
361 leading + (link || "#{prefix}#{sep}#{oid}")
363 leading + (link || "#{prefix}#{sep}#{oid}")
362 end
364 end
363
365
364 text
366 text
365 end
367 end
366
368
367 # Same as Rails' simple_format helper without using paragraphs
369 # Same as Rails' simple_format helper without using paragraphs
368 def simple_format_without_paragraph(text)
370 def simple_format_without_paragraph(text)
369 text.to_s.
371 text.to_s.
370 gsub(/\r\n?/, "\n"). # \r\n and \r -> \n
372 gsub(/\r\n?/, "\n"). # \r\n and \r -> \n
371 gsub(/\n\n+/, "<br /><br />"). # 2+ newline -> 2 br
373 gsub(/\n\n+/, "<br /><br />"). # 2+ newline -> 2 br
372 gsub(/([^\n]\n)(?=[^\n])/, '\1<br />') # 1 newline -> br
374 gsub(/([^\n]\n)(?=[^\n])/, '\1<br />') # 1 newline -> br
373 end
375 end
374
376
375 def error_messages_for(object_name, options = {})
377 def error_messages_for(object_name, options = {})
376 options = options.symbolize_keys
378 options = options.symbolize_keys
377 object = instance_variable_get("@#{object_name}")
379 object = instance_variable_get("@#{object_name}")
378 if object && !object.errors.empty?
380 if object && !object.errors.empty?
379 # build full_messages here with controller current language
381 # build full_messages here with controller current language
380 full_messages = []
382 full_messages = []
381 object.errors.each do |attr, msg|
383 object.errors.each do |attr, msg|
382 next if msg.nil?
384 next if msg.nil?
383 msg = msg.first if msg.is_a? Array
385 msg = msg.first if msg.is_a? Array
384 if attr == "base"
386 if attr == "base"
385 full_messages << l(msg)
387 full_messages << l(msg)
386 else
388 else
387 full_messages << "&#171; " + (l_has_string?("field_" + attr) ? l("field_" + attr) : object.class.human_attribute_name(attr)) + " &#187; " + l(msg) unless attr == "custom_values"
389 full_messages << "&#171; " + (l_has_string?("field_" + attr) ? l("field_" + attr) : object.class.human_attribute_name(attr)) + " &#187; " + l(msg) unless attr == "custom_values"
388 end
390 end
389 end
391 end
390 # retrieve custom values error messages
392 # retrieve custom values error messages
391 if object.errors[:custom_values]
393 if object.errors[:custom_values]
392 object.custom_values.each do |v|
394 object.custom_values.each do |v|
393 v.errors.each do |attr, msg|
395 v.errors.each do |attr, msg|
394 next if msg.nil?
396 next if msg.nil?
395 msg = msg.first if msg.is_a? Array
397 msg = msg.first if msg.is_a? Array
396 full_messages << "&#171; " + v.custom_field.name + " &#187; " + l(msg)
398 full_messages << "&#171; " + v.custom_field.name + " &#187; " + l(msg)
397 end
399 end
398 end
400 end
399 end
401 end
400 content_tag("div",
402 content_tag("div",
401 content_tag(
403 content_tag(
402 options[:header_tag] || "span", lwr(:gui_validation_error, full_messages.length) + ":"
404 options[:header_tag] || "span", lwr(:gui_validation_error, full_messages.length) + ":"
403 ) +
405 ) +
404 content_tag("ul", full_messages.collect { |msg| content_tag("li", msg) }),
406 content_tag("ul", full_messages.collect { |msg| content_tag("li", msg) }),
405 "id" => options[:id] || "errorExplanation", "class" => options[:class] || "errorExplanation"
407 "id" => options[:id] || "errorExplanation", "class" => options[:class] || "errorExplanation"
406 )
408 )
407 else
409 else
408 ""
410 ""
409 end
411 end
410 end
412 end
411
413
412 def lang_options_for_select(blank=true)
414 def lang_options_for_select(blank=true)
413 (blank ? [["(auto)", ""]] : []) +
415 (blank ? [["(auto)", ""]] : []) +
414 GLoc.valid_languages.collect{|lang| [ ll(lang.to_s, :general_lang_name), lang.to_s]}.sort{|x,y| x.last <=> y.last }
416 GLoc.valid_languages.collect{|lang| [ ll(lang.to_s, :general_lang_name), lang.to_s]}.sort{|x,y| x.last <=> y.last }
415 end
417 end
416
418
417 def label_tag_for(name, option_tags = nil, options = {})
419 def label_tag_for(name, option_tags = nil, options = {})
418 label_text = l(("field_"+field.to_s.gsub(/\_id$/, "")).to_sym) + (options.delete(:required) ? @template.content_tag("span", " *", :class => "required"): "")
420 label_text = l(("field_"+field.to_s.gsub(/\_id$/, "")).to_sym) + (options.delete(:required) ? @template.content_tag("span", " *", :class => "required"): "")
419 content_tag("label", label_text)
421 content_tag("label", label_text)
420 end
422 end
421
423
422 def labelled_tabular_form_for(name, object, options, &proc)
424 def labelled_tabular_form_for(name, object, options, &proc)
423 options[:html] ||= {}
425 options[:html] ||= {}
424 options[:html][:class] = 'tabular' unless options[:html].has_key?(:class)
426 options[:html][:class] = 'tabular' unless options[:html].has_key?(:class)
425 form_for(name, object, options.merge({ :builder => TabularFormBuilder, :lang => current_language}), &proc)
427 form_for(name, object, options.merge({ :builder => TabularFormBuilder, :lang => current_language}), &proc)
426 end
428 end
427
429
428 def check_all_links(form_name)
430 def check_all_links(form_name)
429 link_to_function(l(:button_check_all), "checkAll('#{form_name}', true)") +
431 link_to_function(l(:button_check_all), "checkAll('#{form_name}', true)") +
430 " | " +
432 " | " +
431 link_to_function(l(:button_uncheck_all), "checkAll('#{form_name}', false)")
433 link_to_function(l(:button_uncheck_all), "checkAll('#{form_name}', false)")
432 end
434 end
433
435
434 def progress_bar(pcts, options={})
436 def progress_bar(pcts, options={})
435 pcts = [pcts, pcts] unless pcts.is_a?(Array)
437 pcts = [pcts, pcts] unless pcts.is_a?(Array)
436 pcts[1] = pcts[1] - pcts[0]
438 pcts[1] = pcts[1] - pcts[0]
437 pcts << (100 - pcts[1] - pcts[0])
439 pcts << (100 - pcts[1] - pcts[0])
438 width = options[:width] || '100px;'
440 width = options[:width] || '100px;'
439 legend = options[:legend] || ''
441 legend = options[:legend] || ''
440 content_tag('table',
442 content_tag('table',
441 content_tag('tr',
443 content_tag('tr',
442 (pcts[0] > 0 ? content_tag('td', '', :width => "#{pcts[0].floor}%;", :class => 'closed') : '') +
444 (pcts[0] > 0 ? content_tag('td', '', :width => "#{pcts[0].floor}%;", :class => 'closed') : '') +
443 (pcts[1] > 0 ? content_tag('td', '', :width => "#{pcts[1].floor}%;", :class => 'done') : '') +
445 (pcts[1] > 0 ? content_tag('td', '', :width => "#{pcts[1].floor}%;", :class => 'done') : '') +
444 (pcts[2] > 0 ? content_tag('td', '', :width => "#{pcts[2].floor}%;", :class => 'todo') : '')
446 (pcts[2] > 0 ? content_tag('td', '', :width => "#{pcts[2].floor}%;", :class => 'todo') : '')
445 ), :class => 'progress', :style => "width: #{width};") +
447 ), :class => 'progress', :style => "width: #{width};") +
446 content_tag('p', legend, :class => 'pourcent')
448 content_tag('p', legend, :class => 'pourcent')
447 end
449 end
448
450
449 def context_menu_link(name, url, options={})
451 def context_menu_link(name, url, options={})
450 options[:class] ||= ''
452 options[:class] ||= ''
451 if options.delete(:selected)
453 if options.delete(:selected)
452 options[:class] << ' icon-checked disabled'
454 options[:class] << ' icon-checked disabled'
453 options[:disabled] = true
455 options[:disabled] = true
454 end
456 end
455 if options.delete(:disabled)
457 if options.delete(:disabled)
456 options.delete(:method)
458 options.delete(:method)
457 options.delete(:confirm)
459 options.delete(:confirm)
458 options.delete(:onclick)
460 options.delete(:onclick)
459 options[:class] << ' disabled'
461 options[:class] << ' disabled'
460 url = '#'
462 url = '#'
461 end
463 end
462 link_to name, url, options
464 link_to name, url, options
463 end
465 end
464
466
465 def calendar_for(field_id)
467 def calendar_for(field_id)
466 include_calendar_headers_tags
468 include_calendar_headers_tags
467 image_tag("calendar.png", {:id => "#{field_id}_trigger",:class => "calendar-trigger"}) +
469 image_tag("calendar.png", {:id => "#{field_id}_trigger",:class => "calendar-trigger"}) +
468 javascript_tag("Calendar.setup({inputField : '#{field_id}', ifFormat : '%Y-%m-%d', button : '#{field_id}_trigger' });")
470 javascript_tag("Calendar.setup({inputField : '#{field_id}', ifFormat : '%Y-%m-%d', button : '#{field_id}_trigger' });")
469 end
471 end
470
472
471 def include_calendar_headers_tags
473 def include_calendar_headers_tags
472 unless @calendar_headers_tags_included
474 unless @calendar_headers_tags_included
473 @calendar_headers_tags_included = true
475 @calendar_headers_tags_included = true
474 content_for :header_tags do
476 content_for :header_tags do
475 javascript_include_tag('calendar/calendar') +
477 javascript_include_tag('calendar/calendar') +
476 javascript_include_tag("calendar/lang/calendar-#{current_language}.js") +
478 javascript_include_tag("calendar/lang/calendar-#{current_language}.js") +
477 javascript_include_tag('calendar/calendar-setup') +
479 javascript_include_tag('calendar/calendar-setup') +
478 stylesheet_link_tag('calendar')
480 stylesheet_link_tag('calendar')
479 end
481 end
480 end
482 end
481 end
483 end
482
484
483 def wikitoolbar_for(field_id)
485 def wikitoolbar_for(field_id)
484 return '' unless Setting.text_formatting == 'textile'
486 return '' unless Setting.text_formatting == 'textile'
485
487
486 help_link = l(:setting_text_formatting) + ': ' +
488 help_link = l(:setting_text_formatting) + ': ' +
487 link_to(l(:label_help), compute_public_path('wiki_syntax', 'help', 'html'),
489 link_to(l(:label_help), compute_public_path('wiki_syntax', 'help', 'html'),
488 :onclick => "window.open(\"#{ compute_public_path('wiki_syntax', 'help', 'html') }\", \"\", \"resizable=yes, location=no, width=300, height=640, menubar=no, status=no, scrollbars=yes\"); return false;")
490 :onclick => "window.open(\"#{ compute_public_path('wiki_syntax', 'help', 'html') }\", \"\", \"resizable=yes, location=no, width=300, height=640, menubar=no, status=no, scrollbars=yes\"); return false;")
489
491
490 javascript_include_tag('jstoolbar/jstoolbar') +
492 javascript_include_tag('jstoolbar/jstoolbar') +
491 javascript_include_tag("jstoolbar/lang/jstoolbar-#{current_language}") +
493 javascript_include_tag("jstoolbar/lang/jstoolbar-#{current_language}") +
492 javascript_tag("var toolbar = new jsToolBar($('#{field_id}')); toolbar.setHelpLink('#{help_link}'); toolbar.draw();")
494 javascript_tag("var toolbar = new jsToolBar($('#{field_id}')); toolbar.setHelpLink('#{help_link}'); toolbar.draw();")
493 end
495 end
494
496
495 def content_for(name, content = nil, &block)
497 def content_for(name, content = nil, &block)
496 @has_content ||= {}
498 @has_content ||= {}
497 @has_content[name] = true
499 @has_content[name] = true
498 super(name, content, &block)
500 super(name, content, &block)
499 end
501 end
500
502
501 def has_content?(name)
503 def has_content?(name)
502 (@has_content && @has_content[name]) || false
504 (@has_content && @has_content[name]) || false
503 end
505 end
504 end
506 end
@@ -1,38 +1,39
1 ---
1 ---
2 attachments_001:
2 attachments_001:
3 created_on: 2006-07-19 21:07:27 +02:00
3 created_on: 2006-07-19 21:07:27 +02:00
4 downloads: 0
4 downloads: 0
5 content_type: text/plain
5 content_type: text/plain
6 disk_filename: 060719210727_error281.txt
6 disk_filename: 060719210727_error281.txt
7 container_id: 3
7 container_id: 3
8 digest: b91e08d0cf966d5c6ff411bd8c4cc3a2
8 digest: b91e08d0cf966d5c6ff411bd8c4cc3a2
9 id: 1
9 id: 1
10 container_type: Issue
10 container_type: Issue
11 filesize: 28
11 filesize: 28
12 filename: error281.txt
12 filename: error281.txt
13 author_id: 2
13 author_id: 2
14 attachments_002:
14 attachments_002:
15 created_on: 2006-07-19 21:07:27 +02:00
15 created_on: 2006-07-19 21:07:27 +02:00
16 downloads: 0
16 downloads: 0
17 content_type: text/plain
17 content_type: text/plain
18 disk_filename: 060719210727_document.txt
18 disk_filename: 060719210727_document.txt
19 container_id: 1
19 container_id: 1
20 digest: b91e08d0cf966d5c6ff411bd8c4cc3a2
20 digest: b91e08d0cf966d5c6ff411bd8c4cc3a2
21 id: 2
21 id: 2
22 container_type: Document
22 container_type: Document
23 filesize: 28
23 filesize: 28
24 filename: document.txt
24 filename: document.txt
25 author_id: 2
25 author_id: 2
26 attachments_003:
26 attachments_003:
27 created_on: 2006-07-19 21:07:27 +02:00
27 created_on: 2006-07-19 21:07:27 +02:00
28 downloads: 0
28 downloads: 0
29 content_type: image/gif
29 content_type: image/gif
30 disk_filename: 060719210727_logo.gif
30 disk_filename: 060719210727_logo.gif
31 container_id: 4
31 container_id: 4
32 digest: b91e08d0cf966d5c6ff411bd8c4cc3a2
32 digest: b91e08d0cf966d5c6ff411bd8c4cc3a2
33 id: 3
33 id: 3
34 container_type: WikiPage
34 container_type: WikiPage
35 filesize: 280
35 filesize: 280
36 filename: logo.gif
36 filename: logo.gif
37 description: This is a logo
37 author_id: 2
38 author_id: 2
38 No newline at end of file
39
@@ -1,162 +1,163
1 # redMine - project management software
1 # redMine - project management software
2 # Copyright (C) 2006-2007 Jean-Philippe Lang
2 # Copyright (C) 2006-2007 Jean-Philippe Lang
3 #
3 #
4 # This program is free software; you can redistribute it and/or
4 # This program is free software; you can redistribute it and/or
5 # modify it under the terms of the GNU General Public License
5 # modify it under the terms of the GNU General Public License
6 # as published by the Free Software Foundation; either version 2
6 # as published by the Free Software Foundation; either version 2
7 # of the License, or (at your option) any later version.
7 # of the License, or (at your option) any later version.
8 #
8 #
9 # This program is distributed in the hope that it will be useful,
9 # This program is distributed in the hope that it will be useful,
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 # GNU General Public License for more details.
12 # GNU General Public License for more details.
13 #
13 #
14 # You should have received a copy of the GNU General Public License
14 # You should have received a copy of the GNU General Public License
15 # along with this program; if not, write to the Free Software
15 # along with this program; if not, write to the Free Software
16 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
16 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17
17
18 require File.dirname(__FILE__) + '/../test_helper'
18 require File.dirname(__FILE__) + '/../test_helper'
19 require 'wiki_controller'
19 require 'wiki_controller'
20
20
21 # Re-raise errors caught by the controller.
21 # Re-raise errors caught by the controller.
22 class WikiController; def rescue_action(e) raise e end; end
22 class WikiController; def rescue_action(e) raise e end; end
23
23
24 class WikiControllerTest < Test::Unit::TestCase
24 class WikiControllerTest < Test::Unit::TestCase
25 fixtures :projects, :users, :roles, :members, :enabled_modules, :wikis, :wiki_pages, :wiki_contents, :wiki_content_versions, :attachments
25 fixtures :projects, :users, :roles, :members, :enabled_modules, :wikis, :wiki_pages, :wiki_contents, :wiki_content_versions, :attachments
26
26
27 def setup
27 def setup
28 @controller = WikiController.new
28 @controller = WikiController.new
29 @request = ActionController::TestRequest.new
29 @request = ActionController::TestRequest.new
30 @response = ActionController::TestResponse.new
30 @response = ActionController::TestResponse.new
31 User.current = nil
31 User.current = nil
32 end
32 end
33
33
34 def test_show_start_page
34 def test_show_start_page
35 get :index, :id => 1
35 get :index, :id => 1
36 assert_response :success
36 assert_response :success
37 assert_template 'show'
37 assert_template 'show'
38 assert_tag :tag => 'h1', :content => /CookBook documentation/
38 assert_tag :tag => 'h1', :content => /CookBook documentation/
39 end
39 end
40
40
41 def test_show_page_with_name
41 def test_show_page_with_name
42 get :index, :id => 1, :page => 'Another_page'
42 get :index, :id => 1, :page => 'Another_page'
43 assert_response :success
43 assert_response :success
44 assert_template 'show'
44 assert_template 'show'
45 assert_tag :tag => 'h1', :content => /Another page/
45 assert_tag :tag => 'h1', :content => /Another page/
46 # Included page with an inline image
46 # Included page with an inline image
47 assert_tag :tag => 'p', :content => /This is an inline image/
47 assert_tag :tag => 'p', :content => /This is an inline image/
48 assert_tag :tag => 'img', :attributes => { :src => '/attachments/download/3' }
48 assert_tag :tag => 'img', :attributes => { :src => '/attachments/download/3',
49 :alt => 'This is a logo' }
49 end
50 end
50
51
51 def test_show_unexistent_page_without_edit_right
52 def test_show_unexistent_page_without_edit_right
52 get :index, :id => 1, :page => 'Unexistent page'
53 get :index, :id => 1, :page => 'Unexistent page'
53 assert_response 404
54 assert_response 404
54 end
55 end
55
56
56 def test_show_unexistent_page_with_edit_right
57 def test_show_unexistent_page_with_edit_right
57 @request.session[:user_id] = 2
58 @request.session[:user_id] = 2
58 get :index, :id => 1, :page => 'Unexistent page'
59 get :index, :id => 1, :page => 'Unexistent page'
59 assert_response :success
60 assert_response :success
60 assert_template 'edit'
61 assert_template 'edit'
61 end
62 end
62
63
63 def test_create_page
64 def test_create_page
64 @request.session[:user_id] = 2
65 @request.session[:user_id] = 2
65 post :edit, :id => 1,
66 post :edit, :id => 1,
66 :page => 'New page',
67 :page => 'New page',
67 :content => {:comments => 'Created the page',
68 :content => {:comments => 'Created the page',
68 :text => "h1. New page\n\nThis is a new page",
69 :text => "h1. New page\n\nThis is a new page",
69 :version => 0}
70 :version => 0}
70 assert_redirected_to 'wiki/ecookbook/New_page'
71 assert_redirected_to 'wiki/ecookbook/New_page'
71 page = Project.find(1).wiki.find_page('New page')
72 page = Project.find(1).wiki.find_page('New page')
72 assert !page.new_record?
73 assert !page.new_record?
73 assert_not_nil page.content
74 assert_not_nil page.content
74 assert_equal 'Created the page', page.content.comments
75 assert_equal 'Created the page', page.content.comments
75 end
76 end
76
77
77 def test_preview
78 def test_preview
78 @request.session[:user_id] = 2
79 @request.session[:user_id] = 2
79 xhr :post, :preview, :id => 1, :page => 'CookBook_documentation',
80 xhr :post, :preview, :id => 1, :page => 'CookBook_documentation',
80 :content => { :comments => '',
81 :content => { :comments => '',
81 :text => 'this is a *previewed text*',
82 :text => 'this is a *previewed text*',
82 :version => 3 }
83 :version => 3 }
83 assert_response :success
84 assert_response :success
84 assert_template 'common/_preview'
85 assert_template 'common/_preview'
85 assert_tag :tag => 'strong', :content => /previewed text/
86 assert_tag :tag => 'strong', :content => /previewed text/
86 end
87 end
87
88
88 def test_history
89 def test_history
89 get :history, :id => 1, :page => 'CookBook_documentation'
90 get :history, :id => 1, :page => 'CookBook_documentation'
90 assert_response :success
91 assert_response :success
91 assert_template 'history'
92 assert_template 'history'
92 assert_not_nil assigns(:versions)
93 assert_not_nil assigns(:versions)
93 assert_equal 3, assigns(:versions).size
94 assert_equal 3, assigns(:versions).size
94 end
95 end
95
96
96 def test_diff
97 def test_diff
97 get :diff, :id => 1, :page => 'CookBook_documentation', :version => 2, :version_from => 1
98 get :diff, :id => 1, :page => 'CookBook_documentation', :version => 2, :version_from => 1
98 assert_response :success
99 assert_response :success
99 assert_template 'diff'
100 assert_template 'diff'
100 assert_tag :tag => 'span', :attributes => { :class => 'diff_in'},
101 assert_tag :tag => 'span', :attributes => { :class => 'diff_in'},
101 :content => /updated/
102 :content => /updated/
102 end
103 end
103
104
104 def test_annotate
105 def test_annotate
105 get :annotate, :id => 1, :page => 'CookBook_documentation', :version => 2
106 get :annotate, :id => 1, :page => 'CookBook_documentation', :version => 2
106 assert_response :success
107 assert_response :success
107 assert_template 'annotate'
108 assert_template 'annotate'
108 # Line 1
109 # Line 1
109 assert_tag :tag => 'tr', :child => { :tag => 'th', :attributes => {:class => 'line-num'}, :content => '1' },
110 assert_tag :tag => 'tr', :child => { :tag => 'th', :attributes => {:class => 'line-num'}, :content => '1' },
110 :child => { :tag => 'td', :attributes => {:class => 'author'}, :content => /John Smith/ },
111 :child => { :tag => 'td', :attributes => {:class => 'author'}, :content => /John Smith/ },
111 :child => { :tag => 'td', :content => /h1\. CookBook documentation/ }
112 :child => { :tag => 'td', :content => /h1\. CookBook documentation/ }
112 # Line 2
113 # Line 2
113 assert_tag :tag => 'tr', :child => { :tag => 'th', :attributes => {:class => 'line-num'}, :content => '2' },
114 assert_tag :tag => 'tr', :child => { :tag => 'th', :attributes => {:class => 'line-num'}, :content => '2' },
114 :child => { :tag => 'td', :attributes => {:class => 'author'}, :content => /redMine Admin/ },
115 :child => { :tag => 'td', :attributes => {:class => 'author'}, :content => /redMine Admin/ },
115 :child => { :tag => 'td', :content => /Some updated \[\[documentation\]\] here/ }
116 :child => { :tag => 'td', :content => /Some updated \[\[documentation\]\] here/ }
116 end
117 end
117
118
118 def test_rename_with_redirect
119 def test_rename_with_redirect
119 @request.session[:user_id] = 2
120 @request.session[:user_id] = 2
120 post :rename, :id => 1, :page => 'Another_page',
121 post :rename, :id => 1, :page => 'Another_page',
121 :wiki_page => { :title => 'Another renamed page',
122 :wiki_page => { :title => 'Another renamed page',
122 :redirect_existing_links => 1 }
123 :redirect_existing_links => 1 }
123 assert_redirected_to 'wiki/ecookbook/Another_renamed_page'
124 assert_redirected_to 'wiki/ecookbook/Another_renamed_page'
124 wiki = Project.find(1).wiki
125 wiki = Project.find(1).wiki
125 # Check redirects
126 # Check redirects
126 assert_not_nil wiki.find_page('Another page')
127 assert_not_nil wiki.find_page('Another page')
127 assert_nil wiki.find_page('Another page', :with_redirect => false)
128 assert_nil wiki.find_page('Another page', :with_redirect => false)
128 end
129 end
129
130
130 def test_rename_without_redirect
131 def test_rename_without_redirect
131 @request.session[:user_id] = 2
132 @request.session[:user_id] = 2
132 post :rename, :id => 1, :page => 'Another_page',
133 post :rename, :id => 1, :page => 'Another_page',
133 :wiki_page => { :title => 'Another renamed page',
134 :wiki_page => { :title => 'Another renamed page',
134 :redirect_existing_links => "0" }
135 :redirect_existing_links => "0" }
135 assert_redirected_to 'wiki/ecookbook/Another_renamed_page'
136 assert_redirected_to 'wiki/ecookbook/Another_renamed_page'
136 wiki = Project.find(1).wiki
137 wiki = Project.find(1).wiki
137 # Check that there's no redirects
138 # Check that there's no redirects
138 assert_nil wiki.find_page('Another page')
139 assert_nil wiki.find_page('Another page')
139 end
140 end
140
141
141 def test_destroy
142 def test_destroy
142 @request.session[:user_id] = 2
143 @request.session[:user_id] = 2
143 post :destroy, :id => 1, :page => 'CookBook_documentation'
144 post :destroy, :id => 1, :page => 'CookBook_documentation'
144 assert_redirected_to 'wiki/ecookbook/Page_index/special'
145 assert_redirected_to 'wiki/ecookbook/Page_index/special'
145 end
146 end
146
147
147 def test_page_index
148 def test_page_index
148 get :special, :id => 'ecookbook', :page => 'Page_index'
149 get :special, :id => 'ecookbook', :page => 'Page_index'
149 assert_response :success
150 assert_response :success
150 assert_template 'special_page_index'
151 assert_template 'special_page_index'
151 pages = assigns(:pages)
152 pages = assigns(:pages)
152 assert_not_nil pages
153 assert_not_nil pages
153 assert_equal Project.find(1).wiki.pages.size, pages.size
154 assert_equal Project.find(1).wiki.pages.size, pages.size
154 assert_tag :tag => 'a', :attributes => { :href => '/wiki/ecookbook/CookBook_documentation' },
155 assert_tag :tag => 'a', :attributes => { :href => '/wiki/ecookbook/CookBook_documentation' },
155 :content => /CookBook documentation/
156 :content => /CookBook documentation/
156 end
157 end
157
158
158 def test_not_found
159 def test_not_found
159 get :index, :id => 999
160 get :index, :id => 999
160 assert_response 404
161 assert_response 404
161 end
162 end
162 end
163 end
General Comments 0
You need to be logged in to leave comments. Login now