object_manager_attributes_spec.rb 33 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114
  1. # Copyright (C) 2012-2024 Zammad Foundation, https://zammad-foundation.org/
  2. require 'rails_helper'
  3. RSpec.describe 'ObjectManager Attributes', type: :request do
  4. let(:admin) do
  5. create(:admin)
  6. end
  7. describe 'request handling' do
  8. it 'does add new ticket text object' do
  9. authenticated_as(admin)
  10. post '/api/v1/object_manager_attributes', params: {}, as: :json
  11. # token based on headers
  12. params = {
  13. name: 'test1',
  14. object: 'Ticket',
  15. display: 'Test 1',
  16. active: true,
  17. data_type: 'input',
  18. data_option: {
  19. default: 'test',
  20. type: 'text',
  21. maxlength: 120
  22. },
  23. screens: {
  24. create_middle: {
  25. 'ticket.customer': {
  26. shown: true,
  27. item_class: 'column'
  28. },
  29. 'ticket.agent': {
  30. shown: true,
  31. item_class: 'column'
  32. }
  33. },
  34. edit: {
  35. 'ticket.customer': {
  36. shown: true
  37. },
  38. 'ticket.agent': {
  39. shown: true
  40. }
  41. }
  42. },
  43. id: 'c-196'
  44. }
  45. post '/api/v1/object_manager_attributes', params: params, as: :json
  46. expect(response).to have_http_status(:created)
  47. expect(json_response).to be_truthy
  48. expect(json_response['data_option']['null']).to be_truthy
  49. expect(json_response['data_option']['null']).to be(true)
  50. expect(json_response['name']).to eq('test1')
  51. end
  52. it 'does add new ticket text object - no default' do
  53. authenticated_as(admin)
  54. post '/api/v1/object_manager_attributes', params: {}, as: :json
  55. # token based on headers
  56. params = {
  57. name: 'test2',
  58. object: 'Ticket',
  59. display: 'Test 2',
  60. active: true,
  61. data_type: 'input',
  62. data_option: {
  63. type: 'text',
  64. maxlength: 120
  65. },
  66. screens: {
  67. create_middle: {
  68. 'ticket.customer': {
  69. shown: true,
  70. item_class: 'column'
  71. },
  72. 'ticket.agent': {
  73. shown: true,
  74. item_class: 'column'
  75. }
  76. },
  77. edit: {
  78. 'ticket.customer': {
  79. shown: true
  80. },
  81. 'ticket.agent': {
  82. shown: true
  83. }
  84. }
  85. },
  86. id: 'c-196'
  87. }
  88. post '/api/v1/object_manager_attributes', params: params, as: :json
  89. expect(response).to have_http_status(:created)
  90. expect(json_response).to be_truthy
  91. expect(json_response['data_option']['null']).to be_truthy
  92. expect(json_response['data_option']['null']).to be(true)
  93. expect(json_response['name']).to eq('test2')
  94. end
  95. it 'does update ticket text object', db_strategy: :reset do
  96. # add a new object
  97. object = create(:object_manager_attribute_text)
  98. migration = ObjectManager::Attribute.migration_execute
  99. expect(migration).to be(true)
  100. authenticated_as(admin)
  101. post "/api/v1/object_manager_attributes/#{object.id}", params: {}, as: :json
  102. # parameters for updating
  103. params = {
  104. name: object.name,
  105. object: 'Ticket',
  106. display: 'Test 4',
  107. active: true,
  108. data_type: 'input',
  109. data_option: {
  110. default: 'test',
  111. type: 'text',
  112. maxlength: 120
  113. },
  114. screens: {
  115. create_middle: {
  116. 'ticket.customer': {
  117. shown: true,
  118. item_class: 'column'
  119. },
  120. 'ticket.agent': {
  121. shown: true,
  122. item_class: 'column'
  123. }
  124. },
  125. edit: {
  126. 'ticket.customer': {
  127. shown: true
  128. },
  129. 'ticket.agent': {
  130. shown: true
  131. }
  132. }
  133. },
  134. id: 'c-196'
  135. }
  136. # update the object
  137. put "/api/v1/object_manager_attributes/#{object.id}", params: params, as: :json
  138. expect(response).to have_http_status(:ok)
  139. expect(json_response).to be_truthy
  140. expect(json_response['data_option']['null']).to be_truthy
  141. expect(json_response['name']).to eq(object.name)
  142. expect(json_response['display']).to eq('Test 4')
  143. end
  144. it 'does add new ticket boolean object' do
  145. authenticated_as(admin)
  146. post '/api/v1/object_manager_attributes', params: {}, as: :json
  147. # token based on headers
  148. params = {
  149. active: true,
  150. data_option: {
  151. options: {
  152. false: 'no',
  153. true: 'yes'
  154. }
  155. },
  156. data_type: 'boolean',
  157. display: 'Boolean 2',
  158. id: 'c-200',
  159. name: 'bool2',
  160. object: 'Ticket',
  161. screens: {
  162. create_middle: {
  163. 'ticket.agent' => {
  164. item_class: 'column',
  165. shown: true
  166. },
  167. 'ticket.customer' => {
  168. item_class: 'column',
  169. shown: true
  170. }
  171. },
  172. edit: {
  173. 'ticket.agent' => {
  174. shown: true
  175. },
  176. 'ticket.customer' => {
  177. shown: true
  178. }
  179. }
  180. }
  181. }
  182. post '/api/v1/object_manager_attributes', params: params, as: :json
  183. expect(response).to have_http_status(:created)
  184. expect(json_response).to be_truthy
  185. expect(json_response['data_option']['null']).to be_truthy
  186. expect(json_response['data_option']['null']).to be(true)
  187. expect(json_response['name']).to eq('bool2')
  188. end
  189. it 'does add new user select object' do
  190. authenticated_as(admin)
  191. post '/api/v1/object_manager_attributes', params: {}, as: :json
  192. # token based on headers
  193. params = {
  194. active: true,
  195. data_option: {
  196. options: {
  197. key1: 'foo'
  198. }
  199. },
  200. data_type: 'select',
  201. display: 'Test 5',
  202. id: 'c-204',
  203. name: 'test5',
  204. object: 'User',
  205. screens: {
  206. create: {
  207. 'admin.user' => {
  208. shown: true
  209. },
  210. 'ticket.agent' => {
  211. shown: true
  212. },
  213. 'ticket.customer' => {
  214. shown: true
  215. }
  216. },
  217. edit: {
  218. 'admin.user' => {
  219. shown: true
  220. },
  221. 'ticket.agent' => {
  222. shown: true
  223. }
  224. },
  225. view: {
  226. 'admin.user' => {
  227. shown: true
  228. },
  229. 'ticket.agent' => {
  230. shown: true
  231. },
  232. 'ticket.customer' => {
  233. shown: true
  234. }
  235. }
  236. }
  237. }
  238. post '/api/v1/object_manager_attributes', params: params, as: :json
  239. expect(response).to have_http_status(:created)
  240. expect(json_response).to be_truthy
  241. expect(json_response['data_option']['null']).to be_truthy
  242. expect(json_response['data_option']['null']).to be(true)
  243. expect(json_response['name']).to eq('test5')
  244. end
  245. it 'does update user select object', authenticated_as: -> { admin }, db_strategy: :reset do
  246. # add a new object
  247. object = create(:object_manager_attribute_text, object_name: 'User')
  248. migration = ObjectManager::Attribute.migration_execute
  249. expect(migration).to be(true)
  250. post "/api/v1/object_manager_attributes/#{object.id}", params: {}, as: :json
  251. # parameters for updating
  252. params = {
  253. active: true,
  254. data_option: {
  255. options: {
  256. key1: 'foo',
  257. key2: 'bar'
  258. }
  259. },
  260. data_type: 'select',
  261. display: 'Test 7',
  262. id: 'c-204',
  263. name: object.name,
  264. object: 'User',
  265. screens: {
  266. create: {
  267. 'admin.user' => {
  268. shown: true
  269. },
  270. 'ticket.agent' => {
  271. shown: true
  272. },
  273. 'ticket.customer' => {
  274. shown: true
  275. }
  276. },
  277. edit: {
  278. 'admin.user' => {
  279. shown: true
  280. },
  281. 'ticket.agent' => {
  282. shown: true
  283. }
  284. },
  285. view: {
  286. 'admin.user' => {
  287. shown: true
  288. },
  289. 'ticket.agent' => {
  290. shown: true
  291. },
  292. 'ticket.customer' => {
  293. shown: true
  294. }
  295. }
  296. }
  297. }
  298. # update the object
  299. put "/api/v1/object_manager_attributes/#{object.id}", params: params, as: :json
  300. expect(response).to have_http_status(:ok)
  301. expect(json_response).to be_truthy
  302. expect(json_response['data_option']['options']).to be_truthy
  303. expect(json_response['name']).to eq(object.name)
  304. expect(json_response['display']).to eq('Test 7')
  305. end
  306. it 'does converts string to boolean for default value for boolean data type with true (01)', db_strategy: :reset do
  307. params = {
  308. name: "customerdescription#{SecureRandom.uuid.tr('-', '_')}",
  309. object: 'Ticket',
  310. display: "custom description#{SecureRandom.uuid.tr('-', '_')}",
  311. active: true,
  312. data_type: 'boolean',
  313. data_option: {
  314. options: {
  315. true: '',
  316. false: '',
  317. },
  318. default: 'true',
  319. screens: {
  320. create_middle: {
  321. 'ticket.customer': {
  322. shown: true,
  323. item_class: 'column'
  324. },
  325. 'ticket.agent': {
  326. shown: true,
  327. item_class: 'column'
  328. }
  329. },
  330. edit: {
  331. 'ticket.customer': {
  332. shown: true
  333. },
  334. 'ticket.agent': {
  335. shown: true
  336. }
  337. }
  338. }
  339. },
  340. id: 'c-201'
  341. }
  342. authenticated_as(admin)
  343. post '/api/v1/object_manager_attributes', params: params, as: :json
  344. migration = ObjectManager::Attribute.migration_execute
  345. expect(migration).to be(true)
  346. expect(response).to have_http_status(:created) # created
  347. expect(json_response).to be_truthy
  348. expect(json_response['data_option']['default']).to be_truthy
  349. expect(json_response['data_option']['default']).to be(true)
  350. expect(json_response['data_type']).to eq('boolean')
  351. end
  352. it 'does converts string to boolean for default value for boolean data type with false (02)', db_strategy: :reset do
  353. params = {
  354. name: "customerdescription_#{SecureRandom.uuid.tr('-', '_')}",
  355. object: 'Ticket',
  356. display: "custom description #{SecureRandom.uuid.tr('-', '_')}",
  357. active: true,
  358. data_type: 'boolean',
  359. data_option: {
  360. options: {
  361. true: '',
  362. false: '',
  363. },
  364. default: 'false',
  365. screens: {
  366. create_middle: {
  367. 'ticket.customer': {
  368. shown: true,
  369. item_class: 'column'
  370. },
  371. 'ticket.agent': {
  372. shown: true,
  373. item_class: 'column'
  374. }
  375. },
  376. edit: {
  377. 'ticket.customer': {
  378. shown: true
  379. },
  380. 'ticket.agent': {
  381. shown: true
  382. }
  383. }
  384. }
  385. },
  386. }
  387. authenticated_as(admin)
  388. post '/api/v1/object_manager_attributes', params: params, as: :json
  389. migration = ObjectManager::Attribute.migration_execute
  390. expect(migration).to be(true)
  391. expect(response).to have_http_status(:created) # created
  392. expect(json_response).to be_truthy
  393. expect(json_response['data_option']['default']).to be_falsey
  394. expect(json_response['data_option']['default']).to be(false)
  395. expect(json_response['data_type']).to eq('boolean')
  396. end
  397. it 'does ticket attributes cannot be removed when it is referenced by an overview (03)', db_strategy: :reset do
  398. # 1. create a new ticket attribute and execute migration
  399. ObjectManager::Attribute.migration_execute
  400. params = {
  401. name: 'test_attribute_referenced_by_an_overview',
  402. object: 'Ticket',
  403. display: 'Test Attribute',
  404. active: true,
  405. data_type: 'input',
  406. data_option: {
  407. default: '',
  408. type: 'text',
  409. maxlength: 120,
  410. null: true,
  411. options: {},
  412. relation: ''
  413. },
  414. screens: {
  415. create_middle: {
  416. 'ticket.customer': {
  417. shown: true,
  418. item_class: 'column'
  419. },
  420. 'ticket.agent': {
  421. shown: true,
  422. item_class: 'column'
  423. }
  424. },
  425. edit: {
  426. 'ticket.customer': {
  427. shown: true
  428. },
  429. 'ticket.agent': {
  430. shown: true
  431. }
  432. }
  433. },
  434. }
  435. authenticated_as(admin)
  436. post '/api/v1/object_manager_attributes', params: params, as: :json
  437. migration = ObjectManager::Attribute.migration_execute
  438. expect(migration).to be(true)
  439. # 2. create an overview that uses the attribute
  440. params = {
  441. name: 'test_overview',
  442. roles: Role.where(name: 'Agent').pluck(:name),
  443. condition: {
  444. 'ticket.state_id': {
  445. operator: 'is',
  446. value: Ticket::State.pluck(:id),
  447. },
  448. 'ticket.test_attribute_referenced_by_an_overview': {
  449. operator: 'contains',
  450. value: 'DUMMY'
  451. },
  452. },
  453. order: {
  454. by: 'created_at',
  455. direction: 'DESC',
  456. },
  457. view: {
  458. d: %w[title customer state created_at],
  459. s: %w[number title customer state created_at],
  460. m: %w[number title customer state created_at],
  461. view_mode_default: 's',
  462. },
  463. user_ids: [ '1' ],
  464. }
  465. if Overview.where('name like ?', '%test%').empty?
  466. post '/api/v1/overviews', params: params, as: :json
  467. expect(response).to have_http_status(:created)
  468. expect(Hash).to eq(json_response.class)
  469. expect(json_response['name']).to eq('test_overview')
  470. end
  471. # 3. attempt to delete the ticket attribute
  472. get '/api/v1/object_manager_attributes', as: :json
  473. expect(response).to have_http_status(:ok)
  474. target_attribute = json_response.select { |x| x['name'] == 'test_attribute_referenced_by_an_overview' && x['object'] == 'Ticket' }
  475. expect(target_attribute.size).to eq(1)
  476. target_id = target_attribute[0]['id']
  477. delete "/api/v1/object_manager_attributes/#{target_id}", as: :json
  478. expect(response).to have_http_status(:unprocessable_entity)
  479. expect(response.body).to include('Overview')
  480. expect(response.body).to include('test_overview')
  481. expect(response.body).to include('cannot be deleted!')
  482. end
  483. it 'does ticket attributes cannot be removed when it is referenced by a trigger (04)', db_strategy: :reset do
  484. # 1. create a new ticket attribute and execute migration
  485. ObjectManager::Attribute.migration_execute
  486. params = {
  487. name: 'test_attribute_referenced_by_a_trigger',
  488. object: 'Ticket',
  489. display: 'Test Attribute',
  490. active: true,
  491. data_type: 'input',
  492. data_option: {
  493. default: '',
  494. type: 'text',
  495. maxlength: 120,
  496. null: true,
  497. options: {},
  498. relation: ''
  499. },
  500. screens: {
  501. create_middle: {
  502. 'ticket.customer': {
  503. shown: true,
  504. item_class: 'column'
  505. },
  506. 'ticket.agent': {
  507. shown: true,
  508. item_class: 'column'
  509. }
  510. },
  511. edit: {
  512. 'ticket.customer': {
  513. shown: true
  514. },
  515. 'ticket.agent': {
  516. shown: true
  517. }
  518. }
  519. },
  520. }
  521. authenticated_as(admin)
  522. post '/api/v1/object_manager_attributes', params: params, as: :json
  523. migration = ObjectManager::Attribute.migration_execute
  524. expect(migration).to be(true)
  525. # 2. create an trigger that uses the attribute
  526. params = {
  527. name: 'test_trigger',
  528. condition: {
  529. 'ticket.test_attribute_referenced_by_a_trigger': {
  530. operator: 'contains',
  531. value: 'DUMMY'
  532. }
  533. },
  534. perform: {
  535. 'ticket.state_id': {
  536. value: '2'
  537. }
  538. },
  539. active: true,
  540. id: 'c-3'
  541. }
  542. if Trigger.where('name like ?', '%test%').empty?
  543. post '/api/v1/triggers', params: params, as: :json
  544. expect(response).to have_http_status(:created)
  545. expect(Hash).to eq(json_response.class)
  546. expect(json_response['name']).to eq('test_trigger')
  547. end
  548. # 3. attempt to delete the ticket attribute
  549. get '/api/v1/object_manager_attributes', as: :json
  550. expect(response).to have_http_status(:ok)
  551. target_attribute = json_response.select { |x| x['name'] == 'test_attribute_referenced_by_a_trigger' && x['object'] == 'Ticket' }
  552. expect(target_attribute.size).to eq(1)
  553. target_id = target_attribute[0]['id']
  554. delete "/api/v1/object_manager_attributes/#{target_id}", as: :json
  555. expect(response).to have_http_status(:unprocessable_entity)
  556. expect(response.body).to include('Trigger')
  557. expect(response.body).to include('test_trigger')
  558. expect(response.body).to include('cannot be deleted!')
  559. end
  560. it 'does ticket attributes cannot be removed when it is referenced by a scheduler (05)', db_strategy: :reset do
  561. # 1. create a new ticket attribute and execute migration
  562. ObjectManager::Attribute.migration_execute
  563. params = {
  564. name: 'test_attribute_referenced_by_a_scheduler',
  565. object: 'Ticket',
  566. display: 'Test Attribute',
  567. active: true,
  568. data_type: 'input',
  569. data_option: {
  570. default: '',
  571. type: 'text',
  572. maxlength: 120,
  573. null: true,
  574. options: {},
  575. relation: ''
  576. },
  577. screens: {
  578. create_middle: {
  579. 'ticket.customer': {
  580. shown: true,
  581. item_class: 'column'
  582. },
  583. 'ticket.agent': {
  584. shown: true,
  585. item_class: 'column'
  586. }
  587. },
  588. edit: {
  589. 'ticket.customer': {
  590. shown: true
  591. },
  592. 'ticket.agent': {
  593. shown: true
  594. }
  595. }
  596. },
  597. }
  598. authenticated_as(admin)
  599. post '/api/v1/object_manager_attributes', params: params, as: :json
  600. migration = ObjectManager::Attribute.migration_execute
  601. expect(migration).to be(true)
  602. # 2. create a scheduler that uses the attribute
  603. params = {
  604. name: 'test_scheduler',
  605. object: 'Ticket',
  606. timeplan: {
  607. days: {
  608. Mon: true,
  609. Tue: false,
  610. Wed: false,
  611. Thu: false,
  612. Fri: false,
  613. Sat: false,
  614. Sun: false
  615. },
  616. hours: {
  617. '0': true,
  618. '1': false,
  619. '2': false,
  620. '3': false,
  621. '4': false,
  622. '5': false,
  623. '6': false,
  624. '7': false,
  625. '8': false,
  626. '9': false,
  627. '10': false,
  628. '11': false,
  629. '12': false,
  630. '13': false,
  631. '14': false,
  632. '15': false,
  633. '16': false,
  634. '17': false,
  635. '18': false,
  636. '19': false,
  637. '20': false,
  638. '21': false,
  639. '22': false,
  640. '23': false
  641. },
  642. minutes: {
  643. '0': true,
  644. '10': false,
  645. '20': false,
  646. '30': false,
  647. '40': false,
  648. '50': false
  649. }
  650. },
  651. condition: {
  652. 'ticket.test_attribute_referenced_by_a_scheduler': {
  653. operator: 'contains',
  654. value: 'DUMMY'
  655. }
  656. },
  657. perform: {
  658. 'ticket.state_id': {
  659. value: '2'
  660. }
  661. },
  662. disable_notification: true,
  663. note: '',
  664. active: true,
  665. id: 'c-0'
  666. }
  667. if Job.where('name like ?', '%test%').empty?
  668. post '/api/v1/jobs', params: params, as: :json
  669. expect(response).to have_http_status(:created)
  670. expect(Hash).to eq(json_response.class)
  671. expect(json_response['name']).to eq('test_scheduler')
  672. end
  673. # 3. attempt to delete the ticket attribute
  674. get '/api/v1/object_manager_attributes', as: :json
  675. expect(response).to have_http_status(:ok)
  676. target_attribute = json_response.select { |x| x['name'] == 'test_attribute_referenced_by_a_scheduler' && x['object'] == 'Ticket' }
  677. expect(target_attribute.size).to eq(1)
  678. target_id = target_attribute[0]['id']
  679. delete "/api/v1/object_manager_attributes/#{target_id}", as: :json
  680. expect(response).to have_http_status(:unprocessable_entity)
  681. expect(response.body).to include('Job')
  682. expect(response.body).to include('test_scheduler')
  683. expect(response.body).to include('cannot be deleted!')
  684. end
  685. it 'does ticket attributes can be removed when it is referenced by an overview but by user object (06)', db_strategy: :reset do
  686. # 1. create a new ticket attribute and execute migration
  687. ObjectManager::Attribute.migration_execute
  688. params = {
  689. name: 'test_attribute_referenced_by_an_overview',
  690. object: 'Ticket',
  691. display: 'Test Attribute',
  692. active: true,
  693. data_type: 'input',
  694. data_option: {
  695. default: '',
  696. type: 'text',
  697. maxlength: 120,
  698. null: true,
  699. options: {},
  700. relation: ''
  701. },
  702. screens: {
  703. create_middle: {
  704. 'ticket.customer': {
  705. shown: true,
  706. item_class: 'column'
  707. },
  708. 'ticket.agent': {
  709. shown: true,
  710. item_class: 'column'
  711. }
  712. },
  713. edit: {
  714. 'ticket.customer': {
  715. shown: true
  716. },
  717. 'ticket.agent': {
  718. shown: true
  719. }
  720. }
  721. },
  722. }
  723. authenticated_as(admin)
  724. post '/api/v1/object_manager_attributes', params: params, as: :json
  725. params = {
  726. name: 'test_attribute_referenced_by_an_overview',
  727. object: 'User',
  728. display: 'Test Attribute',
  729. active: true,
  730. data_type: 'input',
  731. data_option: {
  732. default: '',
  733. type: 'text',
  734. maxlength: 120,
  735. null: true,
  736. options: {},
  737. relation: ''
  738. },
  739. screens: {
  740. create_middle: {
  741. 'ticket.customer': {
  742. shown: true,
  743. item_class: 'column'
  744. },
  745. 'ticket.agent': {
  746. shown: true,
  747. item_class: 'column'
  748. }
  749. },
  750. edit: {
  751. 'ticket.customer': {
  752. shown: true
  753. },
  754. 'ticket.agent': {
  755. shown: true
  756. }
  757. }
  758. },
  759. }
  760. post '/api/v1/object_manager_attributes', params: params, as: :json
  761. migration = ObjectManager::Attribute.migration_execute
  762. expect(migration).to be(true)
  763. # 2. create an overview that uses the attribute
  764. params = {
  765. name: 'test_overview',
  766. roles: Role.where(name: 'Agent').pluck(:name),
  767. condition: {
  768. 'ticket.state_id': {
  769. operator: 'is',
  770. value: Ticket::State.pluck(:id),
  771. },
  772. 'ticket.test_attribute_referenced_by_an_overview': {
  773. operator: 'contains',
  774. value: 'DUMMY'
  775. },
  776. },
  777. order: {
  778. by: 'created_at',
  779. direction: 'DESC',
  780. },
  781. view: {
  782. d: %w[title customer state created_at],
  783. s: %w[number title customer state created_at],
  784. m: %w[number title customer state created_at],
  785. view_mode_default: 's',
  786. },
  787. user_ids: [ '1' ],
  788. }
  789. if Overview.where('name like ?', '%test%').empty?
  790. post '/api/v1/overviews', params: params, as: :json
  791. expect(response).to have_http_status(:created)
  792. expect(Hash).to eq(json_response.class)
  793. expect(json_response['name']).to eq('test_overview')
  794. end
  795. # 3. attempt to delete the ticket attribute
  796. get '/api/v1/object_manager_attributes', as: :json
  797. expect(response).to have_http_status(:ok)
  798. all_json_response = json_response
  799. target_attribute = all_json_response.select { |x| x['name'] == 'test_attribute_referenced_by_an_overview' && x['object'] == 'User' }
  800. expect(target_attribute.size).to eq(1)
  801. target_id = target_attribute[0]['id']
  802. delete "/api/v1/object_manager_attributes/#{target_id}", as: :json
  803. expect(response).to have_http_status(:ok)
  804. target_attribute = all_json_response.select { |x| x['name'] == 'test_attribute_referenced_by_an_overview' && x['object'] == 'Ticket' }
  805. expect(target_attribute.size).to eq(1)
  806. target_id = target_attribute[0]['id']
  807. delete "/api/v1/object_manager_attributes/#{target_id}", as: :json
  808. expect(response).to have_http_status(:unprocessable_entity)
  809. expect(response.body).to include('Overview')
  810. expect(response.body).to include('test_overview')
  811. expect(response.body).to include('cannot be deleted!')
  812. migration = ObjectManager::Attribute.migration_execute
  813. expect(migration).to be(true)
  814. end
  815. it 'does verify if attribute type can not be changed (07)', db_strategy: :reset do
  816. params = {
  817. name: "customerdescription_#{SecureRandom.uuid.tr('-', '_')}",
  818. object: 'Ticket',
  819. display: "custom description #{SecureRandom.uuid.tr('-', '_')}",
  820. active: true,
  821. data_type: 'boolean',
  822. data_option: {
  823. options: {
  824. true: '',
  825. false: '',
  826. },
  827. default: 'false',
  828. screens: {
  829. create_middle: {
  830. 'ticket.customer': {
  831. shown: true,
  832. item_class: 'column'
  833. },
  834. 'ticket.agent': {
  835. shown: true,
  836. item_class: 'column'
  837. }
  838. },
  839. edit: {
  840. 'ticket.customer': {
  841. shown: true
  842. },
  843. 'ticket.agent': {
  844. shown: true
  845. }
  846. }
  847. }
  848. },
  849. }
  850. authenticated_as(admin)
  851. post '/api/v1/object_manager_attributes', params: params, as: :json
  852. expect(response).to have_http_status(:created) # created
  853. expect(json_response).to be_truthy
  854. expect(json_response['data_option']['default']).to be_falsey
  855. expect(json_response['data_option']['default']).to be(false)
  856. expect(json_response['data_type']).to eq('boolean')
  857. migration = ObjectManager::Attribute.migration_execute
  858. expect(migration).to be(true)
  859. params['data_type'] = 'input'
  860. params['data_option'] = {
  861. default: 'test',
  862. type: 'text',
  863. maxlength: 120
  864. }
  865. put "/api/v1/object_manager_attributes/#{json_response['id']}", params: params, as: :json
  866. expect(response).to have_http_status(:unprocessable_entity)
  867. expect(json_response).to be_truthy
  868. expect(json_response['error']).to be_truthy
  869. end
  870. it 'does verify if attribute type can be changed (08)', db_strategy: :reset do
  871. params = {
  872. name: "customerdescription_#{SecureRandom.uuid.tr('-', '_')}",
  873. object: 'Ticket',
  874. display: "custom description #{SecureRandom.uuid.tr('-', '_')}",
  875. active: true,
  876. data_type: 'input',
  877. data_option: {
  878. default: 'test',
  879. type: 'text',
  880. maxlength: 120,
  881. },
  882. screens: {
  883. create_middle: {
  884. 'ticket.customer': {
  885. shown: true,
  886. item_class: 'column'
  887. },
  888. 'ticket.agent': {
  889. shown: true,
  890. item_class: 'column'
  891. }
  892. },
  893. edit: {
  894. 'ticket.customer': {
  895. shown: true
  896. },
  897. 'ticket.agent': {
  898. shown: true
  899. }
  900. },
  901. },
  902. }
  903. authenticated_as(admin)
  904. post '/api/v1/object_manager_attributes', params: params, as: :json
  905. expect(response).to have_http_status(:created) # created
  906. expect(json_response).to be_truthy
  907. expect(json_response['data_option']['default']).to eq('test')
  908. expect(json_response['data_type']).to eq('input')
  909. migration = ObjectManager::Attribute.migration_execute
  910. expect(migration).to be(true)
  911. params['data_type'] = 'select'
  912. params['data_option'] = {
  913. default: 'fuu',
  914. options: {
  915. key1: 'foo',
  916. key2: 'fuu',
  917. }
  918. }
  919. put "/api/v1/object_manager_attributes/#{json_response['id']}", params: params, as: :json
  920. expect(response).to have_http_status(:ok)
  921. expect(json_response).to be_truthy
  922. expect(json_response['data_option']['default']).to eq('test')
  923. expect(json_response['data_option_new']['default']).to eq('fuu')
  924. expect(json_response['data_type']).to eq('select')
  925. end
  926. it "doesn't let to update item that doesn't exist", authenticated_as: -> { admin } do
  927. params = {
  928. active: true,
  929. data_option: {
  930. type: 'text',
  931. maxlength: 200
  932. },
  933. data_type: 'input',
  934. display: 'Test 7',
  935. name: 'attribute_that_doesnt_exist',
  936. object: 'User',
  937. }
  938. # update the object
  939. put '/api/v1/object_manager_attributes/abc', params: params, as: :json
  940. expect(response).to have_http_status(:unprocessable_entity)
  941. end
  942. context 'position handling', authenticated_as: -> { admin } do
  943. let(:base_params) do
  944. {
  945. name: "customerdescription_#{SecureRandom.uuid.tr('-', '_')}",
  946. object: 'Ticket',
  947. display: "custom description #{SecureRandom.uuid.tr('-', '_')}",
  948. active: true,
  949. data_type: 'input',
  950. data_option: {
  951. default: 'test',
  952. type: 'text',
  953. maxlength: 120,
  954. },
  955. }
  956. end
  957. let(:new_attribute_id) { json_response['id'] }
  958. let(:new_attribute_object) { ObjectManager::Attribute.find new_attribute_id }
  959. before { post '/api/v1/object_manager_attributes', params: params, as: :json }
  960. context 'when creating a new attribute' do
  961. let(:params) { base_params }
  962. context 'with no position attribute provided' do
  963. let(:maximum_position) do
  964. ObjectManager::Attribute
  965. .for_object(params[:object])
  966. .maximum(:position)
  967. end
  968. it 'defaults to the maximum available position' do
  969. expect(new_attribute_object.position).to eq maximum_position
  970. end
  971. end
  972. context 'with a position attribute given' do
  973. let(:position) { 50 }
  974. let(:params) { base_params.merge(position: position) }
  975. it 'defaults to given position' do
  976. expect(new_attribute_object.position).to eq position
  977. end
  978. end
  979. end
  980. context 'when updating an existing attribute' do
  981. let(:alternative_position) { 123 }
  982. let(:alternative_display) { 'another description' }
  983. let(:params) { base_params }
  984. let(:alternative_params) { base_params.merge(display: alternative_display) }
  985. before do
  986. new_attribute_object.update! position: alternative_position
  987. put "/api/v1/object_manager_attributes/#{new_attribute_id}", params: alternative_params, as: :json
  988. new_attribute_object.reload
  989. end
  990. # confirm that test build up was correct
  991. it 'request succeeds' do
  992. expect(new_attribute_object.display).to eq alternative_display
  993. end
  994. # https://github.com/zammad/zammad/issues/3044
  995. it 'position did not reset' do
  996. expect(new_attribute_object.position).to eq alternative_position
  997. end
  998. end
  999. end
  1000. end
  1001. end