ticket_generic_time_spec.rb 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416
  1. # Copyright (C) 2012-2022 Zammad Foundation, https://zammad-foundation.org/
  2. require 'rails_helper'
  3. require 'lib/report_examples'
  4. RSpec.describe Report::TicketGenericTime, searchindex: true do
  5. include_examples 'with report examples'
  6. describe '.aggs' do
  7. it 'gets monthly aggregated results by created_at' do
  8. result = described_class.aggs(
  9. range_start: Time.zone.parse('2015-01-01T00:00:00Z'),
  10. range_end: Time.zone.parse('2015-12-31T23:59:59Z'),
  11. interval: 'month', # year, quarter, month, week, day, hour, minute, second
  12. selector: {}, # ticket selector to get only a collection of tickets
  13. params: { field: 'created_at' },
  14. )
  15. expect(result).to eq [0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 1, 0]
  16. end
  17. it 'gets monthly aggregated results by created_at not merged' do
  18. result = described_class.aggs(
  19. range_start: Time.zone.parse('2015-01-01T00:00:00Z'),
  20. range_end: Time.zone.parse('2015-12-31T23:59:59Z'),
  21. interval: 'month', # year, quarter, month, week, day, hour, minute, second
  22. selector: {
  23. 'state' => {
  24. 'operator' => 'is not',
  25. 'value' => 'merged'
  26. }
  27. },
  28. params: { field: 'created_at' },
  29. )
  30. expect(result).to eq [0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 1, 0]
  31. end
  32. end
  33. describe '.items' do
  34. it 'gets items in year range by created_at' do
  35. result = described_class.items(
  36. range_start: Time.zone.parse('2015-01-01T00:00:00Z'),
  37. range_end: Time.zone.parse('2015-12-31T23:59:59Z'),
  38. selector: {}, # ticket selector to get only a collection of tickets
  39. params: { field: 'created_at' },
  40. )
  41. expect(result).to match_tickets ticket_7, ticket_6, ticket_5, ticket_4, ticket_3, ticket_2, ticket_1
  42. end
  43. it 'gets items in year range by created_at not merged' do
  44. result = described_class.items(
  45. range_start: Time.zone.parse('2015-01-01T00:00:00Z'),
  46. range_end: Time.zone.parse('2015-12-31T23:59:59Z'),
  47. selector: {
  48. 'state' => {
  49. 'operator' => 'is not',
  50. 'value' => 'merged'
  51. }
  52. },
  53. params: { field: 'created_at' },
  54. )
  55. expect(result).to match_tickets ticket_7, ticket_6, ticket_5, ticket_4, ticket_3, ticket_2, ticket_1
  56. end
  57. it 'gets items in year range by created_at before oct 31st' do
  58. result = described_class.items(
  59. range_start: Time.zone.parse('2015-01-01T00:00:00Z'),
  60. range_end: Time.zone.parse('2015-12-31T23:59:59Z'),
  61. selector: {
  62. 'created_at' => {
  63. 'operator' => 'before (absolute)',
  64. 'value' => '2015-10-31T00:00:00Z'
  65. }
  66. },
  67. params: { field: 'created_at' },
  68. )
  69. expect(result).to match_tickets ticket_5, ticket_4, ticket_3, ticket_2, ticket_1
  70. end
  71. it 'gets items in year range by created_at after oct 31st' do
  72. result = described_class.items(
  73. range_start: Time.zone.parse('2015-01-01T00:00:00Z'),
  74. range_end: Time.zone.parse('2015-12-31T23:59:59Z'),
  75. selector: {
  76. 'created_at' => {
  77. 'operator' => 'after (absolute)',
  78. 'value' => '2015-10-31T00:00:00Z'
  79. }
  80. },
  81. params: { field: 'created_at' },
  82. )
  83. expect(result).to match_tickets ticket_7, ticket_6
  84. end
  85. it 'gets items in 1 day from now' do
  86. result = described_class.items(
  87. range_start: 1.year.ago.beginning_of_year,
  88. range_end: 1.year.from_now.at_end_of_year,
  89. selector: {
  90. 'created_at' => {
  91. 'operator' => 'after (relative)',
  92. 'range' => 'day',
  93. 'value' => '1'
  94. }
  95. }, # ticket selector to get only a collection of tickets
  96. params: { field: 'created_at' },
  97. )
  98. expect(result).to match_tickets ticket_after_72h
  99. end
  100. it 'gets items in 1 month from now' do
  101. result = described_class.items(
  102. range_start: 1.year.ago.beginning_of_year,
  103. range_end: 1.year.from_now.at_end_of_year,
  104. selector: {
  105. 'created_at' => {
  106. 'operator' => 'after (relative)',
  107. 'range' => 'month',
  108. 'value' => '1'
  109. }
  110. }, # ticket selector to get only a collection of tickets
  111. params: { field: 'created_at' },
  112. )
  113. expect(result).to match_tickets []
  114. end
  115. it 'gets items in 1 month ago' do
  116. result = described_class.items(
  117. range_start: 1.year.ago.beginning_of_year,
  118. range_end: 1.year.from_now.at_end_of_year,
  119. selector: {
  120. 'created_at' => {
  121. 'operator' => 'before (relative)',
  122. 'range' => 'month',
  123. 'value' => '1'
  124. }
  125. }, # ticket selector to get only a collection of tickets
  126. params: { field: 'created_at' },
  127. )
  128. expect(result).to match_tickets ticket_before_40d
  129. end
  130. it 'gets items in 5 months ago' do
  131. result = described_class.items(
  132. range_start: 1.year.ago.beginning_of_year,
  133. range_end: 1.year.from_now.at_end_of_year,
  134. selector: {
  135. 'created_at' => {
  136. 'operator' => 'before (relative)',
  137. 'range' => 'month',
  138. 'value' => '5'
  139. }
  140. }, # ticket selector to get only a collection of tickets
  141. params: { field: 'created_at' },
  142. )
  143. expect(result).to match_tickets []
  144. end
  145. it 'gets items with aaa+bbb' do
  146. result = described_class.items(
  147. range_start: Time.zone.parse('2015-01-01T00:00:00Z'),
  148. range_end: Time.zone.parse('2015-12-31T23:59:59Z'),
  149. selector: {
  150. 'tags' => {
  151. 'operator' => 'contains all',
  152. 'value' => 'aaa, bbb'
  153. }
  154. },
  155. params: { field: 'created_at' },
  156. )
  157. expect(result).to match_tickets ticket_1
  158. end
  159. it 'gets items with not aaa+bbb' do
  160. result = described_class.items(
  161. range_start: Time.zone.parse('2015-01-01T00:00:00Z'),
  162. range_end: Time.zone.parse('2015-12-31T23:59:59Z'),
  163. selector: {
  164. 'tags' => {
  165. 'operator' => 'contains all not',
  166. 'value' => 'aaa, bbb'
  167. }
  168. },
  169. params: { field: 'created_at' },
  170. )
  171. expect(result).to match_tickets ticket_7, ticket_6, ticket_5, ticket_4, ticket_3, ticket_2
  172. end
  173. it 'gets items with aaa' do
  174. result = described_class.items(
  175. range_start: Time.zone.parse('2015-01-01T00:00:00Z'),
  176. range_end: Time.zone.parse('2015-12-31T23:59:59Z'),
  177. selector: {
  178. 'tags' => {
  179. 'operator' => 'contains all',
  180. 'value' => 'aaa'
  181. }
  182. },
  183. params: { field: 'created_at' },
  184. )
  185. expect(result).to match_tickets ticket_2, ticket_1
  186. end
  187. it 'gets items with not aaa' do
  188. result = described_class.items(
  189. range_start: Time.zone.parse('2015-01-01T00:00:00Z'),
  190. range_end: Time.zone.parse('2015-12-31T23:59:59Z'),
  191. selector: {
  192. 'tags' => {
  193. 'operator' => 'contains all not',
  194. 'value' => 'aaa'
  195. }
  196. },
  197. params: { field: 'created_at' },
  198. )
  199. expect(result).to match_tickets ticket_7, ticket_6, ticket_5, ticket_4, ticket_3
  200. end
  201. it 'gets items with one not aaa' do
  202. result = described_class.items(
  203. range_start: Time.zone.parse('2015-01-01T00:00:00Z'),
  204. range_end: Time.zone.parse('2015-12-31T23:59:59Z'),
  205. selector: {
  206. 'tags' => {
  207. 'operator' => 'contains one not',
  208. 'value' => 'aaa'
  209. }
  210. },
  211. params: { field: 'created_at' },
  212. )
  213. expect(result).to match_tickets ticket_7, ticket_6, ticket_5, ticket_4, ticket_3
  214. end
  215. it 'gets items with one not aaa+bbb' do
  216. result = described_class.items(
  217. range_start: Time.zone.parse('2015-01-01T00:00:00Z'),
  218. range_end: Time.zone.parse('2015-12-31T23:59:59Z'),
  219. selector: {
  220. 'tags' => {
  221. 'operator' => 'contains one not',
  222. 'value' => 'aaa, bbb'
  223. }
  224. },
  225. params: { field: 'created_at' },
  226. )
  227. expect(result).to match_tickets ticket_7, ticket_6, ticket_4, ticket_3
  228. end
  229. it 'gets items with one aaa' do
  230. result = described_class.items(
  231. range_start: Time.zone.parse('2015-01-01T00:00:00Z'),
  232. range_end: Time.zone.parse('2015-12-31T23:59:59Z'),
  233. selector: {
  234. 'tags' => {
  235. 'operator' => 'contains one',
  236. 'value' => 'aaa'
  237. }
  238. },
  239. params: { field: 'created_at' },
  240. )
  241. expect(result).to match_tickets ticket_2, ticket_1
  242. end
  243. it 'gets items with one aaa+bbb' do
  244. result = described_class.items(
  245. range_start: Time.zone.parse('2015-01-01T00:00:00Z'),
  246. range_end: Time.zone.parse('2015-12-31T23:59:59Z'),
  247. selector: {
  248. 'tags' => {
  249. 'operator' => 'contains one',
  250. 'value' => 'aaa, bbb'
  251. }
  252. },
  253. params: { field: 'created_at' },
  254. )
  255. expect(result).to match_tickets ticket_5, ticket_2, ticket_1
  256. end
  257. it 'gets items with test' do
  258. result = described_class.items(
  259. range_start: Time.zone.parse('2015-01-01T00:00:00Z'),
  260. range_end: Time.zone.parse('2015-12-31T23:59:59Z'),
  261. selector: {
  262. 'title' => {
  263. 'operator' => 'contains',
  264. 'value' => 'Test'
  265. }
  266. },
  267. params: { field: 'created_at' },
  268. )
  269. expect(result).to match_tickets ticket_7, ticket_6, ticket_5, ticket_4, ticket_3, ticket_2, ticket_1
  270. end
  271. it 'gets items with not test' do
  272. result = described_class.items(
  273. range_start: Time.zone.parse('2015-01-01T00:00:00Z'),
  274. range_end: Time.zone.parse('2015-12-31T23:59:59Z'),
  275. selector: {
  276. 'title' => {
  277. 'operator' => 'contains not',
  278. 'value' => 'Test'
  279. }
  280. },
  281. params: { field: 'created_at' },
  282. )
  283. expect(result).to match_tickets []
  284. end
  285. # Regression test for issue #2246 - Records in Reporting not updated when single ActiveRecord can not be found
  286. it 'correctly handles missing tickets', searchindex: false do
  287. class_double(SearchIndexBackend, selectors: { ticket_ids: [-1] }, drop_index: nil, drop_pipeline: nil).as_stubbed_const
  288. expect do
  289. described_class.items(
  290. range_start: Time.zone.parse('2015-01-01T00:00:00Z'),
  291. range_end: Time.zone.parse('2015-12-31T23:59:59Z'),
  292. selector: {}, # ticket selector to get only a collection of tickets
  293. params: { field: 'created_at' },
  294. )
  295. end.not_to raise_error
  296. end
  297. end
  298. context 'when additional attribute exists', db_strategy: :reset do
  299. before do
  300. ObjectManager::Attribute.add(
  301. object: 'Ticket',
  302. name: 'test_category',
  303. display: 'Test 1',
  304. data_type: 'tree_select',
  305. data_option: {
  306. maxlength: 200,
  307. null: false,
  308. default: '',
  309. options: [
  310. { 'name' => 'aa', 'value' => 'aa', 'children' => [{ 'name' => 'aa', 'value' => 'aa::aa' }, { 'name' => 'bb', 'value' => 'aa::bb' }, { 'name' => 'cc', 'value' => 'aa::cc' }] },
  311. { 'name' => 'bb', 'value' => 'bb', 'children' => [{ 'name' => 'aa', 'value' => 'bb::aa' }, { 'name' => 'bb', 'value' => 'bb::bb' }, { 'name' => 'cc', 'value' => 'bb::cc' }] },
  312. { 'name' => 'cc', 'value' => 'cc', 'children' => [{ 'name' => 'aa', 'value' => 'cc::aa' }, { 'name' => 'bb', 'value' => 'cc::bb' }, { 'name' => 'cc', 'value' => 'cc::cc' }] },
  313. ]
  314. },
  315. active: true,
  316. screens: {},
  317. position: 20,
  318. created_by_id: 1,
  319. updated_by_id: 1,
  320. editable: false,
  321. to_migrate: false,
  322. )
  323. ObjectManager::Attribute.migration_execute
  324. ticket_with_category
  325. rebuild_searchindex
  326. end
  327. let(:ticket_with_category) do
  328. travel_to DateTime.new 2015, 10, 28, 9, 30
  329. ticket = create(:ticket,
  330. group: group_2,
  331. customer: customer,
  332. test_category: 'cc::bb',
  333. state_name: 'new',
  334. priority_name: '2 normal')
  335. ticket.tag_add('aaa', 1)
  336. ticket.tag_add('bbb', 1)
  337. create(:ticket_article,
  338. :inbound_email,
  339. ticket: ticket)
  340. travel 5.hours
  341. ticket.update! group: group_1
  342. travel_back
  343. ticket
  344. end
  345. describe '.items' do
  346. it 'gets items with test_category cc:bb' do
  347. result = described_class.items(
  348. range_start: Time.zone.parse('2015-01-01T00:00:00Z'),
  349. range_end: Time.zone.parse('2015-12-31T23:59:59Z'),
  350. selector: {
  351. 'test_category' => {
  352. 'operator' => 'is',
  353. 'value' => 'cc::bb'
  354. },
  355. },
  356. params: { field: 'created_at' },
  357. )
  358. expect(result).to match_tickets ticket_with_category
  359. end
  360. end
  361. end
  362. end