ticket_articles_controller_test.rb 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518
  1. require 'test_helper'
  2. class TicketArticlesControllerTest < ActionDispatch::IntegrationTest
  3. setup do
  4. # set accept header
  5. @headers = { 'ACCEPT' => 'application/json', 'CONTENT_TYPE' => 'application/json' }
  6. # create agent
  7. roles = Role.where(name: %w[Admin Agent])
  8. groups = Group.all
  9. UserInfo.current_user_id = 1
  10. @admin = User.create!(
  11. login: 'tickets-admin',
  12. firstname: 'Tickets',
  13. lastname: 'Admin',
  14. email: 'tickets-admin@example.com',
  15. password: 'adminpw',
  16. active: true,
  17. roles: roles,
  18. groups: groups,
  19. )
  20. # create agent
  21. roles = Role.where(name: 'Agent')
  22. @agent = User.create!(
  23. login: 'tickets-agent@example.com',
  24. firstname: 'Tickets',
  25. lastname: 'Agent',
  26. email: 'tickets-agent@example.com',
  27. password: 'agentpw',
  28. active: true,
  29. roles: roles,
  30. groups: groups,
  31. )
  32. # create customer without org
  33. roles = Role.where(name: 'Customer')
  34. @customer_without_org = User.create!(
  35. login: 'tickets-customer1@example.com',
  36. firstname: 'Tickets',
  37. lastname: 'Customer1',
  38. email: 'tickets-customer1@example.com',
  39. password: 'customer1pw',
  40. active: true,
  41. roles: roles,
  42. )
  43. end
  44. test '01.01 ticket create with agent and articles' do
  45. credentials = ActionController::HttpAuthentication::Basic.encode_credentials('tickets-agent@example.com', 'agentpw')
  46. params = {
  47. title: 'a new ticket #1',
  48. group: 'Users',
  49. customer_id: @customer_without_org.id,
  50. article: {
  51. body: 'some body',
  52. }
  53. }
  54. post '/api/v1/tickets', params: params.to_json, headers: @headers.merge('Authorization' => credentials)
  55. assert_response(201)
  56. result = JSON.parse(@response.body)
  57. params = {
  58. ticket_id: result['id'],
  59. content_type: 'text/plain', # or text/html
  60. body: 'some body',
  61. type: 'note',
  62. }
  63. post '/api/v1/ticket_articles', params: params.to_json, headers: @headers.merge('Authorization' => credentials)
  64. assert_response(201)
  65. result = JSON.parse(@response.body)
  66. assert_equal(Hash, result.class)
  67. assert_nil(result['subject'])
  68. assert_equal('some body', result['body'])
  69. assert_equal('text/plain', result['content_type'])
  70. assert_equal(@agent.id, result['updated_by_id'])
  71. assert_equal(@agent.id, result['created_by_id'])
  72. ticket = Ticket.find(result['ticket_id'])
  73. assert_equal(2, ticket.articles.count)
  74. assert_equal(0, ticket.articles[0].attachments.count)
  75. assert_equal(0, ticket.articles[1].attachments.count)
  76. params = {
  77. ticket_id: result['ticket_id'],
  78. content_type: 'text/html', # or text/html
  79. body: 'some body <img src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAUA
  80. AAAFCAYAAACNbyblAAAAHElEQVQI12P4//8/w38GIAXDIBKE0DHxgljNBAAO
  81. 9TXL0Y4OHwAAAABJRU5ErkJggg==" alt="Red dot" />',
  82. type: 'note',
  83. }
  84. post '/api/v1/ticket_articles', params: params.to_json, headers: @headers.merge('Authorization' => credentials)
  85. assert_response(201)
  86. result = JSON.parse(@response.body)
  87. assert_equal(Hash, result.class)
  88. assert_nil(result['subject'])
  89. assert_no_match(/some body <img src="cid:.+?/, result['body'])
  90. assert_match(%r{some body <img src="/api/v1/ticket_attachment/.+?" alt="Red dot"}, result['body'])
  91. assert_equal('text/html', result['content_type'])
  92. assert_equal(@agent.id, result['updated_by_id'])
  93. assert_equal(@agent.id, result['created_by_id'])
  94. assert_equal(3, ticket.articles.count)
  95. assert_equal(0, ticket.articles[0].attachments.count)
  96. assert_equal(0, ticket.articles[1].attachments.count)
  97. assert_equal(1, ticket.articles[2].attachments.count)
  98. assert(ticket.articles[2].attachments[0]['id'])
  99. assert_equal('image1.png', ticket.articles[2].attachments[0]['filename'])
  100. assert_equal('21', ticket.articles[2].attachments[0]['size'])
  101. assert_equal('image/png', ticket.articles[2].attachments[0]['preferences']['Mime-Type'])
  102. assert_equal('inline', ticket.articles[2].attachments[0]['preferences']['Content-Disposition'])
  103. assert_match(/@zammad.example.com/, ticket.articles[2].attachments[0]['preferences']['Content-ID'])
  104. params = {
  105. ticket_id: result['ticket_id'],
  106. content_type: 'text/html', # or text/html
  107. body: 'some body',
  108. type: 'note',
  109. attachments: [
  110. 'filename' => 'some_file.txt',
  111. 'data' => 'dGVzdCAxMjM=',
  112. 'mime-type' => 'text/plain',
  113. ],
  114. }
  115. post '/api/v1/ticket_articles', params: params.to_json, headers: @headers.merge('Authorization' => credentials)
  116. assert_response(201)
  117. result = JSON.parse(@response.body)
  118. assert_equal(Hash, result.class)
  119. assert_nil(result['subject'])
  120. assert_equal('some body', result['body'])
  121. assert_equal('text/html', result['content_type'])
  122. assert_equal(@agent.id, result['updated_by_id'])
  123. assert_equal(@agent.id, result['created_by_id'])
  124. assert_equal(4, ticket.articles.count)
  125. assert_equal(0, ticket.articles[0].attachments.count)
  126. assert_equal(0, ticket.articles[1].attachments.count)
  127. assert_equal(1, ticket.articles[2].attachments.count)
  128. assert_equal(1, ticket.articles[3].attachments.count)
  129. get "/api/v1/ticket_articles/#{result['id']}?expand=true", params: {}.to_json, headers: @headers.merge('Authorization' => credentials)
  130. assert_response(200)
  131. result = JSON.parse(@response.body)
  132. assert_equal(Hash, result.class)
  133. assert_equal(1, result['attachments'].count)
  134. assert(result['attachments'][0]['id'])
  135. assert_equal('some_file.txt', result['attachments'][0]['filename'])
  136. assert_equal('8', result['attachments'][0]['size'])
  137. assert_equal('text/plain', result['attachments'][0]['preferences']['Mime-Type'])
  138. end
  139. test '02.01 ticket create with customer and articles' do
  140. credentials = ActionController::HttpAuthentication::Basic.encode_credentials('tickets-customer1@example.com', 'customer1pw')
  141. params = {
  142. title: 'a new ticket #2',
  143. group: 'Users',
  144. article: {
  145. body: 'some body',
  146. }
  147. }
  148. post '/api/v1/tickets', params: params.to_json, headers: @headers.merge('Authorization' => credentials)
  149. assert_response(201)
  150. result = JSON.parse(@response.body)
  151. params = {
  152. ticket_id: result['id'],
  153. content_type: 'text/plain', # or text/html
  154. body: 'some body',
  155. type: 'note',
  156. }
  157. post '/api/v1/ticket_articles', params: params.to_json, headers: @headers.merge('Authorization' => credentials)
  158. assert_response(201)
  159. result = JSON.parse(@response.body)
  160. assert_equal(Hash, result.class)
  161. assert_nil(result['subject'])
  162. assert_equal('some body', result['body'])
  163. assert_equal('text/plain', result['content_type'])
  164. assert_equal(@customer_without_org.id, result['updated_by_id'])
  165. assert_equal(@customer_without_org.id, result['created_by_id'])
  166. ticket = Ticket.find(result['ticket_id'])
  167. assert_equal(2, ticket.articles.count)
  168. assert_equal('Customer', ticket.articles[1].sender.name)
  169. assert_equal(0, ticket.articles[0].attachments.count)
  170. assert_equal(0, ticket.articles[1].attachments.count)
  171. params = {
  172. ticket_id: result['ticket_id'],
  173. content_type: 'text/plain', # or text/html
  174. body: 'some body',
  175. sender: 'Agent',
  176. type: 'note',
  177. }
  178. post '/api/v1/ticket_articles', params: params.to_json, headers: @headers.merge('Authorization' => credentials)
  179. assert_response(201)
  180. result = JSON.parse(@response.body)
  181. assert_equal(Hash, result.class)
  182. assert_nil(result['subject'])
  183. assert_equal('some body', result['body'])
  184. assert_equal('text/plain', result['content_type'])
  185. assert_equal(@customer_without_org.id, result['updated_by_id'])
  186. assert_equal(@customer_without_org.id, result['created_by_id'])
  187. ticket = Ticket.find(result['ticket_id'])
  188. assert_equal(3, ticket.articles.count)
  189. assert_equal('Customer', ticket.articles[2].sender.name)
  190. assert_equal(false, ticket.articles[2].internal)
  191. assert_equal(0, ticket.articles[0].attachments.count)
  192. assert_equal(0, ticket.articles[1].attachments.count)
  193. assert_equal(0, ticket.articles[2].attachments.count)
  194. params = {
  195. ticket_id: result['ticket_id'],
  196. content_type: 'text/plain', # or text/html
  197. body: 'some body 2',
  198. sender: 'Agent',
  199. type: 'note',
  200. internal: true,
  201. }
  202. post '/api/v1/ticket_articles', params: params.to_json, headers: @headers.merge('Authorization' => credentials)
  203. assert_response(201)
  204. result = JSON.parse(@response.body)
  205. assert_equal(Hash, result.class)
  206. assert_nil(result['subject'])
  207. assert_equal('some body 2', result['body'])
  208. assert_equal('text/plain', result['content_type'])
  209. assert_equal(@customer_without_org.id, result['updated_by_id'])
  210. assert_equal(@customer_without_org.id, result['created_by_id'])
  211. ticket = Ticket.find(result['ticket_id'])
  212. assert_equal(4, ticket.articles.count)
  213. assert_equal('Customer', ticket.articles[3].sender.name)
  214. assert_equal(false, ticket.articles[3].internal)
  215. assert_equal(0, ticket.articles[0].attachments.count)
  216. assert_equal(0, ticket.articles[1].attachments.count)
  217. assert_equal(0, ticket.articles[2].attachments.count)
  218. assert_equal(0, ticket.articles[3].attachments.count)
  219. # add internal article
  220. article = Ticket::Article.create(
  221. ticket_id: ticket.id,
  222. from: 'some_sender@example.com',
  223. to: 'some_recipient@example.com',
  224. subject: 'some subject',
  225. message_id: 'some@id',
  226. body: 'some message 123',
  227. internal: true,
  228. sender: Ticket::Article::Sender.find_by(name: 'Agent'),
  229. type: Ticket::Article::Type.find_by(name: 'note'),
  230. updated_by_id: 1,
  231. created_by_id: 1,
  232. )
  233. assert_equal(5, ticket.articles.count)
  234. assert_equal('Agent', ticket.articles[4].sender.name)
  235. assert_equal(1, ticket.articles[4].updated_by_id)
  236. assert_equal(1, ticket.articles[4].created_by_id)
  237. assert_equal(0, ticket.articles[0].attachments.count)
  238. assert_equal(0, ticket.articles[1].attachments.count)
  239. assert_equal(0, ticket.articles[2].attachments.count)
  240. assert_equal(0, ticket.articles[3].attachments.count)
  241. assert_equal(0, ticket.articles[4].attachments.count)
  242. get "/api/v1/ticket_articles/#{article.id}", params: {}.to_json, headers: @headers.merge('Authorization' => credentials)
  243. assert_response(401)
  244. result = JSON.parse(@response.body)
  245. assert_equal(Hash, result.class)
  246. assert_equal('Not authorized', result['error'])
  247. put "/api/v1/ticket_articles/#{article.id}", params: { internal: false }.to_json, headers: @headers.merge('Authorization' => credentials)
  248. assert_response(401)
  249. result = JSON.parse(@response.body)
  250. assert_equal(Hash, result.class)
  251. assert_equal('Not authorized', result['error'])
  252. end
  253. test '03.01 create phone ticket for customer and expected origin_by_id' do
  254. credentials = ActionController::HttpAuthentication::Basic.encode_credentials('tickets-agent@example.com', 'agentpw')
  255. params = {
  256. title: 'a new ticket #1',
  257. group: 'Users',
  258. customer_id: @customer_without_org.id,
  259. article: {
  260. body: 'some body',
  261. sender: 'Customer',
  262. type: 'phone',
  263. }
  264. }
  265. post '/api/v1/tickets', params: params.to_json, headers: @headers.merge('Authorization' => credentials)
  266. assert_response(201)
  267. result = JSON.parse(@response.body)
  268. assert_equal(Hash, result.class)
  269. article = Ticket::Article.find_by(ticket_id: result['id'])
  270. assert_equal(@customer_without_org.id, article.origin_by_id)
  271. assert_equal('Tickets Customer1 <tickets-customer1@example.com>', article.from)
  272. end
  273. test '03.02 create phone ticket by customer and manipulate origin_by_id' do
  274. credentials = ActionController::HttpAuthentication::Basic.encode_credentials('tickets-customer1@example.com', 'customer1pw')
  275. params = {
  276. title: 'a new ticket #1',
  277. group: 'Users',
  278. customer_id: @customer_without_org.id,
  279. article: {
  280. body: 'some body',
  281. sender: 'Customer',
  282. type: 'phone',
  283. origin_by_id: 1,
  284. }
  285. }
  286. post '/api/v1/tickets', params: params.to_json, headers: @headers.merge('Authorization' => credentials)
  287. assert_response(201)
  288. result = JSON.parse(@response.body)
  289. assert_equal(Hash, result.class)
  290. article = Ticket::Article.find_by(ticket_id: result['id'])
  291. assert_equal(@customer_without_org.id, article.origin_by_id)
  292. end
  293. test '04.01 ticket split with html - check attachments' do
  294. ticket = Ticket.create!(
  295. title: 'some title',
  296. group: Group.lookup(name: 'Users'),
  297. customer_id: @customer_without_org.id,
  298. state: Ticket::State.lookup(name: 'new'),
  299. priority: Ticket::Priority.lookup(name: '2 normal'),
  300. updated_by_id: @agent.id,
  301. created_by_id: @agent.id,
  302. )
  303. article = Ticket::Article.create!(
  304. type: Ticket::Article::Type.lookup(name: 'note'),
  305. sender: Ticket::Article::Sender.lookup(name: 'Customer'),
  306. from: 'sender',
  307. subject: 'subject',
  308. body: '<b>test</b> <img src="cid:15.274327094.140938@ZAMMAD.example.com"/> test <img src="cid:15.274327094.140938.3@ZAMMAD.example.com"/>',
  309. content_type: 'text/html',
  310. ticket_id: ticket.id,
  311. updated_by_id: 1,
  312. created_by_id: 1,
  313. )
  314. Store.add(
  315. object: 'Ticket::Article',
  316. o_id: article.id,
  317. data: 'content_file1_normally_should_be_an_image',
  318. filename: 'some_file1.jpg',
  319. preferences: {
  320. 'Content-Type' => 'image/jpeg',
  321. 'Mime-Type' => 'image/jpeg',
  322. 'Content-ID' => '15.274327094.140938@zammad.example.com',
  323. 'Content-Disposition' => 'inline',
  324. },
  325. created_by_id: 1,
  326. )
  327. Store.add(
  328. object: 'Ticket::Article',
  329. o_id: article.id,
  330. data: 'content_file2_normally_should_be_an_image',
  331. filename: 'some_file2.jpg',
  332. preferences: {
  333. 'Content-Type' => 'image/jpeg',
  334. 'Mime-Type' => 'image/jpeg',
  335. 'Content-ID' => '15.274327094.140938.2@zammad.example.com',
  336. 'Content-Disposition' => 'inline',
  337. },
  338. created_by_id: 1,
  339. )
  340. Store.add(
  341. object: 'Ticket::Article',
  342. o_id: article.id,
  343. data: 'content_file3_normally_should_be_an_image',
  344. filename: 'some_file3.jpg',
  345. preferences: {
  346. 'Content-Type' => 'image/jpeg',
  347. 'Mime-Type' => 'image/jpeg',
  348. 'Content-ID' => '15.274327094.140938.3@zammad.example.com',
  349. },
  350. created_by_id: 1,
  351. )
  352. Store.add(
  353. object: 'Ticket::Article',
  354. o_id: article.id,
  355. data: 'content_file4_normally_should_be_an_image',
  356. filename: 'some_file4.jpg',
  357. preferences: {
  358. 'Content-Type' => 'image/jpeg',
  359. 'Mime-Type' => 'image/jpeg',
  360. 'Content-ID' => '15.274327094.140938.4@zammad.example.com',
  361. },
  362. created_by_id: 1,
  363. )
  364. Store.add(
  365. object: 'Ticket::Article',
  366. o_id: article.id,
  367. data: 'content_file1_normally_should_be_an_pdf',
  368. filename: 'Rechnung_RE-2018-200.pdf',
  369. preferences: {
  370. 'Content-Type' => 'application/octet-stream; name="Rechnung_RE-2018-200.pdf"',
  371. 'Mime-Type' => 'application/octet-stream',
  372. 'Content-ID' => '8AB0BEC88984EE4EBEF643C79C8E0346@zammad.example.com',
  373. 'Content-Description' => 'Rechnung_RE-2018-200.pdf',
  374. 'Content-Disposition' => 'attachment',
  375. },
  376. created_by_id: 1,
  377. )
  378. credentials = ActionController::HttpAuthentication::Basic.encode_credentials('tickets-agent@example.com', 'agentpw')
  379. params = {
  380. form_id: 'new_form_id123',
  381. }
  382. post "/api/v1/ticket_attachment_upload_clone_by_article/#{article.id}", params: params.to_json, headers: @headers.merge('Authorization' => credentials)
  383. assert_response(200)
  384. result = JSON.parse(@response.body)
  385. assert_equal(Hash, result.class)
  386. assert(result['attachments'])
  387. assert_equal(result['attachments'].count, 3)
  388. post "/api/v1/ticket_attachment_upload_clone_by_article/#{article.id}", params: params.to_json, headers: @headers.merge('Authorization' => credentials)
  389. assert_response(200)
  390. result = JSON.parse(@response.body)
  391. assert_equal(Hash, result.class)
  392. assert(result['attachments'])
  393. assert_equal(result['attachments'].count, 0)
  394. end
  395. test '04.02 ticket split with plain - check attachments' do
  396. ticket = Ticket.create!(
  397. title: 'some title',
  398. group: Group.lookup(name: 'Users'),
  399. customer_id: @customer_without_org.id,
  400. state: Ticket::State.lookup(name: 'new'),
  401. priority: Ticket::Priority.lookup(name: '2 normal'),
  402. updated_by_id: @agent.id,
  403. created_by_id: @agent.id,
  404. )
  405. article = Ticket::Article.create!(
  406. type: Ticket::Article::Type.lookup(name: 'note'),
  407. sender: Ticket::Article::Sender.lookup(name: 'Customer'),
  408. from: 'sender',
  409. subject: 'subject',
  410. body: '<b>test</b> <img src="cid:15.274327094.140938@zammad.example.com"/>',
  411. content_type: 'text/plain',
  412. ticket_id: ticket.id,
  413. updated_by_id: 1,
  414. created_by_id: 1,
  415. )
  416. Store.add(
  417. object: 'Ticket::Article',
  418. o_id: article.id,
  419. data: 'content_file1_normally_should_be_an_image',
  420. filename: 'some_file1.jpg',
  421. preferences: {
  422. 'Content-Type' => 'image/jpeg',
  423. 'Mime-Type' => 'image/jpeg',
  424. 'Content-ID' => '15.274327094.140938@zammad.example.com',
  425. 'Content-Disposition' => 'inline',
  426. },
  427. created_by_id: 1,
  428. )
  429. Store.add(
  430. object: 'Ticket::Article',
  431. o_id: article.id,
  432. data: 'content_file1_normally_should_be_an_image',
  433. filename: 'some_file2.jpg',
  434. preferences: {
  435. 'Content-Type' => 'image/jpeg',
  436. 'Mime-Type' => 'image/jpeg',
  437. 'Content-ID' => '15.274327094.140938.2@zammad.example.com',
  438. 'Content-Disposition' => 'inline',
  439. },
  440. created_by_id: 1,
  441. )
  442. Store.add(
  443. object: 'Ticket::Article',
  444. o_id: article.id,
  445. data: 'content_file1_normally_should_be_an_pdf',
  446. filename: 'Rechnung_RE-2018-200.pdf',
  447. preferences: {
  448. 'Content-Type' => 'application/octet-stream; name="Rechnung_RE-2018-200.pdf"',
  449. 'Mime-Type' => 'application/octet-stream',
  450. 'Content-ID' => '8AB0BEC88984EE4EBEF643C79C8E0346@zammad.example.com',
  451. 'Content-Description' => 'Rechnung_RE-2018-200.pdf',
  452. 'Content-Disposition' => 'attachment',
  453. },
  454. created_by_id: 1,
  455. )
  456. credentials = ActionController::HttpAuthentication::Basic.encode_credentials('tickets-agent@example.com', 'agentpw')
  457. params = {
  458. form_id: 'new_form_id123',
  459. }
  460. post "/api/v1/ticket_attachment_upload_clone_by_article/#{article.id}", params: params.to_json, headers: @headers.merge('Authorization' => credentials)
  461. assert_response(200)
  462. result = JSON.parse(@response.body)
  463. assert_equal(Hash, result.class)
  464. assert(result['attachments'])
  465. assert_equal(result['attachments'].count, 3)
  466. post "/api/v1/ticket_attachment_upload_clone_by_article/#{article.id}", params: params.to_json, headers: @headers.merge('Authorization' => credentials)
  467. assert_response(200)
  468. result = JSON.parse(@response.body)
  469. assert_equal(Hash, result.class)
  470. assert(result['attachments'])
  471. assert_equal(result['attachments'].count, 0)
  472. end
  473. end