##// END OF EJS Templates
Fixed attachment fixture (should be attached to issue 3 because one of its journals references it), r13937....
Jean-Philippe Lang -
r13560:b50fa8fec19b
parent child
Show More
@@ -1,269 +1,269
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 disk_directory: "2006/07"
7 disk_directory: "2006/07"
8 container_id: 3
8 container_id: 3
9 digest: b91e08d0cf966d5c6ff411bd8c4cc3a2
9 digest: b91e08d0cf966d5c6ff411bd8c4cc3a2
10 id: 1
10 id: 1
11 container_type: Issue
11 container_type: Issue
12 filesize: 28
12 filesize: 28
13 filename: error281.txt
13 filename: error281.txt
14 author_id: 2
14 author_id: 2
15 attachments_002:
15 attachments_002:
16 created_on: 2007-01-27 15:08:27 +01:00
16 created_on: 2007-01-27 15:08:27 +01:00
17 downloads: 0
17 downloads: 0
18 content_type: text/plain
18 content_type: text/plain
19 disk_filename: 060719210727_document.txt
19 disk_filename: 060719210727_document.txt
20 disk_directory: "2006/07"
20 disk_directory: "2006/07"
21 container_id: 1
21 container_id: 1
22 digest: b91e08d0cf966d5c6ff411bd8c4cc3a2
22 digest: b91e08d0cf966d5c6ff411bd8c4cc3a2
23 id: 2
23 id: 2
24 container_type: Document
24 container_type: Document
25 filesize: 28
25 filesize: 28
26 filename: document.txt
26 filename: document.txt
27 author_id: 2
27 author_id: 2
28 attachments_003:
28 attachments_003:
29 created_on: 2006-07-19 21:07:27 +02:00
29 created_on: 2006-07-19 21:07:27 +02:00
30 downloads: 0
30 downloads: 0
31 content_type: image/gif
31 content_type: image/gif
32 disk_filename: 060719210727_logo.gif
32 disk_filename: 060719210727_logo.gif
33 disk_directory: "2006/07"
33 disk_directory: "2006/07"
34 container_id: 4
34 container_id: 4
35 digest: b91e08d0cf966d5c6ff411bd8c4cc3a2
35 digest: b91e08d0cf966d5c6ff411bd8c4cc3a2
36 id: 3
36 id: 3
37 container_type: WikiPage
37 container_type: WikiPage
38 filesize: 280
38 filesize: 280
39 filename: logo.gif
39 filename: logo.gif
40 description: This is a logo
40 description: This is a logo
41 author_id: 2
41 author_id: 2
42 attachments_004:
42 attachments_004:
43 created_on: 2006-07-19 21:07:27 +02:00
43 created_on: 2006-07-19 21:07:27 +02:00
44 container_type: Issue
44 container_type: Issue
45 container_id: 3
45 container_id: 2
46 downloads: 0
46 downloads: 0
47 disk_filename: 060719210727_source.rb
47 disk_filename: 060719210727_source.rb
48 disk_directory: "2006/07"
48 disk_directory: "2006/07"
49 digest: b91e08d0cf966d5c6ff411bd8c4cc3a2
49 digest: b91e08d0cf966d5c6ff411bd8c4cc3a2
50 id: 4
50 id: 4
51 filesize: 153
51 filesize: 153
52 filename: source.rb
52 filename: source.rb
53 author_id: 2
53 author_id: 2
54 description: This is a Ruby source file
54 description: This is a Ruby source file
55 content_type: application/x-ruby
55 content_type: application/x-ruby
56 attachments_005:
56 attachments_005:
57 created_on: 2006-07-19 21:07:27 +02:00
57 created_on: 2006-07-19 21:07:27 +02:00
58 container_type: Issue
58 container_type: Issue
59 container_id: 3
59 container_id: 3
60 downloads: 0
60 downloads: 0
61 disk_filename: 060719210727_changeset_iso8859-1.diff
61 disk_filename: 060719210727_changeset_iso8859-1.diff
62 disk_directory: "2006/07"
62 disk_directory: "2006/07"
63 digest: b91e08d0cf966d5c6ff411bd8c4cc3a2
63 digest: b91e08d0cf966d5c6ff411bd8c4cc3a2
64 id: 5
64 id: 5
65 filesize: 687
65 filesize: 687
66 filename: changeset_iso8859-1.diff
66 filename: changeset_iso8859-1.diff
67 author_id: 2
67 author_id: 2
68 content_type: text/x-diff
68 content_type: text/x-diff
69 attachments_006:
69 attachments_006:
70 created_on: 2006-07-19 21:07:27 +02:00
70 created_on: 2006-07-19 21:07:27 +02:00
71 container_type: Issue
71 container_type: Issue
72 container_id: 3
72 container_id: 3
73 downloads: 0
73 downloads: 0
74 disk_filename: 060719210727_archive.zip
74 disk_filename: 060719210727_archive.zip
75 disk_directory: "2006/07"
75 disk_directory: "2006/07"
76 digest: b91e08d0cf966d5c6ff411bd8c4cc3a2
76 digest: b91e08d0cf966d5c6ff411bd8c4cc3a2
77 id: 6
77 id: 6
78 filesize: 157
78 filesize: 157
79 filename: archive.zip
79 filename: archive.zip
80 author_id: 2
80 author_id: 2
81 content_type: application/octet-stream
81 content_type: application/octet-stream
82 attachments_007:
82 attachments_007:
83 created_on: 2006-07-19 21:07:27 +02:00
83 created_on: 2006-07-19 21:07:27 +02:00
84 container_type: Issue
84 container_type: Issue
85 container_id: 4
85 container_id: 4
86 downloads: 0
86 downloads: 0
87 disk_filename: 060719210727_archive.zip
87 disk_filename: 060719210727_archive.zip
88 disk_directory: "2006/07"
88 disk_directory: "2006/07"
89 digest: b91e08d0cf966d5c6ff411bd8c4cc3a2
89 digest: b91e08d0cf966d5c6ff411bd8c4cc3a2
90 id: 7
90 id: 7
91 filesize: 157
91 filesize: 157
92 filename: archive.zip
92 filename: archive.zip
93 author_id: 1
93 author_id: 1
94 content_type: application/octet-stream
94 content_type: application/octet-stream
95 attachments_008:
95 attachments_008:
96 created_on: 2006-07-19 21:07:27 +02:00
96 created_on: 2006-07-19 21:07:27 +02:00
97 container_type: Project
97 container_type: Project
98 container_id: 1
98 container_id: 1
99 downloads: 0
99 downloads: 0
100 disk_filename: 060719210727_project_file.zip
100 disk_filename: 060719210727_project_file.zip
101 disk_directory: "2006/07"
101 disk_directory: "2006/07"
102 digest: b91e08d0cf966d5c6ff411bd8c4cc3a2
102 digest: b91e08d0cf966d5c6ff411bd8c4cc3a2
103 id: 8
103 id: 8
104 filesize: 320
104 filesize: 320
105 filename: project_file.zip
105 filename: project_file.zip
106 author_id: 2
106 author_id: 2
107 content_type: application/octet-stream
107 content_type: application/octet-stream
108 attachments_009:
108 attachments_009:
109 created_on: 2006-07-19 21:07:27 +02:00
109 created_on: 2006-07-19 21:07:27 +02:00
110 container_type: Version
110 container_type: Version
111 container_id: 1
111 container_id: 1
112 downloads: 0
112 downloads: 0
113 disk_filename: 060719210727_archive.zip
113 disk_filename: 060719210727_archive.zip
114 disk_directory: "2006/07"
114 disk_directory: "2006/07"
115 digest: b91e08d0cf966d5c6ff411bd8c4cc3a2
115 digest: b91e08d0cf966d5c6ff411bd8c4cc3a2
116 id: 9
116 id: 9
117 filesize: 452
117 filesize: 452
118 filename: version_file.zip
118 filename: version_file.zip
119 author_id: 2
119 author_id: 2
120 content_type: application/octet-stream
120 content_type: application/octet-stream
121 attachments_010:
121 attachments_010:
122 created_on: 2006-07-19 21:07:27 +02:00
122 created_on: 2006-07-19 21:07:27 +02:00
123 container_type: Issue
123 container_type: Issue
124 container_id: 2
124 container_id: 2
125 downloads: 0
125 downloads: 0
126 disk_filename: 060719210727_picture.jpg
126 disk_filename: 060719210727_picture.jpg
127 disk_directory: "2006/07"
127 disk_directory: "2006/07"
128 digest: b91e08d0cf966d5c6ff411bd8c4cc3a2
128 digest: b91e08d0cf966d5c6ff411bd8c4cc3a2
129 id: 10
129 id: 10
130 filesize: 452
130 filesize: 452
131 filename: picture.jpg
131 filename: picture.jpg
132 author_id: 2
132 author_id: 2
133 content_type: image/jpeg
133 content_type: image/jpeg
134 attachments_011:
134 attachments_011:
135 created_on: 2007-02-12 15:08:27 +01:00
135 created_on: 2007-02-12 15:08:27 +01:00
136 container_type: Document
136 container_type: Document
137 container_id: 1
137 container_id: 1
138 downloads: 0
138 downloads: 0
139 disk_filename: 060719210727_picture.jpg
139 disk_filename: 060719210727_picture.jpg
140 disk_directory: "2006/07"
140 disk_directory: "2006/07"
141 digest: b91e08d0cf966d5c6ff411bd8c4cc3a2
141 digest: b91e08d0cf966d5c6ff411bd8c4cc3a2
142 id: 11
142 id: 11
143 filesize: 452
143 filesize: 452
144 filename: picture.jpg
144 filename: picture.jpg
145 author_id: 2
145 author_id: 2
146 content_type: image/jpeg
146 content_type: image/jpeg
147 attachments_012:
147 attachments_012:
148 created_on: 2006-07-19 21:07:27 +02:00
148 created_on: 2006-07-19 21:07:27 +02:00
149 container_type: Version
149 container_type: Version
150 container_id: 1
150 container_id: 1
151 downloads: 0
151 downloads: 0
152 disk_filename: 060719210727_version_file.zip
152 disk_filename: 060719210727_version_file.zip
153 disk_directory: "2006/07"
153 disk_directory: "2006/07"
154 digest: b91e08d0cf966d5c6ff411bd8c4cc3a2
154 digest: b91e08d0cf966d5c6ff411bd8c4cc3a2
155 id: 12
155 id: 12
156 filesize: 452
156 filesize: 452
157 filename: version_file.zip
157 filename: version_file.zip
158 author_id: 2
158 author_id: 2
159 content_type: application/octet-stream
159 content_type: application/octet-stream
160 attachments_013:
160 attachments_013:
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: Message
162 container_type: Message
163 container_id: 1
163 container_id: 1
164 downloads: 0
164 downloads: 0
165 disk_filename: 060719210727_foo.zip
165 disk_filename: 060719210727_foo.zip
166 disk_directory: "2006/07"
166 disk_directory: "2006/07"
167 digest: b91e08d0cf966d5c6ff411bd8c4cc3a2
167 digest: b91e08d0cf966d5c6ff411bd8c4cc3a2
168 id: 13
168 id: 13
169 filesize: 452
169 filesize: 452
170 filename: foo.zip
170 filename: foo.zip
171 author_id: 2
171 author_id: 2
172 content_type: application/octet-stream
172 content_type: application/octet-stream
173 attachments_014:
173 attachments_014:
174 created_on: 2006-07-19 21:07:27 +02:00
174 created_on: 2006-07-19 21:07:27 +02:00
175 container_type: Issue
175 container_type: Issue
176 container_id: 3
176 container_id: 3
177 downloads: 0
177 downloads: 0
178 disk_filename: 060719210727_changeset_utf8.diff
178 disk_filename: 060719210727_changeset_utf8.diff
179 disk_directory: "2006/07"
179 disk_directory: "2006/07"
180 digest: b91e08d0cf966d5c6ff411bd8c4cc3a2
180 digest: b91e08d0cf966d5c6ff411bd8c4cc3a2
181 id: 14
181 id: 14
182 filesize: 687
182 filesize: 687
183 filename: changeset_utf8.diff
183 filename: changeset_utf8.diff
184 author_id: 2
184 author_id: 2
185 content_type: text/x-diff
185 content_type: text/x-diff
186 attachments_015:
186 attachments_015:
187 id: 15
187 id: 15
188 created_on: 2010-07-19 21:07:27 +02:00
188 created_on: 2010-07-19 21:07:27 +02:00
189 container_type: Issue
189 container_type: Issue
190 container_id: 14
190 container_id: 14
191 downloads: 0
191 downloads: 0
192 disk_filename: 060719210727_changeset_utf8.diff
192 disk_filename: 060719210727_changeset_utf8.diff
193 disk_directory: "2006/07"
193 disk_directory: "2006/07"
194 digest: b91e08d0cf966d5c6ff411bd8c4cc3a2
194 digest: b91e08d0cf966d5c6ff411bd8c4cc3a2
195 filesize: 687
195 filesize: 687
196 filename: private.diff
196 filename: private.diff
197 author_id: 2
197 author_id: 2
198 content_type: text/x-diff
198 content_type: text/x-diff
199 description: attachement of a private issue
199 description: attachement of a private issue
200 attachments_016:
200 attachments_016:
201 content_type: image/png
201 content_type: image/png
202 downloads: 0
202 downloads: 0
203 created_on: 2010-11-23 16:14:50 +09:00
203 created_on: 2010-11-23 16:14:50 +09:00
204 disk_filename: 101123161450_testfile_1.png
204 disk_filename: 101123161450_testfile_1.png
205 disk_directory: "2010/11"
205 disk_directory: "2010/11"
206 container_id: 14
206 container_id: 14
207 digest: 8e0294de2441577c529f170b6fb8f638
207 digest: 8e0294de2441577c529f170b6fb8f638
208 id: 16
208 id: 16
209 container_type: Issue
209 container_type: Issue
210 description: ""
210 description: ""
211 filename: testfile.png
211 filename: testfile.png
212 filesize: 2654
212 filesize: 2654
213 author_id: 2
213 author_id: 2
214 attachments_017:
214 attachments_017:
215 content_type: image/png
215 content_type: image/png
216 downloads: 0
216 downloads: 0
217 created_on: 2010-12-23 16:14:50 +09:00
217 created_on: 2010-12-23 16:14:50 +09:00
218 disk_filename: 101223161450_testfile_2.png
218 disk_filename: 101223161450_testfile_2.png
219 disk_directory: "2010/12"
219 disk_directory: "2010/12"
220 container_id: 14
220 container_id: 14
221 digest: 6bc2963e8d7ea0d3e68d12d1fba3d6ca
221 digest: 6bc2963e8d7ea0d3e68d12d1fba3d6ca
222 id: 17
222 id: 17
223 container_type: Issue
223 container_type: Issue
224 description: ""
224 description: ""
225 filename: testfile.PNG
225 filename: testfile.PNG
226 filesize: 3582
226 filesize: 3582
227 author_id: 2
227 author_id: 2
228 attachments_018:
228 attachments_018:
229 content_type: image/png
229 content_type: image/png
230 downloads: 0
230 downloads: 0
231 created_on: 2011-01-23 16:14:50 +09:00
231 created_on: 2011-01-23 16:14:50 +09:00
232 disk_filename: 101123161450_testfile_1.png
232 disk_filename: 101123161450_testfile_1.png
233 disk_directory: "2010/11"
233 disk_directory: "2010/11"
234 container_id: 14
234 container_id: 14
235 digest: 8e0294de2441577c529f170b6fb8f638
235 digest: 8e0294de2441577c529f170b6fb8f638
236 id: 18
236 id: 18
237 container_type: Issue
237 container_type: Issue
238 description: ""
238 description: ""
239 filename: testγƒ†γ‚Ήγƒˆ.png
239 filename: testγƒ†γ‚Ήγƒˆ.png
240 filesize: 2654
240 filesize: 2654
241 author_id: 2
241 author_id: 2
242 attachments_019:
242 attachments_019:
243 content_type: image/png
243 content_type: image/png
244 downloads: 0
244 downloads: 0
245 created_on: 2011-02-23 16:14:50 +09:00
245 created_on: 2011-02-23 16:14:50 +09:00
246 disk_filename: 101223161450_testfile_2.png
246 disk_filename: 101223161450_testfile_2.png
247 disk_directory: "2010/12"
247 disk_directory: "2010/12"
248 container_id: 14
248 container_id: 14
249 digest: 6bc2963e8d7ea0d3e68d12d1fba3d6ca
249 digest: 6bc2963e8d7ea0d3e68d12d1fba3d6ca
250 id: 19
250 id: 19
251 container_type: Issue
251 container_type: Issue
252 description: ""
252 description: ""
253 filename: Testγƒ†γ‚Ήγƒˆ.PNG
253 filename: Testγƒ†γ‚Ήγƒˆ.PNG
254 filesize: 3582
254 filesize: 3582
255 author_id: 2
255 author_id: 2
256 attachments_020:
256 attachments_020:
257 content_type: text/plain
257 content_type: text/plain
258 downloads: 0
258 downloads: 0
259 created_on: 2012-05-12 16:14:50 +09:00
259 created_on: 2012-05-12 16:14:50 +09:00
260 disk_filename: 120512161450_root_attachment.txt
260 disk_filename: 120512161450_root_attachment.txt
261 disk_directory:
261 disk_directory:
262 container_id: 14
262 container_id: 14
263 digest: b0fe2abdb2599743d554a61d7da7ff74
263 digest: b0fe2abdb2599743d554a61d7da7ff74
264 id: 20
264 id: 20
265 container_type: Issue
265 container_type: Issue
266 description: ""
266 description: ""
267 filename: root_attachment.txt
267 filename: root_attachment.txt
268 filesize: 54
268 filesize: 54
269 author_id: 2
269 author_id: 2
@@ -1,458 +1,458
1 # encoding: utf-8
1 # encoding: utf-8
2 #
2 #
3 # Redmine - project management software
3 # Redmine - project management software
4 # Copyright (C) 2006-2015 Jean-Philippe Lang
4 # Copyright (C) 2006-2015 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
21
22 class AttachmentsControllerTest < ActionController::TestCase
22 class AttachmentsControllerTest < ActionController::TestCase
23 fixtures :users, :projects, :roles, :members, :member_roles,
23 fixtures :users, :projects, :roles, :members, :member_roles,
24 :enabled_modules, :issues, :trackers, :attachments,
24 :enabled_modules, :issues, :trackers, :attachments,
25 :versions, :wiki_pages, :wikis, :documents
25 :versions, :wiki_pages, :wikis, :documents
26
26
27 def setup
27 def setup
28 User.current = nil
28 User.current = nil
29 set_fixtures_attachments_directory
29 set_fixtures_attachments_directory
30 end
30 end
31
31
32 def teardown
32 def teardown
33 set_tmp_attachments_directory
33 set_tmp_attachments_directory
34 end
34 end
35
35
36 def test_show_diff
36 def test_show_diff
37 ['inline', 'sbs'].each do |dt|
37 ['inline', 'sbs'].each do |dt|
38 # 060719210727_changeset_utf8.diff
38 # 060719210727_changeset_utf8.diff
39 get :show, :id => 14, :type => dt
39 get :show, :id => 14, :type => dt
40 assert_response :success
40 assert_response :success
41 assert_template 'diff'
41 assert_template 'diff'
42 assert_equal 'text/html', @response.content_type
42 assert_equal 'text/html', @response.content_type
43 assert_select 'th.filename', :text => /issues_controller.rb\t\(rΓ©vision 1484\)/
43 assert_select 'th.filename', :text => /issues_controller.rb\t\(rΓ©vision 1484\)/
44 assert_select 'td.line-code', :text => /Demande créée avec succès/
44 assert_select 'td.line-code', :text => /Demande créée avec succès/
45 end
45 end
46 set_tmp_attachments_directory
46 set_tmp_attachments_directory
47 end
47 end
48
48
49 def test_show_diff_replace_cannot_convert_content
49 def test_show_diff_replace_cannot_convert_content
50 with_settings :repositories_encodings => 'UTF-8' do
50 with_settings :repositories_encodings => 'UTF-8' do
51 ['inline', 'sbs'].each do |dt|
51 ['inline', 'sbs'].each do |dt|
52 # 060719210727_changeset_iso8859-1.diff
52 # 060719210727_changeset_iso8859-1.diff
53 get :show, :id => 5, :type => dt
53 get :show, :id => 5, :type => dt
54 assert_response :success
54 assert_response :success
55 assert_template 'diff'
55 assert_template 'diff'
56 assert_equal 'text/html', @response.content_type
56 assert_equal 'text/html', @response.content_type
57 assert_select 'th.filename', :text => /issues_controller.rb\t\(r\?vision 1484\)/
57 assert_select 'th.filename', :text => /issues_controller.rb\t\(r\?vision 1484\)/
58 assert_select 'td.line-code', :text => /Demande cr\?\?e avec succ\?s/
58 assert_select 'td.line-code', :text => /Demande cr\?\?e avec succ\?s/
59 end
59 end
60 end
60 end
61 set_tmp_attachments_directory
61 set_tmp_attachments_directory
62 end
62 end
63
63
64 def test_show_diff_latin_1
64 def test_show_diff_latin_1
65 with_settings :repositories_encodings => 'UTF-8,ISO-8859-1' do
65 with_settings :repositories_encodings => 'UTF-8,ISO-8859-1' do
66 ['inline', 'sbs'].each do |dt|
66 ['inline', 'sbs'].each do |dt|
67 # 060719210727_changeset_iso8859-1.diff
67 # 060719210727_changeset_iso8859-1.diff
68 get :show, :id => 5, :type => dt
68 get :show, :id => 5, :type => dt
69 assert_response :success
69 assert_response :success
70 assert_template 'diff'
70 assert_template 'diff'
71 assert_equal 'text/html', @response.content_type
71 assert_equal 'text/html', @response.content_type
72 assert_select 'th.filename', :text => /issues_controller.rb\t\(rΓ©vision 1484\)/
72 assert_select 'th.filename', :text => /issues_controller.rb\t\(rΓ©vision 1484\)/
73 assert_select 'td.line-code', :text => /Demande créée avec succès/
73 assert_select 'td.line-code', :text => /Demande créée avec succès/
74 end
74 end
75 end
75 end
76 set_tmp_attachments_directory
76 set_tmp_attachments_directory
77 end
77 end
78
78
79 def test_save_diff_type
79 def test_save_diff_type
80 user1 = User.find(1)
80 user1 = User.find(1)
81 user1.pref[:diff_type] = nil
81 user1.pref[:diff_type] = nil
82 user1.preference.save
82 user1.preference.save
83 user = User.find(1)
83 user = User.find(1)
84 assert_nil user.pref[:diff_type]
84 assert_nil user.pref[:diff_type]
85
85
86 @request.session[:user_id] = 1 # admin
86 @request.session[:user_id] = 1 # admin
87 get :show, :id => 5
87 get :show, :id => 5
88 assert_response :success
88 assert_response :success
89 assert_template 'diff'
89 assert_template 'diff'
90 user.reload
90 user.reload
91 assert_equal "inline", user.pref[:diff_type]
91 assert_equal "inline", user.pref[:diff_type]
92 get :show, :id => 5, :type => 'sbs'
92 get :show, :id => 5, :type => 'sbs'
93 assert_response :success
93 assert_response :success
94 assert_template 'diff'
94 assert_template 'diff'
95 user.reload
95 user.reload
96 assert_equal "sbs", user.pref[:diff_type]
96 assert_equal "sbs", user.pref[:diff_type]
97 end
97 end
98
98
99 def test_diff_show_filename_in_mercurial_export
99 def test_diff_show_filename_in_mercurial_export
100 set_tmp_attachments_directory
100 set_tmp_attachments_directory
101 a = Attachment.new(:container => Issue.find(1),
101 a = Attachment.new(:container => Issue.find(1),
102 :file => uploaded_test_file("hg-export.diff", "text/plain"),
102 :file => uploaded_test_file("hg-export.diff", "text/plain"),
103 :author => User.find(1))
103 :author => User.find(1))
104 assert a.save
104 assert a.save
105 assert_equal 'hg-export.diff', a.filename
105 assert_equal 'hg-export.diff', a.filename
106
106
107 get :show, :id => a.id, :type => 'inline'
107 get :show, :id => a.id, :type => 'inline'
108 assert_response :success
108 assert_response :success
109 assert_template 'diff'
109 assert_template 'diff'
110 assert_equal 'text/html', @response.content_type
110 assert_equal 'text/html', @response.content_type
111 assert_select 'th.filename', :text => 'test1.txt'
111 assert_select 'th.filename', :text => 'test1.txt'
112 end
112 end
113
113
114 def test_show_text_file
114 def test_show_text_file
115 get :show, :id => 4
115 get :show, :id => 4
116 assert_response :success
116 assert_response :success
117 assert_template 'file'
117 assert_template 'file'
118 assert_equal 'text/html', @response.content_type
118 assert_equal 'text/html', @response.content_type
119 set_tmp_attachments_directory
119 set_tmp_attachments_directory
120 end
120 end
121
121
122 def test_show_text_file_utf_8
122 def test_show_text_file_utf_8
123 set_tmp_attachments_directory
123 set_tmp_attachments_directory
124 a = Attachment.new(:container => Issue.find(1),
124 a = Attachment.new(:container => Issue.find(1),
125 :file => uploaded_test_file("japanese-utf-8.txt", "text/plain"),
125 :file => uploaded_test_file("japanese-utf-8.txt", "text/plain"),
126 :author => User.find(1))
126 :author => User.find(1))
127 assert a.save
127 assert a.save
128 assert_equal 'japanese-utf-8.txt', a.filename
128 assert_equal 'japanese-utf-8.txt', a.filename
129
129
130 str_japanese = "\xe6\x97\xa5\xe6\x9c\xac\xe8\xaa\x9e".force_encoding('UTF-8')
130 str_japanese = "\xe6\x97\xa5\xe6\x9c\xac\xe8\xaa\x9e".force_encoding('UTF-8')
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_select 'tr#L1' do
136 assert_select 'tr#L1' do
137 assert_select 'th.line-num', :text => '1'
137 assert_select 'th.line-num', :text => '1'
138 assert_select 'td', :text => /#{str_japanese}/
138 assert_select 'td', :text => /#{str_japanese}/
139 end
139 end
140 end
140 end
141
141
142 def test_show_text_file_replace_cannot_convert_content
142 def test_show_text_file_replace_cannot_convert_content
143 set_tmp_attachments_directory
143 set_tmp_attachments_directory
144 with_settings :repositories_encodings => 'UTF-8' do
144 with_settings :repositories_encodings => 'UTF-8' do
145 a = Attachment.new(:container => Issue.find(1),
145 a = Attachment.new(:container => Issue.find(1),
146 :file => uploaded_test_file("iso8859-1.txt", "text/plain"),
146 :file => uploaded_test_file("iso8859-1.txt", "text/plain"),
147 :author => User.find(1))
147 :author => User.find(1))
148 assert a.save
148 assert a.save
149 assert_equal 'iso8859-1.txt', a.filename
149 assert_equal 'iso8859-1.txt', a.filename
150
150
151 get :show, :id => a.id
151 get :show, :id => a.id
152 assert_response :success
152 assert_response :success
153 assert_template 'file'
153 assert_template 'file'
154 assert_equal 'text/html', @response.content_type
154 assert_equal 'text/html', @response.content_type
155 assert_select 'tr#L7' do
155 assert_select 'tr#L7' do
156 assert_select 'th.line-num', :text => '7'
156 assert_select 'th.line-num', :text => '7'
157 assert_select 'td', :text => /Demande cr\?\?e avec succ\?s/
157 assert_select 'td', :text => /Demande cr\?\?e avec succ\?s/
158 end
158 end
159 end
159 end
160 end
160 end
161
161
162 def test_show_text_file_latin_1
162 def test_show_text_file_latin_1
163 set_tmp_attachments_directory
163 set_tmp_attachments_directory
164 with_settings :repositories_encodings => 'UTF-8,ISO-8859-1' do
164 with_settings :repositories_encodings => 'UTF-8,ISO-8859-1' do
165 a = Attachment.new(:container => Issue.find(1),
165 a = Attachment.new(:container => Issue.find(1),
166 :file => uploaded_test_file("iso8859-1.txt", "text/plain"),
166 :file => uploaded_test_file("iso8859-1.txt", "text/plain"),
167 :author => User.find(1))
167 :author => User.find(1))
168 assert a.save
168 assert a.save
169 assert_equal 'iso8859-1.txt', a.filename
169 assert_equal 'iso8859-1.txt', a.filename
170
170
171 get :show, :id => a.id
171 get :show, :id => a.id
172 assert_response :success
172 assert_response :success
173 assert_template 'file'
173 assert_template 'file'
174 assert_equal 'text/html', @response.content_type
174 assert_equal 'text/html', @response.content_type
175 assert_select 'tr#L7' do
175 assert_select 'tr#L7' do
176 assert_select 'th.line-num', :text => '7'
176 assert_select 'th.line-num', :text => '7'
177 assert_select 'td', :text => /Demande créée avec succès/
177 assert_select 'td', :text => /Demande créée avec succès/
178 end
178 end
179 end
179 end
180 end
180 end
181
181
182 def test_show_text_file_should_send_if_too_big
182 def test_show_text_file_should_send_if_too_big
183 with_settings :file_max_size_displayed => 512 do
183 with_settings :file_max_size_displayed => 512 do
184 Attachment.find(4).update_attribute :filesize, 754.kilobyte
184 Attachment.find(4).update_attribute :filesize, 754.kilobyte
185 get :show, :id => 4
185 get :show, :id => 4
186 assert_response :success
186 assert_response :success
187 assert_equal 'application/x-ruby', @response.content_type
187 assert_equal 'application/x-ruby', @response.content_type
188 end
188 end
189 set_tmp_attachments_directory
189 set_tmp_attachments_directory
190 end
190 end
191
191
192 def test_show_other
192 def test_show_other
193 get :show, :id => 6
193 get :show, :id => 6
194 assert_response :success
194 assert_response :success
195 assert_equal 'application/octet-stream', @response.content_type
195 assert_equal 'application/octet-stream', @response.content_type
196 set_tmp_attachments_directory
196 set_tmp_attachments_directory
197 end
197 end
198
198
199 def test_show_file_from_private_issue_without_permission
199 def test_show_file_from_private_issue_without_permission
200 get :show, :id => 15
200 get :show, :id => 15
201 assert_redirected_to '/login?back_url=http%3A%2F%2Ftest.host%2Fattachments%2F15'
201 assert_redirected_to '/login?back_url=http%3A%2F%2Ftest.host%2Fattachments%2F15'
202 set_tmp_attachments_directory
202 set_tmp_attachments_directory
203 end
203 end
204
204
205 def test_show_file_from_private_issue_with_permission
205 def test_show_file_from_private_issue_with_permission
206 @request.session[:user_id] = 2
206 @request.session[:user_id] = 2
207 get :show, :id => 15
207 get :show, :id => 15
208 assert_response :success
208 assert_response :success
209 assert_select 'h2', :text => /private.diff/
209 assert_select 'h2', :text => /private.diff/
210 set_tmp_attachments_directory
210 set_tmp_attachments_directory
211 end
211 end
212
212
213 def test_show_file_without_container_should_be_allowed_to_author
213 def test_show_file_without_container_should_be_allowed_to_author
214 set_tmp_attachments_directory
214 set_tmp_attachments_directory
215 attachment = Attachment.create!(:file => uploaded_test_file("testfile.txt", "text/plain"), :author_id => 2)
215 attachment = Attachment.create!(:file => uploaded_test_file("testfile.txt", "text/plain"), :author_id => 2)
216
216
217 @request.session[:user_id] = 2
217 @request.session[:user_id] = 2
218 get :show, :id => attachment.id
218 get :show, :id => attachment.id
219 assert_response 200
219 assert_response 200
220 end
220 end
221
221
222 def test_show_file_without_container_should_be_denied_to_other_users
222 def test_show_file_without_container_should_be_denied_to_other_users
223 set_tmp_attachments_directory
223 set_tmp_attachments_directory
224 attachment = Attachment.create!(:file => uploaded_test_file("testfile.txt", "text/plain"), :author_id => 2)
224 attachment = Attachment.create!(:file => uploaded_test_file("testfile.txt", "text/plain"), :author_id => 2)
225
225
226 @request.session[:user_id] = 3
226 @request.session[:user_id] = 3
227 get :show, :id => attachment.id
227 get :show, :id => attachment.id
228 assert_response 403
228 assert_response 403
229 end
229 end
230
230
231 def test_show_invalid_should_respond_with_404
231 def test_show_invalid_should_respond_with_404
232 get :show, :id => 999
232 get :show, :id => 999
233 assert_response 404
233 assert_response 404
234 end
234 end
235
235
236 def test_download_text_file
236 def test_download_text_file
237 get :download, :id => 4
237 get :download, :id => 4
238 assert_response :success
238 assert_response :success
239 assert_equal 'application/x-ruby', @response.content_type
239 assert_equal 'application/x-ruby', @response.content_type
240 etag = @response.etag
240 etag = @response.etag
241 assert_not_nil etag
241 assert_not_nil etag
242
242
243 @request.env["HTTP_IF_NONE_MATCH"] = etag
243 @request.env["HTTP_IF_NONE_MATCH"] = etag
244 get :download, :id => 4
244 get :download, :id => 4
245 assert_response 304
245 assert_response 304
246
246
247 set_tmp_attachments_directory
247 set_tmp_attachments_directory
248 end
248 end
249
249
250 def test_download_version_file_with_issue_tracking_disabled
250 def test_download_version_file_with_issue_tracking_disabled
251 Project.find(1).disable_module! :issue_tracking
251 Project.find(1).disable_module! :issue_tracking
252 get :download, :id => 9
252 get :download, :id => 9
253 assert_response :success
253 assert_response :success
254 end
254 end
255
255
256 def test_download_should_assign_content_type_if_blank
256 def test_download_should_assign_content_type_if_blank
257 Attachment.find(4).update_attribute(:content_type, '')
257 Attachment.find(4).update_attribute(:content_type, '')
258
258
259 get :download, :id => 4
259 get :download, :id => 4
260 assert_response :success
260 assert_response :success
261 assert_equal 'text/x-ruby', @response.content_type
261 assert_equal 'text/x-ruby', @response.content_type
262 set_tmp_attachments_directory
262 set_tmp_attachments_directory
263 end
263 end
264
264
265 def test_download_missing_file
265 def test_download_missing_file
266 get :download, :id => 2
266 get :download, :id => 2
267 assert_response 404
267 assert_response 404
268 set_tmp_attachments_directory
268 set_tmp_attachments_directory
269 end
269 end
270
270
271 def test_download_should_be_denied_without_permission
271 def test_download_should_be_denied_without_permission
272 get :download, :id => 7
272 get :download, :id => 7
273 assert_redirected_to '/login?back_url=http%3A%2F%2Ftest.host%2Fattachments%2Fdownload%2F7'
273 assert_redirected_to '/login?back_url=http%3A%2F%2Ftest.host%2Fattachments%2Fdownload%2F7'
274 set_tmp_attachments_directory
274 set_tmp_attachments_directory
275 end
275 end
276
276
277 if convert_installed?
277 if convert_installed?
278 def test_thumbnail
278 def test_thumbnail
279 Attachment.clear_thumbnails
279 Attachment.clear_thumbnails
280 @request.session[:user_id] = 2
280 @request.session[:user_id] = 2
281 get :thumbnail, :id => 16
281 get :thumbnail, :id => 16
282 assert_response :success
282 assert_response :success
283 assert_equal 'image/png', response.content_type
283 assert_equal 'image/png', response.content_type
284
284
285 etag = @response.etag
285 etag = @response.etag
286 assert_not_nil etag
286 assert_not_nil etag
287
287
288 @request.env["HTTP_IF_NONE_MATCH"] = etag
288 @request.env["HTTP_IF_NONE_MATCH"] = etag
289 get :thumbnail, :id => 16
289 get :thumbnail, :id => 16
290 assert_response 304
290 assert_response 304
291 end
291 end
292
292
293 def test_thumbnail_should_not_exceed_maximum_size
293 def test_thumbnail_should_not_exceed_maximum_size
294 Redmine::Thumbnail.expects(:generate).with {|source, target, size| size == 800}
294 Redmine::Thumbnail.expects(:generate).with {|source, target, size| size == 800}
295
295
296 @request.session[:user_id] = 2
296 @request.session[:user_id] = 2
297 get :thumbnail, :id => 16, :size => 2000
297 get :thumbnail, :id => 16, :size => 2000
298 end
298 end
299
299
300 def test_thumbnail_should_round_size
300 def test_thumbnail_should_round_size
301 Redmine::Thumbnail.expects(:generate).with {|source, target, size| size == 250}
301 Redmine::Thumbnail.expects(:generate).with {|source, target, size| size == 250}
302
302
303 @request.session[:user_id] = 2
303 @request.session[:user_id] = 2
304 get :thumbnail, :id => 16, :size => 260
304 get :thumbnail, :id => 16, :size => 260
305 end
305 end
306
306
307 def test_thumbnail_should_return_404_for_non_image_attachment
307 def test_thumbnail_should_return_404_for_non_image_attachment
308 @request.session[:user_id] = 2
308 @request.session[:user_id] = 2
309
309
310 get :thumbnail, :id => 15
310 get :thumbnail, :id => 15
311 assert_response 404
311 assert_response 404
312 end
312 end
313
313
314 def test_thumbnail_should_return_404_if_thumbnail_generation_failed
314 def test_thumbnail_should_return_404_if_thumbnail_generation_failed
315 Attachment.any_instance.stubs(:thumbnail).returns(nil)
315 Attachment.any_instance.stubs(:thumbnail).returns(nil)
316 @request.session[:user_id] = 2
316 @request.session[:user_id] = 2
317
317
318 get :thumbnail, :id => 16
318 get :thumbnail, :id => 16
319 assert_response 404
319 assert_response 404
320 end
320 end
321
321
322 def test_thumbnail_should_be_denied_without_permission
322 def test_thumbnail_should_be_denied_without_permission
323 get :thumbnail, :id => 16
323 get :thumbnail, :id => 16
324 assert_redirected_to '/login?back_url=http%3A%2F%2Ftest.host%2Fattachments%2Fthumbnail%2F16'
324 assert_redirected_to '/login?back_url=http%3A%2F%2Ftest.host%2Fattachments%2Fthumbnail%2F16'
325 end
325 end
326 else
326 else
327 puts '(ImageMagick convert not available)'
327 puts '(ImageMagick convert not available)'
328 end
328 end
329
329
330 def test_edit
330 def test_edit
331 @request.session[:user_id] = 2
331 @request.session[:user_id] = 2
332 get :edit, :object_type => 'issues', :object_id => '3'
332 get :edit, :object_type => 'issues', :object_id => '2'
333 assert_response :success
333 assert_response :success
334 assert_template 'edit'
334 assert_template 'edit'
335
335
336 container = Issue.find(3)
336 container = Issue.find(2)
337 assert_equal container, assigns(:container)
337 assert_equal container, assigns(:container)
338 assert_equal container.attachments.size, assigns(:attachments).size
338 assert_equal container.attachments.size, assigns(:attachments).size
339
339
340 assert_select 'form[action=?]', '/attachments/issues/3' do
340 assert_select 'form[action=?]', '/attachments/issues/2' do
341 assert_select 'tr#attachment-4' do
341 assert_select 'tr#attachment-4' do
342 assert_select 'input[name=?][value=?]', 'attachments[4][filename]', 'source.rb'
342 assert_select 'input[name=?][value=?]', 'attachments[4][filename]', 'source.rb'
343 assert_select 'input[name=?][value=?]', 'attachments[4][description]', 'This is a Ruby source file'
343 assert_select 'input[name=?][value=?]', 'attachments[4][description]', 'This is a Ruby source file'
344 end
344 end
345 end
345 end
346 end
346 end
347
347
348 def test_edit_invalid_container_class_should_return_404
348 def test_edit_invalid_container_class_should_return_404
349 get :edit, :object_type => 'nuggets', :object_id => '3'
349 get :edit, :object_type => 'nuggets', :object_id => '3'
350 assert_response 404
350 assert_response 404
351 end
351 end
352
352
353 def test_edit_invalid_object_should_return_404
353 def test_edit_invalid_object_should_return_404
354 get :edit, :object_type => 'issues', :object_id => '999'
354 get :edit, :object_type => 'issues', :object_id => '999'
355 assert_response 404
355 assert_response 404
356 end
356 end
357
357
358 def test_edit_for_object_that_is_not_visible_should_return_403
358 def test_edit_for_object_that_is_not_visible_should_return_403
359 get :edit, :object_type => 'issues', :object_id => '4'
359 get :edit, :object_type => 'issues', :object_id => '4'
360 assert_response 403
360 assert_response 403
361 end
361 end
362
362
363 def test_update
363 def test_update
364 @request.session[:user_id] = 2
364 @request.session[:user_id] = 2
365 patch :update, :object_type => 'issues', :object_id => '3', :attachments => {
365 patch :update, :object_type => 'issues', :object_id => '2', :attachments => {
366 '1' => {:filename => 'newname.text', :description => ''},
366 '1' => {:filename => 'newname.text', :description => ''},
367 '4' => {:filename => 'newname.rb', :description => 'Renamed'},
367 '4' => {:filename => 'newname.rb', :description => 'Renamed'},
368 }
368 }
369
369
370 assert_response 302
370 assert_response 302
371 attachment = Attachment.find(4)
371 attachment = Attachment.find(4)
372 assert_equal 'newname.rb', attachment.filename
372 assert_equal 'newname.rb', attachment.filename
373 assert_equal 'Renamed', attachment.description
373 assert_equal 'Renamed', attachment.description
374 end
374 end
375
375
376 def test_update_with_failure
376 def test_update_with_failure
377 @request.session[:user_id] = 2
377 @request.session[:user_id] = 2
378 patch :update, :object_type => 'issues', :object_id => '3', :attachments => {
378 patch :update, :object_type => 'issues', :object_id => '3', :attachments => {
379 '1' => {:filename => '', :description => ''},
379 '1' => {:filename => '', :description => ''},
380 '4' => {:filename => 'newname.rb', :description => 'Renamed'},
380 '4' => {:filename => 'newname.rb', :description => 'Renamed'},
381 }
381 }
382
382
383 assert_response :success
383 assert_response :success
384 assert_template 'edit'
384 assert_template 'edit'
385 assert_select_error /file cannot be blank/i
385 assert_select_error /file cannot be blank/i
386
386
387 # The other attachment should not be updated
387 # The other attachment should not be updated
388 attachment = Attachment.find(4)
388 attachment = Attachment.find(4)
389 assert_equal 'source.rb', attachment.filename
389 assert_equal 'source.rb', attachment.filename
390 assert_equal 'This is a Ruby source file', attachment.description
390 assert_equal 'This is a Ruby source file', attachment.description
391 end
391 end
392
392
393 def test_destroy_issue_attachment
393 def test_destroy_issue_attachment
394 set_tmp_attachments_directory
394 set_tmp_attachments_directory
395 issue = Issue.find(3)
395 issue = Issue.find(3)
396 @request.session[:user_id] = 2
396 @request.session[:user_id] = 2
397
397
398 assert_difference 'issue.attachments.count', -1 do
398 assert_difference 'issue.attachments.count', -1 do
399 assert_difference 'Journal.count' do
399 assert_difference 'Journal.count' do
400 delete :destroy, :id => 1
400 delete :destroy, :id => 1
401 assert_redirected_to '/projects/ecookbook'
401 assert_redirected_to '/projects/ecookbook'
402 end
402 end
403 end
403 end
404 assert_nil Attachment.find_by_id(1)
404 assert_nil Attachment.find_by_id(1)
405 j = Journal.order('id DESC').first
405 j = Journal.order('id DESC').first
406 assert_equal issue, j.journalized
406 assert_equal issue, j.journalized
407 assert_equal 'attachment', j.details.first.property
407 assert_equal 'attachment', j.details.first.property
408 assert_equal '1', j.details.first.prop_key
408 assert_equal '1', j.details.first.prop_key
409 assert_equal 'error281.txt', j.details.first.old_value
409 assert_equal 'error281.txt', j.details.first.old_value
410 assert_equal User.find(2), j.user
410 assert_equal User.find(2), j.user
411 end
411 end
412
412
413 def test_destroy_wiki_page_attachment
413 def test_destroy_wiki_page_attachment
414 set_tmp_attachments_directory
414 set_tmp_attachments_directory
415 @request.session[:user_id] = 2
415 @request.session[:user_id] = 2
416 assert_difference 'Attachment.count', -1 do
416 assert_difference 'Attachment.count', -1 do
417 delete :destroy, :id => 3
417 delete :destroy, :id => 3
418 assert_response 302
418 assert_response 302
419 end
419 end
420 end
420 end
421
421
422 def test_destroy_project_attachment
422 def test_destroy_project_attachment
423 set_tmp_attachments_directory
423 set_tmp_attachments_directory
424 @request.session[:user_id] = 2
424 @request.session[:user_id] = 2
425 assert_difference 'Attachment.count', -1 do
425 assert_difference 'Attachment.count', -1 do
426 delete :destroy, :id => 8
426 delete :destroy, :id => 8
427 assert_response 302
427 assert_response 302
428 end
428 end
429 end
429 end
430
430
431 def test_destroy_version_attachment
431 def test_destroy_version_attachment
432 set_tmp_attachments_directory
432 set_tmp_attachments_directory
433 @request.session[:user_id] = 2
433 @request.session[:user_id] = 2
434 assert_difference 'Attachment.count', -1 do
434 assert_difference 'Attachment.count', -1 do
435 delete :destroy, :id => 9
435 delete :destroy, :id => 9
436 assert_response 302
436 assert_response 302
437 end
437 end
438 end
438 end
439
439
440 def test_destroy_version_attachment_with_issue_tracking_disabled
440 def test_destroy_version_attachment_with_issue_tracking_disabled
441 Project.find(1).disable_module! :issue_tracking
441 Project.find(1).disable_module! :issue_tracking
442 set_tmp_attachments_directory
442 set_tmp_attachments_directory
443 @request.session[:user_id] = 2
443 @request.session[:user_id] = 2
444 assert_difference 'Attachment.count', -1 do
444 assert_difference 'Attachment.count', -1 do
445 delete :destroy, :id => 9
445 delete :destroy, :id => 9
446 assert_response 302
446 assert_response 302
447 end
447 end
448 end
448 end
449
449
450 def test_destroy_without_permission
450 def test_destroy_without_permission
451 set_tmp_attachments_directory
451 set_tmp_attachments_directory
452 assert_no_difference 'Attachment.count' do
452 assert_no_difference 'Attachment.count' do
453 delete :destroy, :id => 3
453 delete :destroy, :id => 3
454 end
454 end
455 assert_response 302
455 assert_response 302
456 assert Attachment.find_by_id(3)
456 assert Attachment.find_by_id(3)
457 end
457 end
458 end
458 end
@@ -1,650 +1,650
1 # Redmine - project management software
1 # Redmine - project management software
2 # Copyright (C) 2006-2015 Jean-Philippe Lang
2 # Copyright (C) 2006-2015 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.expand_path('../../../test_helper', __FILE__)
18 require File.expand_path('../../../test_helper', __FILE__)
19
19
20 class Redmine::ApiTest::IssuesTest < Redmine::ApiTest::Base
20 class Redmine::ApiTest::IssuesTest < Redmine::ApiTest::Base
21 fixtures :projects,
21 fixtures :projects,
22 :users,
22 :users,
23 :roles,
23 :roles,
24 :members,
24 :members,
25 :member_roles,
25 :member_roles,
26 :issues,
26 :issues,
27 :issue_statuses,
27 :issue_statuses,
28 :issue_relations,
28 :issue_relations,
29 :versions,
29 :versions,
30 :trackers,
30 :trackers,
31 :projects_trackers,
31 :projects_trackers,
32 :issue_categories,
32 :issue_categories,
33 :enabled_modules,
33 :enabled_modules,
34 :enumerations,
34 :enumerations,
35 :attachments,
35 :attachments,
36 :workflows,
36 :workflows,
37 :custom_fields,
37 :custom_fields,
38 :custom_values,
38 :custom_values,
39 :custom_fields_projects,
39 :custom_fields_projects,
40 :custom_fields_trackers,
40 :custom_fields_trackers,
41 :time_entries,
41 :time_entries,
42 :journals,
42 :journals,
43 :journal_details,
43 :journal_details,
44 :queries,
44 :queries,
45 :attachments
45 :attachments
46
46
47 test "GET /issues.xml should contain metadata" do
47 test "GET /issues.xml should contain metadata" do
48 get '/issues.xml'
48 get '/issues.xml'
49 assert_select 'issues[type=array][total_count=?][limit="25"][offset="0"]',
49 assert_select 'issues[type=array][total_count=?][limit="25"][offset="0"]',
50 assigns(:issue_count).to_s
50 assigns(:issue_count).to_s
51 end
51 end
52
52
53 test "GET /issues.xml with nometa param should not contain metadata" do
53 test "GET /issues.xml with nometa param should not contain metadata" do
54 get '/issues.xml?nometa=1'
54 get '/issues.xml?nometa=1'
55 assert_select 'issues[type=array]:not([total_count]):not([limit]):not([offset])'
55 assert_select 'issues[type=array]:not([total_count]):not([limit]):not([offset])'
56 end
56 end
57
57
58 test "GET /issues.xml with nometa header should not contain metadata" do
58 test "GET /issues.xml with nometa header should not contain metadata" do
59 get '/issues.xml', {}, {'X-Redmine-Nometa' => '1'}
59 get '/issues.xml', {}, {'X-Redmine-Nometa' => '1'}
60 assert_select 'issues[type=array]:not([total_count]):not([limit]):not([offset])'
60 assert_select 'issues[type=array]:not([total_count]):not([limit]):not([offset])'
61 end
61 end
62
62
63 test "GET /issues.xml with offset and limit" do
63 test "GET /issues.xml with offset and limit" do
64 get '/issues.xml?offset=2&limit=3'
64 get '/issues.xml?offset=2&limit=3'
65
65
66 assert_equal 3, assigns(:limit)
66 assert_equal 3, assigns(:limit)
67 assert_equal 2, assigns(:offset)
67 assert_equal 2, assigns(:offset)
68 assert_select 'issues issue', 3
68 assert_select 'issues issue', 3
69 end
69 end
70
70
71 test "GET /issues.xml with relations" do
71 test "GET /issues.xml with relations" do
72 get '/issues.xml?include=relations'
72 get '/issues.xml?include=relations'
73
73
74 assert_response :success
74 assert_response :success
75 assert_equal 'application/xml', @response.content_type
75 assert_equal 'application/xml', @response.content_type
76
76
77 assert_select 'issue id', :text => '3' do
77 assert_select 'issue id', :text => '3' do
78 assert_select '~ relations relation', 1
78 assert_select '~ relations relation', 1
79 assert_select '~ relations relation[id="2"][issue_id="2"][issue_to_id="3"][relation_type=relates]'
79 assert_select '~ relations relation[id="2"][issue_id="2"][issue_to_id="3"][relation_type=relates]'
80 end
80 end
81
81
82 assert_select 'issue id', :text => '1' do
82 assert_select 'issue id', :text => '1' do
83 assert_select '~ relations'
83 assert_select '~ relations'
84 assert_select '~ relations relation', 0
84 assert_select '~ relations relation', 0
85 end
85 end
86 end
86 end
87
87
88 test "GET /issues.xml with invalid query params" do
88 test "GET /issues.xml with invalid query params" do
89 get '/issues.xml', {:f => ['start_date'], :op => {:start_date => '='}}
89 get '/issues.xml', {:f => ['start_date'], :op => {:start_date => '='}}
90
90
91 assert_response :unprocessable_entity
91 assert_response :unprocessable_entity
92 assert_equal 'application/xml', @response.content_type
92 assert_equal 'application/xml', @response.content_type
93 assert_select 'errors error', :text => "Start date cannot be blank"
93 assert_select 'errors error', :text => "Start date cannot be blank"
94 end
94 end
95
95
96 test "GET /issues.xml with custom field filter" do
96 test "GET /issues.xml with custom field filter" do
97 get '/issues.xml',
97 get '/issues.xml',
98 {:set_filter => 1, :f => ['cf_1'], :op => {:cf_1 => '='}, :v => {:cf_1 => ['MySQL']}}
98 {:set_filter => 1, :f => ['cf_1'], :op => {:cf_1 => '='}, :v => {:cf_1 => ['MySQL']}}
99
99
100 expected_ids = Issue.visible.
100 expected_ids = Issue.visible.
101 joins(:custom_values).
101 joins(:custom_values).
102 where(:custom_values => {:custom_field_id => 1, :value => 'MySQL'}).map(&:id)
102 where(:custom_values => {:custom_field_id => 1, :value => 'MySQL'}).map(&:id)
103 assert expected_ids.any?
103 assert expected_ids.any?
104
104
105 assert_select 'issues > issue > id', :count => expected_ids.count do |ids|
105 assert_select 'issues > issue > id', :count => expected_ids.count do |ids|
106 ids.each { |id| assert expected_ids.delete(id.children.first.content.to_i) }
106 ids.each { |id| assert expected_ids.delete(id.children.first.content.to_i) }
107 end
107 end
108 end
108 end
109
109
110 test "GET /issues.xml with custom field filter (shorthand method)" do
110 test "GET /issues.xml with custom field filter (shorthand method)" do
111 get '/issues.xml', {:cf_1 => 'MySQL'}
111 get '/issues.xml', {:cf_1 => 'MySQL'}
112
112
113 expected_ids = Issue.visible.
113 expected_ids = Issue.visible.
114 joins(:custom_values).
114 joins(:custom_values).
115 where(:custom_values => {:custom_field_id => 1, :value => 'MySQL'}).map(&:id)
115 where(:custom_values => {:custom_field_id => 1, :value => 'MySQL'}).map(&:id)
116 assert expected_ids.any?
116 assert expected_ids.any?
117
117
118 assert_select 'issues > issue > id', :count => expected_ids.count do |ids|
118 assert_select 'issues > issue > id', :count => expected_ids.count do |ids|
119 ids.each { |id| assert expected_ids.delete(id.children.first.content.to_i) }
119 ids.each { |id| assert expected_ids.delete(id.children.first.content.to_i) }
120 end
120 end
121 end
121 end
122
122
123 def test_index_should_include_issue_attributes
123 def test_index_should_include_issue_attributes
124 get '/issues.xml'
124 get '/issues.xml'
125 assert_select 'issues>issue>is_private', :text => 'false'
125 assert_select 'issues>issue>is_private', :text => 'false'
126 end
126 end
127
127
128 def test_index_should_allow_timestamp_filtering
128 def test_index_should_allow_timestamp_filtering
129 Issue.delete_all
129 Issue.delete_all
130 Issue.generate!(:subject => '1').update_column(:updated_on, Time.parse("2014-01-02T10:25:00Z"))
130 Issue.generate!(:subject => '1').update_column(:updated_on, Time.parse("2014-01-02T10:25:00Z"))
131 Issue.generate!(:subject => '2').update_column(:updated_on, Time.parse("2014-01-02T12:13:00Z"))
131 Issue.generate!(:subject => '2').update_column(:updated_on, Time.parse("2014-01-02T12:13:00Z"))
132
132
133 get '/issues.xml',
133 get '/issues.xml',
134 {:set_filter => 1, :f => ['updated_on'], :op => {:updated_on => '<='},
134 {:set_filter => 1, :f => ['updated_on'], :op => {:updated_on => '<='},
135 :v => {:updated_on => ['2014-01-02T12:00:00Z']}}
135 :v => {:updated_on => ['2014-01-02T12:00:00Z']}}
136 assert_select 'issues>issue', :count => 1
136 assert_select 'issues>issue', :count => 1
137 assert_select 'issues>issue>subject', :text => '1'
137 assert_select 'issues>issue>subject', :text => '1'
138
138
139 get '/issues.xml',
139 get '/issues.xml',
140 {:set_filter => 1, :f => ['updated_on'], :op => {:updated_on => '>='},
140 {:set_filter => 1, :f => ['updated_on'], :op => {:updated_on => '>='},
141 :v => {:updated_on => ['2014-01-02T12:00:00Z']}}
141 :v => {:updated_on => ['2014-01-02T12:00:00Z']}}
142 assert_select 'issues>issue', :count => 1
142 assert_select 'issues>issue', :count => 1
143 assert_select 'issues>issue>subject', :text => '2'
143 assert_select 'issues>issue>subject', :text => '2'
144
144
145 get '/issues.xml',
145 get '/issues.xml',
146 {:set_filter => 1, :f => ['updated_on'], :op => {:updated_on => '>='},
146 {:set_filter => 1, :f => ['updated_on'], :op => {:updated_on => '>='},
147 :v => {:updated_on => ['2014-01-02T08:00:00Z']}}
147 :v => {:updated_on => ['2014-01-02T08:00:00Z']}}
148 assert_select 'issues>issue', :count => 2
148 assert_select 'issues>issue', :count => 2
149 end
149 end
150
150
151 test "GET /issues.xml with filter" do
151 test "GET /issues.xml with filter" do
152 get '/issues.xml?status_id=5'
152 get '/issues.xml?status_id=5'
153
153
154 expected_ids = Issue.visible.where(:status_id => 5).map(&:id)
154 expected_ids = Issue.visible.where(:status_id => 5).map(&:id)
155 assert expected_ids.any?
155 assert expected_ids.any?
156
156
157 assert_select 'issues > issue > id', :count => expected_ids.count do |ids|
157 assert_select 'issues > issue > id', :count => expected_ids.count do |ids|
158 ids.each { |id| assert expected_ids.delete(id.children.first.content.to_i) }
158 ids.each { |id| assert expected_ids.delete(id.children.first.content.to_i) }
159 end
159 end
160 end
160 end
161
161
162 test "GET /issues.json with filter" do
162 test "GET /issues.json with filter" do
163 get '/issues.json?status_id=5'
163 get '/issues.json?status_id=5'
164
164
165 json = ActiveSupport::JSON.decode(response.body)
165 json = ActiveSupport::JSON.decode(response.body)
166 status_ids_used = json['issues'].collect {|j| j['status']['id'] }
166 status_ids_used = json['issues'].collect {|j| j['status']['id'] }
167 assert_equal 3, status_ids_used.length
167 assert_equal 3, status_ids_used.length
168 assert status_ids_used.all? {|id| id == 5 }
168 assert status_ids_used.all? {|id| id == 5 }
169 end
169 end
170
170
171 test "GET /issues/:id.xml with journals" do
171 test "GET /issues/:id.xml with journals" do
172 get '/issues/1.xml?include=journals'
172 get '/issues/1.xml?include=journals'
173
173
174 assert_select 'issue journals[type=array]' do
174 assert_select 'issue journals[type=array]' do
175 assert_select 'journal[id="1"]' do
175 assert_select 'journal[id="1"]' do
176 assert_select 'details[type=array]' do
176 assert_select 'details[type=array]' do
177 assert_select 'detail[name=status_id]' do
177 assert_select 'detail[name=status_id]' do
178 assert_select 'old_value', :text => '1'
178 assert_select 'old_value', :text => '1'
179 assert_select 'new_value', :text => '2'
179 assert_select 'new_value', :text => '2'
180 end
180 end
181 end
181 end
182 end
182 end
183 end
183 end
184 end
184 end
185
185
186 test "GET /issues/:id.xml with custom fields" do
186 test "GET /issues/:id.xml with custom fields" do
187 get '/issues/3.xml'
187 get '/issues/3.xml'
188
188
189 assert_select 'issue custom_fields[type=array]' do
189 assert_select 'issue custom_fields[type=array]' do
190 assert_select 'custom_field[id="1"]' do
190 assert_select 'custom_field[id="1"]' do
191 assert_select 'value', :text => 'MySQL'
191 assert_select 'value', :text => 'MySQL'
192 end
192 end
193 end
193 end
194 assert_nothing_raised do
194 assert_nothing_raised do
195 Hash.from_xml(response.body).to_xml
195 Hash.from_xml(response.body).to_xml
196 end
196 end
197 end
197 end
198
198
199 test "GET /issues/:id.xml with multi custom fields" do
199 test "GET /issues/:id.xml with multi custom fields" do
200 field = CustomField.find(1)
200 field = CustomField.find(1)
201 field.update_attribute :multiple, true
201 field.update_attribute :multiple, true
202 issue = Issue.find(3)
202 issue = Issue.find(3)
203 issue.custom_field_values = {1 => ['MySQL', 'Oracle']}
203 issue.custom_field_values = {1 => ['MySQL', 'Oracle']}
204 issue.save!
204 issue.save!
205
205
206 get '/issues/3.xml'
206 get '/issues/3.xml'
207 assert_response :success
207 assert_response :success
208
208
209 assert_select 'issue custom_fields[type=array]' do
209 assert_select 'issue custom_fields[type=array]' do
210 assert_select 'custom_field[id="1"]' do
210 assert_select 'custom_field[id="1"]' do
211 assert_select 'value[type=array] value', 2
211 assert_select 'value[type=array] value', 2
212 end
212 end
213 end
213 end
214 xml = Hash.from_xml(response.body)
214 xml = Hash.from_xml(response.body)
215 custom_fields = xml['issue']['custom_fields']
215 custom_fields = xml['issue']['custom_fields']
216 assert_kind_of Array, custom_fields
216 assert_kind_of Array, custom_fields
217 field = custom_fields.detect {|f| f['id'] == '1'}
217 field = custom_fields.detect {|f| f['id'] == '1'}
218 assert_kind_of Hash, field
218 assert_kind_of Hash, field
219 assert_equal ['MySQL', 'Oracle'], field['value'].sort
219 assert_equal ['MySQL', 'Oracle'], field['value'].sort
220 end
220 end
221
221
222 test "GET /issues/:id.json with multi custom fields" do
222 test "GET /issues/:id.json with multi custom fields" do
223 field = CustomField.find(1)
223 field = CustomField.find(1)
224 field.update_attribute :multiple, true
224 field.update_attribute :multiple, true
225 issue = Issue.find(3)
225 issue = Issue.find(3)
226 issue.custom_field_values = {1 => ['MySQL', 'Oracle']}
226 issue.custom_field_values = {1 => ['MySQL', 'Oracle']}
227 issue.save!
227 issue.save!
228
228
229 get '/issues/3.json'
229 get '/issues/3.json'
230 assert_response :success
230 assert_response :success
231
231
232 json = ActiveSupport::JSON.decode(response.body)
232 json = ActiveSupport::JSON.decode(response.body)
233 custom_fields = json['issue']['custom_fields']
233 custom_fields = json['issue']['custom_fields']
234 assert_kind_of Array, custom_fields
234 assert_kind_of Array, custom_fields
235 field = custom_fields.detect {|f| f['id'] == 1}
235 field = custom_fields.detect {|f| f['id'] == 1}
236 assert_kind_of Hash, field
236 assert_kind_of Hash, field
237 assert_equal ['MySQL', 'Oracle'], field['value'].sort
237 assert_equal ['MySQL', 'Oracle'], field['value'].sort
238 end
238 end
239
239
240 test "GET /issues/:id.xml with empty value for multi custom field" do
240 test "GET /issues/:id.xml with empty value for multi custom field" do
241 field = CustomField.find(1)
241 field = CustomField.find(1)
242 field.update_attribute :multiple, true
242 field.update_attribute :multiple, true
243 issue = Issue.find(3)
243 issue = Issue.find(3)
244 issue.custom_field_values = {1 => ['']}
244 issue.custom_field_values = {1 => ['']}
245 issue.save!
245 issue.save!
246
246
247 get '/issues/3.xml'
247 get '/issues/3.xml'
248
248
249 assert_select 'issue custom_fields[type=array]' do
249 assert_select 'issue custom_fields[type=array]' do
250 assert_select 'custom_field[id="1"]' do
250 assert_select 'custom_field[id="1"]' do
251 assert_select 'value[type=array]:empty'
251 assert_select 'value[type=array]:empty'
252 end
252 end
253 end
253 end
254 xml = Hash.from_xml(response.body)
254 xml = Hash.from_xml(response.body)
255 custom_fields = xml['issue']['custom_fields']
255 custom_fields = xml['issue']['custom_fields']
256 assert_kind_of Array, custom_fields
256 assert_kind_of Array, custom_fields
257 field = custom_fields.detect {|f| f['id'] == '1'}
257 field = custom_fields.detect {|f| f['id'] == '1'}
258 assert_kind_of Hash, field
258 assert_kind_of Hash, field
259 assert_equal [], field['value']
259 assert_equal [], field['value']
260 end
260 end
261
261
262 test "GET /issues/:id.json with empty value for multi custom field" do
262 test "GET /issues/:id.json with empty value for multi custom field" do
263 field = CustomField.find(1)
263 field = CustomField.find(1)
264 field.update_attribute :multiple, true
264 field.update_attribute :multiple, true
265 issue = Issue.find(3)
265 issue = Issue.find(3)
266 issue.custom_field_values = {1 => ['']}
266 issue.custom_field_values = {1 => ['']}
267 issue.save!
267 issue.save!
268
268
269 get '/issues/3.json'
269 get '/issues/3.json'
270 assert_response :success
270 assert_response :success
271 json = ActiveSupport::JSON.decode(response.body)
271 json = ActiveSupport::JSON.decode(response.body)
272 custom_fields = json['issue']['custom_fields']
272 custom_fields = json['issue']['custom_fields']
273 assert_kind_of Array, custom_fields
273 assert_kind_of Array, custom_fields
274 field = custom_fields.detect {|f| f['id'] == 1}
274 field = custom_fields.detect {|f| f['id'] == 1}
275 assert_kind_of Hash, field
275 assert_kind_of Hash, field
276 assert_equal [], field['value'].sort
276 assert_equal [], field['value'].sort
277 end
277 end
278
278
279 test "GET /issues/:id.xml with attachments" do
279 test "GET /issues/:id.xml with attachments" do
280 get '/issues/3.xml?include=attachments'
280 get '/issues/3.xml?include=attachments'
281
281
282 assert_select 'issue attachments[type=array]' do
282 assert_select 'issue attachments[type=array]' do
283 assert_select 'attachment', 5
283 assert_select 'attachment', 4
284 assert_select 'attachment id', :text => '4' do
284 assert_select 'attachment id', :text => '1' do
285 assert_select '~ filename', :text => 'source.rb'
285 assert_select '~ filename', :text => 'error281.txt'
286 assert_select '~ content_url', :text => 'http://www.example.com/attachments/download/4/source.rb'
286 assert_select '~ content_url', :text => 'http://www.example.com/attachments/download/1/error281.txt'
287 end
287 end
288 end
288 end
289 end
289 end
290
290
291 test "GET /issues/:id.xml with subtasks" do
291 test "GET /issues/:id.xml with subtasks" do
292 issue = Issue.generate_with_descendants!(:project_id => 1)
292 issue = Issue.generate_with_descendants!(:project_id => 1)
293 get "/issues/#{issue.id}.xml?include=children"
293 get "/issues/#{issue.id}.xml?include=children"
294
294
295 assert_select 'issue id', :text => issue.id.to_s do
295 assert_select 'issue id', :text => issue.id.to_s do
296 assert_select '~ children[type=array] > issue', 2
296 assert_select '~ children[type=array] > issue', 2
297 assert_select '~ children[type=array] > issue > children', 1
297 assert_select '~ children[type=array] > issue > children', 1
298 end
298 end
299 end
299 end
300
300
301 test "GET /issues/:id.json with subtasks" do
301 test "GET /issues/:id.json with subtasks" do
302 issue = Issue.generate_with_descendants!(:project_id => 1)
302 issue = Issue.generate_with_descendants!(:project_id => 1)
303 get "/issues/#{issue.id}.json?include=children"
303 get "/issues/#{issue.id}.json?include=children"
304
304
305 json = ActiveSupport::JSON.decode(response.body)
305 json = ActiveSupport::JSON.decode(response.body)
306 assert_equal 2, json['issue']['children'].size
306 assert_equal 2, json['issue']['children'].size
307 assert_equal 1, json['issue']['children'].select {|child| child.key?('children')}.size
307 assert_equal 1, json['issue']['children'].select {|child| child.key?('children')}.size
308 end
308 end
309
309
310 def test_show_should_include_issue_attributes
310 def test_show_should_include_issue_attributes
311 get '/issues/1.xml'
311 get '/issues/1.xml'
312 assert_select 'issue>is_private', :text => 'false'
312 assert_select 'issue>is_private', :text => 'false'
313 end
313 end
314
314
315 test "GET /issues/:id.xml?include=watchers should include watchers" do
315 test "GET /issues/:id.xml?include=watchers should include watchers" do
316 Watcher.create!(:user_id => 3, :watchable => Issue.find(1))
316 Watcher.create!(:user_id => 3, :watchable => Issue.find(1))
317
317
318 get '/issues/1.xml?include=watchers', {}, credentials('jsmith')
318 get '/issues/1.xml?include=watchers', {}, credentials('jsmith')
319
319
320 assert_response :ok
320 assert_response :ok
321 assert_equal 'application/xml', response.content_type
321 assert_equal 'application/xml', response.content_type
322 assert_select 'issue' do
322 assert_select 'issue' do
323 assert_select 'watchers', Issue.find(1).watchers.count
323 assert_select 'watchers', Issue.find(1).watchers.count
324 assert_select 'watchers' do
324 assert_select 'watchers' do
325 assert_select 'user[id="3"]'
325 assert_select 'user[id="3"]'
326 end
326 end
327 end
327 end
328 end
328 end
329
329
330 test "POST /issues.xml should create an issue with the attributes" do
330 test "POST /issues.xml should create an issue with the attributes" do
331
331
332 payload = <<-XML
332 payload = <<-XML
333 <?xml version="1.0" encoding="UTF-8" ?>
333 <?xml version="1.0" encoding="UTF-8" ?>
334 <issue>
334 <issue>
335 <project_id>1</project_id>
335 <project_id>1</project_id>
336 <tracker_id>2</tracker_id>
336 <tracker_id>2</tracker_id>
337 <status_id>3</status_id>
337 <status_id>3</status_id>
338 <subject>API test</subject>
338 <subject>API test</subject>
339 </issue>
339 </issue>
340 XML
340 XML
341
341
342 assert_difference('Issue.count') do
342 assert_difference('Issue.count') do
343 post '/issues.xml', payload, {"CONTENT_TYPE" => 'application/xml'}.merge(credentials('jsmith'))
343 post '/issues.xml', payload, {"CONTENT_TYPE" => 'application/xml'}.merge(credentials('jsmith'))
344 end
344 end
345 issue = Issue.order('id DESC').first
345 issue = Issue.order('id DESC').first
346 assert_equal 1, issue.project_id
346 assert_equal 1, issue.project_id
347 assert_equal 2, issue.tracker_id
347 assert_equal 2, issue.tracker_id
348 assert_equal 3, issue.status_id
348 assert_equal 3, issue.status_id
349 assert_equal 'API test', issue.subject
349 assert_equal 'API test', issue.subject
350
350
351 assert_response :created
351 assert_response :created
352 assert_equal 'application/xml', @response.content_type
352 assert_equal 'application/xml', @response.content_type
353 assert_select 'issue > id', :text => issue.id.to_s
353 assert_select 'issue > id', :text => issue.id.to_s
354 end
354 end
355
355
356 test "POST /issues.xml with watcher_user_ids should create issue with watchers" do
356 test "POST /issues.xml with watcher_user_ids should create issue with watchers" do
357 assert_difference('Issue.count') do
357 assert_difference('Issue.count') do
358 post '/issues.xml',
358 post '/issues.xml',
359 {:issue => {:project_id => 1, :subject => 'Watchers',
359 {:issue => {:project_id => 1, :subject => 'Watchers',
360 :tracker_id => 2, :status_id => 3, :watcher_user_ids => [3, 1]}}, credentials('jsmith')
360 :tracker_id => 2, :status_id => 3, :watcher_user_ids => [3, 1]}}, credentials('jsmith')
361 assert_response :created
361 assert_response :created
362 end
362 end
363 issue = Issue.order('id desc').first
363 issue = Issue.order('id desc').first
364 assert_equal 2, issue.watchers.size
364 assert_equal 2, issue.watchers.size
365 assert_equal [1, 3], issue.watcher_user_ids.sort
365 assert_equal [1, 3], issue.watcher_user_ids.sort
366 end
366 end
367
367
368 test "POST /issues.xml with failure should return errors" do
368 test "POST /issues.xml with failure should return errors" do
369 assert_no_difference('Issue.count') do
369 assert_no_difference('Issue.count') do
370 post '/issues.xml', {:issue => {:project_id => 1}}, credentials('jsmith')
370 post '/issues.xml', {:issue => {:project_id => 1}}, credentials('jsmith')
371 end
371 end
372
372
373 assert_select 'errors error', :text => "Subject cannot be blank"
373 assert_select 'errors error', :text => "Subject cannot be blank"
374 end
374 end
375
375
376 test "POST /issues.json should create an issue with the attributes" do
376 test "POST /issues.json should create an issue with the attributes" do
377
377
378 payload = <<-JSON
378 payload = <<-JSON
379 {
379 {
380 "issue": {
380 "issue": {
381 "project_id": "1",
381 "project_id": "1",
382 "tracker_id": "2",
382 "tracker_id": "2",
383 "status_id": "3",
383 "status_id": "3",
384 "subject": "API test"
384 "subject": "API test"
385 }
385 }
386 }
386 }
387 JSON
387 JSON
388
388
389 assert_difference('Issue.count') do
389 assert_difference('Issue.count') do
390 post '/issues.json', payload, {"CONTENT_TYPE" => 'application/json'}.merge(credentials('jsmith'))
390 post '/issues.json', payload, {"CONTENT_TYPE" => 'application/json'}.merge(credentials('jsmith'))
391 end
391 end
392
392
393 issue = Issue.order('id DESC').first
393 issue = Issue.order('id DESC').first
394 assert_equal 1, issue.project_id
394 assert_equal 1, issue.project_id
395 assert_equal 2, issue.tracker_id
395 assert_equal 2, issue.tracker_id
396 assert_equal 3, issue.status_id
396 assert_equal 3, issue.status_id
397 assert_equal 'API test', issue.subject
397 assert_equal 'API test', issue.subject
398 end
398 end
399
399
400 test "POST /issues.json with failure should return errors" do
400 test "POST /issues.json with failure should return errors" do
401 assert_no_difference('Issue.count') do
401 assert_no_difference('Issue.count') do
402 post '/issues.json', {:issue => {:project_id => 1}}, credentials('jsmith')
402 post '/issues.json', {:issue => {:project_id => 1}}, credentials('jsmith')
403 end
403 end
404
404
405 json = ActiveSupport::JSON.decode(response.body)
405 json = ActiveSupport::JSON.decode(response.body)
406 assert json['errors'].include?("Subject cannot be blank")
406 assert json['errors'].include?("Subject cannot be blank")
407 end
407 end
408
408
409 test "PUT /issues/:id.xml" do
409 test "PUT /issues/:id.xml" do
410 assert_difference('Journal.count') do
410 assert_difference('Journal.count') do
411 put '/issues/6.xml',
411 put '/issues/6.xml',
412 {:issue => {:subject => 'API update', :notes => 'A new note'}},
412 {:issue => {:subject => 'API update', :notes => 'A new note'}},
413 credentials('jsmith')
413 credentials('jsmith')
414 end
414 end
415
415
416 issue = Issue.find(6)
416 issue = Issue.find(6)
417 assert_equal "API update", issue.subject
417 assert_equal "API update", issue.subject
418 journal = Journal.last
418 journal = Journal.last
419 assert_equal "A new note", journal.notes
419 assert_equal "A new note", journal.notes
420 end
420 end
421
421
422 test "PUT /issues/:id.xml with custom fields" do
422 test "PUT /issues/:id.xml with custom fields" do
423 put '/issues/3.xml',
423 put '/issues/3.xml',
424 {:issue => {:custom_fields => [
424 {:issue => {:custom_fields => [
425 {'id' => '1', 'value' => 'PostgreSQL' },
425 {'id' => '1', 'value' => 'PostgreSQL' },
426 {'id' => '2', 'value' => '150'}
426 {'id' => '2', 'value' => '150'}
427 ]}},
427 ]}},
428 credentials('jsmith')
428 credentials('jsmith')
429
429
430 issue = Issue.find(3)
430 issue = Issue.find(3)
431 assert_equal '150', issue.custom_value_for(2).value
431 assert_equal '150', issue.custom_value_for(2).value
432 assert_equal 'PostgreSQL', issue.custom_value_for(1).value
432 assert_equal 'PostgreSQL', issue.custom_value_for(1).value
433 end
433 end
434
434
435 test "PUT /issues/:id.xml with multi custom fields" do
435 test "PUT /issues/:id.xml with multi custom fields" do
436 field = CustomField.find(1)
436 field = CustomField.find(1)
437 field.update_attribute :multiple, true
437 field.update_attribute :multiple, true
438
438
439 put '/issues/3.xml',
439 put '/issues/3.xml',
440 {:issue => {:custom_fields => [
440 {:issue => {:custom_fields => [
441 {'id' => '1', 'value' => ['MySQL', 'PostgreSQL'] },
441 {'id' => '1', 'value' => ['MySQL', 'PostgreSQL'] },
442 {'id' => '2', 'value' => '150'}
442 {'id' => '2', 'value' => '150'}
443 ]}},
443 ]}},
444 credentials('jsmith')
444 credentials('jsmith')
445
445
446 issue = Issue.find(3)
446 issue = Issue.find(3)
447 assert_equal '150', issue.custom_value_for(2).value
447 assert_equal '150', issue.custom_value_for(2).value
448 assert_equal ['MySQL', 'PostgreSQL'], issue.custom_field_value(1).sort
448 assert_equal ['MySQL', 'PostgreSQL'], issue.custom_field_value(1).sort
449 end
449 end
450
450
451 test "PUT /issues/:id.xml with project change" do
451 test "PUT /issues/:id.xml with project change" do
452 put '/issues/3.xml',
452 put '/issues/3.xml',
453 {:issue => {:project_id => 2, :subject => 'Project changed'}},
453 {:issue => {:project_id => 2, :subject => 'Project changed'}},
454 credentials('jsmith')
454 credentials('jsmith')
455
455
456 issue = Issue.find(3)
456 issue = Issue.find(3)
457 assert_equal 2, issue.project_id
457 assert_equal 2, issue.project_id
458 assert_equal 'Project changed', issue.subject
458 assert_equal 'Project changed', issue.subject
459 end
459 end
460
460
461 test "PUT /issues/:id.xml with failed update" do
461 test "PUT /issues/:id.xml with failed update" do
462 put '/issues/6.xml', {:issue => {:subject => ''}}, credentials('jsmith')
462 put '/issues/6.xml', {:issue => {:subject => ''}}, credentials('jsmith')
463
463
464 assert_response :unprocessable_entity
464 assert_response :unprocessable_entity
465 assert_select 'errors error', :text => "Subject cannot be blank"
465 assert_select 'errors error', :text => "Subject cannot be blank"
466 end
466 end
467
467
468 test "PUT /issues/:id.json" do
468 test "PUT /issues/:id.json" do
469 assert_difference('Journal.count') do
469 assert_difference('Journal.count') do
470 put '/issues/6.json',
470 put '/issues/6.json',
471 {:issue => {:subject => 'API update', :notes => 'A new note'}},
471 {:issue => {:subject => 'API update', :notes => 'A new note'}},
472 credentials('jsmith')
472 credentials('jsmith')
473
473
474 assert_response :ok
474 assert_response :ok
475 assert_equal '', response.body
475 assert_equal '', response.body
476 end
476 end
477
477
478 issue = Issue.find(6)
478 issue = Issue.find(6)
479 assert_equal "API update", issue.subject
479 assert_equal "API update", issue.subject
480 journal = Journal.last
480 journal = Journal.last
481 assert_equal "A new note", journal.notes
481 assert_equal "A new note", journal.notes
482 end
482 end
483
483
484 test "PUT /issues/:id.json with failed update" do
484 test "PUT /issues/:id.json with failed update" do
485 put '/issues/6.json', {:issue => {:subject => ''}}, credentials('jsmith')
485 put '/issues/6.json', {:issue => {:subject => ''}}, credentials('jsmith')
486
486
487 assert_response :unprocessable_entity
487 assert_response :unprocessable_entity
488 json = ActiveSupport::JSON.decode(response.body)
488 json = ActiveSupport::JSON.decode(response.body)
489 assert json['errors'].include?("Subject cannot be blank")
489 assert json['errors'].include?("Subject cannot be blank")
490 end
490 end
491
491
492 test "DELETE /issues/:id.xml" do
492 test "DELETE /issues/:id.xml" do
493 assert_difference('Issue.count', -1) do
493 assert_difference('Issue.count', -1) do
494 delete '/issues/6.xml', {}, credentials('jsmith')
494 delete '/issues/6.xml', {}, credentials('jsmith')
495
495
496 assert_response :ok
496 assert_response :ok
497 assert_equal '', response.body
497 assert_equal '', response.body
498 end
498 end
499 assert_nil Issue.find_by_id(6)
499 assert_nil Issue.find_by_id(6)
500 end
500 end
501
501
502 test "DELETE /issues/:id.json" do
502 test "DELETE /issues/:id.json" do
503 assert_difference('Issue.count', -1) do
503 assert_difference('Issue.count', -1) do
504 delete '/issues/6.json', {}, credentials('jsmith')
504 delete '/issues/6.json', {}, credentials('jsmith')
505
505
506 assert_response :ok
506 assert_response :ok
507 assert_equal '', response.body
507 assert_equal '', response.body
508 end
508 end
509 assert_nil Issue.find_by_id(6)
509 assert_nil Issue.find_by_id(6)
510 end
510 end
511
511
512 test "POST /issues/:id/watchers.xml should add watcher" do
512 test "POST /issues/:id/watchers.xml should add watcher" do
513 assert_difference 'Watcher.count' do
513 assert_difference 'Watcher.count' do
514 post '/issues/1/watchers.xml', {:user_id => 3}, credentials('jsmith')
514 post '/issues/1/watchers.xml', {:user_id => 3}, credentials('jsmith')
515
515
516 assert_response :ok
516 assert_response :ok
517 assert_equal '', response.body
517 assert_equal '', response.body
518 end
518 end
519 watcher = Watcher.order('id desc').first
519 watcher = Watcher.order('id desc').first
520 assert_equal Issue.find(1), watcher.watchable
520 assert_equal Issue.find(1), watcher.watchable
521 assert_equal User.find(3), watcher.user
521 assert_equal User.find(3), watcher.user
522 end
522 end
523
523
524 test "DELETE /issues/:id/watchers/:user_id.xml should remove watcher" do
524 test "DELETE /issues/:id/watchers/:user_id.xml should remove watcher" do
525 Watcher.create!(:user_id => 3, :watchable => Issue.find(1))
525 Watcher.create!(:user_id => 3, :watchable => Issue.find(1))
526
526
527 assert_difference 'Watcher.count', -1 do
527 assert_difference 'Watcher.count', -1 do
528 delete '/issues/1/watchers/3.xml', {}, credentials('jsmith')
528 delete '/issues/1/watchers/3.xml', {}, credentials('jsmith')
529
529
530 assert_response :ok
530 assert_response :ok
531 assert_equal '', response.body
531 assert_equal '', response.body
532 end
532 end
533 assert_equal false, Issue.find(1).watched_by?(User.find(3))
533 assert_equal false, Issue.find(1).watched_by?(User.find(3))
534 end
534 end
535
535
536 def test_create_issue_with_uploaded_file
536 def test_create_issue_with_uploaded_file
537 token = xml_upload('test_create_with_upload', credentials('jsmith'))
537 token = xml_upload('test_create_with_upload', credentials('jsmith'))
538 attachment = Attachment.find_by_token(token)
538 attachment = Attachment.find_by_token(token)
539
539
540 # create the issue with the upload's token
540 # create the issue with the upload's token
541 assert_difference 'Issue.count' do
541 assert_difference 'Issue.count' do
542 post '/issues.xml',
542 post '/issues.xml',
543 {:issue => {:project_id => 1, :subject => 'Uploaded file',
543 {:issue => {:project_id => 1, :subject => 'Uploaded file',
544 :uploads => [{:token => token, :filename => 'test.txt',
544 :uploads => [{:token => token, :filename => 'test.txt',
545 :content_type => 'text/plain'}]}},
545 :content_type => 'text/plain'}]}},
546 credentials('jsmith')
546 credentials('jsmith')
547 assert_response :created
547 assert_response :created
548 end
548 end
549 issue = Issue.order('id DESC').first
549 issue = Issue.order('id DESC').first
550 assert_equal 1, issue.attachments.count
550 assert_equal 1, issue.attachments.count
551 assert_equal attachment, issue.attachments.first
551 assert_equal attachment, issue.attachments.first
552
552
553 attachment.reload
553 attachment.reload
554 assert_equal 'test.txt', attachment.filename
554 assert_equal 'test.txt', attachment.filename
555 assert_equal 'text/plain', attachment.content_type
555 assert_equal 'text/plain', attachment.content_type
556 assert_equal 'test_create_with_upload'.size, attachment.filesize
556 assert_equal 'test_create_with_upload'.size, attachment.filesize
557 assert_equal 2, attachment.author_id
557 assert_equal 2, attachment.author_id
558
558
559 # get the issue with its attachments
559 # get the issue with its attachments
560 get "/issues/#{issue.id}.xml", :include => 'attachments'
560 get "/issues/#{issue.id}.xml", :include => 'attachments'
561 assert_response :success
561 assert_response :success
562 xml = Hash.from_xml(response.body)
562 xml = Hash.from_xml(response.body)
563 attachments = xml['issue']['attachments']
563 attachments = xml['issue']['attachments']
564 assert_kind_of Array, attachments
564 assert_kind_of Array, attachments
565 assert_equal 1, attachments.size
565 assert_equal 1, attachments.size
566 url = attachments.first['content_url']
566 url = attachments.first['content_url']
567 assert_not_nil url
567 assert_not_nil url
568
568
569 # download the attachment
569 # download the attachment
570 get url
570 get url
571 assert_response :success
571 assert_response :success
572 assert_equal 'test_create_with_upload', response.body
572 assert_equal 'test_create_with_upload', response.body
573 end
573 end
574
574
575 def test_create_issue_with_multiple_uploaded_files_as_xml
575 def test_create_issue_with_multiple_uploaded_files_as_xml
576 token1 = xml_upload('File content 1', credentials('jsmith'))
576 token1 = xml_upload('File content 1', credentials('jsmith'))
577 token2 = xml_upload('File content 2', credentials('jsmith'))
577 token2 = xml_upload('File content 2', credentials('jsmith'))
578
578
579 payload = <<-XML
579 payload = <<-XML
580 <?xml version="1.0" encoding="UTF-8" ?>
580 <?xml version="1.0" encoding="UTF-8" ?>
581 <issue>
581 <issue>
582 <project_id>1</project_id>
582 <project_id>1</project_id>
583 <tracker_id>1</tracker_id>
583 <tracker_id>1</tracker_id>
584 <subject>Issue with multiple attachments</subject>
584 <subject>Issue with multiple attachments</subject>
585 <uploads type="array">
585 <uploads type="array">
586 <upload>
586 <upload>
587 <token>#{token1}</token>
587 <token>#{token1}</token>
588 <filename>test1.txt</filename>
588 <filename>test1.txt</filename>
589 </upload>
589 </upload>
590 <upload>
590 <upload>
591 <token>#{token2}</token>
591 <token>#{token2}</token>
592 <filename>test1.txt</filename>
592 <filename>test1.txt</filename>
593 </upload>
593 </upload>
594 </uploads>
594 </uploads>
595 </issue>
595 </issue>
596 XML
596 XML
597
597
598 assert_difference 'Issue.count' do
598 assert_difference 'Issue.count' do
599 post '/issues.xml', payload, {"CONTENT_TYPE" => 'application/xml'}.merge(credentials('jsmith'))
599 post '/issues.xml', payload, {"CONTENT_TYPE" => 'application/xml'}.merge(credentials('jsmith'))
600 assert_response :created
600 assert_response :created
601 end
601 end
602 issue = Issue.order('id DESC').first
602 issue = Issue.order('id DESC').first
603 assert_equal 2, issue.attachments.count
603 assert_equal 2, issue.attachments.count
604 end
604 end
605
605
606 def test_create_issue_with_multiple_uploaded_files_as_json
606 def test_create_issue_with_multiple_uploaded_files_as_json
607 token1 = json_upload('File content 1', credentials('jsmith'))
607 token1 = json_upload('File content 1', credentials('jsmith'))
608 token2 = json_upload('File content 2', credentials('jsmith'))
608 token2 = json_upload('File content 2', credentials('jsmith'))
609
609
610 payload = <<-JSON
610 payload = <<-JSON
611 {
611 {
612 "issue": {
612 "issue": {
613 "project_id": "1",
613 "project_id": "1",
614 "tracker_id": "1",
614 "tracker_id": "1",
615 "subject": "Issue with multiple attachments",
615 "subject": "Issue with multiple attachments",
616 "uploads": [
616 "uploads": [
617 {"token": "#{token1}", "filename": "test1.txt"},
617 {"token": "#{token1}", "filename": "test1.txt"},
618 {"token": "#{token2}", "filename": "test2.txt"}
618 {"token": "#{token2}", "filename": "test2.txt"}
619 ]
619 ]
620 }
620 }
621 }
621 }
622 JSON
622 JSON
623
623
624 assert_difference 'Issue.count' do
624 assert_difference 'Issue.count' do
625 post '/issues.json', payload, {"CONTENT_TYPE" => 'application/json'}.merge(credentials('jsmith'))
625 post '/issues.json', payload, {"CONTENT_TYPE" => 'application/json'}.merge(credentials('jsmith'))
626 assert_response :created
626 assert_response :created
627 end
627 end
628 issue = Issue.order('id DESC').first
628 issue = Issue.order('id DESC').first
629 assert_equal 2, issue.attachments.count
629 assert_equal 2, issue.attachments.count
630 end
630 end
631
631
632 def test_update_issue_with_uploaded_file
632 def test_update_issue_with_uploaded_file
633 token = xml_upload('test_upload_with_upload', credentials('jsmith'))
633 token = xml_upload('test_upload_with_upload', credentials('jsmith'))
634 attachment = Attachment.find_by_token(token)
634 attachment = Attachment.find_by_token(token)
635
635
636 # update the issue with the upload's token
636 # update the issue with the upload's token
637 assert_difference 'Journal.count' do
637 assert_difference 'Journal.count' do
638 put '/issues/1.xml',
638 put '/issues/1.xml',
639 {:issue => {:notes => 'Attachment added',
639 {:issue => {:notes => 'Attachment added',
640 :uploads => [{:token => token, :filename => 'test.txt',
640 :uploads => [{:token => token, :filename => 'test.txt',
641 :content_type => 'text/plain'}]}},
641 :content_type => 'text/plain'}]}},
642 credentials('jsmith')
642 credentials('jsmith')
643 assert_response :ok
643 assert_response :ok
644 assert_equal '', @response.body
644 assert_equal '', @response.body
645 end
645 end
646
646
647 issue = Issue.find(1)
647 issue = Issue.find(1)
648 assert_include attachment, issue.attachments
648 assert_include attachment, issue.attachments
649 end
649 end
650 end
650 end
General Comments 0
You need to be logged in to leave comments. Login now