Вы не можете выбрать более 25 тем Темы должны начинаться с буквы или цифры, могут содержать дефисы(-) и должны содержать не более 35 символов.

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397
  1. # frozen_string_literal: true
  2. # Redmine - project management software
  3. # Copyright (C) 2006-2019 Jean-Philippe Lang
  4. #
  5. # This program is free software; you can redistribute it and/or
  6. # modify it under the terms of the GNU General Public License
  7. # as published by the Free Software Foundation; either version 2
  8. # of the License, or (at your option) any later version.
  9. #
  10. # This program is distributed in the hope that it will be useful,
  11. # but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. # GNU General Public License for more details.
  14. #
  15. # You should have received a copy of the GNU General Public License
  16. # along with this program; if not, write to the Free Software
  17. # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
  18. require File.expand_path('../../../test_helper', __FILE__)
  19. class Redmine::ApiTest::NewsTest < Redmine::ApiTest::Base
  20. fixtures :projects, :trackers, :issue_statuses, :issues,
  21. :enumerations, :users, :issue_categories,
  22. :projects_trackers,
  23. :roles,
  24. :member_roles,
  25. :members,
  26. :enabled_modules,
  27. :news,
  28. :comments,
  29. :attachments
  30. test "GET /news.xml should return news" do
  31. get '/news.xml'
  32. assert_select 'news[type=array] news id', :text => '2'
  33. end
  34. test "GET /news.json should return news" do
  35. get '/news.json'
  36. json = ActiveSupport::JSON.decode(response.body)
  37. assert_kind_of Hash, json
  38. assert_kind_of Array, json['news']
  39. assert_kind_of Hash, json['news'].first
  40. assert_equal 2, json['news'].first['id']
  41. end
  42. test "GET /projects/:project_id/news.xml should return news" do
  43. get '/projects/ecookbook/news.xml'
  44. assert_select 'news[type=array] news id', :text => '2'
  45. end
  46. test "GET /projects/:project_id/news.json should return news" do
  47. get '/projects/ecookbook/news.json'
  48. json = ActiveSupport::JSON.decode(response.body)
  49. assert_kind_of Hash, json
  50. assert_kind_of Array, json['news']
  51. assert_kind_of Hash, json['news'].first
  52. assert_equal 2, json['news'].first['id']
  53. end
  54. test "GET /news/:id.xml" do
  55. get "/news/1.xml"
  56. assert_response :success
  57. assert_equal 'application/xml', response.media_type
  58. assert_select 'news' do
  59. assert_select 'id', 1
  60. assert_select "project[id=1][name=\"eCookbook\"]"
  61. assert_select "author[id=2][name=\"John Smith\"]"
  62. assert_select 'title', 'eCookbook first release !'
  63. assert_select 'summary', 'First version was released...'
  64. assert_select 'description', "eCookbook 1.0 has been released.\n\nVisit http://ecookbook.somenet.foo/"
  65. assert_select 'created_on', News.find(1).created_on.iso8601
  66. end
  67. end
  68. test "GET /news/:id.json" do
  69. get "/news/1.json"
  70. assert_response :success
  71. assert_equal 'application/json', response.media_type
  72. json = ActiveSupport::JSON.decode(response.body)
  73. assert_equal 1, json['news']['id']
  74. end
  75. test "GET /news/:id.xml with attachments" do
  76. news = News.find(1)
  77. attachment = Attachment.first
  78. attachment.container = news
  79. attachment.save!
  80. get "/news/1.xml?include=attachments"
  81. assert_select 'news attachments[type=array]' do
  82. assert_select 'attachment id', :text => '1' do
  83. assert_select '~ filename', :text => 'error281.txt'
  84. assert_select '~ content_url', :text => 'http://www.example.com/attachments/download/1/error281.txt'
  85. end
  86. end
  87. end
  88. test "GET /news/:id.xml with comments" do
  89. get "/news/1.xml?include=comments"
  90. assert_select 'news comments[type=array]' do
  91. assert_select 'comment', 2
  92. assert_select 'comment[id=1]' do
  93. assert_select 'author[id=1][name="Redmine Admin"]'
  94. assert_select 'content', :text => 'my first comment'
  95. end
  96. assert_select 'comment[id=2]' do
  97. assert_select 'author[id=2][name="John Smith"]'
  98. assert_select 'content', :text => 'This is an other comment'
  99. end
  100. end
  101. end
  102. test "POST /project/:project_id/news.xml should create a news with the attributes" do
  103. payload = <<~XML
  104. <?xml version="1.0" encoding="UTF-8" ?>
  105. <news>
  106. <title>NewsXmlApiTest</title>
  107. <summary>News XML-API Test</summary>
  108. <description>This is the description</description>
  109. </news>
  110. XML
  111. assert_difference('News.count') do
  112. post(
  113. '/projects/1/news.xml',
  114. :params => payload,
  115. :headers => {"CONTENT_TYPE" => 'application/xml'}.merge(credentials('jsmith')))
  116. end
  117. news = News.find_by(:title => 'NewsXmlApiTest')
  118. assert_not_nil news
  119. assert_equal 'News XML-API Test', news.summary
  120. assert_equal 'This is the description', news.description
  121. assert_equal User.find_by_login('jsmith'), news.author
  122. assert_equal Project.find(1), news.project
  123. assert_response :no_content
  124. end
  125. test "POST /project/:project_id/news.xml with failure should return errors" do
  126. assert_no_difference('News.count') do
  127. post(
  128. '/projects/1/news.xml',
  129. :params => {:news => {:title => ''}},
  130. :headers => credentials('jsmith'))
  131. end
  132. assert_select 'errors error', :text => "Title cannot be blank"
  133. end
  134. test "POST /project/:project_id/news.json should create a news with the attributes" do
  135. payload = <<~JSON
  136. {
  137. "news": {
  138. "title": "NewsJsonApiTest",
  139. "summary": "News JSON-API Test",
  140. "description": "This is the description"
  141. }
  142. }
  143. JSON
  144. assert_difference('News.count') do
  145. post(
  146. '/projects/1/news.json',
  147. :params => payload,
  148. :headers => {"CONTENT_TYPE" => 'application/json'}.merge(credentials('jsmith')))
  149. end
  150. news = News.find_by(:title => 'NewsJsonApiTest')
  151. assert_not_nil news
  152. assert_equal 'News JSON-API Test', news.summary
  153. assert_equal 'This is the description', news.description
  154. assert_equal User.find_by_login('jsmith'), news.author
  155. assert_equal Project.find(1), news.project
  156. assert_response :no_content
  157. end
  158. test "POST /project/:project_id/news.json with failure should return errors" do
  159. assert_no_difference('News.count') do
  160. post(
  161. '/projects/1/news.json',
  162. :params => {:news => {:title => ''}},
  163. :headers => credentials('jsmith'))
  164. end
  165. json = ActiveSupport::JSON.decode(response.body)
  166. assert json['errors'].include?("Title cannot be blank")
  167. end
  168. test "POST /project/:project_id/news.xml with attachment should create a news with attachment" do
  169. token = xml_upload('test_create_with_attachment', credentials('jsmith'))
  170. attachment = Attachment.find_by_token(token)
  171. assert_difference 'News.count' do
  172. post(
  173. '/projects/1/news.xml',
  174. :params => {:news => {:title => 'News XML-API with Attachment',
  175. :description => 'desc'},
  176. :attachments => [{:token => token, :filename => 'test.txt',
  177. :content_type => 'text/plain'}]},
  178. :headers => credentials('jsmith'))
  179. assert_response :no_content
  180. end
  181. news = News.find_by(:title => 'News XML-API with Attachment')
  182. assert_equal attachment, news.attachments.first
  183. attachment.reload
  184. assert_equal 'test.txt', attachment.filename
  185. assert_equal 'text/plain', attachment.content_type
  186. assert_equal 'test_create_with_attachment'.size, attachment.filesize
  187. assert_equal 2, attachment.author_id
  188. end
  189. test "POST /project/:project_id/news.xml with multiple attachment should create a news with attachments" do
  190. token1 = xml_upload('File content 1', credentials('jsmith'))
  191. token2 = xml_upload('File content 2', credentials('jsmith'))
  192. payload = <<~XML
  193. <?xml version="1.0" encoding="UTF-8" ?>
  194. <news>
  195. <title>News XML-API with attachments</title>
  196. <description>News with multiple attachments</description>
  197. <uploads type="array">
  198. <upload>
  199. <token>#{token1}</token>
  200. <filename>test1.txt</filename>
  201. </upload>
  202. <upload>
  203. <token>#{token2}</token>
  204. <filename>test2.txt</filename>
  205. </upload>
  206. </uploads>
  207. </news>
  208. XML
  209. assert_difference('News.count') do
  210. post(
  211. '/projects/1/news.xml',
  212. :params => payload,
  213. :headers => {"CONTENT_TYPE" => 'application/xml'}.merge(credentials('jsmith')))
  214. assert_response :no_content
  215. end
  216. news = News.find_by(:title => 'News XML-API with attachments')
  217. assert_equal 2, news.attachments.count
  218. end
  219. test "POST /project/:project_id/news.json with multiple attachment should create a news with attachments" do
  220. token1 = json_upload('File content 1', credentials('jsmith'))
  221. token2 = json_upload('File content 2', credentials('jsmith'))
  222. payload = <<~JSON
  223. {
  224. "news": {
  225. "title": "News JSON-API with attachments",
  226. "description": "News with multiple attachments",
  227. "uploads": [
  228. {"token": "#{token1}", "filename": "test1.txt"},
  229. {"token": "#{token2}", "filename": "test2.txt"}
  230. ]
  231. }
  232. }
  233. JSON
  234. assert_difference('News.count') do
  235. post(
  236. '/projects/1/news.json',
  237. :params => payload,
  238. :headers => {"CONTENT_TYPE" => 'application/json'}.merge(credentials('jsmith')))
  239. assert_response :no_content
  240. end
  241. news = News.find_by(:title => 'News JSON-API with attachments')
  242. assert_equal 2, news.attachments.count
  243. end
  244. test "PUT /news/:id.xml" do
  245. payload = <<~XML
  246. <?xml version="1.0" encoding="UTF-8" ?>
  247. <news>
  248. <title>NewsUpdateXmlApiTest</title>
  249. <summary>News Update XML-API Test</summary>
  250. <description>update description via xml api</description>
  251. </news>
  252. XML
  253. put(
  254. '/news/1.xml',
  255. :params => payload,
  256. :headers => {"CONTENT_TYPE" => 'application/xml'}.merge(credentials('jsmith')))
  257. news = News.find(1)
  258. assert_equal 'NewsUpdateXmlApiTest', news.title
  259. assert_equal 'News Update XML-API Test', news.summary
  260. assert_equal 'update description via xml api', news.description
  261. end
  262. test "PUT /news/:id.json" do
  263. payload = <<~JSON
  264. {
  265. "news": {
  266. "title": "NewsUpdateJsonApiTest",
  267. "summary": "News Update JSON-API Test",
  268. "description": "update description via json api"
  269. }
  270. }
  271. JSON
  272. put(
  273. '/news/1.json',
  274. :params => payload,
  275. :headers => {"CONTENT_TYPE" => 'application/json'}.merge(credentials('jsmith')))
  276. news = News.find(1)
  277. assert_equal 'NewsUpdateJsonApiTest', news.title
  278. assert_equal 'News Update JSON-API Test', news.summary
  279. assert_equal 'update description via json api', news.description
  280. end
  281. test "PUT /news/:id.xml with failed update" do
  282. put(
  283. '/news/1.xml',
  284. :params => {:news => {:title => ''}},
  285. :headers => credentials('jsmith'))
  286. assert_response :unprocessable_entity
  287. assert_select 'errors error', :text => "Title cannot be blank"
  288. end
  289. test "PUT /news/:id.json with failed update" do
  290. put(
  291. '/news/1.json',
  292. :params => {:news => {:title => ''}},
  293. :headers => credentials('jsmith'))
  294. assert_response :unprocessable_entity
  295. json = ActiveSupport::JSON.decode(response.body)
  296. assert json['errors'].include?("Title cannot be blank")
  297. end
  298. test "PUT /news/:id.xml with multiple attachment should update a news with attachments" do
  299. token1 = xml_upload('File content 1', credentials('jsmith'))
  300. token2 = xml_upload('File content 2', credentials('jsmith'))
  301. payload = <<~XML
  302. <?xml version="1.0" encoding="UTF-8" ?>
  303. <news>
  304. <title>News Update XML-API with attachments</title>
  305. <uploads type="array">
  306. <upload>
  307. <token>#{token1}</token>
  308. <filename>test1.txt</filename>
  309. </upload>
  310. <upload>
  311. <token>#{token2}</token>
  312. <filename>test2.txt</filename>
  313. </upload>
  314. </uploads>
  315. </news>
  316. XML
  317. put(
  318. '/news/1.xml',
  319. :params => payload,
  320. :headers => {"CONTENT_TYPE" => 'application/xml'}.merge(credentials('jsmith')))
  321. assert_response :no_content
  322. news = News.find_by(:title => 'News Update XML-API with attachments')
  323. assert_equal 2, news.attachments.count
  324. end
  325. test "PUT /news/:id.json with multiple attachment should update a news with attachments" do
  326. token1 = json_upload('File content 1', credentials('jsmith'))
  327. token2 = json_upload('File content 2', credentials('jsmith'))
  328. payload = <<~JSON
  329. {
  330. "news": {
  331. "title": "News Update JSON-API with attachments",
  332. "uploads": [
  333. {"token": "#{token1}", "filename": "test1.txt"},
  334. {"token": "#{token2}", "filename": "test2.txt"}
  335. ]
  336. }
  337. }
  338. JSON
  339. put(
  340. '/news/1.json',
  341. :params => payload,
  342. :headers => {"CONTENT_TYPE" => 'application/json'}.merge(credentials('jsmith')))
  343. assert_response :no_content
  344. news = News.find_by(:title => 'News Update JSON-API with attachments')
  345. assert_equal 2, news.attachments.count
  346. end
  347. test "DELETE /news/:id.xml" do
  348. assert_difference('News.count', -1) do
  349. delete '/news/1.xml', :headers => credentials('jsmith')
  350. assert_response :no_content
  351. assert_equal '', response.body
  352. end
  353. assert_nil News.find_by_id(1)
  354. end
  355. test "DELETE /news/:id.json" do
  356. assert_difference('News.count', -1) do
  357. delete '/news/1.json', :headers => credentials('jsmith')
  358. assert_response :no_content
  359. assert_equal '', response.body
  360. end
  361. assert_nil News.find_by_id(6)
  362. end
  363. end