##// END OF EJS Templates
Fixed: version files in Files module cannot be downloaded if issue tracking is disabled (#9055)....
Jean-Philippe Lang -
r7864:d92c204ed389
parent child
Show More
@@ -1,234 +1,239
1 # Redmine - project management software
1 # Redmine - project management software
2 # Copyright (C) 2006-2011 Jean-Philippe Lang
2 # Copyright (C) 2006-2011 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 class Version < ActiveRecord::Base
18 class Version < ActiveRecord::Base
19 after_update :update_issues_from_sharing_change
19 after_update :update_issues_from_sharing_change
20 belongs_to :project
20 belongs_to :project
21 has_many :fixed_issues, :class_name => 'Issue', :foreign_key => 'fixed_version_id', :dependent => :nullify
21 has_many :fixed_issues, :class_name => 'Issue', :foreign_key => 'fixed_version_id', :dependent => :nullify
22 acts_as_customizable
22 acts_as_customizable
23 acts_as_attachable :view_permission => :view_files,
23 acts_as_attachable :view_permission => :view_files,
24 :delete_permission => :manage_files
24 :delete_permission => :manage_files
25
25
26 VERSION_STATUSES = %w(open locked closed)
26 VERSION_STATUSES = %w(open locked closed)
27 VERSION_SHARINGS = %w(none descendants hierarchy tree system)
27 VERSION_SHARINGS = %w(none descendants hierarchy tree system)
28
28
29 validates_presence_of :name
29 validates_presence_of :name
30 validates_uniqueness_of :name, :scope => [:project_id]
30 validates_uniqueness_of :name, :scope => [:project_id]
31 validates_length_of :name, :maximum => 60
31 validates_length_of :name, :maximum => 60
32 validates_format_of :effective_date, :with => /^\d{4}-\d{2}-\d{2}$/, :message => :not_a_date, :allow_nil => true
32 validates_format_of :effective_date, :with => /^\d{4}-\d{2}-\d{2}$/, :message => :not_a_date, :allow_nil => true
33 validates_inclusion_of :status, :in => VERSION_STATUSES
33 validates_inclusion_of :status, :in => VERSION_STATUSES
34 validates_inclusion_of :sharing, :in => VERSION_SHARINGS
34 validates_inclusion_of :sharing, :in => VERSION_SHARINGS
35
35
36 named_scope :named, lambda {|arg| { :conditions => ["LOWER(#{table_name}.name) = LOWER(?)", arg.to_s.strip]}}
36 named_scope :named, lambda {|arg| { :conditions => ["LOWER(#{table_name}.name) = LOWER(?)", arg.to_s.strip]}}
37 named_scope :open, :conditions => {:status => 'open'}
37 named_scope :open, :conditions => {:status => 'open'}
38 named_scope :visible, lambda {|*args| { :include => :project,
38 named_scope :visible, lambda {|*args| { :include => :project,
39 :conditions => Project.allowed_to_condition(args.first || User.current, :view_issues) } }
39 :conditions => Project.allowed_to_condition(args.first || User.current, :view_issues) } }
40
40
41 # Returns true if +user+ or current user is allowed to view the version
41 # Returns true if +user+ or current user is allowed to view the version
42 def visible?(user=User.current)
42 def visible?(user=User.current)
43 user.allowed_to?(:view_issues, self.project)
43 user.allowed_to?(:view_issues, self.project)
44 end
44 end
45
45
46 # Version files have same visibility as project files
47 def attachments_visible?(*args)
48 project.present? && project.attachments_visible?(*args)
49 end
50
46 def start_date
51 def start_date
47 @start_date ||= fixed_issues.minimum('start_date')
52 @start_date ||= fixed_issues.minimum('start_date')
48 end
53 end
49
54
50 def due_date
55 def due_date
51 effective_date
56 effective_date
52 end
57 end
53
58
54 # Returns the total estimated time for this version
59 # Returns the total estimated time for this version
55 # (sum of leaves estimated_hours)
60 # (sum of leaves estimated_hours)
56 def estimated_hours
61 def estimated_hours
57 @estimated_hours ||= fixed_issues.leaves.sum(:estimated_hours).to_f
62 @estimated_hours ||= fixed_issues.leaves.sum(:estimated_hours).to_f
58 end
63 end
59
64
60 # Returns the total reported time for this version
65 # Returns the total reported time for this version
61 def spent_hours
66 def spent_hours
62 @spent_hours ||= TimeEntry.sum(:hours, :include => :issue, :conditions => ["#{Issue.table_name}.fixed_version_id = ?", id]).to_f
67 @spent_hours ||= TimeEntry.sum(:hours, :include => :issue, :conditions => ["#{Issue.table_name}.fixed_version_id = ?", id]).to_f
63 end
68 end
64
69
65 def closed?
70 def closed?
66 status == 'closed'
71 status == 'closed'
67 end
72 end
68
73
69 def open?
74 def open?
70 status == 'open'
75 status == 'open'
71 end
76 end
72
77
73 # Returns true if the version is completed: due date reached and no open issues
78 # Returns true if the version is completed: due date reached and no open issues
74 def completed?
79 def completed?
75 effective_date && (effective_date <= Date.today) && (open_issues_count == 0)
80 effective_date && (effective_date <= Date.today) && (open_issues_count == 0)
76 end
81 end
77
82
78 def behind_schedule?
83 def behind_schedule?
79 if completed_pourcent == 100
84 if completed_pourcent == 100
80 return false
85 return false
81 elsif due_date && start_date
86 elsif due_date && start_date
82 done_date = start_date + ((due_date - start_date+1)* completed_pourcent/100).floor
87 done_date = start_date + ((due_date - start_date+1)* completed_pourcent/100).floor
83 return done_date <= Date.today
88 return done_date <= Date.today
84 else
89 else
85 false # No issues so it's not late
90 false # No issues so it's not late
86 end
91 end
87 end
92 end
88
93
89 # Returns the completion percentage of this version based on the amount of open/closed issues
94 # Returns the completion percentage of this version based on the amount of open/closed issues
90 # and the time spent on the open issues.
95 # and the time spent on the open issues.
91 def completed_pourcent
96 def completed_pourcent
92 if issues_count == 0
97 if issues_count == 0
93 0
98 0
94 elsif open_issues_count == 0
99 elsif open_issues_count == 0
95 100
100 100
96 else
101 else
97 issues_progress(false) + issues_progress(true)
102 issues_progress(false) + issues_progress(true)
98 end
103 end
99 end
104 end
100
105
101 # Returns the percentage of issues that have been marked as 'closed'.
106 # Returns the percentage of issues that have been marked as 'closed'.
102 def closed_pourcent
107 def closed_pourcent
103 if issues_count == 0
108 if issues_count == 0
104 0
109 0
105 else
110 else
106 issues_progress(false)
111 issues_progress(false)
107 end
112 end
108 end
113 end
109
114
110 # Returns true if the version is overdue: due date reached and some open issues
115 # Returns true if the version is overdue: due date reached and some open issues
111 def overdue?
116 def overdue?
112 effective_date && (effective_date < Date.today) && (open_issues_count > 0)
117 effective_date && (effective_date < Date.today) && (open_issues_count > 0)
113 end
118 end
114
119
115 # Returns assigned issues count
120 # Returns assigned issues count
116 def issues_count
121 def issues_count
117 @issue_count ||= fixed_issues.count
122 @issue_count ||= fixed_issues.count
118 end
123 end
119
124
120 # Returns the total amount of open issues for this version.
125 # Returns the total amount of open issues for this version.
121 def open_issues_count
126 def open_issues_count
122 @open_issues_count ||= Issue.count(:all, :conditions => ["fixed_version_id = ? AND is_closed = ?", self.id, false], :include => :status)
127 @open_issues_count ||= Issue.count(:all, :conditions => ["fixed_version_id = ? AND is_closed = ?", self.id, false], :include => :status)
123 end
128 end
124
129
125 # Returns the total amount of closed issues for this version.
130 # Returns the total amount of closed issues for this version.
126 def closed_issues_count
131 def closed_issues_count
127 @closed_issues_count ||= Issue.count(:all, :conditions => ["fixed_version_id = ? AND is_closed = ?", self.id, true], :include => :status)
132 @closed_issues_count ||= Issue.count(:all, :conditions => ["fixed_version_id = ? AND is_closed = ?", self.id, true], :include => :status)
128 end
133 end
129
134
130 def wiki_page
135 def wiki_page
131 if project.wiki && !wiki_page_title.blank?
136 if project.wiki && !wiki_page_title.blank?
132 @wiki_page ||= project.wiki.find_page(wiki_page_title)
137 @wiki_page ||= project.wiki.find_page(wiki_page_title)
133 end
138 end
134 @wiki_page
139 @wiki_page
135 end
140 end
136
141
137 def to_s; name end
142 def to_s; name end
138
143
139 def to_s_with_project
144 def to_s_with_project
140 "#{project} - #{name}"
145 "#{project} - #{name}"
141 end
146 end
142
147
143 # Versions are sorted by effective_date and "Project Name - Version name"
148 # Versions are sorted by effective_date and "Project Name - Version name"
144 # Those with no effective_date are at the end, sorted by "Project Name - Version name"
149 # Those with no effective_date are at the end, sorted by "Project Name - Version name"
145 def <=>(version)
150 def <=>(version)
146 if self.effective_date
151 if self.effective_date
147 if version.effective_date
152 if version.effective_date
148 if self.effective_date == version.effective_date
153 if self.effective_date == version.effective_date
149 "#{self.project.name} - #{self.name}" <=> "#{version.project.name} - #{version.name}"
154 "#{self.project.name} - #{self.name}" <=> "#{version.project.name} - #{version.name}"
150 else
155 else
151 self.effective_date <=> version.effective_date
156 self.effective_date <=> version.effective_date
152 end
157 end
153 else
158 else
154 -1
159 -1
155 end
160 end
156 else
161 else
157 if version.effective_date
162 if version.effective_date
158 1
163 1
159 else
164 else
160 "#{self.project.name} - #{self.name}" <=> "#{version.project.name} - #{version.name}"
165 "#{self.project.name} - #{self.name}" <=> "#{version.project.name} - #{version.name}"
161 end
166 end
162 end
167 end
163 end
168 end
164
169
165 # Returns the sharings that +user+ can set the version to
170 # Returns the sharings that +user+ can set the version to
166 def allowed_sharings(user = User.current)
171 def allowed_sharings(user = User.current)
167 VERSION_SHARINGS.select do |s|
172 VERSION_SHARINGS.select do |s|
168 if sharing == s
173 if sharing == s
169 true
174 true
170 else
175 else
171 case s
176 case s
172 when 'system'
177 when 'system'
173 # Only admin users can set a systemwide sharing
178 # Only admin users can set a systemwide sharing
174 user.admin?
179 user.admin?
175 when 'hierarchy', 'tree'
180 when 'hierarchy', 'tree'
176 # Only users allowed to manage versions of the root project can
181 # Only users allowed to manage versions of the root project can
177 # set sharing to hierarchy or tree
182 # set sharing to hierarchy or tree
178 project.nil? || user.allowed_to?(:manage_versions, project.root)
183 project.nil? || user.allowed_to?(:manage_versions, project.root)
179 else
184 else
180 true
185 true
181 end
186 end
182 end
187 end
183 end
188 end
184 end
189 end
185
190
186 private
191 private
187
192
188 # Update the issue's fixed versions. Used if a version's sharing changes.
193 # Update the issue's fixed versions. Used if a version's sharing changes.
189 def update_issues_from_sharing_change
194 def update_issues_from_sharing_change
190 if sharing_changed?
195 if sharing_changed?
191 if VERSION_SHARINGS.index(sharing_was).nil? ||
196 if VERSION_SHARINGS.index(sharing_was).nil? ||
192 VERSION_SHARINGS.index(sharing).nil? ||
197 VERSION_SHARINGS.index(sharing).nil? ||
193 VERSION_SHARINGS.index(sharing_was) > VERSION_SHARINGS.index(sharing)
198 VERSION_SHARINGS.index(sharing_was) > VERSION_SHARINGS.index(sharing)
194 Issue.update_versions_from_sharing_change self
199 Issue.update_versions_from_sharing_change self
195 end
200 end
196 end
201 end
197 end
202 end
198
203
199 # Returns the average estimated time of assigned issues
204 # Returns the average estimated time of assigned issues
200 # or 1 if no issue has an estimated time
205 # or 1 if no issue has an estimated time
201 # Used to weigth unestimated issues in progress calculation
206 # Used to weigth unestimated issues in progress calculation
202 def estimated_average
207 def estimated_average
203 if @estimated_average.nil?
208 if @estimated_average.nil?
204 average = fixed_issues.average(:estimated_hours).to_f
209 average = fixed_issues.average(:estimated_hours).to_f
205 if average == 0
210 if average == 0
206 average = 1
211 average = 1
207 end
212 end
208 @estimated_average = average
213 @estimated_average = average
209 end
214 end
210 @estimated_average
215 @estimated_average
211 end
216 end
212
217
213 # Returns the total progress of open or closed issues. The returned percentage takes into account
218 # Returns the total progress of open or closed issues. The returned percentage takes into account
214 # the amount of estimated time set for this version.
219 # the amount of estimated time set for this version.
215 #
220 #
216 # Examples:
221 # Examples:
217 # issues_progress(true) => returns the progress percentage for open issues.
222 # issues_progress(true) => returns the progress percentage for open issues.
218 # issues_progress(false) => returns the progress percentage for closed issues.
223 # issues_progress(false) => returns the progress percentage for closed issues.
219 def issues_progress(open)
224 def issues_progress(open)
220 @issues_progress ||= {}
225 @issues_progress ||= {}
221 @issues_progress[open] ||= begin
226 @issues_progress[open] ||= begin
222 progress = 0
227 progress = 0
223 if issues_count > 0
228 if issues_count > 0
224 ratio = open ? 'done_ratio' : 100
229 ratio = open ? 'done_ratio' : 100
225
230
226 done = fixed_issues.sum("COALESCE(estimated_hours, #{estimated_average}) * #{ratio}",
231 done = fixed_issues.sum("COALESCE(estimated_hours, #{estimated_average}) * #{ratio}",
227 :include => :status,
232 :include => :status,
228 :conditions => ["is_closed = ?", !open]).to_f
233 :conditions => ["is_closed = ?", !open]).to_f
229 progress = done / (estimated_average * issues_count)
234 progress = done / (estimated_average * issues_count)
230 end
235 end
231 progress
236 progress
232 end
237 end
233 end
238 end
234 end
239 end
@@ -1,236 +1,236
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: 2007-01-27 15:08:27 +01:00
15 created_on: 2007-01-27 15:08:27 +01: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 description: This is a logo
38 author_id: 2
38 author_id: 2
39 attachments_004:
39 attachments_004:
40 created_on: 2006-07-19 21:07:27 +02:00
40 created_on: 2006-07-19 21:07:27 +02:00
41 container_type: Issue
41 container_type: Issue
42 container_id: 3
42 container_id: 3
43 downloads: 0
43 downloads: 0
44 disk_filename: 060719210727_source.rb
44 disk_filename: 060719210727_source.rb
45 digest: b91e08d0cf966d5c6ff411bd8c4cc3a2
45 digest: b91e08d0cf966d5c6ff411bd8c4cc3a2
46 id: 4
46 id: 4
47 filesize: 153
47 filesize: 153
48 filename: source.rb
48 filename: source.rb
49 author_id: 2
49 author_id: 2
50 description: This is a Ruby source file
50 description: This is a Ruby source file
51 content_type: application/x-ruby
51 content_type: application/x-ruby
52 attachments_005:
52 attachments_005:
53 created_on: 2006-07-19 21:07:27 +02:00
53 created_on: 2006-07-19 21:07:27 +02:00
54 container_type: Issue
54 container_type: Issue
55 container_id: 3
55 container_id: 3
56 downloads: 0
56 downloads: 0
57 disk_filename: 060719210727_changeset_iso8859-1.diff
57 disk_filename: 060719210727_changeset_iso8859-1.diff
58 digest: b91e08d0cf966d5c6ff411bd8c4cc3a2
58 digest: b91e08d0cf966d5c6ff411bd8c4cc3a2
59 id: 5
59 id: 5
60 filesize: 687
60 filesize: 687
61 filename: changeset_iso8859-1.diff
61 filename: changeset_iso8859-1.diff
62 author_id: 2
62 author_id: 2
63 content_type: text/x-diff
63 content_type: text/x-diff
64 attachments_006:
64 attachments_006:
65 created_on: 2006-07-19 21:07:27 +02:00
65 created_on: 2006-07-19 21:07:27 +02:00
66 container_type: Issue
66 container_type: Issue
67 container_id: 3
67 container_id: 3
68 downloads: 0
68 downloads: 0
69 disk_filename: 060719210727_archive.zip
69 disk_filename: 060719210727_archive.zip
70 digest: b91e08d0cf966d5c6ff411bd8c4cc3a2
70 digest: b91e08d0cf966d5c6ff411bd8c4cc3a2
71 id: 6
71 id: 6
72 filesize: 157
72 filesize: 157
73 filename: archive.zip
73 filename: archive.zip
74 author_id: 2
74 author_id: 2
75 content_type: application/octet-stream
75 content_type: application/octet-stream
76 attachments_007:
76 attachments_007:
77 created_on: 2006-07-19 21:07:27 +02:00
77 created_on: 2006-07-19 21:07:27 +02:00
78 container_type: Issue
78 container_type: Issue
79 container_id: 4
79 container_id: 4
80 downloads: 0
80 downloads: 0
81 disk_filename: 060719210727_archive.zip
81 disk_filename: 060719210727_archive.zip
82 digest: b91e08d0cf966d5c6ff411bd8c4cc3a2
82 digest: b91e08d0cf966d5c6ff411bd8c4cc3a2
83 id: 7
83 id: 7
84 filesize: 157
84 filesize: 157
85 filename: archive.zip
85 filename: archive.zip
86 author_id: 1
86 author_id: 1
87 content_type: application/octet-stream
87 content_type: application/octet-stream
88 attachments_008:
88 attachments_008:
89 created_on: 2006-07-19 21:07:27 +02:00
89 created_on: 2006-07-19 21:07:27 +02:00
90 container_type: Project
90 container_type: Project
91 container_id: 1
91 container_id: 1
92 downloads: 0
92 downloads: 0
93 disk_filename: 060719210727_project_file.zip
93 disk_filename: 060719210727_project_file.zip
94 digest: b91e08d0cf966d5c6ff411bd8c4cc3a2
94 digest: b91e08d0cf966d5c6ff411bd8c4cc3a2
95 id: 8
95 id: 8
96 filesize: 320
96 filesize: 320
97 filename: project_file.zip
97 filename: project_file.zip
98 author_id: 2
98 author_id: 2
99 content_type: application/octet-stream
99 content_type: application/octet-stream
100 attachments_009:
100 attachments_009:
101 created_on: 2006-07-19 21:07:27 +02:00
101 created_on: 2006-07-19 21:07:27 +02:00
102 container_type: Version
102 container_type: Version
103 container_id: 1
103 container_id: 1
104 downloads: 0
104 downloads: 0
105 disk_filename: 060719210727_version_file.zip
105 disk_filename: 060719210727_archive.zip
106 digest: b91e08d0cf966d5c6ff411bd8c4cc3a2
106 digest: b91e08d0cf966d5c6ff411bd8c4cc3a2
107 id: 9
107 id: 9
108 filesize: 452
108 filesize: 452
109 filename: version_file.zip
109 filename: version_file.zip
110 author_id: 2
110 author_id: 2
111 content_type: application/octet-stream
111 content_type: application/octet-stream
112 attachments_010:
112 attachments_010:
113 created_on: 2006-07-19 21:07:27 +02:00
113 created_on: 2006-07-19 21:07:27 +02:00
114 container_type: Issue
114 container_type: Issue
115 container_id: 2
115 container_id: 2
116 downloads: 0
116 downloads: 0
117 disk_filename: 060719210727_picture.jpg
117 disk_filename: 060719210727_picture.jpg
118 digest: b91e08d0cf966d5c6ff411bd8c4cc3a2
118 digest: b91e08d0cf966d5c6ff411bd8c4cc3a2
119 id: 10
119 id: 10
120 filesize: 452
120 filesize: 452
121 filename: picture.jpg
121 filename: picture.jpg
122 author_id: 2
122 author_id: 2
123 content_type: image/jpeg
123 content_type: image/jpeg
124 attachments_011:
124 attachments_011:
125 created_on: 2007-02-12 15:08:27 +01:00
125 created_on: 2007-02-12 15:08:27 +01:00
126 container_type: Document
126 container_type: Document
127 container_id: 1
127 container_id: 1
128 downloads: 0
128 downloads: 0
129 disk_filename: 060719210727_picture.jpg
129 disk_filename: 060719210727_picture.jpg
130 digest: b91e08d0cf966d5c6ff411bd8c4cc3a2
130 digest: b91e08d0cf966d5c6ff411bd8c4cc3a2
131 id: 11
131 id: 11
132 filesize: 452
132 filesize: 452
133 filename: picture.jpg
133 filename: picture.jpg
134 author_id: 2
134 author_id: 2
135 content_type: image/jpeg
135 content_type: image/jpeg
136 attachments_012:
136 attachments_012:
137 created_on: 2006-07-19 21:07:27 +02:00
137 created_on: 2006-07-19 21:07:27 +02:00
138 container_type: Version
138 container_type: Version
139 container_id: 1
139 container_id: 1
140 downloads: 0
140 downloads: 0
141 disk_filename: 060719210727_version_file.zip
141 disk_filename: 060719210727_version_file.zip
142 digest: b91e08d0cf966d5c6ff411bd8c4cc3a2
142 digest: b91e08d0cf966d5c6ff411bd8c4cc3a2
143 id: 12
143 id: 12
144 filesize: 452
144 filesize: 452
145 filename: version_file.zip
145 filename: version_file.zip
146 author_id: 2
146 author_id: 2
147 content_type: application/octet-stream
147 content_type: application/octet-stream
148 attachments_013:
148 attachments_013:
149 created_on: 2006-07-19 21:07:27 +02:00
149 created_on: 2006-07-19 21:07:27 +02:00
150 container_type: Message
150 container_type: Message
151 container_id: 1
151 container_id: 1
152 downloads: 0
152 downloads: 0
153 disk_filename: 060719210727_foo.zip
153 disk_filename: 060719210727_foo.zip
154 digest: b91e08d0cf966d5c6ff411bd8c4cc3a2
154 digest: b91e08d0cf966d5c6ff411bd8c4cc3a2
155 id: 13
155 id: 13
156 filesize: 452
156 filesize: 452
157 filename: foo.zip
157 filename: foo.zip
158 author_id: 2
158 author_id: 2
159 content_type: application/octet-stream
159 content_type: application/octet-stream
160 attachments_014:
160 attachments_014:
161 created_on: 2006-07-19 21:07:27 +02:00
161 created_on: 2006-07-19 21:07:27 +02:00
162 container_type: Issue
162 container_type: Issue
163 container_id: 3
163 container_id: 3
164 downloads: 0
164 downloads: 0
165 disk_filename: 060719210727_changeset_utf8.diff
165 disk_filename: 060719210727_changeset_utf8.diff
166 digest: b91e08d0cf966d5c6ff411bd8c4cc3a2
166 digest: b91e08d0cf966d5c6ff411bd8c4cc3a2
167 id: 14
167 id: 14
168 filesize: 687
168 filesize: 687
169 filename: changeset_utf8.diff
169 filename: changeset_utf8.diff
170 author_id: 2
170 author_id: 2
171 content_type: text/x-diff
171 content_type: text/x-diff
172 attachments_015:
172 attachments_015:
173 id: 15
173 id: 15
174 created_on: 2010-07-19 21:07:27 +02:00
174 created_on: 2010-07-19 21:07:27 +02:00
175 container_type: Issue
175 container_type: Issue
176 container_id: 14
176 container_id: 14
177 downloads: 0
177 downloads: 0
178 disk_filename: 060719210727_changeset_utf8.diff
178 disk_filename: 060719210727_changeset_utf8.diff
179 digest: b91e08d0cf966d5c6ff411bd8c4cc3a2
179 digest: b91e08d0cf966d5c6ff411bd8c4cc3a2
180 filesize: 687
180 filesize: 687
181 filename: private.diff
181 filename: private.diff
182 author_id: 2
182 author_id: 2
183 content_type: text/x-diff
183 content_type: text/x-diff
184 description: attachement of a private issue
184 description: attachement of a private issue
185 attachments_016:
185 attachments_016:
186 content_type: image/png
186 content_type: image/png
187 downloads: 0
187 downloads: 0
188 created_on: 2010-11-23 16:14:50 +09:00
188 created_on: 2010-11-23 16:14:50 +09:00
189 disk_filename: 101123161450_testfile_1.png
189 disk_filename: 101123161450_testfile_1.png
190 container_id: 14
190 container_id: 14
191 digest: 8e0294de2441577c529f170b6fb8f638
191 digest: 8e0294de2441577c529f170b6fb8f638
192 id: 16
192 id: 16
193 container_type: Issue
193 container_type: Issue
194 description: ""
194 description: ""
195 filename: testfile.png
195 filename: testfile.png
196 filesize: 2654
196 filesize: 2654
197 author_id: 2
197 author_id: 2
198 attachments_017:
198 attachments_017:
199 content_type: image/png
199 content_type: image/png
200 downloads: 0
200 downloads: 0
201 created_on: 2010-12-23 16:14:50 +09:00
201 created_on: 2010-12-23 16:14:50 +09:00
202 disk_filename: 101223161450_testfile_2.png
202 disk_filename: 101223161450_testfile_2.png
203 container_id: 14
203 container_id: 14
204 digest: 6bc2963e8d7ea0d3e68d12d1fba3d6ca
204 digest: 6bc2963e8d7ea0d3e68d12d1fba3d6ca
205 id: 17
205 id: 17
206 container_type: Issue
206 container_type: Issue
207 description: ""
207 description: ""
208 filename: testfile.PNG
208 filename: testfile.PNG
209 filesize: 3582
209 filesize: 3582
210 author_id: 2
210 author_id: 2
211 attachments_018:
211 attachments_018:
212 content_type: image/png
212 content_type: image/png
213 downloads: 0
213 downloads: 0
214 created_on: 2011-01-23 16:14:50 +09:00
214 created_on: 2011-01-23 16:14:50 +09:00
215 disk_filename: 101123161450_testfile_1.png
215 disk_filename: 101123161450_testfile_1.png
216 container_id: 14
216 container_id: 14
217 digest: 8e0294de2441577c529f170b6fb8f638
217 digest: 8e0294de2441577c529f170b6fb8f638
218 id: 18
218 id: 18
219 container_type: Issue
219 container_type: Issue
220 description: ""
220 description: ""
221 filename: testγƒ†γ‚Ήγƒˆ.png
221 filename: testγƒ†γ‚Ήγƒˆ.png
222 filesize: 2654
222 filesize: 2654
223 author_id: 2
223 author_id: 2
224 attachments_019:
224 attachments_019:
225 content_type: image/png
225 content_type: image/png
226 downloads: 0
226 downloads: 0
227 created_on: 2011-02-23 16:14:50 +09:00
227 created_on: 2011-02-23 16:14:50 +09:00
228 disk_filename: 101223161450_testfile_2.png
228 disk_filename: 101223161450_testfile_2.png
229 container_id: 14
229 container_id: 14
230 digest: 6bc2963e8d7ea0d3e68d12d1fba3d6ca
230 digest: 6bc2963e8d7ea0d3e68d12d1fba3d6ca
231 id: 19
231 id: 19
232 container_type: Issue
232 container_type: Issue
233 description: ""
233 description: ""
234 filename: Testγƒ†γ‚Ήγƒˆ.PNG
234 filename: Testγƒ†γ‚Ήγƒˆ.PNG
235 filesize: 3582
235 filesize: 3582
236 author_id: 2
236 author_id: 2
@@ -1,274 +1,280
1 # encoding: utf-8
1 # encoding: utf-8
2 #
2 #
3 # Redmine - project management software
3 # Redmine - project management software
4 # Copyright (C) 2006-2011 Jean-Philippe Lang
4 # Copyright (C) 2006-2011 Jean-Philippe Lang
5 #
5 #
6 # This program is free software; you can redistribute it and/or
6 # This program is free software; you can redistribute it and/or
7 # modify it under the terms of the GNU General Public License
7 # modify it under the terms of the GNU General Public License
8 # as published by the Free Software Foundation; either version 2
8 # as published by the Free Software Foundation; either version 2
9 # of the License, or (at your option) any later version.
9 # of the License, or (at your option) any later version.
10 #
10 #
11 # This program is distributed in the hope that it will be useful,
11 # This program is distributed in the hope that it will be useful,
12 # but WITHOUT ANY WARRANTY; without even the implied warranty of
12 # but WITHOUT ANY WARRANTY; without even the implied warranty of
13 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 # GNU General Public License for more details.
14 # GNU General Public License for more details.
15 #
15 #
16 # You should have received a copy of the GNU General Public License
16 # You should have received a copy of the GNU General Public License
17 # along with this program; if not, write to the Free Software
17 # along with this program; if not, write to the Free Software
18 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
18 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
19
19
20 require File.expand_path('../../test_helper', __FILE__)
20 require File.expand_path('../../test_helper', __FILE__)
21 require 'attachments_controller'
21 require 'attachments_controller'
22
22
23 # Re-raise errors caught by the controller.
23 # Re-raise errors caught by the controller.
24 class AttachmentsController; def rescue_action(e) raise e end; end
24 class AttachmentsController; def rescue_action(e) raise e end; end
25
25
26 class AttachmentsControllerTest < ActionController::TestCase
26 class AttachmentsControllerTest < ActionController::TestCase
27 fixtures :users, :projects, :roles, :members, :member_roles,
27 fixtures :users, :projects, :roles, :members, :member_roles,
28 :enabled_modules, :issues, :trackers, :attachments,
28 :enabled_modules, :issues, :trackers, :attachments,
29 :versions, :wiki_pages, :wikis, :documents
29 :versions, :wiki_pages, :wikis, :documents
30
30
31 def setup
31 def setup
32 @controller = AttachmentsController.new
32 @controller = AttachmentsController.new
33 @request = ActionController::TestRequest.new
33 @request = ActionController::TestRequest.new
34 @response = ActionController::TestResponse.new
34 @response = ActionController::TestResponse.new
35 Attachment.storage_path = "#{Rails.root}/test/fixtures/files"
35 Attachment.storage_path = "#{Rails.root}/test/fixtures/files"
36 User.current = nil
36 User.current = nil
37 end
37 end
38
38
39 def test_show_diff
39 def test_show_diff
40 ['inline', 'sbs'].each do |dt|
40 ['inline', 'sbs'].each do |dt|
41 # 060719210727_changeset_utf8.diff
41 # 060719210727_changeset_utf8.diff
42 get :show, :id => 14, :type => dt
42 get :show, :id => 14, :type => dt
43 assert_response :success
43 assert_response :success
44 assert_template 'diff'
44 assert_template 'diff'
45 assert_equal 'text/html', @response.content_type
45 assert_equal 'text/html', @response.content_type
46 assert_tag 'th',
46 assert_tag 'th',
47 :attributes => {:class => /filename/},
47 :attributes => {:class => /filename/},
48 :content => /issues_controller.rb\t\(rΓ©vision 1484\)/
48 :content => /issues_controller.rb\t\(rΓ©vision 1484\)/
49 assert_tag 'td',
49 assert_tag 'td',
50 :attributes => {:class => /line-code/},
50 :attributes => {:class => /line-code/},
51 :content => /Demande créée avec succès/
51 :content => /Demande créée avec succès/
52 end
52 end
53 set_tmp_attachments_directory
53 set_tmp_attachments_directory
54 end
54 end
55
55
56 def test_show_diff_replcace_cannot_convert_content
56 def test_show_diff_replcace_cannot_convert_content
57 with_settings :repositories_encodings => 'UTF-8' do
57 with_settings :repositories_encodings => 'UTF-8' do
58 ['inline', 'sbs'].each do |dt|
58 ['inline', 'sbs'].each do |dt|
59 # 060719210727_changeset_iso8859-1.diff
59 # 060719210727_changeset_iso8859-1.diff
60 get :show, :id => 5, :type => dt
60 get :show, :id => 5, :type => dt
61 assert_response :success
61 assert_response :success
62 assert_template 'diff'
62 assert_template 'diff'
63 assert_equal 'text/html', @response.content_type
63 assert_equal 'text/html', @response.content_type
64 assert_tag 'th',
64 assert_tag 'th',
65 :attributes => {:class => "filename"},
65 :attributes => {:class => "filename"},
66 :content => /issues_controller.rb\t\(r\?vision 1484\)/
66 :content => /issues_controller.rb\t\(r\?vision 1484\)/
67 assert_tag 'td',
67 assert_tag 'td',
68 :attributes => {:class => /line-code/},
68 :attributes => {:class => /line-code/},
69 :content => /Demande cr\?\?e avec succ\?s/
69 :content => /Demande cr\?\?e avec succ\?s/
70 end
70 end
71 end
71 end
72 set_tmp_attachments_directory
72 set_tmp_attachments_directory
73 end
73 end
74
74
75 def test_show_diff_latin_1
75 def test_show_diff_latin_1
76 with_settings :repositories_encodings => 'UTF-8,ISO-8859-1' do
76 with_settings :repositories_encodings => 'UTF-8,ISO-8859-1' do
77 ['inline', 'sbs'].each do |dt|
77 ['inline', 'sbs'].each do |dt|
78 # 060719210727_changeset_iso8859-1.diff
78 # 060719210727_changeset_iso8859-1.diff
79 get :show, :id => 5, :type => dt
79 get :show, :id => 5, :type => dt
80 assert_response :success
80 assert_response :success
81 assert_template 'diff'
81 assert_template 'diff'
82 assert_equal 'text/html', @response.content_type
82 assert_equal 'text/html', @response.content_type
83 assert_tag 'th',
83 assert_tag 'th',
84 :attributes => {:class => "filename"},
84 :attributes => {:class => "filename"},
85 :content => /issues_controller.rb\t\(rΓ©vision 1484\)/
85 :content => /issues_controller.rb\t\(rΓ©vision 1484\)/
86 assert_tag 'td',
86 assert_tag 'td',
87 :attributes => {:class => /line-code/},
87 :attributes => {:class => /line-code/},
88 :content => /Demande créée avec succès/
88 :content => /Demande créée avec succès/
89 end
89 end
90 end
90 end
91 set_tmp_attachments_directory
91 set_tmp_attachments_directory
92 end
92 end
93
93
94 def test_show_text_file
94 def test_show_text_file
95 get :show, :id => 4
95 get :show, :id => 4
96 assert_response :success
96 assert_response :success
97 assert_template 'file'
97 assert_template 'file'
98 assert_equal 'text/html', @response.content_type
98 assert_equal 'text/html', @response.content_type
99 set_tmp_attachments_directory
99 set_tmp_attachments_directory
100 end
100 end
101
101
102 def test_show_text_file_utf_8
102 def test_show_text_file_utf_8
103 set_tmp_attachments_directory
103 set_tmp_attachments_directory
104 a = Attachment.new(:container => Issue.find(1),
104 a = Attachment.new(:container => Issue.find(1),
105 :file => uploaded_test_file("japanese-utf-8.txt", "text/plain"),
105 :file => uploaded_test_file("japanese-utf-8.txt", "text/plain"),
106 :author => User.find(1))
106 :author => User.find(1))
107 assert a.save
107 assert a.save
108 assert_equal 'japanese-utf-8.txt', a.filename
108 assert_equal 'japanese-utf-8.txt', a.filename
109
109
110 str_japanese = "\xe6\x97\xa5\xe6\x9c\xac\xe8\xaa\x9e"
110 str_japanese = "\xe6\x97\xa5\xe6\x9c\xac\xe8\xaa\x9e"
111 str_japanese.force_encoding('UTF-8') if str_japanese.respond_to?(:force_encoding)
111 str_japanese.force_encoding('UTF-8') if str_japanese.respond_to?(:force_encoding)
112
112
113 get :show, :id => a.id
113 get :show, :id => a.id
114 assert_response :success
114 assert_response :success
115 assert_template 'file'
115 assert_template 'file'
116 assert_equal 'text/html', @response.content_type
116 assert_equal 'text/html', @response.content_type
117 assert_tag :tag => 'th',
117 assert_tag :tag => 'th',
118 :content => '1',
118 :content => '1',
119 :attributes => { :class => 'line-num' },
119 :attributes => { :class => 'line-num' },
120 :sibling => { :tag => 'td', :content => /#{str_japanese}/ }
120 :sibling => { :tag => 'td', :content => /#{str_japanese}/ }
121 end
121 end
122
122
123 def test_show_text_file_replcace_cannot_convert_content
123 def test_show_text_file_replcace_cannot_convert_content
124 set_tmp_attachments_directory
124 set_tmp_attachments_directory
125 with_settings :repositories_encodings => 'UTF-8' do
125 with_settings :repositories_encodings => 'UTF-8' do
126 a = Attachment.new(:container => Issue.find(1),
126 a = Attachment.new(:container => Issue.find(1),
127 :file => uploaded_test_file("iso8859-1.txt", "text/plain"),
127 :file => uploaded_test_file("iso8859-1.txt", "text/plain"),
128 :author => User.find(1))
128 :author => User.find(1))
129 assert a.save
129 assert a.save
130 assert_equal 'iso8859-1.txt', a.filename
130 assert_equal 'iso8859-1.txt', a.filename
131
131
132 get :show, :id => a.id
132 get :show, :id => a.id
133 assert_response :success
133 assert_response :success
134 assert_template 'file'
134 assert_template 'file'
135 assert_equal 'text/html', @response.content_type
135 assert_equal 'text/html', @response.content_type
136 assert_tag :tag => 'th',
136 assert_tag :tag => 'th',
137 :content => '7',
137 :content => '7',
138 :attributes => { :class => 'line-num' },
138 :attributes => { :class => 'line-num' },
139 :sibling => { :tag => 'td', :content => /Demande cr\?\?e avec succ\?s/ }
139 :sibling => { :tag => 'td', :content => /Demande cr\?\?e avec succ\?s/ }
140 end
140 end
141 end
141 end
142
142
143 def test_show_text_file_latin_1
143 def test_show_text_file_latin_1
144 set_tmp_attachments_directory
144 set_tmp_attachments_directory
145 with_settings :repositories_encodings => 'UTF-8,ISO-8859-1' do
145 with_settings :repositories_encodings => 'UTF-8,ISO-8859-1' do
146 a = Attachment.new(:container => Issue.find(1),
146 a = Attachment.new(:container => Issue.find(1),
147 :file => uploaded_test_file("iso8859-1.txt", "text/plain"),
147 :file => uploaded_test_file("iso8859-1.txt", "text/plain"),
148 :author => User.find(1))
148 :author => User.find(1))
149 assert a.save
149 assert a.save
150 assert_equal 'iso8859-1.txt', a.filename
150 assert_equal 'iso8859-1.txt', a.filename
151
151
152 get :show, :id => a.id
152 get :show, :id => a.id
153 assert_response :success
153 assert_response :success
154 assert_template 'file'
154 assert_template 'file'
155 assert_equal 'text/html', @response.content_type
155 assert_equal 'text/html', @response.content_type
156 assert_tag :tag => 'th',
156 assert_tag :tag => 'th',
157 :content => '7',
157 :content => '7',
158 :attributes => { :class => 'line-num' },
158 :attributes => { :class => 'line-num' },
159 :sibling => { :tag => 'td', :content => /Demande créée avec succès/ }
159 :sibling => { :tag => 'td', :content => /Demande créée avec succès/ }
160 end
160 end
161 end
161 end
162
162
163 def test_show_text_file_should_send_if_too_big
163 def test_show_text_file_should_send_if_too_big
164 Setting.file_max_size_displayed = 512
164 Setting.file_max_size_displayed = 512
165 Attachment.find(4).update_attribute :filesize, 754.kilobyte
165 Attachment.find(4).update_attribute :filesize, 754.kilobyte
166
166
167 get :show, :id => 4
167 get :show, :id => 4
168 assert_response :success
168 assert_response :success
169 assert_equal 'application/x-ruby', @response.content_type
169 assert_equal 'application/x-ruby', @response.content_type
170 set_tmp_attachments_directory
170 set_tmp_attachments_directory
171 end
171 end
172
172
173 def test_show_other
173 def test_show_other
174 get :show, :id => 6
174 get :show, :id => 6
175 assert_response :success
175 assert_response :success
176 assert_equal 'application/octet-stream', @response.content_type
176 assert_equal 'application/octet-stream', @response.content_type
177 set_tmp_attachments_directory
177 set_tmp_attachments_directory
178 end
178 end
179
179
180 def test_show_file_from_private_issue_without_permission
180 def test_show_file_from_private_issue_without_permission
181 get :show, :id => 15
181 get :show, :id => 15
182 assert_redirected_to '/login?back_url=http%3A%2F%2Ftest.host%2Fattachments%2F15'
182 assert_redirected_to '/login?back_url=http%3A%2F%2Ftest.host%2Fattachments%2F15'
183 set_tmp_attachments_directory
183 set_tmp_attachments_directory
184 end
184 end
185
185
186 def test_show_file_from_private_issue_with_permission
186 def test_show_file_from_private_issue_with_permission
187 @request.session[:user_id] = 2
187 @request.session[:user_id] = 2
188 get :show, :id => 15
188 get :show, :id => 15
189 assert_response :success
189 assert_response :success
190 assert_tag 'h2', :content => /private.diff/
190 assert_tag 'h2', :content => /private.diff/
191 set_tmp_attachments_directory
191 set_tmp_attachments_directory
192 end
192 end
193
193
194 def test_download_text_file
194 def test_download_text_file
195 get :download, :id => 4
195 get :download, :id => 4
196 assert_response :success
196 assert_response :success
197 assert_equal 'application/x-ruby', @response.content_type
197 assert_equal 'application/x-ruby', @response.content_type
198 set_tmp_attachments_directory
198 set_tmp_attachments_directory
199 end
199 end
200
200
201 def test_download_version_file_with_issue_tracking_disabled
202 Project.find(1).disable_module! :issue_tracking
203 get :download, :id => 9
204 assert_response :success
205 end
206
201 def test_download_should_assign_content_type_if_blank
207 def test_download_should_assign_content_type_if_blank
202 Attachment.find(4).update_attribute(:content_type, '')
208 Attachment.find(4).update_attribute(:content_type, '')
203
209
204 get :download, :id => 4
210 get :download, :id => 4
205 assert_response :success
211 assert_response :success
206 assert_equal 'text/x-ruby', @response.content_type
212 assert_equal 'text/x-ruby', @response.content_type
207 set_tmp_attachments_directory
213 set_tmp_attachments_directory
208 end
214 end
209
215
210 def test_download_missing_file
216 def test_download_missing_file
211 get :download, :id => 2
217 get :download, :id => 2
212 assert_response 404
218 assert_response 404
213 set_tmp_attachments_directory
219 set_tmp_attachments_directory
214 end
220 end
215
221
216 def test_anonymous_on_private_private
222 def test_anonymous_on_private_private
217 get :download, :id => 7
223 get :download, :id => 7
218 assert_redirected_to '/login?back_url=http%3A%2F%2Ftest.host%2Fattachments%2Fdownload%2F7'
224 assert_redirected_to '/login?back_url=http%3A%2F%2Ftest.host%2Fattachments%2Fdownload%2F7'
219 set_tmp_attachments_directory
225 set_tmp_attachments_directory
220 end
226 end
221
227
222 def test_destroy_issue_attachment
228 def test_destroy_issue_attachment
223 set_tmp_attachments_directory
229 set_tmp_attachments_directory
224 issue = Issue.find(3)
230 issue = Issue.find(3)
225 @request.session[:user_id] = 2
231 @request.session[:user_id] = 2
226
232
227 assert_difference 'issue.attachments.count', -1 do
233 assert_difference 'issue.attachments.count', -1 do
228 delete :destroy, :id => 1
234 delete :destroy, :id => 1
229 end
235 end
230 # no referrer
236 # no referrer
231 assert_redirected_to '/projects/ecookbook'
237 assert_redirected_to '/projects/ecookbook'
232 assert_nil Attachment.find_by_id(1)
238 assert_nil Attachment.find_by_id(1)
233 j = issue.journals.find(:first, :order => 'created_on DESC')
239 j = issue.journals.find(:first, :order => 'created_on DESC')
234 assert_equal 'attachment', j.details.first.property
240 assert_equal 'attachment', j.details.first.property
235 assert_equal '1', j.details.first.prop_key
241 assert_equal '1', j.details.first.prop_key
236 assert_equal 'error281.txt', j.details.first.old_value
242 assert_equal 'error281.txt', j.details.first.old_value
237 end
243 end
238
244
239 def test_destroy_wiki_page_attachment
245 def test_destroy_wiki_page_attachment
240 set_tmp_attachments_directory
246 set_tmp_attachments_directory
241 @request.session[:user_id] = 2
247 @request.session[:user_id] = 2
242 assert_difference 'Attachment.count', -1 do
248 assert_difference 'Attachment.count', -1 do
243 delete :destroy, :id => 3
249 delete :destroy, :id => 3
244 assert_response 302
250 assert_response 302
245 end
251 end
246 end
252 end
247
253
248 def test_destroy_project_attachment
254 def test_destroy_project_attachment
249 set_tmp_attachments_directory
255 set_tmp_attachments_directory
250 @request.session[:user_id] = 2
256 @request.session[:user_id] = 2
251 assert_difference 'Attachment.count', -1 do
257 assert_difference 'Attachment.count', -1 do
252 delete :destroy, :id => 8
258 delete :destroy, :id => 8
253 assert_response 302
259 assert_response 302
254 end
260 end
255 end
261 end
256
262
257 def test_destroy_version_attachment
263 def test_destroy_version_attachment
258 set_tmp_attachments_directory
264 set_tmp_attachments_directory
259 @request.session[:user_id] = 2
265 @request.session[:user_id] = 2
260 assert_difference 'Attachment.count', -1 do
266 assert_difference 'Attachment.count', -1 do
261 delete :destroy, :id => 9
267 delete :destroy, :id => 9
262 assert_response 302
268 assert_response 302
263 end
269 end
264 end
270 end
265
271
266 def test_destroy_without_permission
272 def test_destroy_without_permission
267 set_tmp_attachments_directory
273 set_tmp_attachments_directory
268 assert_no_difference 'Attachment.count' do
274 assert_no_difference 'Attachment.count' do
269 delete :destroy, :id => 3
275 delete :destroy, :id => 3
270 end
276 end
271 assert_response 302
277 assert_response 302
272 assert Attachment.find_by_id(3)
278 assert Attachment.find_by_id(3)
273 end
279 end
274 end
280 end
General Comments 0
You need to be logged in to leave comments. Login now