article_spec.rb 28 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739
  1. require 'rails_helper'
  2. RSpec.describe 'Ticket Article API endpoints', type: :request do
  3. let(:admin) do
  4. create(:admin, groups: Group.all)
  5. end
  6. let!(:group) { create(:group) }
  7. let(:agent) do
  8. create(:agent, groups: Group.all)
  9. end
  10. let(:customer) do
  11. create(:customer)
  12. end
  13. describe 'request handling' do
  14. it 'does ticket create with agent and articles' do
  15. params = {
  16. title: 'a new ticket #1',
  17. group: 'Users',
  18. customer_id: customer.id,
  19. article: {
  20. body: 'some body',
  21. }
  22. }
  23. authenticated_as(agent)
  24. post '/api/v1/tickets', params: params, as: :json
  25. expect(response).to have_http_status(:created)
  26. params = {
  27. ticket_id: json_response['id'],
  28. content_type: 'text/plain', # or text/html
  29. body: 'some body',
  30. type: 'note',
  31. }
  32. post '/api/v1/ticket_articles', params: params, as: :json
  33. expect(response).to have_http_status(:created)
  34. expect(json_response).to be_a_kind_of(Hash)
  35. expect(json_response['subject']).to be_nil
  36. expect(json_response['body']).to eq('some body')
  37. expect(json_response['content_type']).to eq('text/plain')
  38. expect(json_response['updated_by_id']).to eq(agent.id)
  39. expect(json_response['created_by_id']).to eq(agent.id)
  40. ticket = Ticket.find(json_response['ticket_id'])
  41. expect(ticket.articles.count).to eq(2)
  42. expect(ticket.articles[0].attachments.count).to eq(0)
  43. expect(ticket.articles[1].attachments.count).to eq(0)
  44. params = {
  45. ticket_id: json_response['ticket_id'],
  46. content_type: 'text/html', # or text/html
  47. body: 'some body <img src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAUA
  48. AAAFCAYAAACNbyblAAAAHElEQVQI12P4//8/w38GIAXDIBKE0DHxgljNBAAO
  49. 9TXL0Y4OHwAAAABJRU5ErkJggg==" alt="Red dot" />',
  50. type: 'note',
  51. }
  52. post '/api/v1/ticket_articles', params: params, as: :json
  53. expect(response).to have_http_status(:created)
  54. expect(json_response).to be_a_kind_of(Hash)
  55. expect(json_response['subject']).to be_nil
  56. expect(json_response['body']).not_to match(%r{some body <img src="cid:.+?})
  57. expect(json_response['body']).to match(%r{some body <img src="/api/v1/ticket_attachment/.+?" alt="Red dot"})
  58. expect(json_response['content_type']).to eq('text/html')
  59. expect(json_response['updated_by_id']).to eq(agent.id)
  60. expect(json_response['created_by_id']).to eq(agent.id)
  61. expect(ticket.articles.count).to eq(3)
  62. expect(ticket.articles[0].attachments.count).to eq(0)
  63. expect(ticket.articles[1].attachments.count).to eq(0)
  64. expect(ticket.articles[2].attachments.count).to eq(1)
  65. expect(ticket.articles[2].attachments[0]['id']).to be_truthy
  66. expect(ticket.articles[2].attachments[0]['filename']).to eq('image1.png')
  67. expect(ticket.articles[2].attachments[0]['size']).to eq('21')
  68. expect(ticket.articles[2].attachments[0]['preferences']['Mime-Type']).to eq('image/png')
  69. expect(ticket.articles[2].attachments[0]['preferences']['Content-Disposition']).to eq('inline')
  70. expect(ticket.articles[2].attachments[0]['preferences']['Content-ID']).to match(%r{@zammad.example.com})
  71. params = {
  72. ticket_id: json_response['ticket_id'],
  73. content_type: 'text/html', # or text/html
  74. body: 'some body',
  75. type: 'note',
  76. attachments: [
  77. { 'filename' => 'some_file.txt',
  78. 'data' => 'dGVzdCAxMjM=',
  79. 'mime-type' => 'text/plain' },
  80. ],
  81. }
  82. post '/api/v1/ticket_articles', params: params, as: :json
  83. expect(response).to have_http_status(:created)
  84. expect(json_response).to be_a_kind_of(Hash)
  85. expect(json_response['subject']).to be_nil
  86. expect(json_response['body']).to eq('some body')
  87. expect(json_response['content_type']).to eq('text/html')
  88. expect(json_response['updated_by_id']).to eq(agent.id)
  89. expect(json_response['created_by_id']).to eq(agent.id)
  90. expect(ticket.articles.count).to eq(4)
  91. expect(ticket.articles[0].attachments.count).to eq(0)
  92. expect(ticket.articles[1].attachments.count).to eq(0)
  93. expect(ticket.articles[2].attachments.count).to eq(1)
  94. expect(ticket.articles[3].attachments.count).to eq(1)
  95. get "/api/v1/ticket_articles/#{json_response['id']}?expand=true", params: {}, as: :json
  96. expect(response).to have_http_status(:ok)
  97. expect(json_response).to be_a_kind_of(Hash)
  98. expect(json_response['attachments'].count).to eq(1)
  99. expect(json_response['attachments'][0]['id']).to be_truthy
  100. expect(json_response['attachments'][0]['filename']).to eq('some_file.txt')
  101. expect(json_response['attachments'][0]['size']).to eq('8')
  102. expect(json_response['attachments'][0]['preferences']['Mime-Type']).to eq('text/plain')
  103. params = {
  104. ticket_id: json_response['ticket_id'],
  105. content_type: 'text/plain',
  106. body: 'some body',
  107. type: 'note',
  108. internal: false,
  109. preferences: {
  110. some_key1: 123,
  111. highlight: '123',
  112. },
  113. }
  114. post '/api/v1/ticket_articles', params: params, as: :json
  115. expect(response).to have_http_status(:created)
  116. expect(json_response).to be_a_kind_of(Hash)
  117. expect(json_response['subject']).to be_nil
  118. expect(json_response['body']).to eq('some body')
  119. expect(json_response['internal']).to eq(false)
  120. expect(json_response['content_type']).to eq('text/plain')
  121. expect(json_response['updated_by_id']).to eq(agent.id)
  122. expect(json_response['created_by_id']).to eq(agent.id)
  123. expect(json_response['preferences']['some_key1']).to eq(123)
  124. expect(json_response['preferences']['highlight']).to eq('123')
  125. expect(ticket.articles.count).to eq(5)
  126. params = {
  127. body: 'some body 2',
  128. internal: true,
  129. preferences: {
  130. some_key2: 'abc',
  131. highlight: '234',
  132. },
  133. }
  134. put "/api/v1/ticket_articles/#{json_response['id']}", params: params, as: :json
  135. expect(response).to have_http_status(:ok)
  136. expect(json_response).to be_a_kind_of(Hash)
  137. expect(json_response['subject']).to be_nil
  138. expect(json_response['body']).not_to eq('some body 2')
  139. expect(json_response['internal']).to eq(true)
  140. expect(json_response['content_type']).to eq('text/plain')
  141. expect(json_response['updated_by_id']).to eq(agent.id)
  142. expect(json_response['created_by_id']).to eq(agent.id)
  143. expect(json_response['preferences']['some_key1']).to eq(123)
  144. expect(json_response['preferences']['some_key2']).not_to eq('abc')
  145. expect(json_response['preferences']['highlight']).to eq('234')
  146. end
  147. it 'does ticket create with customer and articles' do
  148. params = {
  149. title: 'a new ticket #2',
  150. group: 'Users',
  151. article: {
  152. body: 'some body',
  153. }
  154. }
  155. authenticated_as(customer)
  156. post '/api/v1/tickets', params: params, as: :json
  157. expect(response).to have_http_status(:created)
  158. params = {
  159. ticket_id: json_response['id'],
  160. content_type: 'text/plain', # or text/html
  161. body: 'some body',
  162. type: 'note',
  163. }
  164. post '/api/v1/ticket_articles', params: params, as: :json
  165. expect(response).to have_http_status(:created)
  166. expect(json_response).to be_a_kind_of(Hash)
  167. expect(json_response['subject']).to be_nil
  168. expect(json_response['body']).to eq('some body')
  169. expect(json_response['content_type']).to eq('text/plain')
  170. expect(json_response['updated_by_id']).to eq(customer.id)
  171. expect(json_response['created_by_id']).to eq(customer.id)
  172. ticket = Ticket.find(json_response['ticket_id'])
  173. expect(ticket.articles.count).to eq(2)
  174. expect(ticket.articles[1].sender.name).to eq('Customer')
  175. expect(ticket.articles[0].attachments.count).to eq(0)
  176. expect(ticket.articles[1].attachments.count).to eq(0)
  177. params = {
  178. ticket_id: json_response['ticket_id'],
  179. content_type: 'text/plain', # or text/html
  180. body: 'some body',
  181. sender: 'Agent',
  182. type: 'note',
  183. }
  184. post '/api/v1/ticket_articles', params: params, as: :json
  185. expect(response).to have_http_status(:created)
  186. expect(json_response).to be_a_kind_of(Hash)
  187. expect(json_response['subject']).to be_nil
  188. expect(json_response['body']).to eq('some body')
  189. expect(json_response['content_type']).to eq('text/plain')
  190. expect(json_response['updated_by_id']).to eq(customer.id)
  191. expect(json_response['created_by_id']).to eq(customer.id)
  192. ticket = Ticket.find(json_response['ticket_id'])
  193. expect(ticket.articles.count).to eq(3)
  194. expect(ticket.articles[2].sender.name).to eq('Customer')
  195. expect(ticket.articles[2].internal).to eq(false)
  196. expect(ticket.articles[0].attachments.count).to eq(0)
  197. expect(ticket.articles[1].attachments.count).to eq(0)
  198. expect(ticket.articles[2].attachments.count).to eq(0)
  199. params = {
  200. ticket_id: json_response['ticket_id'],
  201. content_type: 'text/plain', # or text/html
  202. body: 'some body 2',
  203. sender: 'Agent',
  204. type: 'note',
  205. internal: true,
  206. }
  207. post '/api/v1/ticket_articles', params: params, as: :json
  208. expect(response).to have_http_status(:created)
  209. expect(json_response).to be_a_kind_of(Hash)
  210. expect(json_response['subject']).to be_nil
  211. expect(json_response['body']).to eq('some body 2')
  212. expect(json_response['content_type']).to eq('text/plain')
  213. expect(json_response['updated_by_id']).to eq(customer.id)
  214. expect(json_response['created_by_id']).to eq(customer.id)
  215. ticket = Ticket.find(json_response['ticket_id'])
  216. expect(ticket.articles.count).to eq(4)
  217. expect(ticket.articles[3].sender.name).to eq('Customer')
  218. expect(ticket.articles[3].internal).to eq(false)
  219. expect(ticket.articles[0].attachments.count).to eq(0)
  220. expect(ticket.articles[1].attachments.count).to eq(0)
  221. expect(ticket.articles[2].attachments.count).to eq(0)
  222. expect(ticket.articles[3].attachments.count).to eq(0)
  223. # add internal article
  224. article = create(
  225. :ticket_article,
  226. ticket_id: ticket.id,
  227. internal: true,
  228. sender: Ticket::Article::Sender.find_by(name: 'Agent'),
  229. type: Ticket::Article::Type.find_by(name: 'note'),
  230. )
  231. expect(ticket.articles.count).to eq(5)
  232. expect(ticket.articles[4].sender.name).to eq('Agent')
  233. expect(ticket.articles[4].updated_by_id).to eq(1)
  234. expect(ticket.articles[4].created_by_id).to eq(1)
  235. expect(ticket.articles[0].attachments.count).to eq(0)
  236. expect(ticket.articles[1].attachments.count).to eq(0)
  237. expect(ticket.articles[2].attachments.count).to eq(0)
  238. expect(ticket.articles[3].attachments.count).to eq(0)
  239. expect(ticket.articles[4].attachments.count).to eq(0)
  240. get "/api/v1/ticket_articles/#{article.id}", params: {}, as: :json
  241. expect(response).to have_http_status(:forbidden)
  242. expect(json_response).to be_a_kind_of(Hash)
  243. expect(json_response['error']).to eq('Not authorized')
  244. put "/api/v1/ticket_articles/#{article.id}", params: { internal: false }, as: :json
  245. expect(response).to have_http_status(:forbidden)
  246. expect(json_response).to be_a_kind_of(Hash)
  247. expect(json_response['error']).to eq('Not authorized')
  248. end
  249. it 'does create phone ticket for customer and expected origin_by_id' do
  250. params = {
  251. title: 'a new ticket #1',
  252. group: 'Users',
  253. customer_id: customer.id,
  254. article: {
  255. body: 'some body',
  256. sender: 'Customer',
  257. type: 'phone',
  258. }
  259. }
  260. authenticated_as(agent)
  261. post '/api/v1/tickets', params: params, as: :json
  262. expect(response).to have_http_status(:created)
  263. expect(json_response).to be_a_kind_of(Hash)
  264. expect(json_response['title']).to eq('a new ticket #1')
  265. expect(Ticket::Article.where(ticket_id: json_response['id']).count).to eq(2) # original + auto responder
  266. article = Ticket::Article.where(ticket_id: json_response['id']).first
  267. expect(article.origin_by_id).to eq(customer.id)
  268. expect(article.from).to eq("#{customer.firstname} #{customer.lastname} <#{customer.email}>")
  269. end
  270. it 'does create phone ticket by customer and manipulate origin_by_id' do
  271. params = {
  272. title: 'a new ticket #1',
  273. group: 'Users',
  274. customer_id: customer.id,
  275. article: {
  276. body: 'some body',
  277. sender: 'Customer',
  278. type: 'phone',
  279. origin_by_id: 1,
  280. }
  281. }
  282. authenticated_as(customer)
  283. post '/api/v1/tickets', params: params, as: :json
  284. expect(response).to have_http_status(:created)
  285. expect(json_response).to be_a_kind_of(Hash)
  286. expect(Ticket::Article.where(ticket_id: json_response['id']).count).to eq(1) # ony original
  287. article = Ticket::Article.where(ticket_id: json_response['id']).first
  288. expect(article.origin_by_id).to eq(customer.id)
  289. end
  290. it 'does ticket split with html - check attachments' do
  291. ticket = create(:ticket, group: group)
  292. article = create(
  293. :ticket_article,
  294. ticket_id: ticket.id,
  295. type: Ticket::Article::Type.lookup(name: 'note'),
  296. sender: Ticket::Article::Sender.lookup(name: 'Customer'),
  297. body: '<b>test</b> <img src="cid:15.274327094.140938@ZAMMAD.example.com"/> test <img src="cid:15.274327094.140938.3@ZAMMAD.example.com"/>',
  298. content_type: 'text/html',
  299. )
  300. Store.add(
  301. object: 'Ticket::Article',
  302. o_id: article.id,
  303. data: 'content_file1_normally_should_be_an_image',
  304. filename: 'some_file1.jpg',
  305. preferences: {
  306. 'Content-Type' => 'image/jpeg',
  307. 'Mime-Type' => 'image/jpeg',
  308. 'Content-ID' => '15.274327094.140938@zammad.example.com',
  309. 'Content-Disposition' => 'inline',
  310. },
  311. created_by_id: 1,
  312. )
  313. Store.add(
  314. object: 'Ticket::Article',
  315. o_id: article.id,
  316. data: 'content_file2_normally_should_be_an_image',
  317. filename: 'some_file2.jpg',
  318. preferences: {
  319. 'Content-Type' => 'image/jpeg',
  320. 'Mime-Type' => 'image/jpeg',
  321. 'Content-ID' => '15.274327094.140938.2@zammad.example.com',
  322. 'Content-Disposition' => 'inline',
  323. },
  324. created_by_id: 1,
  325. )
  326. Store.add(
  327. object: 'Ticket::Article',
  328. o_id: article.id,
  329. data: 'content_file3_normally_should_be_an_image',
  330. filename: 'some_file3.jpg',
  331. preferences: {
  332. 'Content-Type' => 'image/jpeg',
  333. 'Mime-Type' => 'image/jpeg',
  334. 'Content-ID' => '15.274327094.140938.3@zammad.example.com',
  335. },
  336. created_by_id: 1,
  337. )
  338. Store.add(
  339. object: 'Ticket::Article',
  340. o_id: article.id,
  341. data: 'content_file4_normally_should_be_an_image',
  342. filename: 'some_file4.jpg',
  343. preferences: {
  344. 'Content-Type' => 'image/jpeg',
  345. 'Mime-Type' => 'image/jpeg',
  346. 'Content-ID' => '15.274327094.140938.4@zammad.example.com',
  347. },
  348. created_by_id: 1,
  349. )
  350. Store.add(
  351. object: 'Ticket::Article',
  352. o_id: article.id,
  353. data: 'content_file1_normally_should_be_an_pdf',
  354. filename: 'Rechnung_RE-2018-200.pdf',
  355. preferences: {
  356. 'Content-Type' => 'application/octet-stream; name="Rechnung_RE-2018-200.pdf"',
  357. 'Mime-Type' => 'application/octet-stream',
  358. 'Content-ID' => '8AB0BEC88984EE4EBEF643C79C8E0346@zammad.example.com',
  359. 'Content-Description' => 'Rechnung_RE-2018-200.pdf',
  360. 'Content-Disposition' => 'attachment',
  361. },
  362. created_by_id: 1,
  363. )
  364. params = {
  365. form_id: 'new_form_id123',
  366. }
  367. authenticated_as(agent)
  368. post "/api/v1/ticket_attachment_upload_clone_by_article/#{article.id}", params: params, as: :json
  369. expect(response).to have_http_status(:ok)
  370. expect(json_response).to be_a_kind_of(Hash)
  371. expect(json_response['attachments']).to be_truthy
  372. expect(json_response['attachments'].count).to eq(3)
  373. post "/api/v1/ticket_attachment_upload_clone_by_article/#{article.id}", params: params, as: :json
  374. expect(response).to have_http_status(:ok)
  375. expect(json_response).to be_a_kind_of(Hash)
  376. expect(json_response['attachments']).to be_truthy
  377. expect(json_response['attachments'].count).to eq(0)
  378. end
  379. it 'does ticket split with plain - check attachments' do
  380. ticket = create(
  381. :ticket,
  382. group: group,
  383. updated_by_id: agent.id,
  384. created_by_id: agent.id,
  385. )
  386. article = create(
  387. :ticket_article,
  388. ticket_id: ticket.id,
  389. type: Ticket::Article::Type.lookup(name: 'note'),
  390. sender: Ticket::Article::Sender.lookup(name: 'Customer'),
  391. body: '<b>test</b> <img src="cid:15.274327094.140938@zammad.example.com"/>',
  392. content_type: 'text/plain',
  393. updated_by_id: 1,
  394. created_by_id: 1,
  395. )
  396. Store.add(
  397. object: 'Ticket::Article',
  398. o_id: article.id,
  399. data: 'content_file1_normally_should_be_an_image',
  400. filename: 'some_file1.jpg',
  401. preferences: {
  402. 'Content-Type' => 'image/jpeg',
  403. 'Mime-Type' => 'image/jpeg',
  404. 'Content-ID' => '15.274327094.140938@zammad.example.com',
  405. 'Content-Disposition' => 'inline',
  406. },
  407. created_by_id: 1,
  408. )
  409. Store.add(
  410. object: 'Ticket::Article',
  411. o_id: article.id,
  412. data: 'content_file1_normally_should_be_an_image',
  413. filename: 'some_file2.jpg',
  414. preferences: {
  415. 'Content-Type' => 'image/jpeg',
  416. 'Mime-Type' => 'image/jpeg',
  417. 'Content-ID' => '15.274327094.140938.2@zammad.example.com',
  418. 'Content-Disposition' => 'inline',
  419. },
  420. created_by_id: 1,
  421. )
  422. Store.add(
  423. object: 'Ticket::Article',
  424. o_id: article.id,
  425. data: 'content_file1_normally_should_be_an_pdf',
  426. filename: 'Rechnung_RE-2018-200.pdf',
  427. preferences: {
  428. 'Content-Type' => 'application/octet-stream; name="Rechnung_RE-2018-200.pdf"',
  429. 'Mime-Type' => 'application/octet-stream',
  430. 'Content-ID' => '8AB0BEC88984EE4EBEF643C79C8E0346@zammad.example.com',
  431. 'Content-Description' => 'Rechnung_RE-2018-200.pdf',
  432. 'Content-Disposition' => 'attachment',
  433. },
  434. created_by_id: 1,
  435. )
  436. params = {
  437. form_id: 'new_form_id123',
  438. }
  439. authenticated_as(agent)
  440. post "/api/v1/ticket_attachment_upload_clone_by_article/#{article.id}", params: params, as: :json
  441. expect(response).to have_http_status(:ok)
  442. expect(json_response).to be_a_kind_of(Hash)
  443. expect(json_response['attachments']).to be_truthy
  444. expect(json_response['attachments'].count).to eq(3)
  445. post "/api/v1/ticket_attachment_upload_clone_by_article/#{article.id}", params: params, as: :json
  446. expect(response).to have_http_status(:ok)
  447. expect(json_response).to be_a_kind_of(Hash)
  448. expect(json_response['attachments']).to be_truthy
  449. expect(json_response['attachments'].count).to eq(0)
  450. end
  451. it 'does ticket create with mentions' do
  452. params = {
  453. title: 'a new ticket #1',
  454. group: 'Users',
  455. customer_id: customer.id,
  456. article: {
  457. body: "some body <a data-mention-user-id=\"#{agent.id}\">agent</a>",
  458. }
  459. }
  460. authenticated_as(agent)
  461. post '/api/v1/tickets', params: params, as: :json
  462. expect(response).to have_http_status(:created)
  463. expect(Mention.where(mentionable: Ticket.last).count).to eq(1)
  464. end
  465. it 'does not ticket create with mentions when customer' do
  466. params = {
  467. title: 'a new ticket #1',
  468. group: 'Users',
  469. customer_id: customer.id,
  470. article: {
  471. body: "some body <a data-mention-user-id=\"#{agent.id}\">agent</a>",
  472. }
  473. }
  474. authenticated_as(customer)
  475. post '/api/v1/tickets', params: params, as: :json
  476. expect(response).to have_http_status(:internal_server_error)
  477. expect(Mention.count).to eq(0)
  478. end
  479. end
  480. describe 'DELETE /api/v1/ticket_articles/:id', authenticated_as: -> { user } do
  481. let(:other_agent) { create(:agent, groups: [Group.first]) }
  482. let(:ticket) do
  483. create(:ticket, group: Group.first)
  484. end
  485. let(:article_communication) do
  486. create(:ticket_article,
  487. sender_name: 'Agent', type_name: 'email', ticket: ticket,
  488. updated_by_id: agent.id, created_by_id: agent.id )
  489. end
  490. let(:article_note_self) do
  491. create(:ticket_article,
  492. sender_name: 'Agent', internal: true, type_name: 'note', ticket: ticket,
  493. updated_by_id: user.id, created_by_id: user.id )
  494. end
  495. let(:article_note_other) do
  496. create(:ticket_article,
  497. sender_name: 'Agent', internal: true, type_name: 'note', ticket: ticket,
  498. updated_by_id: other_agent.id, created_by_id: other_agent.id )
  499. end
  500. let(:article_note_customer) do
  501. create(:ticket_article,
  502. sender_name: 'Customer', internal: false, type_name: 'note', ticket: ticket,
  503. updated_by_id: customer.id, created_by_id: customer.id )
  504. end
  505. let(:article_note_communication_self) do
  506. create(:ticket_article_type, name: 'note_communication', communication: true)
  507. create(:ticket_article,
  508. sender_name: 'Agent', internal: true, type_name: 'note_communication', ticket: ticket,
  509. updated_by_id: user.id, created_by_id: user.id )
  510. end
  511. let(:article_note_communication_other) do
  512. create(:ticket_article_type, name: 'note_communication', communication: true)
  513. create(:ticket_article,
  514. sender_name: 'Agent', internal: true, type_name: 'note_communication', ticket: ticket,
  515. updated_by_id: other_agent.id, created_by_id: other_agent.id )
  516. end
  517. def delete_article_via_rest(article)
  518. delete "/api/v1/ticket_articles/#{article.id}", params: {}, as: :json
  519. end
  520. shared_examples 'succeeds' do
  521. it 'succeeds' do
  522. expect { delete_article_via_rest(article) }.to change { Ticket::Article.exists?(id: article.id) }
  523. end
  524. end
  525. shared_examples 'fails' do
  526. it 'fails' do
  527. expect { delete_article_via_rest(article) }.not_to change { Ticket::Article.exists?(id: article.id) }
  528. end
  529. end
  530. shared_examples 'deleting' do |item:, now:, later:, much_later:|
  531. context "deleting #{item}" do
  532. let(:article) { send(item) }
  533. include_examples now ? 'succeeds' : 'fails'
  534. context '8 minutes later' do
  535. before { article && travel(8.minutes) }
  536. include_examples later ? 'succeeds' : 'fails'
  537. end
  538. context '11 minutes later' do
  539. before { article && travel(11.minutes) }
  540. include_examples much_later ? 'succeeds' : 'fails'
  541. end
  542. end
  543. end
  544. context 'as admin' do
  545. let(:user) { admin }
  546. include_examples 'deleting',
  547. item: 'article_communication',
  548. now: false, later: false, much_later: false
  549. include_examples 'deleting',
  550. item: 'article_note_self',
  551. now: true, later: true, much_later: false
  552. include_examples 'deleting',
  553. item: 'article_note_other',
  554. now: false, later: false, much_later: false
  555. include_examples 'deleting',
  556. item: 'article_note_customer',
  557. now: false, later: false, much_later: false
  558. include_examples 'deleting',
  559. item: 'article_note_communication_self',
  560. now: true, later: true, much_later: false
  561. include_examples 'deleting',
  562. item: 'article_note_communication_other',
  563. now: false, later: false, much_later: false
  564. end
  565. context 'as agent' do
  566. let(:user) { agent }
  567. include_examples 'deleting',
  568. item: 'article_communication',
  569. now: false, later: false, much_later: false
  570. include_examples 'deleting',
  571. item: 'article_note_self',
  572. now: true, later: true, much_later: false
  573. include_examples 'deleting',
  574. item: 'article_note_other',
  575. now: false, later: false, much_later: false
  576. include_examples 'deleting',
  577. item: 'article_note_customer',
  578. now: false, later: false, much_later: false
  579. include_examples 'deleting',
  580. item: 'article_note_communication_self',
  581. now: true, later: true, much_later: false
  582. include_examples 'deleting',
  583. item: 'article_note_communication_other',
  584. now: false, later: false, much_later: false
  585. end
  586. context 'as customer' do
  587. let(:user) { customer }
  588. include_examples 'deleting',
  589. item: 'article_communication',
  590. now: false, later: false, much_later: false
  591. include_examples 'deleting',
  592. item: 'article_note_other',
  593. now: false, later: false, much_later: false
  594. include_examples 'deleting',
  595. item: 'article_note_customer',
  596. now: false, later: false, much_later: false
  597. include_examples 'deleting',
  598. item: 'article_note_communication_self',
  599. now: false, later: false, much_later: false
  600. include_examples 'deleting',
  601. item: 'article_note_communication_other',
  602. now: false, later: false, much_later: false
  603. end
  604. context 'with custom timeframe' do
  605. before { Setting.set 'ui_ticket_zoom_article_delete_timeframe', 6000 }
  606. let(:article) { article_note_self }
  607. context 'as admin' do
  608. let(:user) { admin }
  609. context 'deleting before timeframe' do
  610. before { article && travel(5000.seconds) }
  611. include_examples 'succeeds'
  612. end
  613. context 'deleting after timeframe' do
  614. before { article && travel(8000.seconds) }
  615. include_examples 'fails'
  616. end
  617. end
  618. context 'as agent' do
  619. let(:user) { agent }
  620. context 'deleting before timeframe' do
  621. before { article && travel(5000.seconds) }
  622. include_examples 'succeeds'
  623. end
  624. context 'deleting after timeframe' do
  625. before { article && travel(8000.seconds) }
  626. include_examples 'fails'
  627. end
  628. end
  629. end
  630. context 'with timeframe as 0' do
  631. before { Setting.set 'ui_ticket_zoom_article_delete_timeframe', 0 }
  632. let(:article) { article_note_self }
  633. context 'as agent' do
  634. let(:user) { agent }
  635. context 'deleting long after' do
  636. before { article && travel(99.days) }
  637. include_examples 'succeeds'
  638. end
  639. end
  640. end
  641. end
  642. end