reports_kit 0.1.0 → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (66) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +6 -5
  3. data/app/assets/javascripts/reports_kit/lib/chart.js +33 -8
  4. data/app/assets/javascripts/reports_kit/lib/report.js +27 -26
  5. data/app/assets/javascripts/reports_kit/lib/table.js +58 -0
  6. data/app/assets/javascripts/reports_kit/vendor/jquery.tablesorter.min.js +4 -0
  7. data/app/assets/stylesheets/reports_kit/reports.css.sass +20 -0
  8. data/config/initializers/mime_types.rb +1 -0
  9. data/docs/dimensions.md +34 -26
  10. data/docs/display_options.md +15 -12
  11. data/docs/filters.md +2 -2
  12. data/docs/measures.md +4 -3
  13. data/gemfiles/mysql.gemfile.lock +14 -1
  14. data/gemfiles/postgresql.gemfile.lock +14 -1
  15. data/lib/reports_kit.rb +15 -0
  16. data/lib/reports_kit/cache.rb +37 -0
  17. data/lib/reports_kit/configuration.rb +13 -1
  18. data/lib/reports_kit/helper.rb +54 -3
  19. data/lib/reports_kit/model_configuration.rb +6 -1
  20. data/lib/reports_kit/order.rb +33 -0
  21. data/lib/reports_kit/relative_time.rb +42 -0
  22. data/lib/reports_kit/report_builder.rb +34 -15
  23. data/lib/reports_kit/reports/abstract_measure.rb +9 -0
  24. data/lib/reports_kit/reports/adapters/mysql.rb +8 -1
  25. data/lib/reports_kit/reports/adapters/postgresql.rb +8 -1
  26. data/lib/reports_kit/reports/composite_measure.rb +43 -0
  27. data/lib/reports_kit/reports/data/chart_options.rb +5 -0
  28. data/lib/reports_kit/reports/data/composite_aggregation.rb +96 -0
  29. data/lib/reports_kit/reports/data/entity.rb +7 -0
  30. data/lib/reports_kit/reports/data/format_one_dimension.rb +120 -0
  31. data/lib/reports_kit/reports/data/format_two_dimensions.rb +141 -0
  32. data/lib/reports_kit/reports/data/generate.rb +72 -25
  33. data/lib/reports_kit/reports/data/generate_for_properties.rb +75 -0
  34. data/lib/reports_kit/reports/data/one_dimension.rb +15 -49
  35. data/lib/reports_kit/reports/data/populate_one_dimension.rb +36 -0
  36. data/lib/reports_kit/reports/data/populate_two_dimensions.rb +104 -0
  37. data/lib/reports_kit/reports/data/two_dimensions.rb +15 -110
  38. data/lib/reports_kit/reports/data/utils.rb +77 -12
  39. data/lib/reports_kit/reports/data/value.rb +7 -0
  40. data/lib/reports_kit/reports/dimension.rb +4 -110
  41. data/lib/reports_kit/reports/dimension_with_measure.rb +137 -0
  42. data/lib/reports_kit/reports/filter.rb +5 -64
  43. data/lib/reports_kit/reports/filter_types/base.rb +1 -1
  44. data/lib/reports_kit/reports/filter_types/boolean.rb +9 -7
  45. data/lib/reports_kit/reports/filter_types/datetime.rb +7 -5
  46. data/lib/reports_kit/reports/filter_types/number.rb +2 -0
  47. data/lib/reports_kit/reports/filter_with_measure.rb +84 -0
  48. data/lib/reports_kit/reports/generate_autocomplete_results.rb +1 -1
  49. data/lib/reports_kit/reports/inferrable_configuration.rb +32 -13
  50. data/lib/reports_kit/reports/measure.rb +48 -12
  51. data/lib/reports_kit/reports_controller.rb +42 -3
  52. data/lib/reports_kit/version.rb +1 -1
  53. data/reports_kit.gemspec +2 -0
  54. data/spec/fixtures/generate_inputs.yml +146 -21
  55. data/spec/fixtures/generate_outputs.yml +768 -17
  56. data/spec/reports_kit/relative_time_spec.rb +29 -0
  57. data/spec/reports_kit/report_builder_spec.rb +28 -0
  58. data/spec/reports_kit/reports/data/generate_spec.rb +614 -27
  59. data/spec/reports_kit/reports/dimension_with_measure_spec.rb +69 -0
  60. data/spec/reports_kit/reports/{filter_spec.rb → filter_with_measure_spec.rb} +4 -3
  61. data/spec/spec_helper.rb +7 -2
  62. data/spec/support/config.rb +11 -0
  63. data/spec/support/helpers.rb +3 -3
  64. data/spec/support/models/issue.rb +7 -0
  65. metadata +53 -4
  66. data/spec/reports_kit/reports/dimension_spec.rb +0 -54
@@ -0,0 +1,29 @@
1
+ require 'spec_helper'
2
+
3
+ describe ReportsKit::RelativeTime do
4
+ subject { described_class.parse(string) }
5
+
6
+ Timecop.freeze(TIMECOP_TIME) do
7
+ STRINGS_EXPECTED_VALUES = {
8
+ '2s' => 2.seconds.from_now,
9
+ '-3s' => 3.seconds.ago,
10
+ '4m' => 4.minutes.from_now,
11
+ '5h' => 5.hours.from_now,
12
+ '-6d' => 6.days.ago,
13
+ '7w' => 7.weeks.from_now,
14
+ '8M' => 8.months.from_now,
15
+ '9y' => 9.years.from_now,
16
+ '-2M1w' => (2.months + 1.week).ago
17
+ }
18
+ end
19
+
20
+ STRINGS_EXPECTED_VALUES.each do |string, expected_value|
21
+ context string do
22
+ let(:string) { string }
23
+
24
+ it 'transforms the filter criteria' do
25
+ expect(subject).to eq(expected_value)
26
+ end
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,28 @@
1
+ require 'spec_helper'
2
+
3
+ describe ReportsKit::ReportBuilder do
4
+ subject { described_class.new(properties) }
5
+
6
+ context 'with a datetime dimension' do
7
+ let(:properties) do
8
+ {
9
+ measure: {
10
+ key: 'issue',
11
+ filters: [
12
+ {
13
+ key: 'opened_at',
14
+ criteria: {
15
+ operator: 'between',
16
+ value: '-1w - now'
17
+ }
18
+ }
19
+ ]
20
+ }
21
+ }
22
+ end
23
+
24
+ it 'transforms the filter criteria' do
25
+ expect(subject.date_range('opened_at')).to include("#{format_criteria_time(1.week.ago)} - #{format_criteria_time(Time.zone.now)}")
26
+ end
27
+ end
28
+ end
@@ -13,6 +13,9 @@ describe ReportsKit::Reports::Data::Generate do
13
13
  end
14
14
  chart_data
15
15
  end
16
+ let(:table_data) do
17
+ subject[:table_data]
18
+ end
16
19
 
17
20
  let(:chart_type) { subject[:type] }
18
21
  let(:chart_options) { subject[:chart_data][:options] }
@@ -21,8 +24,10 @@ describe ReportsKit::Reports::Data::Generate do
21
24
  context 'with default granularity' do
22
25
  let(:properties) do
23
26
  {
24
- measure: 'issue',
25
- dimensions: %w(opened_at)
27
+ measure: {
28
+ key: 'issue',
29
+ dimensions: %w(opened_at)
30
+ }
26
31
  }
27
32
  end
28
33
  let!(:issues) do
@@ -63,12 +68,12 @@ describe ReportsKit::Reports::Data::Generate do
63
68
  key: 'opened_at',
64
69
  criteria: {
65
70
  operator: 'between',
66
- value: "#{date_string_for_filter(now - 1.week)} - #{date_string_for_filter(now)}"
71
+ value: "#{format_criteria_time(now - 1.week)} - #{format_criteria_time(now)}"
67
72
  }
68
73
  }
69
- ]
70
- },
71
- dimensions: %w(opened_at)
74
+ ],
75
+ dimensions: %w(opened_at)
76
+ }
72
77
  }
73
78
  end
74
79
 
@@ -83,14 +88,95 @@ describe ReportsKit::Reports::Data::Generate do
83
88
  ]
84
89
  })
85
90
  end
91
+
92
+ context 'with zero results' do
93
+ let(:properties) do
94
+ {
95
+ measure: {
96
+ key: 'tag',
97
+ filters: [
98
+ {
99
+ key: 'created_at',
100
+ criteria: {
101
+ operator: 'between',
102
+ value: "#{format_criteria_time(now - 1.week)} - #{format_criteria_time(now)}"
103
+ }
104
+ }
105
+ ],
106
+ dimensions: %w(created_at)
107
+ }
108
+ }
109
+ end
110
+
111
+ it 'returns the data' do
112
+ expect(chart_data).to eq({
113
+ labels: [
114
+ format_week_offset(1),
115
+ format_week_offset(0)
116
+ ],
117
+ datasets: [
118
+ {
119
+ label: 'Tags',
120
+ data: [0, 0]
121
+ }
122
+ ]
123
+ })
124
+ end
125
+ end
126
+
127
+ context 'with multiple measures and datetime filters with different keys' do
128
+ let!(:tags) do
129
+ [
130
+ create(:tag, repo: repo, created_at: now - 1.weeks),
131
+ create(:tag, repo: repo, created_at: now)
132
+ ]
133
+ end
134
+ let(:properties) do
135
+ {
136
+ measures: [
137
+ {
138
+ key: 'issue',
139
+ filters: %w(opened_at),
140
+ dimensions: %w(opened_at)
141
+ },
142
+ {
143
+ key: 'tag',
144
+ filters: %w(created_at),
145
+ dimensions: %w(created_at)
146
+ }
147
+ ],
148
+ ui_filters: {
149
+ created_at: "#{format_criteria_time(now - 1.week)} - #{format_criteria_time(now)}"
150
+ }
151
+ }
152
+ end
153
+
154
+ it 'returns the chart_data' do
155
+ expect(chart_data).to eq({
156
+ labels: [format_week_offset(2), format_week_offset(1), format_week_offset(0)],
157
+ datasets: [
158
+ {
159
+ label: "Issues",
160
+ data: [2, 0, 1]
161
+ },
162
+ {
163
+ label: "Tags",
164
+ data: [0, 1, 1]
165
+ }
166
+ ]
167
+ })
168
+ end
169
+ end
86
170
  end
87
171
  end
88
172
 
89
173
  context 'with day granularity' do
90
174
  let(:properties) do
91
175
  {
92
- measure: 'issue',
93
- dimensions: [{ key: 'opened_at', granularity: 'day' }]
176
+ measure: {
177
+ key: 'issue',
178
+ dimensions: [{ key: 'opened_at', granularity: 'day' }]
179
+ }
94
180
  }
95
181
  end
96
182
  let!(:issues) do
@@ -121,8 +207,10 @@ describe ReportsKit::Reports::Data::Generate do
121
207
  context 'with an association dimension' do
122
208
  let(:properties) do
123
209
  {
124
- measure: 'issue',
125
- dimensions: %w(repo)
210
+ measure: {
211
+ key: 'issue',
212
+ dimensions: %w(repo)
213
+ }
126
214
  }
127
215
  end
128
216
  let!(:issues) do
@@ -151,6 +239,51 @@ describe ReportsKit::Reports::Data::Generate do
151
239
  end
152
240
  end
153
241
 
242
+ context 'with a dimension limit' do
243
+ let(:properties) do
244
+ {
245
+ measure: {
246
+ key: 'issue',
247
+ dimensions: [{ key: 'repo', limit: 1 }]
248
+ }
249
+ }
250
+ end
251
+
252
+ it 'returns the chart_data' do
253
+ expect(chart_data).to eq({
254
+ labels: [repo.to_s],
255
+ datasets: [{ label: 'Issues', data: [2] }]
256
+ })
257
+ end
258
+ end
259
+
260
+ context 'with a custom aggregation' do
261
+ let(:properties) do
262
+ {
263
+ measure: {
264
+ key: 'issue',
265
+ name: 'Average Durations',
266
+ aggregation: 'average_duration',
267
+ dimensions: %w(repo)
268
+ }
269
+ }
270
+ end
271
+ let!(:issues) do
272
+ [
273
+ create(:issue, repo: repo, opened_at: now, closed_at: now),
274
+ create(:issue, repo: repo, opened_at: now - 2.weeks, closed_at: now),
275
+ create(:issue, repo: repo2, opened_at: now - 2.weeks, closed_at: now)
276
+ ]
277
+ end
278
+
279
+ it 'returns the chart_data' do
280
+ expect(chart_data).to eq({
281
+ labels: [repo2.to_s, repo.to_s],
282
+ datasets: [{ label: 'Average Durations', data: [14, 7] }]
283
+ })
284
+ end
285
+ end
286
+
154
287
  context 'with a belongs_to association filter' do
155
288
  let(:properties) do
156
289
  {
@@ -164,9 +297,9 @@ describe ReportsKit::Reports::Data::Generate do
164
297
  value: [repo.id]
165
298
  }
166
299
  }
167
- ]
168
- },
169
- dimensions: %w(repo)
300
+ ],
301
+ dimensions: %w(repo)
302
+ }
170
303
  }
171
304
  end
172
305
 
@@ -191,9 +324,9 @@ describe ReportsKit::Reports::Data::Generate do
191
324
  value: [tag.id]
192
325
  }
193
326
  }
194
- ]
195
- },
196
- dimensions: %w(repo)
327
+ ],
328
+ dimensions: %w(repo)
329
+ }
197
330
  }
198
331
  end
199
332
  let(:tag) { create(:tag) }
@@ -223,9 +356,9 @@ describe ReportsKit::Reports::Data::Generate do
223
356
  value: [label.id]
224
357
  }
225
358
  }
226
- ]
227
- },
228
- dimensions: %w(repo)
359
+ ],
360
+ dimensions: %w(repo)
361
+ }
229
362
  }
230
363
  end
231
364
  let(:label) { create(:label) }
@@ -242,11 +375,41 @@ describe ReportsKit::Reports::Data::Generate do
242
375
  end
243
376
  end
244
377
 
378
+ context 'with a boolean dimension' do
379
+ let(:properties) do
380
+ {
381
+ measure: {
382
+ key: 'issue',
383
+ dimensions: %w(locked)
384
+ }
385
+ }
386
+ end
387
+ let!(:issues) do
388
+ [
389
+ create(:issue, locked: true),
390
+ create(:issue, locked: false),
391
+ create(:issue, locked: false)
392
+ ]
393
+ end
394
+
395
+ it 'returns the chart_data' do
396
+ expect(chart_data).to eq({
397
+ labels: ['false', 'true'],
398
+ datasets: [{ label: 'Issues', data: [2, 1] }]
399
+ })
400
+ end
401
+ end
402
+
245
403
  context 'with datetime and association dimensions' do
246
404
  let(:properties) do
247
405
  {
248
- measure: 'issue',
249
- dimensions: %w(opened_at repo)
406
+ measure: {
407
+ key: 'issue',
408
+ dimensions: [
409
+ { key: 'opened_at', label: nil },
410
+ { key: 'repo' }
411
+ ]
412
+ }
250
413
  }
251
414
  end
252
415
  let!(:issues) do
@@ -272,32 +435,456 @@ describe ReportsKit::Reports::Data::Generate do
272
435
  ]
273
436
  })
274
437
  end
438
+
439
+ context "with format: 'table'" do
440
+ subject { described_class.new(properties.merge(format: 'table'), context_record: context_record).perform }
441
+
442
+ it 'returns the table_data' do
443
+ expect(table_data).to eq([
444
+ [nil, repo.to_s, repo2.to_s],
445
+ [format_week_offset(2), 1, 0],
446
+ [format_week_offset(1), 0, 0],
447
+ [format_week_offset(0), 1, 1]
448
+ ])
449
+ end
450
+ end
451
+
452
+ context "with a data_format_method" do
453
+ subject { described_class.new(properties.merge(data_format_method: 'add_label_suffix'), context_record: context_record).perform }
454
+
455
+ it 'returns the chart_data' do
456
+ expect(chart_data).to eq({
457
+ labels: ["#{format_week_offset(2)} Foo", "#{format_week_offset(1)} Foo", "#{format_week_offset(0)} Foo"],
458
+ datasets: [
459
+ {
460
+ label: repo.to_s,
461
+ data: [1, 0, 1]
462
+ },
463
+ {
464
+ label: repo2.to_s,
465
+ data: [0, 0, 1]
466
+ }
467
+ ]
468
+ })
469
+ end
470
+ end
471
+ end
472
+
473
+ context 'with two measures' do
474
+ let(:properties) do
475
+ {
476
+ measures: [
477
+ {
478
+ key: 'issue',
479
+ dimensions: [{ key: 'created_at', label: nil }]
480
+ },
481
+ {
482
+ key: 'tag',
483
+ dimensions: %w(created_at)
484
+ },
485
+ ]
486
+ }
487
+ end
488
+ let!(:issues) do
489
+ [
490
+ create(:issue, repo: repo, created_at: now),
491
+ create(:issue, repo: repo, created_at: now - 2.weeks),
492
+ create(:issue, repo: repo2, created_at: now)
493
+ ]
494
+ end
495
+ let!(:tags) do
496
+ [
497
+ create(:tag, repo: repo, created_at: now - 1.week),
498
+ create(:tag, repo: repo, created_at: now - 2.weeks)
499
+ ]
500
+ end
501
+
502
+ it 'returns the chart_data' do
503
+ expect(chart_data).to eq({
504
+ labels: [format_week_offset(2), format_week_offset(1), format_week_offset(0)],
505
+ datasets: [
506
+ {
507
+ label: 'Issues',
508
+ data: [1, 0, 2]
509
+ },
510
+ {
511
+ label: 'Tags',
512
+ data: [1, 1, 0]
513
+ }
514
+ ]
515
+ })
516
+ end
517
+
518
+ context "with format: 'table'" do
519
+ subject { described_class.new(properties.merge(format: 'table'), context_record: context_record).perform }
520
+
521
+ it 'returns the table_data' do
522
+ expect(table_data).to eq([
523
+ [nil, 'Issues', 'Tags'],
524
+ [format_week_offset(2), 1, 1],
525
+ [format_week_offset(1), 0, 1],
526
+ [format_week_offset(0), 2, 0]
527
+ ])
528
+ end
529
+ end
530
+ end
531
+
532
+ context 'with two dimensions' do
533
+ context 'with a custom aggregation' do
534
+ let(:properties) do
535
+ {
536
+ measure: {
537
+ key: 'issue',
538
+ aggregation: 'average_duration',
539
+ dimensions: %w(repo created_at)
540
+ }
541
+ }
542
+ end
543
+ let!(:issues) do
544
+ [
545
+ create(:issue, repo: repo, opened_at: now, closed_at: now),
546
+ create(:issue, repo: repo, opened_at: now - 2.weeks, closed_at: now),
547
+ create(:issue, repo: repo2, opened_at: now - 2.weeks, closed_at: now)
548
+ ]
549
+ end
550
+
551
+ it 'returns the chart_data' do
552
+ expect(chart_data).to eq({
553
+ labels: [repo2.to_s, repo.to_s],
554
+ datasets: [{ label: format_week_offset(0), data: [14, 7] }]
555
+ })
556
+ end
557
+ end
558
+ end
559
+
560
+ describe 'composite aggregations' do
561
+ context 'with two measures' do
562
+ let(:properties) do
563
+ {
564
+ name: name,
565
+ composite_operator: composite_operator,
566
+ measures: [
567
+ {
568
+ key: 'issue',
569
+ dimensions: %w(created_at)
570
+ },
571
+ {
572
+ key: 'tag',
573
+ dimensions: %w(created_at)
574
+ }
575
+ ]
576
+ }
577
+ end
578
+ let!(:issues) do
579
+ [
580
+ create(:issue, repo: repo, created_at: now),
581
+ create(:issue, repo: repo, created_at: now - 2.weeks),
582
+ create(:issue, repo: repo2, created_at: now)
583
+ ]
584
+ end
585
+ let!(:tags) do
586
+ [
587
+ create(:tag, repo: repo, created_at: now),
588
+ create(:tag, repo: repo, created_at: now - 1.week),
589
+ create(:tag, repo: repo, created_at: now - 1.week)
590
+ ]
591
+ end
592
+ let(:name) { 'My Name' }
593
+
594
+ context 'with +' do
595
+ let(:composite_operator) { '+' }
596
+
597
+ it 'returns the chart_data' do
598
+ expect(chart_data).to eq({
599
+ labels: [format_week_offset(2), format_week_offset(1), format_week_offset(0)],
600
+ datasets: [
601
+ {
602
+ label: name,
603
+ data: [1, 2, 3]
604
+ }
605
+ ]
606
+ })
607
+ end
608
+ end
609
+
610
+ context 'with %' do
611
+ let(:composite_operator) { '%' }
612
+
613
+ it 'returns the chart_data' do
614
+ expect(chart_data).to eq({
615
+ labels: [format_week_offset(2), format_week_offset(1), format_week_offset(0)],
616
+ datasets: [
617
+ {
618
+ label: name,
619
+ data: [0, 0, 200]
620
+ }
621
+ ]
622
+ })
623
+ end
624
+ end
625
+
626
+ context 'with % and a custom value_format_method' do
627
+ let(:composite_operator) { '%' }
628
+ let(:properties) do
629
+ {
630
+ name: name,
631
+ composite_operator: composite_operator,
632
+ value_format_method: 'format_percentage',
633
+ measures: [
634
+ {
635
+ key: 'issue',
636
+ dimensions: %w(created_at)
637
+ },
638
+ {
639
+ key: 'tag',
640
+ dimensions: %w(created_at)
641
+ }
642
+ ]
643
+ }
644
+ end
645
+
646
+ it 'returns the chart_data' do
647
+ expect(chart_data).to eq({
648
+ labels: [format_week_offset(2), format_week_offset(1), format_week_offset(0)],
649
+ datasets: [
650
+ {
651
+ label: name,
652
+ data: ['0%', '0%', '200%']
653
+ }
654
+ ]
655
+ })
656
+ end
657
+ end
658
+
659
+ context 'with a boolean dimension' do
660
+ let!(:issues) do
661
+ [
662
+ create(:issue, locked: true),
663
+ create(:issue, locked: false),
664
+ create(:issue, locked: false)
665
+ ]
666
+ end
667
+ let(:composite_operator) { '+' }
668
+ let(:properties) do
669
+ {
670
+ name: name,
671
+ composite_operator: composite_operator,
672
+ measures: [
673
+ {
674
+ key: 'issue',
675
+ dimensions: %w(locked)
676
+ },
677
+ {
678
+ key: 'issue',
679
+ dimensions: %w(locked)
680
+ }
681
+ ]
682
+ }
683
+ end
684
+
685
+ it 'returns the chart_data' do
686
+ expect(chart_data).to eq({
687
+ labels: ['false', 'true'],
688
+ datasets: [
689
+ {
690
+ label: name,
691
+ data: [4, 2]
692
+ }
693
+ ]
694
+ })
695
+ end
696
+ end
697
+
698
+ context 'with a nested composite aggregation' do
699
+ let(:properties) do
700
+ {
701
+ measures: [
702
+ {
703
+ name: name,
704
+ composite_operator: '+',
705
+ measures: [
706
+ {
707
+ key: 'issue',
708
+ dimensions: %w(created_at)
709
+ },
710
+ {
711
+ key: 'tag',
712
+ dimensions: %w(created_at)
713
+ }
714
+ ]
715
+ },
716
+ {
717
+ key: 'issue',
718
+ dimensions: %w(created_at)
719
+ },
720
+ {
721
+ key: 'tag',
722
+ dimensions: %w(created_at)
723
+ }
724
+ ]
725
+ }
726
+ end
727
+
728
+ it 'returns the chart_data' do
729
+ expect(chart_data).to eq({
730
+ labels: [format_week_offset(2), format_week_offset(1), format_week_offset(0)],
731
+ datasets: [
732
+ {
733
+ label: name,
734
+ data: [1, 2, 3]
735
+ },
736
+ {
737
+ label: 'Issues',
738
+ data: [1, 0, 2]
739
+ },
740
+ {
741
+ label: 'Tags',
742
+ data: [0, 2, 1]
743
+ }
744
+ ]
745
+ })
746
+ end
747
+
748
+ context 'with ui_filters' do
749
+ let(:properties) do
750
+ {
751
+ measures: [
752
+ {
753
+ name: name,
754
+ composite_operator: '+',
755
+ measures: [
756
+ {
757
+ key: 'issue',
758
+ filters: %w(created_at),
759
+ dimensions: %w(created_at)
760
+ },
761
+ {
762
+ key: 'tag',
763
+ filters: %w(created_at),
764
+ dimensions: %w(created_at)
765
+ }
766
+ ]
767
+ },
768
+ {
769
+ key: 'issue',
770
+ filters: %w(created_at),
771
+ dimensions: %w(created_at)
772
+ },
773
+ {
774
+ key: 'tag',
775
+ filters: %w(created_at),
776
+ dimensions: %w(created_at)
777
+ }
778
+ ],
779
+ ui_filters: {
780
+ created_at: "#{format_criteria_time(now - 1.week)} - #{format_criteria_time(now)}"
781
+ }
782
+ }
783
+ end
784
+
785
+ it 'returns the chart_data' do
786
+ expect(chart_data).to eq({
787
+ labels: [format_week_offset(1), format_week_offset(0)],
788
+ datasets: [
789
+ {
790
+ label: name,
791
+ data: [2, 3]
792
+ },
793
+ {
794
+ label: 'Issues',
795
+ data: [0, 2]
796
+ },
797
+ {
798
+ label: 'Tags',
799
+ data: [2, 1]
800
+ }
801
+ ]
802
+ })
803
+ end
804
+ end
805
+
806
+ context 'with two dimensions' do
807
+ let(:properties) do
808
+ {
809
+ measures: [
810
+ {
811
+ name: name,
812
+ composite_operator: '+',
813
+ measures: [
814
+ {
815
+ key: 'issue',
816
+ dimensions: %w(created_at repo)
817
+ },
818
+ {
819
+ key: 'tag',
820
+ dimensions: %w(created_at repo)
821
+ }
822
+ ]
823
+ }
824
+ ]
825
+ }
826
+ end
827
+
828
+ it 'returns the chart_data' do
829
+ expect(chart_data).to eq({
830
+ labels: [format_week_offset(2), format_week_offset(1), format_week_offset(0)],
831
+ datasets: [
832
+ {
833
+ label: repo.to_s,
834
+ data: [1, 2, 2]
835
+ },
836
+ {
837
+ label: repo2.to_s,
838
+ data: [0, 0, 1]
839
+ }
840
+ ]
841
+ })
842
+ end
843
+ end
844
+ end
845
+ end
275
846
  end
276
847
 
277
848
  # These examples allow for quick comparisons of many types of inputs and outputs.
278
849
  # When making functional modifications, run these to see whether the modifications impact the output in any cases.
279
850
  # If the output effects are desired, run `REWRITE_RESULTS=1 rspec` to write them to the outputs YAML file, then verify that the output
280
851
  # modifications are desired, then commit the result and uncomment the `skip`.
281
- describe 'chart options' do
852
+ describe 'YAML-based output comparisons' do
282
853
  FIXTURES_DIRECTORY = File.expand_path(File.join(File.dirname(__FILE__), '..', '..', '..', 'fixtures'))
283
854
 
284
855
  let(:inputs) { YAML.load_file("#{FIXTURES_DIRECTORY}/generate_inputs.yml") }
285
856
  let(:outputs_path) { "#{FIXTURES_DIRECTORY}/generate_outputs.yml" }
286
857
  let(:outputs) { YAML.load_file(outputs_path) }
287
858
 
859
+ let!(:repo) { create(:repo, full_name: 'foo/bar1') }
860
+ let!(:repo2) { create(:repo, full_name: 'foo/bar2') }
861
+ let!(:issues) do
862
+ [
863
+ create(:issue, repo: repo, state: 'open', opened_at: now - 2.weeks),
864
+ create(:issue, repo: repo, state: 'closed', opened_at: now)
865
+ ]
866
+ end
867
+ let!(:labels) do
868
+ [
869
+ create(:label, repo: repo),
870
+ create(:label, repo: repo2),
871
+ create(:label, repo: repo2)
872
+ ]
873
+ end
874
+
288
875
  context 'input examples' do
289
876
  YAML.load_file("#{FIXTURES_DIRECTORY}/generate_inputs.yml").each.with_index do |inputs, index|
290
- it 'returns the expected output' do
291
- expect(described_class.new(inputs).perform).to eq(outputs[index])
877
+ it "returns the expected output for input ##{index}: #{inputs.to_json}" do
878
+ expect(described_class.new(inputs).perform.to_yaml).to eq(outputs[index].to_yaml)
292
879
  end
293
880
  end
294
881
  end
295
882
 
296
883
  context 'writing the outputs' do
297
- # For documentation about this `skip`, see the comment at the top of this `describe` block.
298
- skip unless ENV['REWRITE_RESULTS'] == '1'
299
-
300
884
  it 'writes the outputs' do
885
+ # For documentation about this `skip`, see the comment at the top of this `describe` block.
886
+ skip unless ENV['REWRITE_RESULTS'] == '1'
887
+
301
888
  outputs = inputs.map do |example|
302
889
  described_class.new(example).perform
303
890
  end