@datarailsshared/dr_renderer 1.2.294 → 1.2.296

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.
@@ -1,6 +1,7 @@
1
1
  import * as JQuery from "jquery";
2
2
  import * as lodash from 'lodash';
3
- import * as moment from 'moment';
3
+ import moment from 'moment/min/moment.min';
4
+ import tables from './mock/tables.json';
4
5
  import initPivotTable from "../src/pivottable";
5
6
  import initDRPivotTable from "../src/dr_pivottable";
6
7
 
@@ -394,4 +395,3133 @@ describe('highcharts_renderer', () => {
394
395
  expect(highchartsRenderer.isSystemField(field)).toBe(false);
395
396
  });
396
397
  });
398
+
399
+ describe('function selfStartsWith', () => {
400
+ it('should return true when str starts with searchStr', () => {
401
+ expect(highchartsRenderer.selfStartsWith('hello world', 'hello')).toBe(true);
402
+ });
403
+
404
+ it('should return false when str does not start with searchStr', () => {
405
+ expect(highchartsRenderer.selfStartsWith('hello world', 'world')).toBe(false);
406
+ });
407
+
408
+ it('should return false when str is empty', () => {
409
+ expect(highchartsRenderer.selfStartsWith('', 'hello')).toBe(false);
410
+ });
411
+
412
+ it('should return true when searchStr is empty', () => {
413
+ expect(highchartsRenderer.selfStartsWith('hello world', '')).toBe(true);
414
+ });
415
+
416
+ it('should handle searchStr longer than str', () => {
417
+ expect(highchartsRenderer.selfStartsWith('hello', 'hello world')).toBe(false);
418
+ });
419
+
420
+ it('should handle non-string inputs', () => {
421
+ expect(highchartsRenderer.selfStartsWith(null, 'hello')).toBe(false);
422
+ expect(highchartsRenderer.selfStartsWith(undefined, 'hello')).toBe(false);
423
+ expect(highchartsRenderer.selfStartsWith(123, 'hello')).toBe(false);
424
+ expect(highchartsRenderer.selfStartsWith([], 'hello')).toBe(false);
425
+ });
426
+ });
427
+
428
+ describe('function getSpanWrapper', () => {
429
+ it('should return span element with value', () => {
430
+ expect(highchartsRenderer.getSpanWrapper('Hello')).toBe('<span>\u200EHello</span>');
431
+ expect(highchartsRenderer.getSpanWrapper('123')).toBe('<span>\u200E123</span>');
432
+ expect(highchartsRenderer.getSpanWrapper('')).toBe('<span>\u200E</span>');
433
+ });
434
+
435
+ it('should handle non-string inputs', () => {
436
+ expect(highchartsRenderer.getSpanWrapper(null)).toBe('<span>\u200Enull</span>');
437
+ expect(highchartsRenderer.getSpanWrapper(undefined)).toBe('<span>\u200Eundefined</span>');
438
+ expect(highchartsRenderer.getSpanWrapper(123)).toBe('<span>\u200E123</span>');
439
+ expect(highchartsRenderer.getSpanWrapper([])).toBe('<span>\u200E</span>');
440
+ });
441
+ });
442
+
443
+ describe('function encodeHTMLBrackets', () => {
444
+ it('should encode HTML brackets', () => {
445
+ expect(highchartsRenderer.encodeHTMLBrackets('Hello <World>')).toBe('Hello &lt;World&gt;');
446
+ expect(highchartsRenderer.encodeHTMLBrackets('<script>alert("hello");</script>')).toBe('&lt;script&gt;alert("hello");&lt;/script&gt;');
447
+ expect(highchartsRenderer.encodeHTMLBrackets('<h1>Title</h1>')).toBe('&lt;h1&gt;Title&lt;/h1&gt;');
448
+ });
449
+ });
450
+
451
+ describe('function getSingleValueAgg', () => {
452
+ it('should return correct aggfunc and base for Sum', () => {
453
+ const { aggfunc, base } = highchartsRenderer.getSingleValueAgg({ value: { value: 'Sum' } }, null, null);
454
+ expect(aggfunc).toBe(null);
455
+ expect(base).toBe(null);
456
+ });
457
+
458
+ it('should return correct aggfunc and base for Max', () => {
459
+ const { aggfunc, base } = highchartsRenderer.getSingleValueAgg({ value: { value: 'Max' } }, null, null);
460
+ expect(aggfunc(1, 2)).toBe(2);
461
+ expect(base).toBe(null);
462
+ });
463
+
464
+ it('should return correct aggfunc and base for Min', () => {
465
+ const { aggfunc, base } = highchartsRenderer.getSingleValueAgg({ value: { value: 'Min' } }, null, null);
466
+ expect(aggfunc(1, 2)).toBe(1);
467
+ expect(base).toBe(Number.MAX_VALUE);
468
+ });
469
+
470
+ it('should return correct aggfunc and base for Avg', () => {
471
+ const { aggfunc, base } = highchartsRenderer.getSingleValueAgg({ value: { value: 'Avg' } }, null, null);
472
+ const arr = [1, 2, 3];
473
+ expect(aggfunc(0, 1, 0, arr)).toBe(1);
474
+ expect(aggfunc(0, 2, 1, arr)).toBe(2);
475
+ expect(aggfunc(3, 3, 2, arr)).toBe(2);
476
+ expect(base).toBe(null);
477
+ });
478
+
479
+ it('should return correct aggfunc and base for Unique', () => {
480
+ const { aggfunc, base } = highchartsRenderer.getSingleValueAgg({ value: { value: 'Unique' } }, null, null);
481
+ expect(aggfunc('a', 'b')).toBe('a<br>b');
482
+ expect(base).toBe('');
483
+ });
484
+
485
+ it('should handle invalid input', () => {
486
+ const { aggfunc, base } = highchartsRenderer.getSingleValueAgg({ value: { value: 'Invalid' } }, null, null);
487
+ expect(aggfunc).toBe(null);
488
+ expect(base).toBe(null);
489
+ });
490
+ });
491
+
492
+ describe('function setTitleAndSubTitle', () => {
493
+ it('should set title to null when hideChartHeader is true', () => {
494
+ const chartOptions = { title: {}, subtitle: {} };
495
+ const opts = { chartOptions: { hideChartHeader: true } };
496
+ highchartsRenderer.setTitleAndSubTitle(chartOptions, opts);
497
+ expect(chartOptions.title.text).toBe(null);
498
+ });
499
+
500
+ it('should set title to custom value when chart_title is present', () => {
501
+ const chartOptions = { title: {}, subtitle: {} };
502
+ const opts = { chart_title: 'Custom Title', chartOptions: { hideChartHeader: false } };
503
+ highchartsRenderer.setTitleAndSubTitle(chartOptions, opts);
504
+ expect(chartOptions.title.text).toBe('Custom Title');
505
+ });
506
+
507
+ it('should set subtitle to custom value when subtitle is present in additionOptions', () => {
508
+ const chartOptions = { title: {}, subtitle: {} };
509
+ const additionOptions = { subtitle: { subtitle: 'Custom Subtitle' } };
510
+ highchartsRenderer.setTitleAndSubTitle(chartOptions, { chartOptions: { hideChartHeader: false } }, additionOptions);
511
+ expect(chartOptions.subtitle.text).toBe('Custom Subtitle');
512
+ });
513
+ });
514
+
515
+ describe('function handleGridLines', () => {
516
+ it('should not set grid lines when chartobj is not present', () => {
517
+ const chartOptions = { xAxis: {}, yAxis: {} };
518
+ highchartsRenderer.handleGridLines(null, chartOptions);
519
+ expect(chartOptions.xAxis.gridLineWidth).toBeUndefined();
520
+ expect(chartOptions.yAxis.gridLineWidth).toBeUndefined();
521
+ });
522
+
523
+ it('should not set grid lines when chartobj is present', () => {
524
+ const chartOptions = { };
525
+ highchartsRenderer.handleGridLines({ chart_grid : {} }, chartOptions);
526
+ expect(chartOptions.xAxis).toBeUndefined();
527
+ expect(chartOptions.yAxis).toBeUndefined();
528
+ });
529
+
530
+ it('should set grid lines when chartobj.show is true', () => {
531
+ const chartOptions = { xAxis: {}, yAxis: {} };
532
+ const additionOptions = { chart_grid: { show: true } };
533
+ highchartsRenderer.handleGridLines(additionOptions, chartOptions);
534
+ expect(chartOptions.xAxis.gridLineWidth).toBe(1);
535
+ expect(chartOptions.yAxis.gridLineWidth).toBe(1);
536
+ expect(chartOptions.xAxis.lineWidth).toBe(0);
537
+ expect(chartOptions.yAxis.lineWidth).toBe(0);
538
+ });
539
+
540
+ it('should not set grid lines when chartobj.show is false', () => {
541
+ const chartOptions = { xAxis: {}, yAxis: {} };
542
+ const additionOptions = { chart_grid: { show: false } };
543
+ highchartsRenderer.handleGridLines(additionOptions, chartOptions);
544
+ expect(chartOptions.xAxis.gridLineWidth).toBe(0);
545
+ expect(chartOptions.yAxis.gridLineWidth).toBe(0);
546
+ expect(chartOptions.xAxis.lineWidth).toBe(1);
547
+ expect(chartOptions.yAxis.lineWidth).toBe(1);
548
+ });
549
+ });
550
+
551
+ describe('function getCalculatedValueFormat', () => {
552
+ const calculatedFormats = {
553
+ colKey1: 'format1',
554
+ colKey2: 'format2',
555
+ rowKey1: 'format3',
556
+ rowKey2: 'format4',
557
+ };
558
+
559
+ it('should return an empty string if no calculatedFormats are provided', () => {
560
+ const result = highchartsRenderer.getCalculatedValueFormat(undefined, 'rowKey1', 'colKey1');
561
+ expect(result).toEqual('');
562
+ });
563
+
564
+ it('should return the format of a single row or column key', () => {
565
+ const result1 = highchartsRenderer.getCalculatedValueFormat(calculatedFormats, 'rowKey1', 'colKey1');
566
+ expect(result1).toEqual('format3');
567
+
568
+ const result2 = highchartsRenderer.getCalculatedValueFormat(calculatedFormats, 'rowKey2', 'colKey2');
569
+ expect(result2).toEqual('format4');
570
+ });
571
+
572
+ it('should return the format of an array of row or column keys', () => {
573
+ const result1 = highchartsRenderer.getCalculatedValueFormat(calculatedFormats, ['rowKey1', 'rowKey2'], 'colKey1');
574
+ expect(result1).toEqual('format4');
575
+
576
+ const result2 = highchartsRenderer.getCalculatedValueFormat(calculatedFormats, 'rowKey1', ['colKey1', 'colKey2']);
577
+ expect(result2).toEqual('format3');
578
+ });
579
+
580
+ it('should return an empty string if no format is found for the provided keys', () => {
581
+ const result = highchartsRenderer.getCalculatedValueFormat(calculatedFormats, 'nonexistentRowKey', 'nonexistentColKey');
582
+ expect(result).toEqual('');
583
+ });
584
+
585
+ it('should return an empty string if no calculated formats', () => {
586
+ const result = highchartsRenderer.getCalculatedValueFormat([], ['nonexistentRowKey'], ['nonexistentColKey']);
587
+ expect(result).toEqual('');
588
+ });
589
+ });
590
+
591
+ describe('function isRowKeyShouldBePercentage', () => {
592
+ const renderOptions = {
593
+ comboOptions: {
594
+ secondaryAxisSettings: {
595
+ is_percentage: true
596
+ },
597
+ seriesOptions: [
598
+ { series: 'series1', secondaryAxis: false },
599
+ { series: 'series2', secondaryAxis: true }
600
+ ]
601
+ }
602
+ };
603
+
604
+ it('should return true if the row key has a corresponding series with secondaryAxis true', () => {
605
+ const rowKey = ['series2'];
606
+ const result = highchartsRenderer.isRowKeyShouldBePercentage(renderOptions, rowKey);
607
+ expect(result).toBe(true);
608
+ });
609
+
610
+ it('should return false if the row key does not have a corresponding series', () => {
611
+ const rowKey = ['series3'];
612
+ const result = highchartsRenderer.isRowKeyShouldBePercentage(renderOptions, rowKey);
613
+ expect(result).toBe(false);
614
+ });
615
+
616
+ it('should return false if the corresponding series has secondaryAxis false', () => {
617
+ const rowKey = ['series1'];
618
+ const result = highchartsRenderer.isRowKeyShouldBePercentage(renderOptions, rowKey);
619
+ expect(result).toBe(false);
620
+ });
621
+
622
+ it('should return false if renderOptions or comboOptions or secondaryAxisSettings is not defined', () => {
623
+ const rowKey = ['series2'];
624
+ const result = highchartsRenderer.isRowKeyShouldBePercentage(null, rowKey);
625
+ expect(result).toBe(false);
626
+ });
627
+ });
628
+
629
+ describe('function ignoreIfCalculatedValue', () => {
630
+ let data;
631
+ let rowKey;
632
+ let colKey;
633
+ let record;
634
+ let associatedFields;
635
+ let renderOptions;
636
+ const isGraph = false;
637
+
638
+ beforeEach(() => {
639
+ data = {
640
+ colAttrs: ['col1', 'col2'],
641
+ rowAttrs: ['row1', 'row2']
642
+ }
643
+ rowKey = ['row1value', 'row2value'];
644
+ colKey = ['col1value', 'col2value'];
645
+ record = {
646
+ row1: 'row1value',
647
+ row2: 'row2value',
648
+ col1: 'col1value',
649
+ col2: 'col2value',
650
+ DR_Values: 123
651
+ }
652
+ associatedFields = {
653
+ row1: ['row1value', 'row1value2'],
654
+ row2: ['row2value', 'row2value2']
655
+ }
656
+ renderOptions = {
657
+ chartOptions: {
658
+ table_options: {
659
+ eliminate_calc_totals: true
660
+ }
661
+ }
662
+ }
663
+ });
664
+
665
+ it('should return false if eliminate_calc_totals is false', () => {
666
+ renderOptions.chartOptions.table_options.eliminate_calc_totals = false;
667
+ const result = highchartsRenderer.ignoreIfCalculatedValue(data, rowKey, colKey, record, associatedFields, renderOptions, isGraph);
668
+ expect(result).toBe(false);
669
+ });
670
+
671
+ it('should return false if colAttrs and rowAttrs have same length as colKey and rowKey', () => {
672
+ const result = highchartsRenderer.ignoreIfCalculatedValue(data, rowKey, colKey, record, associatedFields, renderOptions, isGraph);
673
+ expect(result).toBe(false);
674
+ });
675
+
676
+ it('should return true if associatedFields matches record keys and eliminate_calc_totals is true', () => {
677
+ const rKeys = [...rowKey];
678
+ const cKeys = [...colKey, 'col3value'];
679
+ record.row1 = 'row1value2';
680
+ const result = highchartsRenderer.ignoreIfCalculatedValue(data, rKeys, cKeys, record, associatedFields, renderOptions, isGraph);
681
+ expect(result).toBe(true);
682
+ });
683
+
684
+ it('should return true if associatedFields matches DR_Values and eliminate_calc_totals is true', () => {
685
+ const rKeys = [...rowKey, 'row3value'];
686
+ const cKeys = [...colKey];
687
+ record.row1 = 'test';
688
+ record.DR_Values = 'row1value2';
689
+ const result = highchartsRenderer.ignoreIfCalculatedValue(data, rKeys, cKeys, record, associatedFields, renderOptions, isGraph);
690
+ expect(result).toBe(true);
691
+ });
692
+
693
+ it('should return false if isGraph is true', () => {
694
+ const result = highchartsRenderer.ignoreIfCalculatedValue(data, rowKey, colKey, record, associatedFields, renderOptions, true);
695
+ expect(result).toBe(false);
696
+ });
697
+
698
+ it('should return false if associatedFields are empty', () => {
699
+ const result = highchartsRenderer.ignoreIfCalculatedValue(data, rowKey, colKey, record, associatedFields, renderOptions, isGraph);
700
+ expect(result).toBe(false);
701
+ });
702
+ });
703
+
704
+ describe('function getAxis', () => {
705
+ it('returns the given axis if transpose_table is false', () => {
706
+ const opts = { rendererOptions: { chartOptions: { table_options: { transpose_table: false } } }, isTable: true };
707
+ expect(highchartsRenderer.getAxis('row_total', opts)).toEqual('row_total');
708
+ });
709
+
710
+ it('returns the opposite axis if transpose_table is true and axis is col_total', () => {
711
+ const opts = { rendererOptions: { chartOptions: { table_options: { transpose_table: true } } }, isTable: true };
712
+ expect(highchartsRenderer.getAxis('col_total', opts)).toEqual('row_total');
713
+ });
714
+
715
+ it('returns the opposite axis if farceIsTable is true', () => {
716
+ const opts = { rendererOptions: { chartOptions: { table_options: { transpose_table: true } } }, isTable: false };
717
+ expect(highchartsRenderer.getAxis('col_total', opts, true)).toEqual('row_total');
718
+ });
719
+
720
+ it('returns the opposite axis if farceIsTable is true for row_total', () => {
721
+ const opts = { rendererOptions: { chartOptions: { table_options: { transpose_table: true } } }, isTable: false };
722
+ expect(highchartsRenderer.getAxis('row_total', opts, true)).toEqual('col_total');
723
+ });
724
+ });
725
+
726
+ describe('function sanitizeOptions', () => {
727
+ it('should decode chart_title property in rendererOptions', () => {
728
+ const opts = {
729
+ rendererOptions: {
730
+ chart_title: 'Title &amp; subtitle'
731
+ }
732
+ };
733
+ highchartsRenderer.sanitizeOptions(opts);
734
+ expect(opts.rendererOptions.chart_title).toBe('Title & subtitle');
735
+ });
736
+
737
+ it('should decode subtitle property in chartOptions', () => {
738
+ const opts = {
739
+ chartOptions: {
740
+ subtitle: {
741
+ subtitle: 'Subtitle &amp; subtitle'
742
+ }
743
+ }
744
+ };
745
+ highchartsRenderer.sanitizeOptions(opts);
746
+ expect(opts.chartOptions.subtitle.subtitle).toBe('Subtitle & subtitle');
747
+ });
748
+
749
+ it('should decode subtitle property in rendererOptions.chartOptions', () => {
750
+ const opts = {
751
+ rendererOptions: {
752
+ chartOptions: {
753
+ subtitle: {
754
+ subtitle: 'Subtitle &amp; subtitle'
755
+ }
756
+ }
757
+ }
758
+ };
759
+ highchartsRenderer.sanitizeOptions(opts);
760
+ expect(opts.rendererOptions.chartOptions.subtitle.subtitle).toBe('Subtitle & subtitle');
761
+ });
762
+
763
+ it('should not change the options if no property to decode', () => {
764
+ const opts = {
765
+ chartOptions: {
766
+ chart_type: 'column'
767
+ }
768
+ };
769
+ highchartsRenderer.sanitizeOptions(opts);
770
+ expect(opts).toEqual({
771
+ chartOptions: {
772
+ chart_type: 'column'
773
+ }
774
+ });
775
+ });
776
+ });
777
+
778
+ describe('function getIconsForTotalOptions', () => {
779
+ const options = {
780
+ total_value_options: {
781
+ filter_options: {
782
+ axis: 'row'
783
+ }
784
+ }
785
+ };
786
+
787
+ it('should return filter icon for matching axis', () => {
788
+ const axis = 'row'
789
+ const expected = '<i class="fa fa-filter"></i>'
790
+ const result = highchartsRenderer.getIconsForTotalOptions(options, axis)
791
+ expect(result).toEqual(expected)
792
+ });
793
+
794
+ it('should return empty string for non-matching axis', () => {
795
+ const axis = 'col'
796
+ const expected = ''
797
+ const result = highchartsRenderer.getIconsForTotalOptions(options, axis)
798
+ expect(result).toEqual(expected)
799
+ });
800
+
801
+ it('should return empty string for missing filter options', () => {
802
+ const axis = 'row'
803
+ const options = {}
804
+ const expected = ''
805
+ const result = highchartsRenderer.getIconsForTotalOptions(options, axis)
806
+ expect(result).toEqual(expected)
807
+ });
808
+ });
809
+
810
+ describe('function getFieldNameForTable', () => {
811
+ it('should return a function if remove_underscores is false', () => {
812
+ const opt = {
813
+ rendererOptions: {
814
+ chartOptions: {
815
+ table_options: {
816
+ remove_underscores: false
817
+ }
818
+ }
819
+ }
820
+ };
821
+ const result = highchartsRenderer.getFieldNameForTable(opt);
822
+ expect(result).toBe(highchartsRenderer.getFieldName);
823
+ });
824
+
825
+ it('should return a function that removes underscores from field names if remove_underscores is true', () => {
826
+ const opt = {
827
+ rendererOptions: {
828
+ chartOptions: {
829
+ table_options: {
830
+ remove_underscores: true
831
+ }
832
+ }
833
+ }
834
+ };
835
+ const result = highchartsRenderer.getFieldNameForTable(opt);
836
+ const field = 'field_name_with_underscores';
837
+ const expectedResult = 'field name with underscores';
838
+ expect(result(field)).toBe(expectedResult);
839
+ const emptyName = '';
840
+ expect(result(emptyName)).toBe(emptyName);
841
+ });
842
+
843
+ it('should return highchartsRenderer.getFieldName function if option is missing', () => {
844
+ const opt = {};
845
+ const result = highchartsRenderer.getFieldNameForTable(opt);
846
+ expect(result).toBe(highchartsRenderer.getFieldName);
847
+ });
848
+ });
849
+
850
+ describe("function getFieldName", () => {
851
+ it("returns empty string if given an empty string", () => {
852
+ expect(highchartsRenderer.getFieldName("")).toEqual("");
853
+ });
854
+
855
+ it("returns the same string if no replacements are needed", () => {
856
+ expect(highchartsRenderer.getFieldName("Test Field")).toEqual("Test Field");
857
+ });
858
+
859
+ it("replaces specific strings with new names", () => {
860
+ expect(highchartsRenderer.getFieldName("DR_Values")).toEqual("Values");
861
+ expect(highchartsRenderer.getFieldName("Submission_Date")).toEqual("Submission Date");
862
+ expect(highchartsRenderer.getFieldName("VT_Day")).toEqual("Day (Tag)");
863
+ });
864
+
865
+ it("adds '(Dimension)' if field name starts with 'DT_'", () => {
866
+ expect(highchartsRenderer.getFieldName("DT_Test")).toEqual("Test (Dimension)");
867
+ });
868
+
869
+ it("adds '(Scenario)' if field name starts with 'dr_scenario_' and doesn't have 'for_value_' in it", () => {
870
+ expect(highchartsRenderer.getFieldName("dr_scenario_Test")).toEqual("Test (Scenario)");
871
+ });
872
+
873
+ it("no adds '(Scenario)' and uses 'for_value_' to create a new name if field name starts with 'dr_scenario_' and has 'for_value_' in it", () => {
874
+ expect(highchartsRenderer.getFieldName("dr_scenario_Test_for_value_X")).toEqual("X (Test)");
875
+
876
+ });
877
+ it("adds '(Scenario)' and uses 'for_value_' to create a new name if field name starts with 'dr_scenario_' and has 'for_value_' in it", () => {
878
+ expect(highchartsRenderer.getFieldName("dr_scenario_X")).toEqual("X (Scenario)");
879
+ });
880
+
881
+ it("adds '(Split)' if field name contains '_splitted_'", () => {
882
+ expect(highchartsRenderer.getFieldName("Test_splitted_Fiscal_quarter")).toEqual("Test Fiscal Quarter (Split)");
883
+ });
884
+ });
885
+
886
+ describe('function checkFreezePanesAvaliable', () => {
887
+ let pivotView;
888
+
889
+ beforeEach(() => {
890
+ pivotView = document.createElement('div');
891
+ pivotView.innerHTML = `
892
+ <div class="pivot-div">
893
+ <table class="pvtTable">
894
+ <thead>
895
+ <tr>
896
+ <th class="axis-freeze-pane" style="width: 100px;"></th>
897
+ <th class="horizontal-freeze-pane" style="width: 100px;"></th>
898
+ <th style="width: 500px;"></th>
899
+ </tr>
900
+ </thead>
901
+ </table>
902
+ </div>
903
+ `;
904
+ });
905
+
906
+ it('should set dataset.canFreezePanes to false when total width of frozen columns exceeds table width', () => {
907
+ const tableContainer = pivotView.querySelector('.pivot-div');
908
+ const expectedDataset = { canFreezePanes: 'false' };
909
+
910
+ highchartsRenderer.checkFreezePanesAvaliable(pivotView);
911
+ expect(tableContainer.dataset.canFreezePanes).toEqual(expectedDataset.canFreezePanes);
912
+ });
913
+
914
+ it('should remove dataset.canFreezePanes when total width of frozen columns is less than table width', () => {
915
+ const tableContainer ={
916
+ dataset: { canFreezePanes: "false" },
917
+ offsetWidth: 1000
918
+ };
919
+
920
+ const _pivotView = {
921
+ querySelector: (p) => p === '.pivot-div' ? tableContainer : null
922
+ };
923
+ highchartsRenderer.checkFreezePanesAvaliable(_pivotView);
924
+
925
+ expect(tableContainer.dataset.canFreezePanes).toEqual(undefined);
926
+ });
927
+
928
+ it('should not set dataset.canFreezePanes when pivotView or pivotView.querySelector is undefined', () => {
929
+ expect(highchartsRenderer.checkFreezePanesAvaliable(null)).toEqual(undefined);
930
+ });
931
+ });
932
+
933
+ describe('function getOnlyIncludedOfField', () => {
934
+ it('returns includes array if it exists', () => {
935
+ const fieldObj = {
936
+ includes: ['foo', 'bar'],
937
+ values: ['foo', 'bar', 'baz'],
938
+ };
939
+ expect(highchartsRenderer.getOnlyIncludedOfField(fieldObj)).toEqual(['foo', 'bar']);
940
+ });
941
+
942
+ it('returns values array with excludes removed if excludes exists', () => {
943
+ const fieldObj = {
944
+ excludes: ['bar', 'baz'],
945
+ values: ['foo', 'bar', 'baz'],
946
+ };
947
+ expect(highchartsRenderer.getOnlyIncludedOfField(fieldObj)).toEqual(['foo']);
948
+ });
949
+
950
+ it('returns null if neither includes nor excludes exists', () => {
951
+ const fieldObj = {
952
+ values: ['foo', 'bar', 'baz'],
953
+ };
954
+ expect(highchartsRenderer.getOnlyIncludedOfField(fieldObj)).toBeNull();
955
+ });
956
+ });
957
+
958
+ describe('function createOneWidgetField', () => {
959
+ const template_field = {
960
+ name: 'field',
961
+ id: 123,
962
+ type: 'string',
963
+ format: null,
964
+ sorting: null,
965
+ has_drilldown: false,
966
+ is_calculated: false,
967
+ values: [],
968
+ date_field_before_split: null,
969
+ mandatory: false,
970
+ category: 'cat1',
971
+ is_hidden: false,
972
+ description: 'description',
973
+ };
974
+
975
+ it('returns an object with expected properties', () => {
976
+ const result = highchartsRenderer.createOneWidgetField(template_field);
977
+
978
+ expect(result).toHaveProperty('name', 'field');
979
+ expect(result).toHaveProperty('id', 123);
980
+ expect(result).toHaveProperty('type', 'string');
981
+ expect(result).toHaveProperty('format', null);
982
+ expect(result).toHaveProperty('sorting', null);
983
+ expect(result).toHaveProperty('has_drilldown', false);
984
+ expect(result).toHaveProperty('is_calculated', false);
985
+ expect(result).toHaveProperty('values', []);
986
+ expect(result).toHaveProperty('new_name', 'field');
987
+ expect(result).toHaveProperty('name_class', 'blue_filed');
988
+ expect(result).toHaveProperty('date_field_before_split', null);
989
+ expect(result).toHaveProperty('mandatory', false);
990
+ expect(result).toHaveProperty('category', 'cat1');
991
+ expect(result).toHaveProperty('is_hidden', false);
992
+ expect(result).toHaveProperty('description', 'description');
993
+ expect(result).toHaveProperty('description_tooltip');
994
+ });
995
+ });
996
+
997
+ describe('function getDescriptionAndHintValuesTooltip', () => {
998
+ it('returns only field name if no description or hint values are present', () => {
999
+ const field = {
1000
+ name: 'foo',
1001
+ };
1002
+ const tooltip = highchartsRenderer.getDescriptionAndHintValuesTooltip(field);
1003
+ expect(tooltip).toEqual('foo');
1004
+ });
1005
+
1006
+ it('returns description if present and no hint values are present', () => {
1007
+ const field = {
1008
+ name: 'foo',
1009
+ description: 'This is a field description.',
1010
+ };
1011
+ const tooltip = highchartsRenderer.getDescriptionAndHintValuesTooltip(field);
1012
+ expect(tooltip).toEqual('Description:\nThis is a field description.');
1013
+ });
1014
+
1015
+ it('returns hint values if present and no description is present', () => {
1016
+ const field = {
1017
+ name: 'foo',
1018
+ usage_info: {
1019
+ data_info: {
1020
+ samples: ['bar', 'baz'],
1021
+ samples_formatted: ['Bar', 'Baz'],
1022
+ },
1023
+ },
1024
+ };
1025
+ const tooltip = highchartsRenderer.getDescriptionAndHintValuesTooltip(field);
1026
+ expect(tooltip).toEqual('Hint values:\nBar, Baz');
1027
+ });
1028
+
1029
+ it('returns both description and hint values if present', () => {
1030
+ const field = {
1031
+ name: 'foo',
1032
+ description: 'This is a field description.',
1033
+ usage_info: {
1034
+ data_info: {
1035
+ samples: ['bar', 'baz'],
1036
+ samples_formatted: ['Bar', 'Baz'],
1037
+ },
1038
+ },
1039
+ };
1040
+ const tooltip = highchartsRenderer.getDescriptionAndHintValuesTooltip(field);
1041
+ expect(tooltip).toEqual('Description:\nThis is a field description.\n\nHint values:\nBar, Baz');
1042
+ });
1043
+ });
1044
+
1045
+ describe('function getFieldColorClass', () => {
1046
+ it('should return "green_field" if field is not a system field and not mandatory', () => {
1047
+ const field = {
1048
+ name: 'field1',
1049
+ mandatory: false
1050
+ };
1051
+ const result = highchartsRenderer.getFieldColorClass(field);
1052
+ expect(result).toBe('green_field');
1053
+ });
1054
+
1055
+ it('should return "blue_filed" if field is a system field and not mandatory', () => {
1056
+ const field = {
1057
+ name: 'System_Field',
1058
+ mandatory: false,
1059
+ isSystem: true
1060
+ };
1061
+ const result = highchartsRenderer.getFieldColorClass(field);
1062
+ expect(result).toBe('blue_filed');
1063
+ });
1064
+
1065
+ it('should return "green_field mandatoryfieldborder" if field is not a system field and is mandatory', () => {
1066
+ const field = {
1067
+ name: 'field2',
1068
+ mandatory: true
1069
+ };
1070
+ const result = highchartsRenderer.getFieldColorClass(field);
1071
+ expect(result).toBe('green_field mandatoryfieldborder ');
1072
+ });
1073
+
1074
+ it('should return "blue_filed mandatoryfieldborder" if field is a system field and is mandatory', () => {
1075
+ const field = {
1076
+ name: 'System_Field',
1077
+ mandatory: true,
1078
+ isSystem: true
1079
+ };
1080
+ const result = highchartsRenderer.getFieldColorClass(field);
1081
+ expect(result).toBe('blue_filed mandatoryfieldborder ');
1082
+ });
1083
+ });
1084
+
1085
+ describe('function getMiniTemplateObj', () => {
1086
+ it('returns an object with only the id property', () => {
1087
+ const template = {
1088
+ id: 1,
1089
+ name: 'Template 1'
1090
+ }
1091
+ const miniTemplateObj = highchartsRenderer.getMiniTemplateObj(template)
1092
+ expect(miniTemplateObj).toEqual({ id: 1 })
1093
+ })
1094
+ });
1095
+
1096
+ describe('function decodeTemplates', () => {
1097
+ it('should decode tables with fields and others propperties', () => {
1098
+ let templates = lodash.cloneDeep(tables);
1099
+ highchartsRenderer.decodeTemplates (templates);
1100
+ expect(templates[0].name).toBe('Superstore&data');
1101
+ });
1102
+ });
1103
+
1104
+ describe('function setWidgetFieldsToTemplate', () => {
1105
+ it('should set widget fields to selected template if not exists', () => {
1106
+ const selectedTemplate = {
1107
+ id: 1,
1108
+ fields: [...tables[0].fields],
1109
+ widget_fields: null
1110
+ };
1111
+
1112
+ highchartsRenderer.setWidgetFieldsToTemplate(selectedTemplate);
1113
+
1114
+ expect(selectedTemplate.widget_fields.length).toBe(tables[0].fields.length);
1115
+ });
1116
+
1117
+ it('shouldn\'t set new widget fields if already exist exists', () => {
1118
+ const selectedTemplate = {
1119
+ id: 1,
1120
+ fields: [...tables[0].fields],
1121
+ widget_fields: [{}]
1122
+ };
1123
+
1124
+ highchartsRenderer.setWidgetFieldsToTemplate(selectedTemplate);
1125
+
1126
+ expect(selectedTemplate.widget_fields.length).toBe(1);
1127
+ });
1128
+ });
1129
+
1130
+ describe('function setWidgetRawData', () => {
1131
+ it('should create widget_raw_data property if it does not exist', () => {
1132
+ const selectedTemplate = {
1133
+ raw_data: [{ name: 'John', age: 30 }, { name: 'Jane', age: 25 }],
1134
+ fields: [{ name: 'name', type: 'string', format: '' }, { name: 'age', type: 'number', format: '' }]
1135
+ };
1136
+
1137
+ highchartsRenderer.setWidgetRawData(selectedTemplate);
1138
+
1139
+ expect(selectedTemplate.widget_raw_data).toBeDefined();
1140
+ });
1141
+
1142
+ it('should map raw_data to widget_raw_data property', () => {
1143
+ const selectedTemplate = {
1144
+ raw_data: [{ name: 'John', age: 30 }, { name: 'Jane', age: 25 }],
1145
+ fields: [{ name: 'name', type: 'string', format: '' }, { name: 'age', type: 'number', format: '' }]
1146
+ };
1147
+
1148
+ highchartsRenderer.setWidgetRawData(selectedTemplate);
1149
+
1150
+ expect(selectedTemplate.widget_raw_data).toEqual([{ name: 'John', age: 30 }, { name: 'Jane', age: 25 }]);
1151
+ });
1152
+
1153
+ it('should return raw_data values formatted based on their type and format', () => {
1154
+ const selectedTemplate = {
1155
+ raw_data: [{ name: 'John', age: 30.5 }, { name: 'Jane', age: 25 }],
1156
+ fields: [{ name: 'name', type: 'string', format: '' }, { name: 'age', type: 'number', format: '0.00' }]
1157
+ };
1158
+
1159
+ highchartsRenderer.setWidgetRawData(selectedTemplate);
1160
+
1161
+ expect(selectedTemplate.widget_raw_data[0].name).toBe('John');
1162
+ expect(selectedTemplate.widget_raw_data[0].age).toBe(30.5);
1163
+ expect(selectedTemplate.widget_raw_data[1].name).toBe('Jane');
1164
+ expect(selectedTemplate.widget_raw_data[1].age).toBe(25);
1165
+ });
1166
+
1167
+ it('shouldn\'t create widget_raw_data if it exists', () => {
1168
+ const selectedTemplate = {
1169
+ widget_raw_data: [{}],
1170
+ raw_data: [{ name: 'John', age: 30 }, { name: 'Jane', age: 25 }],
1171
+ fields: [{ name: 'name', type: 'string', format: '' }, { name: 'age', type: 'number', format: '' }]
1172
+ };
1173
+
1174
+ highchartsRenderer.setWidgetRawData(selectedTemplate);
1175
+
1176
+ expect(selectedTemplate.widget_raw_data.length).toBe(1);
1177
+ });
1178
+ });
1179
+
1180
+ describe("function objectCopyJsonMethod", () => {
1181
+ it("should return null for null input", () => {
1182
+ expect(highchartsRenderer.objectCopyJsonMethod(null)).toBe(0);
1183
+ });
1184
+
1185
+ it("should return a copy of the object", () => {
1186
+ const obj = { a: 1, b: 2 };
1187
+ const objCopy = highchartsRenderer.objectCopyJsonMethod(obj);
1188
+ expect(objCopy).toEqual(obj);
1189
+ expect(objCopy).not.toBe(obj);
1190
+ });
1191
+
1192
+ it("should return a copy of the array", () => {
1193
+ const arr = [1, 2, 3];
1194
+ const arrCopy = highchartsRenderer.objectCopyJsonMethod(arr);
1195
+ expect(arrCopy).toEqual(arr);
1196
+ expect(arrCopy).not.toBe(arr);
1197
+ });
1198
+ });
1199
+
1200
+ describe('function aggregators', () => {
1201
+ const aggregatorsIds = ['SUM', 'COUNT', 'COUNT_UNIQUE', 'UNIQUE_VALUES', 'AVG', 'MIN', 'MAX'];
1202
+
1203
+ it('Count and names', () => {
1204
+ expect(highchartsRenderer.aggregators.length).toBe(7);
1205
+ expect(lodash.map(highchartsRenderer.aggregators, agg => agg.id)).toEqual(aggregatorsIds);
1206
+ });
1207
+
1208
+ it('function getAggregatorFunctionById', () => {
1209
+ expect(highchartsRenderer.getAggregatorFunctionById(aggregatorsIds[0])).toBe(highchartsRenderer.rhPivotAggregatorSum);
1210
+ expect(highchartsRenderer.getAggregatorFunctionById(aggregatorsIds[1])).toBe(highchartsRenderer.rhPivotCount);
1211
+ expect(highchartsRenderer.getAggregatorFunctionById(aggregatorsIds[2])).toBe(highchartsRenderer.rhPivotCount);
1212
+ expect(highchartsRenderer.getAggregatorFunctionById(aggregatorsIds[3])).toBe(highchartsRenderer.rhPivotAggregatorUniqValues);
1213
+ expect(highchartsRenderer.getAggregatorFunctionById(aggregatorsIds[4])).toBe(highchartsRenderer.rhPivotAggregatorAverage);
1214
+ expect(highchartsRenderer.getAggregatorFunctionById(aggregatorsIds[5])).toBe(highchartsRenderer.rhPivotAggregatorMin);
1215
+ expect(highchartsRenderer.getAggregatorFunctionById(aggregatorsIds[6])).toBe(highchartsRenderer.rhPivotAggregatorMax);
1216
+ expect(highchartsRenderer.getAggregatorFunctionById('nonExistAggregator')).toBe(undefined);
1217
+ });
1218
+
1219
+ it('function getAggregatorNameById', () => {
1220
+ expect(highchartsRenderer.getAggregatorNameById(aggregatorsIds[0])).toBe('Sum');
1221
+ expect(highchartsRenderer.getAggregatorNameById(aggregatorsIds[1])).toBe('Count');
1222
+ expect(highchartsRenderer.getAggregatorNameById(aggregatorsIds[2])).toBe('Count Unique');
1223
+ expect(highchartsRenderer.getAggregatorNameById(aggregatorsIds[3])).toBe('Unique Values');
1224
+ expect(highchartsRenderer.getAggregatorNameById(aggregatorsIds[4])).toBe('Average');
1225
+ expect(highchartsRenderer.getAggregatorNameById(aggregatorsIds[5])).toBe('Minimum');
1226
+ expect(highchartsRenderer.getAggregatorNameById(aggregatorsIds[6])).toBe('Maximum');
1227
+ expect(highchartsRenderer.getAggregatorNameById('nonExistAggregator')).toBe('');
1228
+ });
1229
+
1230
+ describe('function setDefaultAggregator', () => {
1231
+ const field = {};
1232
+
1233
+ it('Integer field type', ()=> {
1234
+ field.type = 'Integer';
1235
+ highchartsRenderer.setDefaultAggregator(field);
1236
+ expect(field.aggregator).toBe(aggregatorsIds[0]);
1237
+ });
1238
+
1239
+ it('Float field type', ()=> {
1240
+ field.type = 'Float';
1241
+ highchartsRenderer.setDefaultAggregator(field);
1242
+ expect(field.aggregator).toBe(aggregatorsIds[0]);
1243
+ });
1244
+
1245
+ it('Non number field type', ()=> {
1246
+ field.type = 'Text';
1247
+ highchartsRenderer.setDefaultAggregator(field);
1248
+ expect(field.aggregator).toBe(aggregatorsIds[3]);
1249
+ });
1250
+ });
1251
+
1252
+ describe('function getValueLabel', () => {
1253
+ const field = {
1254
+ new_name: 'name'
1255
+ };
1256
+
1257
+ it('Field with aggregator should return aggregator name with new field name', ()=> {
1258
+ field.aggregator = aggregatorsIds[4];
1259
+ expect(highchartsRenderer.getValueLabel(field)).toBe('Average of name');
1260
+ });
1261
+
1262
+ it('Number field without aggregator should return aggregator name with new field name', ()=> {
1263
+ field.aggregator = null;
1264
+ field.type = 'Float';
1265
+ expect(highchartsRenderer.getValueLabel(field)).toBe('Sum of name');
1266
+ });
1267
+
1268
+ it('Text field without aggregator should return aggregator name with new field name', ()=> {
1269
+ field.aggregator = null;
1270
+ field.type = 'Text';
1271
+ expect(highchartsRenderer.getValueLabel(field)).toBe('Unique Values of name');
1272
+ });
1273
+ });
1274
+
1275
+ describe('Aggregators functions', () => {
1276
+ describe('Sum aggregator', () => {
1277
+ let arg;
1278
+ let widget_values_format;
1279
+ let is_graph;
1280
+ let render_options;
1281
+ let calculated_info;
1282
+ let aggregator;
1283
+ let aggregatorObject;
1284
+
1285
+ beforeEach(() => {
1286
+ arg = ['Profit'];
1287
+ widget_values_format = '"$"####.##';
1288
+ is_graph = true;
1289
+ render_options = {};
1290
+ calculated_info = {
1291
+ "formats": {
1292
+ "Average category": null,
1293
+ "Region average": "####.##%"
1294
+ },
1295
+ "associated_fields": {
1296
+ "Category": [
1297
+ "Average category"
1298
+ ],
1299
+ "Region": [
1300
+ "Region average"
1301
+ ]
1302
+ }
1303
+ };
1304
+
1305
+ aggregator = highchartsRenderer.rhPivotAggregatorSum(arg, widget_values_format, is_graph, render_options, calculated_info);
1306
+ aggregatorObject = aggregator({}, '', '');
1307
+ });
1308
+
1309
+ it('Aggregation object structure', () => {
1310
+ expect(aggregatorObject.sum).toBe(0);
1311
+ expect(aggregatorObject.ignoreValue).toBe(false);
1312
+ expect(aggregatorObject.data_types).toEqual([]);
1313
+ expect(aggregatorObject.formats).toEqual([]);
1314
+ expect(aggregatorObject.has_errors).toBe(false);
1315
+ expect(aggregatorObject.widget_values_format).toBe(widget_values_format);
1316
+ expect(aggregatorObject.calculated_formats).toBe(calculated_info.formats);
1317
+ expect(aggregatorObject.isChangeable).toBe(false);
1318
+ expect(aggregatorObject.numInputs).toBe(0);
1319
+ expect(typeof aggregatorObject.push).toBe('function');
1320
+ expect(typeof aggregatorObject.value).toBe('function');
1321
+ expect(typeof aggregatorObject.format).toBe('function');
1322
+ });
1323
+
1324
+ it('numInputs should be 1 if there are no argument', () => {
1325
+ const agg = highchartsRenderer.rhPivotAggregatorSum([null], widget_values_format, is_graph, render_options, calculated_info);
1326
+ const aggObject = agg({}, '', '');
1327
+ expect(aggObject.numInputs).toBe(1);
1328
+ });
1329
+
1330
+ describe('Push method', () => {
1331
+ beforeEach(() => {
1332
+ aggregator = highchartsRenderer.rhPivotAggregatorSum(arg, widget_values_format, is_graph, render_options, calculated_info);
1333
+ aggregatorObject = aggregator({}, '', '');
1334
+ });
1335
+
1336
+ it('Should be error if wrong data_types', () => {
1337
+ aggregatorObject.push({
1338
+ data_types: ['d', '1']
1339
+ });
1340
+ expect(aggregatorObject.has_errors).toBe(true);
1341
+ });
1342
+
1343
+ it('Sum should be NaN if value is string', () => {
1344
+ aggregatorObject.push({Profit: 'incorrectValue'});
1345
+ expect(aggregatorObject.sum).toBe(NaN);
1346
+ });
1347
+
1348
+ it('Data types must be filled and uniq', () => {
1349
+ aggregatorObject.push({Profit: 123, data_types: ['1', '1', '2']});
1350
+ expect(aggregatorObject.data_types).toEqual(['1', '2']);
1351
+ });
1352
+
1353
+ it('Formats must be filled and uniq', () => {
1354
+ aggregatorObject.push({Profit: 123, formats: ['####', '####', '#,###']});
1355
+ expect(aggregatorObject.formats).toEqual(['####', '#,###']);
1356
+ });
1357
+
1358
+ it('Value should be a sum of records when server calculation disabled', () => {
1359
+ highchartsRenderer.useTotalsCalculation = false;
1360
+ aggregatorObject.push({Profit: 10});
1361
+ aggregatorObject.push({Profit: 20});
1362
+ expect(aggregatorObject.sum).toEqual(30);
1363
+ });
1364
+
1365
+ it('Value should be a last record value when server calculation enabled', () => {
1366
+ highchartsRenderer.useTotalsCalculation = true;
1367
+ aggregatorObject.push({Profit: 10});
1368
+ aggregatorObject.push({Profit: 20});
1369
+ expect(aggregatorObject.sum).toEqual(20);
1370
+ });
1371
+
1372
+ it('Widget values format must be redefined if row key should be percentage', () => {
1373
+ const options = {
1374
+ comboOptions: {
1375
+ secondaryAxisSettings: {
1376
+ is_percentage: true
1377
+ },
1378
+ seriesOptions: [{series: 'Region', secondaryAxis: true}]
1379
+ }
1380
+ }
1381
+ aggregator = highchartsRenderer.rhPivotAggregatorSum(arg, widget_values_format, is_graph, options, calculated_info);
1382
+ aggregatorObject = aggregator({}, ['Region'], '');
1383
+ aggregatorObject.push({Profit: 20, Region: 'Central'});
1384
+ expect(aggregatorObject.widget_values_format).toEqual('#,###%');
1385
+ });
1386
+
1387
+ it('Value must be ignored if calculated totals disabled', () => {
1388
+ const options = {
1389
+ chartOptions: {
1390
+ table_options: {
1391
+ eliminate_calc_totals: true
1392
+ }
1393
+ }
1394
+ }
1395
+ aggregator = highchartsRenderer.rhPivotAggregatorSum(arg, widget_values_format, false, options, calculated_info);
1396
+ aggregatorObject = aggregator({colAttrs: [], rowAttrs: []}, ['Region average'], '');
1397
+ aggregatorObject.push({Profit: 20, 'Region average': 'Central', Region: 'Region average'});
1398
+ expect(aggregatorObject.ignoreValue).toBe(true);
1399
+ });
1400
+ });
1401
+
1402
+ describe('Value method', () => {
1403
+ beforeEach(() => {
1404
+ aggregator = highchartsRenderer.rhPivotAggregatorSum(arg, widget_values_format, is_graph, render_options, calculated_info);
1405
+ aggregatorObject = aggregator({}, '', '');
1406
+ });
1407
+
1408
+ it('Should return null if ignore', () => {
1409
+ aggregatorObject.ignoreValue = true;
1410
+ expect(aggregatorObject.value()).toBe(null);
1411
+ });
1412
+
1413
+ it('Should return value', () => {
1414
+ aggregatorObject.ignoreValue = false;
1415
+ expect(aggregatorObject.value()).toBe(0);
1416
+ });
1417
+ });
1418
+
1419
+ describe('Format method', () => {
1420
+ beforeEach(() => {
1421
+ aggregator = highchartsRenderer.rhPivotAggregatorSum(arg, widget_values_format, is_graph, render_options, calculated_info);
1422
+ aggregatorObject = aggregator({}, '', '');
1423
+ });
1424
+
1425
+ it('Should return empty string if null or undefined', () => {
1426
+ expect(aggregatorObject.format(null, false)).toBe('');
1427
+ expect(aggregatorObject.format(undefined, false)).toBe('');
1428
+ });
1429
+
1430
+ it('Should return ERROR if has_errors and not only formats', () => {
1431
+ aggregatorObject.has_errors = true;
1432
+ expect(aggregatorObject.format(123, false)).toBe('####ERROR####');
1433
+ });
1434
+
1435
+ it('Should return General format if there are no widget_values_format', () => {
1436
+ aggregatorObject.widget_values_format = null;
1437
+ expect(aggregatorObject.format(123.4567, false)).toBe('123.46');
1438
+ });
1439
+
1440
+ it('Should return widget format if it\'s not calculated value', () => {
1441
+ aggregatorObject.widget_values_format = '\"$\"#,###.###';
1442
+ expect(aggregatorObject.format(1123.4567, false)).toBe('$1,123.457');
1443
+ });
1444
+
1445
+ it('Should return calculated value format if it\'s calculated value', () => {
1446
+ aggregator = highchartsRenderer.rhPivotAggregatorSum(arg, widget_values_format, is_graph, render_options, calculated_info);
1447
+ aggregatorObject = aggregator({}, ['Region average'], '');
1448
+ expect(aggregatorObject.format(1123.45678, false)).toBe('112345.68%');
1449
+ });
1450
+ });
1451
+ });
1452
+
1453
+ describe('Count aggregator', () => {
1454
+ let arg;
1455
+ let widget_values_format;
1456
+ let is_graph;
1457
+ let render_options;
1458
+ let calculated_info;
1459
+ let aggregator;
1460
+ let aggregatorObject;
1461
+
1462
+ beforeEach(() => {
1463
+ arg = ['Profit'];
1464
+ widget_values_format = '"$"####.##';
1465
+ is_graph = true;
1466
+ render_options = {};
1467
+ calculated_info = {
1468
+ "formats": {
1469
+ "Average category": null,
1470
+ "Region average": "####.##%"
1471
+ },
1472
+ "associated_fields": {
1473
+ "Category": [
1474
+ "Average category"
1475
+ ],
1476
+ "Region": [
1477
+ "Region average"
1478
+ ]
1479
+ }
1480
+ };
1481
+
1482
+ aggregator = highchartsRenderer.rhPivotCount(arg, widget_values_format, is_graph, render_options, calculated_info);
1483
+ aggregatorObject = aggregator({}, '', '');
1484
+ });
1485
+
1486
+ it('Aggregation object structure', () => {
1487
+ expect(aggregatorObject.sum).toBe(0);
1488
+ expect(aggregatorObject.ignoreValue).toBe(false);
1489
+ expect(aggregatorObject.data_types).toEqual([]);
1490
+ expect(aggregatorObject.formats).toEqual([]);
1491
+ expect(aggregatorObject.has_errors).toBe(false);
1492
+ expect(aggregatorObject.widget_values_format).toBe(widget_values_format);
1493
+ expect(aggregatorObject.calculated_formats).toBe(calculated_info.formats);
1494
+ expect(aggregatorObject.isChangeable).toBe(false);
1495
+ expect(aggregatorObject.numInputs).toBe(0);
1496
+ expect(typeof aggregatorObject.push).toBe('function');
1497
+ expect(typeof aggregatorObject.value).toBe('function');
1498
+ expect(typeof aggregatorObject.format).toBe('function');
1499
+ });
1500
+
1501
+ it('numInputs should be 1 if there are no argument', () => {
1502
+ const agg = highchartsRenderer.rhPivotCount([null], widget_values_format, is_graph, render_options, calculated_info);
1503
+ const aggObject = agg({}, '', '');
1504
+ expect(aggObject.numInputs).toBe(1);
1505
+ });
1506
+
1507
+ describe('Push method', () => {
1508
+ beforeEach(() => {
1509
+ aggregator = highchartsRenderer.rhPivotCount(arg, widget_values_format, is_graph, render_options, calculated_info);
1510
+ aggregatorObject = aggregator({}, '', '');
1511
+ });
1512
+
1513
+ // it('Should be error if wrong data_types', () => {
1514
+ // aggregatorObject.push({
1515
+ // data_types: ['d', '1']
1516
+ // });
1517
+ // expect(aggregatorObject.has_errors).toBe(true);
1518
+ // });
1519
+
1520
+ // it('Sum should be NaN if value is string', () => {
1521
+ // aggregatorObject.push({Profit: 'incorrectValue'});
1522
+ // expect(aggregatorObject.sum).toBe(NaN);
1523
+ // });
1524
+
1525
+ it('Data types must be filled and uniq', () => {
1526
+ aggregatorObject.push({Profit: 123, data_types: ['1', '1', '2']});
1527
+ expect(aggregatorObject.data_types).toEqual(['1', '2']);
1528
+ });
1529
+
1530
+ it('Formats must be filled and uniq', () => {
1531
+ aggregatorObject.push({Profit: 123, formats: ['####', '####', '#,###']});
1532
+ expect(aggregatorObject.formats).toEqual(['####', '#,###']);
1533
+ });
1534
+
1535
+ it('Value should be a sum of records when server calculation disabled', () => {
1536
+ highchartsRenderer.useTotalsCalculation = false;
1537
+ aggregatorObject.push({Profit: 10});
1538
+ aggregatorObject.push({Profit: 20});
1539
+ expect(aggregatorObject.sum).toEqual(30);
1540
+ });
1541
+
1542
+ it('Value should be a last record value when server calculation enabled', () => {
1543
+ highchartsRenderer.useTotalsCalculation = true;
1544
+ aggregatorObject.push({Profit: 10});
1545
+ aggregatorObject.push({Profit: 20});
1546
+ expect(aggregatorObject.sum).toEqual(20);
1547
+ });
1548
+
1549
+ it('Widget values format must be redefined if row key should be percentage', () => {
1550
+ const options = {
1551
+ comboOptions: {
1552
+ secondaryAxisSettings: {
1553
+ is_percentage: true
1554
+ },
1555
+ seriesOptions: [{series: 'Region', secondaryAxis: true}]
1556
+ }
1557
+ }
1558
+ aggregator = highchartsRenderer.rhPivotCount(arg, widget_values_format, is_graph, options, calculated_info);
1559
+ aggregatorObject = aggregator({}, ['Region'], '');
1560
+ aggregatorObject.push({Profit: 20, Region: 'Central'});
1561
+ expect(aggregatorObject.widget_values_format).toEqual('#,###%');
1562
+ });
1563
+
1564
+ it('Value must be ignored if calculated totals disabled', () => {
1565
+ const options = {
1566
+ chartOptions: {
1567
+ table_options: {
1568
+ eliminate_calc_totals: true
1569
+ }
1570
+ }
1571
+ }
1572
+ aggregator = highchartsRenderer.rhPivotCount(arg, widget_values_format, false, options, calculated_info);
1573
+ aggregatorObject = aggregator({colAttrs: [], rowAttrs: []}, ['Region average'], '');
1574
+ aggregatorObject.push({Profit: 20, 'Region average': 'Central', Region: 'Region average'});
1575
+ expect(aggregatorObject.ignoreValue).toBe(true);
1576
+ });
1577
+ });
1578
+
1579
+ describe('Value method', () => {
1580
+ beforeEach(() => {
1581
+ aggregator = highchartsRenderer.rhPivotCount(arg, widget_values_format, is_graph, render_options, calculated_info);
1582
+ aggregatorObject = aggregator({}, '', '');
1583
+ });
1584
+
1585
+ it('Should return null if ignore', () => {
1586
+ aggregatorObject.ignoreValue = true;
1587
+ expect(aggregatorObject.value()).toBe(null);
1588
+ });
1589
+
1590
+ it('Should return value', () => {
1591
+ aggregatorObject.ignoreValue = false;
1592
+ expect(aggregatorObject.value()).toBe(0);
1593
+ });
1594
+ });
1595
+
1596
+ describe('Format method', () => {
1597
+ beforeEach(() => {
1598
+ aggregator = highchartsRenderer.rhPivotCount(arg, widget_values_format, is_graph, render_options, calculated_info);
1599
+ aggregatorObject = aggregator({}, '', '');
1600
+ });
1601
+
1602
+ it('Should return empty string if null or undefined', () => {
1603
+ expect(aggregatorObject.format(null, false)).toBe('');
1604
+ expect(aggregatorObject.format(undefined, false)).toBe('');
1605
+ });
1606
+
1607
+ it('Should return ERROR if has_errors and not only formats', () => {
1608
+ aggregatorObject.has_errors = true;
1609
+ expect(aggregatorObject.format(123, false)).toBe('####ERROR####');
1610
+ });
1611
+
1612
+ it('Should return General format if there are no widget_values_format', () => {
1613
+ aggregatorObject.widget_values_format = null;
1614
+ expect(aggregatorObject.format(123.4567, false)).toBe('123.46');
1615
+ });
1616
+
1617
+ it('Should return widget format if it\'s not calculated value', () => {
1618
+ aggregatorObject.widget_values_format = '\"$\"#,###.###';
1619
+ expect(aggregatorObject.format(1123.4567, false)).toBe('$1,123.457');
1620
+ });
1621
+
1622
+ it('Should return calculated value format if it\'s calculated value', () => {
1623
+ aggregator = highchartsRenderer.rhPivotCount(arg, widget_values_format, is_graph, render_options, calculated_info);
1624
+ aggregatorObject = aggregator({}, ['Region average'], '');
1625
+ expect(aggregatorObject.format(1123.45678, false)).toBe('112345.68%');
1626
+ });
1627
+ });
1628
+ });
1629
+
1630
+ describe('Uniq values aggregator', () => {
1631
+ let arg;
1632
+ let widget_values_format;
1633
+ let is_graph;
1634
+ let render_options;
1635
+ let calculated_info;
1636
+ let aggregator;
1637
+ let aggregatorObject;
1638
+
1639
+ beforeEach(() => {
1640
+ arg = ['Country'];
1641
+ widget_values_format = '"$"####.##';
1642
+ is_graph = true;
1643
+ render_options = {};
1644
+ calculated_info = {
1645
+ "formats": {
1646
+ "Average category": null,
1647
+ "Region average": "####.##%"
1648
+ },
1649
+ "associated_fields": {
1650
+ "Category": [
1651
+ "Average category"
1652
+ ],
1653
+ "Region": [
1654
+ "Region average"
1655
+ ]
1656
+ }
1657
+ };
1658
+
1659
+ aggregator = highchartsRenderer.rhPivotAggregatorUniqValues(arg, widget_values_format, is_graph, render_options, calculated_info);
1660
+ aggregatorObject = aggregator({}, '', '');
1661
+ });
1662
+
1663
+ it('Aggregation object structure', () => {
1664
+ expect(aggregatorObject.uniq).toEqual([]);
1665
+ expect(aggregatorObject.ignoreValue).toBe(false);
1666
+ expect(aggregatorObject.formated_values).toEqual([]);
1667
+ expect(aggregatorObject.widget_values_format).toBe(widget_values_format);
1668
+ expect(aggregatorObject.calculated_formats).toBe(calculated_info.formats);
1669
+ expect(aggregatorObject.numInputs).toBe(0);
1670
+ expect(typeof aggregatorObject.push).toBe('function');
1671
+ expect(typeof aggregatorObject.value).toBe('function');
1672
+ expect(typeof aggregatorObject.format).toBe('function');
1673
+ });
1674
+
1675
+ it('numInputs should be 1 if there are no argument', () => {
1676
+ const agg = highchartsRenderer.rhPivotAggregatorUniqValues([null], widget_values_format, is_graph, render_options, calculated_info);
1677
+ const aggObject = agg({}, '', '');
1678
+ expect(aggObject.numInputs).toBe(1);
1679
+ });
1680
+
1681
+ describe('Push method', () => {
1682
+ beforeEach(() => {
1683
+ aggregator = highchartsRenderer.rhPivotAggregatorUniqValues(arg, widget_values_format, is_graph, render_options, calculated_info);
1684
+ aggregatorObject = aggregator({}, '', '');
1685
+ });
1686
+
1687
+ it('Sum should be empty if value is not array', () => {
1688
+ expect(aggregatorObject.push({Country: ''})).toBe(0);
1689
+ });
1690
+
1691
+ it('Uniq values from different records without formats', () => {
1692
+ aggregatorObject.push({Country: ['Poland', 'USA']});
1693
+ aggregatorObject.push({Country: ['USA', 'UK']});
1694
+ expect(aggregatorObject.formated_values).toEqual(['Poland', 'USA', 'UK']);
1695
+ });
1696
+
1697
+ it('Value format must applied to value if values_formats match in record', () => {
1698
+ aggregatorObject.push({
1699
+ Country: [123.123, 456.456, 789.789],
1700
+ values_formats: [{value: 123.123, data_type: 'n', format: '\'$\'####.##'}]
1701
+ });
1702
+ expect(aggregatorObject.formated_values).toEqual(['$123.12', 456.456, 789.789]);
1703
+ });
1704
+
1705
+ // it('Value should be a sum of records when server calculation disabled', () => {
1706
+ // highchartsRenderer.useTotalsCalculation = false;
1707
+ // aggregatorObject.push({Profit: 10});
1708
+ // aggregatorObject.push({Profit: 20});
1709
+ // expect(aggregatorObject.sum).toEqual(30);
1710
+ // });
1711
+
1712
+ it('Value must be ignored if calculated totals disabled', () => {
1713
+ const options = {
1714
+ chartOptions: {
1715
+ table_options: {
1716
+ eliminate_calc_totals: true
1717
+ }
1718
+ }
1719
+ }
1720
+ aggregator = highchartsRenderer.rhPivotAggregatorUniqValues(arg, widget_values_format, false, options, calculated_info);
1721
+ aggregatorObject = aggregator({colAttrs: [], rowAttrs: []}, ['Region average'], '');
1722
+ aggregatorObject.push({Profit: 20, 'Region average': 'Central', Region: 'Region average'});
1723
+ expect(aggregatorObject.ignoreValue).toBe(true);
1724
+ });
1725
+ });
1726
+
1727
+ describe('Value method', () => {
1728
+ beforeEach(() => {
1729
+ aggregator = highchartsRenderer.rhPivotAggregatorUniqValues(arg, widget_values_format, is_graph, render_options, calculated_info);
1730
+ aggregatorObject = aggregator({}, '', '');
1731
+ });
1732
+
1733
+ it('Should return null if ignore', () => {
1734
+ aggregatorObject.ignoreValue = true;
1735
+ expect(aggregatorObject.value()).toBe(null);
1736
+ });
1737
+
1738
+ it('Should return length if graph', () => {
1739
+ aggregatorObject.uniq = ['val1', 'val2'];
1740
+ expect(aggregatorObject.value()).toBe(2);
1741
+ });
1742
+
1743
+ it('Should return value if table', () => {
1744
+ aggregator = highchartsRenderer.rhPivotAggregatorUniqValues(arg, widget_values_format, false, render_options, calculated_info);
1745
+ aggregatorObject = aggregator({}, '', '');
1746
+ aggregatorObject.uniq = ['val1', 'val2'];
1747
+ expect(aggregatorObject.value()).toBe('val1<br>val2');
1748
+ });
1749
+ });
1750
+
1751
+ describe('Format method', () => {
1752
+ beforeEach(() => {
1753
+ aggregator = highchartsRenderer.rhPivotAggregatorUniqValues(arg, widget_values_format, is_graph, render_options, calculated_info);
1754
+ aggregatorObject = aggregator({}, '', '');
1755
+ });
1756
+
1757
+ it('Should return empty string if null or undefined', () => {
1758
+ expect(aggregatorObject.format(null, false)).toBe('');
1759
+ expect(aggregatorObject.format(undefined, false)).toBe('');
1760
+ });
1761
+
1762
+ it('Should return widget format if it\'s graph', () => {
1763
+ aggregatorObject.widget_values_format = '\"$\"#,###.###';
1764
+ expect(aggregatorObject.format(2, false)).toBe('$2.0');
1765
+ });
1766
+
1767
+ it('Should return widget format if it\'s only_formats', () => {
1768
+ aggregator = highchartsRenderer.rhPivotAggregatorUniqValues(arg, widget_values_format, false, render_options, calculated_info);
1769
+ aggregatorObject = aggregator({}, '', '');
1770
+ aggregatorObject.widget_values_format = '\"$\"#,###.###';
1771
+ expect(aggregatorObject.format(2, true)).toBe('$2.0');
1772
+ });
1773
+
1774
+ it('Should return uniq values if it\'s table and not only_formats', () => {
1775
+ aggregator = highchartsRenderer.rhPivotAggregatorUniqValues(arg, widget_values_format, false, render_options, calculated_info);
1776
+ aggregatorObject = aggregator({}, '', '');
1777
+ aggregatorObject.formated_values = ['val1', 'val2'];
1778
+ expect(aggregatorObject.format(aggregatorObject.formated_values, false)).toBe('val1<br>val2');
1779
+ });
1780
+ });
1781
+ });
1782
+
1783
+ describe('Average aggregator', () => {
1784
+ let arg;
1785
+ let widget_values_format;
1786
+ let is_graph;
1787
+ let render_options;
1788
+ let calculated_info;
1789
+ let aggregator;
1790
+ let aggregatorObject;
1791
+
1792
+ beforeEach(() => {
1793
+ arg = ['Profit'];
1794
+ widget_values_format = '"$"####.##';
1795
+ is_graph = true;
1796
+ render_options = {};
1797
+ calculated_info = {
1798
+ "formats": {
1799
+ "Average category": null,
1800
+ "Region average": "####.##%"
1801
+ },
1802
+ "associated_fields": {
1803
+ "Category": [
1804
+ "Average category"
1805
+ ],
1806
+ "Region": [
1807
+ "Region average"
1808
+ ]
1809
+ }
1810
+ };
1811
+
1812
+ aggregator = highchartsRenderer.rhPivotAggregatorAverage(arg, widget_values_format, is_graph, render_options, calculated_info);
1813
+ aggregatorObject = aggregator({}, '', '');
1814
+ });
1815
+
1816
+ it('Aggregation object structure', () => {
1817
+ expect(aggregatorObject.sum).toBe(0);
1818
+ expect(aggregatorObject.len).toBe(0);
1819
+ expect(aggregatorObject.ignoreValue).toBe(false);
1820
+ expect(aggregatorObject.data_types).toEqual([]);
1821
+ expect(aggregatorObject.formats).toEqual([]);
1822
+ expect(aggregatorObject.has_errors).toBe(false);
1823
+ expect(aggregatorObject.widget_values_format).toBe(widget_values_format);
1824
+ expect(aggregatorObject.calculated_formats).toBe(calculated_info.formats);
1825
+ expect(aggregatorObject.isChangeable).toBe(false);
1826
+ expect(aggregatorObject.numInputs).toBe(0);
1827
+ expect(typeof aggregatorObject.push).toBe('function');
1828
+ expect(typeof aggregatorObject.value).toBe('function');
1829
+ expect(typeof aggregatorObject.format).toBe('function');
1830
+ });
1831
+
1832
+ it('numInputs should be 1 if there are no argument', () => {
1833
+ const agg = highchartsRenderer.rhPivotAggregatorAverage([null], widget_values_format, is_graph, render_options, calculated_info);
1834
+ const aggObject = agg({}, '', '');
1835
+ expect(aggObject.numInputs).toBe(1);
1836
+ });
1837
+
1838
+ describe('Push method', () => {
1839
+ beforeEach(() => {
1840
+ aggregator = highchartsRenderer.rhPivotAggregatorAverage(arg, widget_values_format, is_graph, render_options, calculated_info);
1841
+ aggregatorObject = aggregator({}, '', '');
1842
+ });
1843
+
1844
+ it('Should be error if wrong data_types', () => {
1845
+ aggregatorObject.push({
1846
+ data_types: ['d', '1']
1847
+ });
1848
+ expect(aggregatorObject.has_errors).toBe(true);
1849
+ });
1850
+
1851
+ it('Sum shouldn\'t be changed if value is string', () => {
1852
+ aggregatorObject.push({Profit: 'incorrectValue'});
1853
+ expect(aggregatorObject.sum).toBe(0);
1854
+ });
1855
+
1856
+ it('Data types must be filled and uniq', () => {
1857
+ aggregatorObject.push({Profit: 123, data_types: ['1', '1', '2']});
1858
+ expect(aggregatorObject.data_types).toEqual(['1', '2']);
1859
+ });
1860
+
1861
+ it('Formats must be filled and uniq', () => {
1862
+ aggregatorObject.push({Profit: 123, formats: ['####', '####', '#,###']});
1863
+ expect(aggregatorObject.formats).toEqual(['####', '#,###']);
1864
+ });
1865
+
1866
+ it('Value should be a sum of records when server calculation disabled', () => {
1867
+ highchartsRenderer.useTotalsCalculation = false;
1868
+ aggregatorObject.push({Profit: 10});
1869
+ aggregatorObject.push({Profit: 20});
1870
+ expect(aggregatorObject.sum).toEqual(30);
1871
+ expect(aggregatorObject.len).toEqual(2);
1872
+ });
1873
+
1874
+ it('Value should be a last record value when server calculation enabled', () => {
1875
+ highchartsRenderer.useTotalsCalculation = true;
1876
+ aggregatorObject.push({Profit: 20});
1877
+ aggregatorObject.push({Profit: 10});
1878
+ expect(aggregatorObject.sum).toEqual(10);
1879
+ expect(aggregatorObject.len).toEqual(2);
1880
+ });
1881
+
1882
+ it('Widget values format must be redefined if row key should be percentage', () => {
1883
+ const options = {
1884
+ comboOptions: {
1885
+ secondaryAxisSettings: {
1886
+ is_percentage: true
1887
+ },
1888
+ seriesOptions: [{series: 'Region', secondaryAxis: true}]
1889
+ }
1890
+ }
1891
+ aggregator = highchartsRenderer.rhPivotAggregatorAverage(arg, widget_values_format, is_graph, options, calculated_info);
1892
+ aggregatorObject = aggregator({}, ['Region'], '');
1893
+ aggregatorObject.push({Profit: 20, Region: 'Central'});
1894
+ expect(aggregatorObject.widget_values_format).toEqual('#,###%');
1895
+ });
1896
+
1897
+ it('Value must be ignored if calculated totals disabled', () => {
1898
+ const options = {
1899
+ chartOptions: {
1900
+ table_options: {
1901
+ eliminate_calc_totals: true
1902
+ }
1903
+ }
1904
+ }
1905
+ aggregator = highchartsRenderer.rhPivotAggregatorAverage(arg, widget_values_format, false, options, calculated_info);
1906
+ aggregatorObject = aggregator({colAttrs: [], rowAttrs: []}, ['Region average'], '');
1907
+ aggregatorObject.push({Profit: 20, 'Region average': 'Central', Region: 'Region average'});
1908
+ expect(aggregatorObject.ignoreValue).toBe(true);
1909
+ });
1910
+ });
1911
+
1912
+ describe('Value method', () => {
1913
+ beforeEach(() => {
1914
+ aggregator = highchartsRenderer.rhPivotAggregatorAverage(arg, widget_values_format, is_graph, render_options, calculated_info);
1915
+ aggregatorObject = aggregator({}, '', '');
1916
+ aggregatorObject.sum = 20;
1917
+ aggregatorObject.len = 4;
1918
+ });
1919
+
1920
+ it('Should return null if ignore', () => {
1921
+ aggregatorObject.ignoreValue = true;
1922
+ expect(aggregatorObject.value()).toBe(null);
1923
+ });
1924
+
1925
+ it('Should return sum if server calculation enabled', () => {
1926
+ highchartsRenderer.useTotalsCalculation = true;
1927
+ aggregatorObject.ignoreValue = false;
1928
+ expect(aggregatorObject.value()).toBe(20);
1929
+ });
1930
+
1931
+ it('Should return average if server calculation disabled', () => {
1932
+ highchartsRenderer.useTotalsCalculation = false;
1933
+ aggregatorObject.ignoreValue = false;
1934
+ expect(aggregatorObject.value()).toBe(5);
1935
+ });
1936
+ });
1937
+
1938
+ describe('Format method', () => {
1939
+ beforeEach(() => {
1940
+ aggregator = highchartsRenderer.rhPivotAggregatorAverage(arg, widget_values_format, is_graph, render_options, calculated_info);
1941
+ aggregatorObject = aggregator({}, '', '');
1942
+ });
1943
+
1944
+ it('Should return empty string if null or undefined', () => {
1945
+ expect(aggregatorObject.format(null, false)).toBe('');
1946
+ expect(aggregatorObject.format(undefined, false)).toBe('');
1947
+ });
1948
+
1949
+ it('Should return ERROR if has_errors and not only formats', () => {
1950
+ aggregatorObject.has_errors = true;
1951
+ expect(aggregatorObject.format(123, false)).toBe('####ERROR####');
1952
+ });
1953
+
1954
+ it('Should return General format if there are no widget_values_format', () => {
1955
+ aggregatorObject.widget_values_format = null;
1956
+ expect(aggregatorObject.format(123.4567, false)).toBe('123.46');
1957
+ });
1958
+
1959
+ it('Should return widget format if it\'s not calculated value', () => {
1960
+ aggregatorObject.widget_values_format = '\"$\"#,###.###';
1961
+ expect(aggregatorObject.format(1123.4567, false)).toBe('$1,123.457');
1962
+ });
1963
+
1964
+ it('Should return calculated value format if it\'s calculated value', () => {
1965
+ aggregator = highchartsRenderer.rhPivotAggregatorAverage(arg, widget_values_format, is_graph, render_options, calculated_info);
1966
+ aggregatorObject = aggregator({}, ['Region average'], '');
1967
+ expect(aggregatorObject.format(1123.45678, false)).toBe('112345.68%');
1968
+ });
1969
+ });
1970
+ });
1971
+
1972
+ describe('Min aggregator', () => {
1973
+ let arg;
1974
+ let widget_values_format;
1975
+ let is_graph;
1976
+ let render_options;
1977
+ let calculated_info;
1978
+ let aggregator;
1979
+ let aggregatorObject;
1980
+
1981
+ beforeEach(() => {
1982
+ arg = ['Profit'];
1983
+ widget_values_format = '"$"####.##';
1984
+ is_graph = true;
1985
+ render_options = {};
1986
+ calculated_info = {
1987
+ "formats": {
1988
+ "Average category": null,
1989
+ "Region average": "####.##%"
1990
+ },
1991
+ "associated_fields": {
1992
+ "Category": [
1993
+ "Average category"
1994
+ ],
1995
+ "Region": [
1996
+ "Region average"
1997
+ ]
1998
+ }
1999
+ };
2000
+
2001
+ aggregator = highchartsRenderer.rhPivotAggregatorMin(arg, widget_values_format, is_graph, render_options, calculated_info);
2002
+ aggregatorObject = aggregator({}, '', '');
2003
+ });
2004
+
2005
+ it('Aggregation object structure', () => {
2006
+ expect(aggregatorObject.val).toBe(null);
2007
+ expect(aggregatorObject.ignoreValue).toBe(false);
2008
+ expect(aggregatorObject.data_types).toEqual([]);
2009
+ expect(aggregatorObject.formats).toEqual([]);
2010
+ expect(aggregatorObject.has_errors).toBe(false);
2011
+ expect(aggregatorObject.widget_values_format).toBe(widget_values_format);
2012
+ expect(aggregatorObject.calculated_formats).toBe(calculated_info.formats);
2013
+ expect(aggregatorObject.isChangeable).toBe(false);
2014
+ expect(aggregatorObject.numInputs).toBe(0);
2015
+ expect(typeof aggregatorObject.push).toBe('function');
2016
+ expect(typeof aggregatorObject.value).toBe('function');
2017
+ expect(typeof aggregatorObject.format).toBe('function');
2018
+ });
2019
+
2020
+ it('numInputs should be 1 if there are no argument', () => {
2021
+ const agg = highchartsRenderer.rhPivotAggregatorMin([null], widget_values_format, is_graph, render_options, calculated_info);
2022
+ const aggObject = agg({}, '', '');
2023
+ expect(aggObject.numInputs).toBe(1);
2024
+ });
2025
+
2026
+ describe('Push method', () => {
2027
+ beforeEach(() => {
2028
+ aggregator = highchartsRenderer.rhPivotAggregatorMin(arg, widget_values_format, is_graph, render_options, calculated_info);
2029
+ aggregatorObject = aggregator({}, '', '');
2030
+ });
2031
+
2032
+ it('Should be error if wrong data_types', () => {
2033
+ aggregatorObject.push({
2034
+ data_types: ['d', '1']
2035
+ });
2036
+ expect(aggregatorObject.has_errors).toBe(true);
2037
+ });
2038
+
2039
+ it('Sum shouldn\'t be changed if value is string', () => {
2040
+ aggregatorObject.push({Profit: 'incorrectValue'});
2041
+ expect(aggregatorObject.val).toBe(null);
2042
+ });
2043
+
2044
+ it('Data types must be filled and uniq', () => {
2045
+ aggregatorObject.push({Profit: 123, data_types: ['1', '1', '2']});
2046
+ expect(aggregatorObject.data_types).toEqual(['1', '2']);
2047
+ });
2048
+
2049
+ it('Formats must be filled and uniq', () => {
2050
+ aggregatorObject.push({Profit: 123, formats: ['####', '####', '#,###']});
2051
+ expect(aggregatorObject.formats).toEqual(['####', '#,###']);
2052
+ });
2053
+
2054
+ it('Value should be a min of records when server calculation disabled', () => {
2055
+ highchartsRenderer.useTotalsCalculation = false;
2056
+ aggregatorObject.push({Profit: 10});
2057
+ aggregatorObject.push({Profit: 20});
2058
+ expect(aggregatorObject.val).toEqual(10);
2059
+ });
2060
+
2061
+ it('Value should be a last record value when server calculation enabled', () => {
2062
+ highchartsRenderer.useTotalsCalculation = true;
2063
+ aggregatorObject.push({Profit: 10});
2064
+ aggregatorObject.push({Profit: 20});
2065
+ expect(aggregatorObject.val).toEqual(20);
2066
+ });
2067
+
2068
+ it('Widget values format must be redefined if row key should be percentage', () => {
2069
+ const options = {
2070
+ comboOptions: {
2071
+ secondaryAxisSettings: {
2072
+ is_percentage: true
2073
+ },
2074
+ seriesOptions: [{series: 'Region', secondaryAxis: true}]
2075
+ }
2076
+ }
2077
+ aggregator = highchartsRenderer.rhPivotAggregatorMin(arg, widget_values_format, is_graph, options, calculated_info);
2078
+ aggregatorObject = aggregator({}, ['Region'], '');
2079
+ aggregatorObject.push({Profit: 20, Region: 'Central'});
2080
+ expect(aggregatorObject.widget_values_format).toEqual('#,###%');
2081
+ });
2082
+
2083
+ it('Value must be ignored if calculated totals disabled', () => {
2084
+ const options = {
2085
+ chartOptions: {
2086
+ table_options: {
2087
+ eliminate_calc_totals: true
2088
+ }
2089
+ }
2090
+ }
2091
+ aggregator = highchartsRenderer.rhPivotAggregatorMin(arg, widget_values_format, false, options, calculated_info);
2092
+ aggregatorObject = aggregator({colAttrs: [], rowAttrs: []}, ['Region average'], '');
2093
+ aggregatorObject.push({Profit: 20, 'Region average': 'Central', Region: 'Region average'});
2094
+ expect(aggregatorObject.ignoreValue).toBe(true);
2095
+ });
2096
+ });
2097
+
2098
+ describe('Value method', () => {
2099
+ beforeEach(() => {
2100
+ aggregator = highchartsRenderer.rhPivotAggregatorMin(arg, widget_values_format, is_graph, render_options, calculated_info);
2101
+ aggregatorObject = aggregator({}, '', '');
2102
+ });
2103
+
2104
+ it('Should return null if ignore', () => {
2105
+ aggregatorObject.ignoreValue = true;
2106
+ expect(aggregatorObject.value()).toBe(null);
2107
+ });
2108
+
2109
+ it('Should return value', () => {
2110
+ aggregatorObject.ignoreValue = false;
2111
+ aggregatorObject.val = 10;
2112
+ expect(aggregatorObject.value()).toBe(10);
2113
+ });
2114
+ });
2115
+
2116
+ describe('Format method', () => {
2117
+ beforeEach(() => {
2118
+ aggregator = highchartsRenderer.rhPivotAggregatorMin(arg, widget_values_format, is_graph, render_options, calculated_info);
2119
+ aggregatorObject = aggregator({}, '', '');
2120
+ });
2121
+
2122
+ it('Should return empty string if null or undefined', () => {
2123
+ expect(aggregatorObject.format(null, false)).toBe('');
2124
+ expect(aggregatorObject.format(undefined, false)).toBe('');
2125
+ });
2126
+
2127
+ it('Should return ERROR if has_errors and not only formats', () => {
2128
+ aggregatorObject.has_errors = true;
2129
+ expect(aggregatorObject.format(123, false)).toBe('####ERROR####');
2130
+ });
2131
+
2132
+ it('Should return General format if there are no widget_values_format', () => {
2133
+ aggregatorObject.widget_values_format = null;
2134
+ expect(aggregatorObject.format(123.4567, false)).toBe('123.46');
2135
+ });
2136
+
2137
+ it('Should return widget format if it\'s not calculated value', () => {
2138
+ aggregatorObject.widget_values_format = '\"$\"#,###.###';
2139
+ expect(aggregatorObject.format(1123.4567, false)).toBe('$1,123.457');
2140
+ });
2141
+
2142
+ it('Should return calculated value format if it\'s calculated value', () => {
2143
+ aggregator = highchartsRenderer.rhPivotAggregatorMin(arg, widget_values_format, is_graph, render_options, calculated_info);
2144
+ aggregatorObject = aggregator({}, ['Region average'], '');
2145
+ expect(aggregatorObject.format(1123.45678, false)).toBe('112345.68%');
2146
+ });
2147
+ });
2148
+ });
2149
+
2150
+ describe('Max aggregator', () => {
2151
+ let arg;
2152
+ let widget_values_format;
2153
+ let is_graph;
2154
+ let render_options;
2155
+ let calculated_info;
2156
+ let aggregator;
2157
+ let aggregatorObject;
2158
+
2159
+ beforeEach(() => {
2160
+ arg = ['Profit'];
2161
+ widget_values_format = '"$"####.##';
2162
+ is_graph = true;
2163
+ render_options = {};
2164
+ calculated_info = {
2165
+ "formats": {
2166
+ "Average category": null,
2167
+ "Region average": "####.##%"
2168
+ },
2169
+ "associated_fields": {
2170
+ "Category": [
2171
+ "Average category"
2172
+ ],
2173
+ "Region": [
2174
+ "Region average"
2175
+ ]
2176
+ }
2177
+ };
2178
+
2179
+ aggregator = highchartsRenderer.rhPivotAggregatorMax(arg, widget_values_format, is_graph, render_options, calculated_info);
2180
+ aggregatorObject = aggregator({}, '', '');
2181
+ });
2182
+
2183
+ it('Aggregation object structure', () => {
2184
+ expect(aggregatorObject.val).toBe(null);
2185
+ expect(aggregatorObject.ignoreValue).toBe(false);
2186
+ expect(aggregatorObject.data_types).toEqual([]);
2187
+ expect(aggregatorObject.formats).toEqual([]);
2188
+ expect(aggregatorObject.has_errors).toBe(false);
2189
+ expect(aggregatorObject.widget_values_format).toBe(widget_values_format);
2190
+ expect(aggregatorObject.calculated_formats).toBe(calculated_info.formats);
2191
+ expect(aggregatorObject.isChangeable).toBe(false);
2192
+ expect(aggregatorObject.numInputs).toBe(0);
2193
+ expect(typeof aggregatorObject.push).toBe('function');
2194
+ expect(typeof aggregatorObject.value).toBe('function');
2195
+ expect(typeof aggregatorObject.format).toBe('function');
2196
+ });
2197
+
2198
+ it('numInputs should be 1 if there are no argument', () => {
2199
+ const agg = highchartsRenderer.rhPivotAggregatorMax([null], widget_values_format, is_graph, render_options, calculated_info);
2200
+ const aggObject = agg({}, '', '');
2201
+ expect(aggObject.numInputs).toBe(1);
2202
+ });
2203
+
2204
+ describe('Push method', () => {
2205
+ beforeEach(() => {
2206
+ aggregator = highchartsRenderer.rhPivotAggregatorMax(arg, widget_values_format, is_graph, render_options, calculated_info);
2207
+ aggregatorObject = aggregator({}, '', '');
2208
+ });
2209
+
2210
+ it('Should be error if wrong data_types', () => {
2211
+ aggregatorObject.push({
2212
+ data_types: ['d', '1']
2213
+ });
2214
+ expect(aggregatorObject.has_errors).toBe(true);
2215
+ });
2216
+
2217
+ it('Sum shouldn\'t be changed if value is string', () => {
2218
+ aggregatorObject.push({Profit: 'incorrectValue'});
2219
+ expect(aggregatorObject.val).toBe(null);
2220
+ });
2221
+
2222
+ it('Data types must be filled and uniq', () => {
2223
+ aggregatorObject.push({Profit: 123, data_types: ['1', '1', '2']});
2224
+ expect(aggregatorObject.data_types).toEqual(['1', '2']);
2225
+ });
2226
+
2227
+ it('Formats must be filled and uniq', () => {
2228
+ aggregatorObject.push({Profit: 123, formats: ['####', '####', '#,###']});
2229
+ expect(aggregatorObject.formats).toEqual(['####', '#,###']);
2230
+ });
2231
+
2232
+ it('Value should be a min of records when server calculation disabled', () => {
2233
+ highchartsRenderer.useTotalsCalculation = false;
2234
+ aggregatorObject.push({Profit: 20});
2235
+ aggregatorObject.push({Profit: 10});
2236
+ expect(aggregatorObject.val).toEqual(20);
2237
+ });
2238
+
2239
+ it('Value should be a last record value when server calculation enabled', () => {
2240
+ highchartsRenderer.useTotalsCalculation = true;
2241
+ aggregatorObject.push({Profit: 20});
2242
+ aggregatorObject.push({Profit: 10});
2243
+ expect(aggregatorObject.val).toEqual(10);
2244
+ });
2245
+
2246
+ it('Widget values format must be redefined if row key should be percentage', () => {
2247
+ const options = {
2248
+ comboOptions: {
2249
+ secondaryAxisSettings: {
2250
+ is_percentage: true
2251
+ },
2252
+ seriesOptions: [{series: 'Region', secondaryAxis: true}]
2253
+ }
2254
+ }
2255
+ aggregator = highchartsRenderer.rhPivotAggregatorMax(arg, widget_values_format, is_graph, options, calculated_info);
2256
+ aggregatorObject = aggregator({}, ['Region'], '');
2257
+ aggregatorObject.push({Profit: 20, Region: 'Central'});
2258
+ expect(aggregatorObject.widget_values_format).toEqual('#,###%');
2259
+ });
2260
+
2261
+ it('Value must be ignored if calculated totals disabled', () => {
2262
+ const options = {
2263
+ chartOptions: {
2264
+ table_options: {
2265
+ eliminate_calc_totals: true
2266
+ }
2267
+ }
2268
+ }
2269
+ aggregator = highchartsRenderer.rhPivotAggregatorMax(arg, widget_values_format, false, options, calculated_info);
2270
+ aggregatorObject = aggregator({colAttrs: [], rowAttrs: []}, ['Region average'], '');
2271
+ aggregatorObject.push({Profit: 20, 'Region average': 'Central', Region: 'Region average'});
2272
+ expect(aggregatorObject.ignoreValue).toBe(true);
2273
+ });
2274
+ });
2275
+
2276
+ describe('Value method', () => {
2277
+ beforeEach(() => {
2278
+ aggregator = highchartsRenderer.rhPivotAggregatorMax(arg, widget_values_format, is_graph, render_options, calculated_info);
2279
+ aggregatorObject = aggregator({}, '', '');
2280
+ });
2281
+
2282
+ it('Should return null if ignore', () => {
2283
+ aggregatorObject.ignoreValue = true;
2284
+ expect(aggregatorObject.value()).toBe(null);
2285
+ });
2286
+
2287
+ it('Should return value', () => {
2288
+ aggregatorObject.ignoreValue = false;
2289
+ aggregatorObject.val = 10;
2290
+ expect(aggregatorObject.value()).toBe(10);
2291
+ });
2292
+ });
2293
+
2294
+ describe('Format method', () => {
2295
+ beforeEach(() => {
2296
+ aggregator = highchartsRenderer.rhPivotAggregatorMax(arg, widget_values_format, is_graph, render_options, calculated_info);
2297
+ aggregatorObject = aggregator({}, '', '');
2298
+ });
2299
+
2300
+ it('Should return empty string if null or undefined', () => {
2301
+ expect(aggregatorObject.format(null, false)).toBe('');
2302
+ expect(aggregatorObject.format(undefined, false)).toBe('');
2303
+ });
2304
+
2305
+ it('Should return ERROR if has_errors and not only formats', () => {
2306
+ aggregatorObject.has_errors = true;
2307
+ expect(aggregatorObject.format(123, false)).toBe('####ERROR####');
2308
+ });
2309
+
2310
+ it('Should return General format if there are no widget_values_format', () => {
2311
+ aggregatorObject.widget_values_format = null;
2312
+ expect(aggregatorObject.format(123.4567, false)).toBe('123.46');
2313
+ });
2314
+
2315
+ it('Should return widget format if it\'s not calculated value', () => {
2316
+ aggregatorObject.widget_values_format = '\"$\"#,###.###';
2317
+ expect(aggregatorObject.format(1123.4567, false)).toBe('$1,123.457');
2318
+ });
2319
+
2320
+ it('Should return calculated value format if it\'s calculated value', () => {
2321
+ aggregator = highchartsRenderer.rhPivotAggregatorMax(arg, widget_values_format, is_graph, render_options, calculated_info);
2322
+ aggregatorObject = aggregator({}, ['Region average'], '');
2323
+ expect(aggregatorObject.format(1123.45678, false)).toBe('112345.68%');
2324
+ });
2325
+ });
2326
+ });
2327
+ });
2328
+ });
2329
+
2330
+
2331
+ describe('function getChartAxisLabel', () => {
2332
+ it('should return default value', () => {
2333
+ expect(highchartsRenderer.getChartAxisLabel('invalidType')).toBe('Axis (Category)')
2334
+ });
2335
+
2336
+ it('should return chart type axisName', () => {
2337
+ expect(highchartsRenderer.getChartAxisLabel(highchartsRenderer.CHART_TYPES.COLUMN_CHART)).toBe('X - Axis')
2338
+ });
2339
+ });
2340
+
2341
+ describe('function getChartLegendLabel', () => {
2342
+ it('should return default value', () => {
2343
+ expect(highchartsRenderer.getChartLegendLabel('invalidType')).toBe('Legend (Series)')
2344
+ });
2345
+
2346
+ it('should return chart type legendName ', () => {
2347
+ expect(highchartsRenderer.getChartLegendLabel(highchartsRenderer.CHART_TYPES.COLUMN_CHART)).toBe('Data series')
2348
+ });
2349
+ });
2350
+
2351
+ describe('Function getFilterLabel', () => {
2352
+ describe('Should present template name', () => {
2353
+ let fieldFilter;
2354
+ let showTemplateName;
2355
+
2356
+ beforeEach(() => {
2357
+ fieldFilter = {
2358
+ name: 'RH_DIM_test',
2359
+ datetypevalues: { datetype: 'range' }
2360
+ };
2361
+ showTemplateName = false;
2362
+ });
2363
+
2364
+ it('should return fieldFilter.new_name without "RH_DIM_" if it exists', () => {
2365
+ fieldFilter.new_name = 'RH_DIM_test_new_name';
2366
+ const result = highchartsRenderer.getFilterLabel(fieldFilter, showTemplateName);
2367
+ expect(result).toEqual({
2368
+ label: 'test_new_name (All)',
2369
+ tooltip: 'test_new_name (All)'
2370
+ });
2371
+ });
2372
+
2373
+ it('should return highchartsRenderer.getFieldName(fieldFilter.name) without "RH_DIM_" if fieldFilter.new_name is falsy', () => {
2374
+ spyOn(highchartsRenderer, 'getFieldName').and.returnValue('RH_DIM_test_fieldName');
2375
+ const result = highchartsRenderer.getFilterLabel(fieldFilter, showTemplateName);
2376
+ expect(highchartsRenderer.getFieldName).toHaveBeenCalledWith('RH_DIM_test');
2377
+ expect(result).toEqual({
2378
+ label: 'test_fieldName (All)',
2379
+ tooltip: 'test_fieldName (All)'
2380
+ });
2381
+ });
2382
+
2383
+ it('should append template_name to displayname if showTemplateName is true and fieldFilter.template_name is truthy', () => {
2384
+ fieldFilter.new_name = null;
2385
+ fieldFilter.template_name = 'templateName';
2386
+ showTemplateName = true;
2387
+ const result = highchartsRenderer.getFilterLabel(fieldFilter, showTemplateName);
2388
+ expect(result).toEqual({
2389
+ label: 'templateName - test (range)',
2390
+ tooltip: 'templateName - test (range)'
2391
+ });
2392
+ });
2393
+
2394
+ it('should append template_name to displayname if showTemplateName is true and fieldFilter.template_name is truthy', () => {
2395
+ fieldFilter.new_name = null;
2396
+ fieldFilter.template_name = 'templateName';
2397
+ showTemplateName = true;
2398
+ const result = highchartsRenderer.getFilterLabel(fieldFilter, showTemplateName);
2399
+ expect(result).toEqual({
2400
+ label: 'templateName - test (range)',
2401
+ tooltip: 'templateName - test (range)'
2402
+ });
2403
+ });
2404
+
2405
+ it('should return label and tooltip with datetypevalues.datetype if datetypevalues is truthy and datetype is "range" or "frame"', () => {
2406
+ fieldFilter.new_name = null;
2407
+ fieldFilter.template_name = 'templateName';
2408
+ fieldFilter.datetypevalues.datetype = 'frame';
2409
+ const result = highchartsRenderer.getFilterLabel(fieldFilter, showTemplateName);
2410
+ expect(result).toEqual({
2411
+ label: 'test (frame)',
2412
+ tooltip: 'test (frame)'
2413
+ });
2414
+ });
2415
+ });
2416
+
2417
+ describe('Should present includes/excludes names', () => {
2418
+ let fieldFilter;
2419
+
2420
+ beforeEach(() => {
2421
+ fieldFilter = {
2422
+ name: 'test',
2423
+ includes: null,
2424
+ excludes: null,
2425
+ type: 'Text',
2426
+ };
2427
+ });
2428
+
2429
+ it('Should return "none" label when excludes empty', () => {
2430
+ fieldFilter.includes = [];
2431
+ const res = highchartsRenderer.getFilterLabel(fieldFilter, false);
2432
+ expect(res.label).toEqual('test (none)');
2433
+ expect(res.tooltip).toEqual('test (none)');
2434
+ });
2435
+
2436
+ it('Should return "All" label when excludes empty', () => {
2437
+ fieldFilter.excludes = [];
2438
+ const res = highchartsRenderer.getFilterLabel(fieldFilter, false);
2439
+ expect(res.label).toEqual('test (All)');
2440
+ expect(res.tooltip).toEqual('test (All)');
2441
+ });
2442
+
2443
+ it('Should return "many" label when includes/excludes has more than MAX_SELECTED_ITEMS_IN_LABEL items', () => {
2444
+ fieldFilter.includes = new Array(highchartsRenderer.MAX_SELECTED_ITEMS_IN_LABEL).fill('val');
2445
+ let res = highchartsRenderer.getFilterLabel(fieldFilter, false);
2446
+ expect(res.label).toEqual('test (many)');
2447
+ expect(res.tooltip).toEqual('test (' + fieldFilter.includes.join(', ') + ')');
2448
+
2449
+ fieldFilter.excludes = fieldFilter.includes;
2450
+ delete fieldFilter.includes;
2451
+ res = highchartsRenderer.getFilterLabel(fieldFilter, false);
2452
+ expect(res.label).toEqual('test (Exclusions many)');
2453
+ expect(res.tooltip).toEqual('test (Exclusions: ' + fieldFilter.excludes.join(', ') + ')');
2454
+ });
2455
+
2456
+ it('Should return "many" in label when includes has label length more than MAX_SELECTED_ITEMS_CHARECHTERS_IN_LABEL', () => {
2457
+ fieldFilter.includes = ['[null]', 'long long long value 2', 'long long long value 3'];
2458
+ let res = highchartsRenderer.getFilterLabel(fieldFilter, false);
2459
+ expect(res.label).toEqual('test (many)');
2460
+ expect(res.tooltip).toEqual('test (' + fieldFilter.includes.join(',') + ')');
2461
+ });
2462
+
2463
+ it('Should return "many" in label when excludes has label length more than MAX_SELECTED_ITEMS_CHARECHTERS_IN_LABEL', () => {
2464
+ fieldFilter.excludes = ['[null]', 'long long long value 2', 'long long long value 3'];
2465
+ let res = highchartsRenderer.getFilterLabel(fieldFilter, false);
2466
+ expect(res.label).toEqual('test (Exclusions: many)');
2467
+ expect(res.tooltip).toEqual('test (Exclusions: ' + fieldFilter.excludes.join(',') + ')');
2468
+ });
2469
+
2470
+ it('Should exclude "[null]" from includes if allow_nulls enabled', () => {
2471
+ fieldFilter.allow_nulls = true;
2472
+ fieldFilter.includes = ['value 1', '[null]'];
2473
+ let res = highchartsRenderer.getFilterLabel(fieldFilter, false);
2474
+ expect(res.label).toEqual('test (value 1)');
2475
+ expect(res.tooltip).toEqual('test (' + fieldFilter.includes[0] + ')');
2476
+ });
2477
+
2478
+ it('Should exclude "[null]" from excludes if allow_nulls enabled', () => {
2479
+ fieldFilter.allow_nulls = true;
2480
+ fieldFilter.excludes = ['value 1', '[null]'];
2481
+ let res = highchartsRenderer.getFilterLabel(fieldFilter, false);
2482
+ expect(res.label).toEqual('test (Exclusions: value 1)');
2483
+ expect(res.tooltip).toEqual('test (Exclusions: ' + fieldFilter.excludes[0] + ')');
2484
+ });
2485
+
2486
+ it('Should present formatted dates in includes. Get formatted value from invertValueFormatMap object if exist ', () => {
2487
+ fieldFilter.includes = [1682063884, 1682060884, 1682013884];
2488
+ fieldFilter.type = 'Date';
2489
+ fieldFilter.valueFormatMap = {
2490
+ 'April 21, 2023': 1682063884
2491
+ };
2492
+ let res = highchartsRenderer.getFilterLabel(fieldFilter, false);
2493
+ expect(res.label).toEqual('test (April 21, 2023,04/21/2023,04/20/2023)');
2494
+ expect(res.tooltip).toEqual('test (April 21, 2023,04/21/2023,04/20/2023)');
2495
+ });
2496
+
2497
+ it('Should present formatted dates in excludes. Get formatted value from invertValueFormatMap object if exist ', () => {
2498
+ fieldFilter.excludes = [1682063884, 1682060884];
2499
+ fieldFilter.type = 'Date';
2500
+ fieldFilter.valueFormatMap = {
2501
+ 'April 21, 2023': 1682063884
2502
+ };
2503
+ let res = highchartsRenderer.getFilterLabel(fieldFilter, false);
2504
+ expect(res.label).toEqual('test (Exclusions: April 21, 2023,04/21/2023)');
2505
+ expect(res.tooltip).toEqual('test (Exclusions: April 21, 2023,04/21/2023)');
2506
+ });
2507
+ });
2508
+
2509
+ describe('Should present date range or frame selection', () => {
2510
+ let fieldFilter;
2511
+
2512
+ beforeEach(() => {
2513
+ fieldFilter = {
2514
+ name: 'test',
2515
+ includes: null,
2516
+ excludes: null,
2517
+ type: 'Date',
2518
+ };
2519
+ });
2520
+
2521
+ it('Should return "range" label when datetype is range', () => {
2522
+ fieldFilter.datetypevalues = {
2523
+ datetype: 'range',
2524
+ val: {
2525
+ fromdate: 1682060884,
2526
+ todate: 1682063884,
2527
+ }
2528
+ };
2529
+ const res = highchartsRenderer.getFilterLabel(fieldFilter, false);
2530
+ expect(res.label).toEqual('test (4/21/2023-4/21/2023)');
2531
+ expect(res.tooltip).toEqual('test (4/21/2023-4/21/2023)');
2532
+ });
2533
+
2534
+ it('Should return "frame" label when datetype is frame', () => {
2535
+ fieldFilter.datetypevalues = {
2536
+ datetype: 'frame',
2537
+ val: {
2538
+ timeframe: 'xday'
2539
+ }
2540
+ };
2541
+ const res = highchartsRenderer.getFilterLabel(fieldFilter, false);
2542
+ expect(res.label).toEqual('test (xday)');
2543
+ expect(res.tooltip).toEqual('test (xday)');
2544
+ });
2545
+
2546
+ it('Should return "All" label when datetype is not selected', () => {
2547
+ fieldFilter.datetypevalues = {};
2548
+ const res = highchartsRenderer.getFilterLabel(fieldFilter, false);
2549
+ expect(res.label).toEqual('test (All)');
2550
+ expect(res.tooltip).toEqual('test (All)');
2551
+ });
2552
+ });
2553
+
2554
+ describe('Should present advanced filter selection', () => {
2555
+ it('Should return "Advanced" label when advanced type in values', () => {
2556
+ const res = highchartsRenderer.getFilterLabel({ name: 'test', values: { type: 'advanced'} }, false);
2557
+ expect(res.label).toEqual('test (Advanced)');
2558
+ expect(res.tooltip).toEqual('test (Advanced)');
2559
+ });
2560
+
2561
+ it('Should return "Advanced" label when advanced type in datetypevalues', () => {
2562
+ const res = highchartsRenderer.getFilterLabel({ name: 'test', datetypevalues: { type: 'advanced'} }, false);
2563
+ expect(res.label).toEqual('test (Advanced)');
2564
+ expect(res.tooltip).toEqual('test (Advanced)');
2565
+ });
2566
+ });
2567
+
2568
+ describe('Should present All if nothing selected', () => {
2569
+ it('Should return "All" label when nothing selected', () => {
2570
+ const res = highchartsRenderer.getFilterLabel({ name: 'test'}, false);
2571
+ expect(res.label).toEqual('test (All)');
2572
+ expect(res.tooltip).toEqual('test (All)');
2573
+ });
2574
+ });
2575
+ });
2576
+
2577
+ describe('function getRelevantFilters', () => {
2578
+ it('should return an empty array if given an empty array', () => {
2579
+ const filters = highchartsRenderer.getRelevantFilters([]);
2580
+ expect(filters).toEqual([]);
2581
+ });
2582
+
2583
+ it('should filter out elements that do not have includes, excludes, or datetypevalues properties', () => {
2584
+ const filters = [
2585
+ {fields: ['field1'], otherProperty: 'value'},
2586
+ {fields: ['field2'], includes: [1, 2, 3]},
2587
+ {fields: ['field3'], excludes: ['abc']},
2588
+ {fields: ['field4'], datetypevalues: {datetype: 'date', start: '2022-01-01', end: '2022-01-31'}}
2589
+ ];
2590
+ const relevantFilters = highchartsRenderer.getRelevantFilters(filters);
2591
+ expect(relevantFilters.length).toEqual(3);
2592
+ expect(relevantFilters).toContainEqual({
2593
+ fields: ['field2'],
2594
+ values: [1, 2, 3],
2595
+ is_excluded: false,
2596
+ allow_nulls: false,
2597
+ inject_only: false
2598
+ });
2599
+ expect(relevantFilters).toContainEqual({
2600
+ fields: ['field3'],
2601
+ values: ['abc'],
2602
+ is_excluded: true,
2603
+ allow_nulls: false,
2604
+ inject_only: false
2605
+ });
2606
+ expect(relevantFilters).toContainEqual({
2607
+ fields: ['field4'],
2608
+ values: {datetype: 'date', start: '2022-01-01', end: '2022-01-31'},
2609
+ is_excluded: false,
2610
+ allow_nulls: false,
2611
+ inject_only: false
2612
+ });
2613
+ });
2614
+
2615
+ it('should handle empty includes and excludes properties by returning an empty values array', () => {
2616
+ const filters = [
2617
+ {fields: ['field1'], includes: []},
2618
+ {fields: ['field2'], includes: [1, 2, 3], excludes: []},
2619
+ {fields: ['field3'], excludes: ['abc']}
2620
+ ];
2621
+ const relevantFilters = highchartsRenderer.getRelevantFilters(filters);
2622
+ expect(relevantFilters.length).toEqual(3);
2623
+ expect(relevantFilters[0].values).toEqual([]);
2624
+ expect(relevantFilters[1].values).toEqual([1, 2, 3]);
2625
+ expect(relevantFilters[2].values).toEqual(['abc']);
2626
+ });
2627
+
2628
+ it('should set is_excluded to true for elements that have an excludes property', () => {
2629
+ const filters = [
2630
+ {fields: ['field1'], includes: [1, 2, 3]},
2631
+ {fields: ['field2'], excludes: ['abc']},
2632
+ {fields: ['field3'], excludes: [null]}
2633
+ ];
2634
+ const relevantFilters = highchartsRenderer.getRelevantFilters(filters);
2635
+ expect(relevantFilters.length).toEqual(3);
2636
+ expect(relevantFilters[0].is_excluded).toBe(false);
2637
+ expect(relevantFilters[1].is_excluded).toBe(true);
2638
+ expect(relevantFilters[2].is_excluded).toBe(true);
2639
+ });
2640
+
2641
+ it('should handle datetypevalues', () => {
2642
+ const filtersList = [
2643
+ {
2644
+ fields: ['date'],
2645
+ datetypevalues: {
2646
+ datetype: 'last_month',
2647
+ from: null,
2648
+ to: null
2649
+ }
2650
+ }
2651
+ ];
2652
+
2653
+ const expected = [
2654
+ {
2655
+ fields: ['date'],
2656
+ values: {
2657
+ datetype: 'last_month',
2658
+ from: null,
2659
+ to: null
2660
+ },
2661
+ is_excluded: false,
2662
+ allow_nulls: false,
2663
+ inject_only: false
2664
+ }
2665
+ ];
2666
+
2667
+ expect(highchartsRenderer.getRelevantFilters(filtersList)).toEqual(expected);
2668
+ });
2669
+ });
2670
+
2671
+ describe('function parseOptionsToObject', () => {
2672
+ it('should return an object when given an object', () => {
2673
+ const obj = { key: 'value' };
2674
+ const result = highchartsRenderer.parseOptionsToObject(obj);
2675
+ expect(result).toEqual(obj);
2676
+ });
2677
+
2678
+ it('should return an empty object when given empty string', () => {
2679
+ let result = highchartsRenderer.parseOptionsToObject('');
2680
+ expect(result).toEqual({});
2681
+ });
2682
+
2683
+ it('should parse a JSON string into an object', () => {
2684
+ const str = '{ "key": "value" }';
2685
+ const result = highchartsRenderer.parseOptionsToObject(str);
2686
+ expect(result).toEqual({ key: 'value' });
2687
+ });
2688
+
2689
+ it('should remove line breaks from the JSON string before parsing', () => {
2690
+ const str = '{\n "key": "value"\n}';
2691
+ const result = highchartsRenderer.parseOptionsToObject(str);
2692
+ expect(result).toEqual({ key: 'value' });
2693
+ });
2694
+
2695
+ it('should throw an error if given an invalid JSON string', () => {
2696
+ const str = '{ "key": "value" ';
2697
+ expect(() => highchartsRenderer.parseOptionsToObject(str)).toThrow();
2698
+ });
2699
+ });
2700
+
2701
+ describe('function getDashboardOverrideValues', () => {
2702
+ let dataModel;
2703
+ let graph;
2704
+ let localCurrentDashboard;
2705
+
2706
+ beforeEach(() => {
2707
+ dataModel = {
2708
+ current_dashboard: {
2709
+ fields_selectors: [
2710
+ {
2711
+ value: 'field1',
2712
+ fields_selector: {
2713
+ default_field: { id: 'field1', name: 'Field 1' },
2714
+ other_fields: [
2715
+ { id: 'field1', name: 'Field 1' },
2716
+ { id: 'field2', name: 'Field 2' },
2717
+ ]
2718
+ }
2719
+ },
2720
+ {
2721
+ value: 'field2',
2722
+ fields_selector: {
2723
+ default_field: { id: 'field2', name: 'Field 2' },
2724
+ other_fields: [
2725
+ { id: 'field1', name: 'Field 1' },
2726
+ { id: 'field2', name: 'Field 2' },
2727
+ ]
2728
+ }
2729
+ }
2730
+ ]
2731
+ },
2732
+ ebmedded_override_value_ids: []
2733
+ };
2734
+
2735
+ graph = {
2736
+ vals: [{ field: 'field1' }]
2737
+ };
2738
+
2739
+ localCurrentDashboard = {
2740
+ fields_selectors: [
2741
+ {
2742
+ value: 'field2',
2743
+ fields_selector: {
2744
+ default_field: { id: 'field1', name: 'Field 1' },
2745
+ other_fields: [
2746
+ { id: 'field1', name: 'Field 1' },
2747
+ { id: 'field2', name: 'Field 2' },
2748
+ ]
2749
+ }
2750
+ }
2751
+ ]
2752
+ };
2753
+ });
2754
+
2755
+ it('should return empty array when no conditions met', () => {
2756
+ expect(highchartsRenderer.getDashboardOverrideValues({}, {}, {})).toEqual([]);
2757
+ });
2758
+
2759
+ it('should return array of value objects when ebmedded_override_value_ids exist', () => {
2760
+ dataModel.ebmedded_override_value_ids = [1, 2, 3]
2761
+ expect(highchartsRenderer.getDashboardOverrideValues(dataModel, {}, {})).toEqual([
2762
+ { id: 1 },
2763
+ { id: 2 },
2764
+ { id: 3 }
2765
+ ]);
2766
+ });
2767
+
2768
+ it('should return empty array when local_current_dashboard undefined', () => {
2769
+ expect(highchartsRenderer.getDashboardOverrideValues({}, graph, undefined)).toEqual([]);
2770
+ });
2771
+
2772
+ it('should return empty array when graph undefined', () => {
2773
+ expect(highchartsRenderer.getDashboardOverrideValues(dataModel, undefined, localCurrentDashboard)).toEqual([]);
2774
+ });
2775
+
2776
+ it('should return empty array when graph vals empty', () => {
2777
+ expect(highchartsRenderer.getDashboardOverrideValues(dataModel, { vals: [] }, localCurrentDashboard)).toEqual([]);
2778
+ });
2779
+
2780
+ it('should return empty array when graph vals length > 1', () => {
2781
+ expect(highchartsRenderer.getDashboardOverrideValues(dataModel, { vals: [{ field: 'field1' }, { field: 'field2' }] }, localCurrentDashboard)).toEqual([]);
2782
+ });
2783
+
2784
+ it('should return empty array when no matching field selector', () => {
2785
+ expect(highchartsRenderer.getDashboardOverrideValues(dataModel, { vals: [{ field: 'field3' }] }, localCurrentDashboard)).toEqual([]);
2786
+ });
2787
+
2788
+ it('should return value object when selector value != graph val field', () => {
2789
+ expect(highchartsRenderer.getDashboardOverrideValues(dataModel, graph, localCurrentDashboard)).toEqual([{ id: 'field2', name: 'Field 2' }]);
2790
+ });
2791
+ });
2792
+
2793
+ describe('function getDashboardFilters', () => {
2794
+ let data_model;
2795
+ let remove_filters_from_global;
2796
+
2797
+ beforeEach(() => {
2798
+ data_model = {
2799
+ current_dashboard: {
2800
+ filters: [
2801
+ {
2802
+ fields: [{id: '1', name: 'Field 1'}],
2803
+ includes: ['value 1']
2804
+ },
2805
+ {
2806
+ fields: [{id: '2', name: 'Field 2'}],
2807
+ includes: ['value 2']
2808
+ }
2809
+ ]
2810
+ },
2811
+ ebmedded_filters: []
2812
+ };
2813
+ remove_filters_from_global = [{id: '2', name: 'Field 2'}];
2814
+ });
2815
+
2816
+ it('should return an empty array when no relevant filters found', () => {
2817
+ const local_current_dashboard = {
2818
+ fields_selectors: [{value: '1', fields_selector: {default_field: {id: '1'}}}]
2819
+ };
2820
+ const result = highchartsRenderer.getDashboardFilters({}, [], local_current_dashboard);
2821
+ expect(result).toEqual([]);
2822
+ });
2823
+
2824
+ it('should return an array of relevant filters from the current dashboard', () => {
2825
+ const result = highchartsRenderer.getDashboardFilters(data_model, [], data_model.current_dashboard);
2826
+ expect(result.length).toEqual(2);
2827
+ });
2828
+
2829
+ it('should return an array of relevant filters from the current dashboard and embedded filters', () => {
2830
+ data_model.ebmedded_filters = [{
2831
+ fields: [{id: '3', name: 'Field 3'}],
2832
+ includes: ['value 3']
2833
+ }];
2834
+ const result = highchartsRenderer.getDashboardFilters(data_model, [], data_model.current_dashboard);
2835
+ expect(result.length).toEqual(3);
2836
+ });
2837
+
2838
+ it('should remove specified fields from the returned filters array', () => {
2839
+ const result = highchartsRenderer.getDashboardFilters(data_model, remove_filters_from_global, data_model.current_dashboard);
2840
+ expect(result.length).toEqual(1);
2841
+ });
2842
+
2843
+ it('should add "[null]" to values array for filters with "allow_nulls" flag', () => {
2844
+ const currentDashboardWithNull = {
2845
+ filters: [
2846
+ {
2847
+ fields: [{ id: 'field1', name: 'Field 1' }],
2848
+ includes: ['value1', 'value2'],
2849
+ allow_nulls: false,
2850
+ },
2851
+ ],
2852
+ };
2853
+ const dataModelWithNull = { current_dashboard: currentDashboardWithNull };
2854
+ const result = highchartsRenderer.getDashboardFilters(dataModelWithNull);
2855
+ expect(result[0].values).toEqual(['value1', 'value2']);
2856
+ });
2857
+
2858
+ it('should not add "[null]" to values array if it is already present', () => {
2859
+ const currentDashboardWithNull = {
2860
+ filters: [
2861
+ {
2862
+ fields: [{ id: 'field1', name: 'Field 1' }],
2863
+ includes: ['value1'],
2864
+ allow_nulls: true,
2865
+ },
2866
+ ],
2867
+ };
2868
+ const dataModelWithNull = { current_dashboard: currentDashboardWithNull };
2869
+ const result = highchartsRenderer.getDashboardFilters(dataModelWithNull);
2870
+ expect(result[0].values).toEqual(['value1', '[null]']);
2871
+ });
2872
+ });
2873
+
2874
+ describe('function getPresentationTagType', () => {
2875
+ it('should return "date_tags" if local_current_dashboard has date tags', () => {
2876
+ const data_model = {
2877
+ current_dashboard: {
2878
+ date_tags: [{ id: 1, name: 'Date Tag 1' }]
2879
+ }
2880
+ };
2881
+ const result = highchartsRenderer.getPresentationTagType(data_model, data_model.current_dashboard);
2882
+ expect(result).toBe('date_tags');
2883
+ });
2884
+
2885
+ it('should return "plan_tags" if local_current_dashboard has plan tags', () => {
2886
+ const data_model = {
2887
+ current_dashboard: {
2888
+ plan_tags: [{ id: 1, name: 'Plan Tag 1' }]
2889
+ }
2890
+ };
2891
+ const result = highchartsRenderer.getPresentationTagType(data_model, data_model.current_dashboard);
2892
+ expect(result).toBe('plan_tags');
2893
+ });
2894
+
2895
+ it('should return undefined if local_current_dashboard has no tags', () => {
2896
+ const data_model = {
2897
+ current_dashboard: {}
2898
+ };
2899
+ const result = highchartsRenderer.getPresentationTagType(data_model);
2900
+ expect(result).toBeUndefined();
2901
+ });
2902
+
2903
+ it('should return "date_tags" if local_current_dashboard is undefined but data_model has date tags', () => {
2904
+ const data_model = {
2905
+ current_dashboard: {
2906
+ date_tags: [{ id: 1, name: 'Date Tag 1' }]
2907
+ }
2908
+ };
2909
+ const result = highchartsRenderer.getPresentationTagType(data_model);
2910
+ expect(result).toBe('date_tags');
2911
+ });
2912
+
2913
+ it('should return "plan_tags" if local_current_dashboard is undefined but data_model has plan tags', () => {
2914
+ const data_model = {
2915
+ current_dashboard: {
2916
+ plan_tags: [{ id: 1, name: 'Plan Tag 1' }]
2917
+ }
2918
+ };
2919
+ const result = highchartsRenderer.getPresentationTagType(data_model);
2920
+ expect(result).toBe('plan_tags');
2921
+ });
2922
+ });
2923
+
2924
+ describe('function getPresentationDataTag', () => {
2925
+ const data_model = { current_dashboard: { presentation_data_tag_object: { value: 'foo' } } };
2926
+ const dataKeyTag = 'date_tags';
2927
+
2928
+ it('returns presentation_data_tag_object value if local_current_dashboard is undefined', () => {
2929
+ const result = highchartsRenderer.getPresentationDataTag(data_model, undefined, dataKeyTag);
2930
+ expect(result).toBe('foo');
2931
+ });
2932
+
2933
+ it('returns presentation_data_tag_object value if local_current_dashboard has presentation_data_tag_object', () => {
2934
+ const local_current_dashboard = { presentation_data_tag_object: { value: 'bar' } };
2935
+ const result = highchartsRenderer.getPresentationDataTag(data_model, local_current_dashboard, dataKeyTag);
2936
+ expect(result).toBe('bar');
2937
+ });
2938
+
2939
+ it('returns value of highest dataKeyTag value in local_current_dashboard', () => {
2940
+ const local_current_dashboard = {
2941
+ date_tags: [
2942
+ { value: '2022-01-01' },
2943
+ { value: '2021-01-01' },
2944
+ { value: '2023-01-01' },
2945
+ ],
2946
+ };
2947
+ const result = highchartsRenderer.getPresentationDataTag(data_model, local_current_dashboard, dataKeyTag);
2948
+ expect(result).toBe('2023-01-01');
2949
+ });
2950
+
2951
+ it('returns null if local_current_dashboard has no presentation_data_tag_object or dataKeyTag values', () => {
2952
+ const local_current_dashboard = {};
2953
+ const result = highchartsRenderer.getPresentationDataTag(data_model, local_current_dashboard, dataKeyTag);
2954
+ expect(result).toBeNull();
2955
+ });
2956
+
2957
+ it('returns null if local_current_dashboard has empty dataKeyTag array', () => {
2958
+ const local_current_dashboard = { date_tags: [] };
2959
+ const result = highchartsRenderer.getPresentationDataTag(data_model, local_current_dashboard, dataKeyTag);
2960
+ expect(result).toBeNull();
2961
+ });
2962
+ });
2963
+
2964
+ describe('function getDashboardApplyScenarios', () => {
2965
+ let data_model;
2966
+ let graph;
2967
+
2968
+ beforeEach(() => {
2969
+ graph = { vals: [{ field: 'field1' }] };
2970
+ data_model = {
2971
+ current_dashboard: {
2972
+ scenario_models: [
2973
+ {
2974
+ value: 1,
2975
+ scenario_model: { source_fields: ['field1'], scenarios: [{ id: 1 }, { id: 2 }] },
2976
+ },
2977
+ {
2978
+ value: 2,
2979
+ scenario_model: { source_fields: ['field2'], scenarios: [{ id: 3 }, { id: 4 }] },
2980
+ },
2981
+ ],
2982
+ },
2983
+ ebmedded_apply_scenario_ids: [],
2984
+ };
2985
+ });
2986
+
2987
+ it('returns ebmedded_apply_scenario_ids if data_model has it', () => {
2988
+ data_model.ebmedded_apply_scenario_ids = [5, 6];
2989
+ const local_current_dashboard = { foo: 'bar' };
2990
+ const result = highchartsRenderer.getDashboardApplyScenarios(data_model, graph, local_current_dashboard);
2991
+ expect(result).toEqual([5, 6]);
2992
+ });
2993
+
2994
+ it('returns empty array if scenario_models in local_current_dashboard are not provided', () => {
2995
+ const result = highchartsRenderer.getDashboardApplyScenarios(data_model, {vals: [null]}, {});
2996
+ expect(result).toEqual([]);
2997
+ });
2998
+
2999
+ it('returns empty array if graph has no vals', () => {
3000
+ const result = highchartsRenderer.getDashboardApplyScenarios(data_model, {});
3001
+ expect(result).toEqual([]);
3002
+ });
3003
+
3004
+ it('returns empty array if graph has more than one val', () => {
3005
+ const graph = { vals: [{ field: 'field1' }, { field: 'field2' }] };
3006
+ const result = highchartsRenderer.getDashboardApplyScenarios(data_model, graph, {});
3007
+ expect(result).toEqual([]);
3008
+ });
3009
+
3010
+ it('returns array of selected scenario ids', () => {
3011
+ const result = highchartsRenderer.getDashboardApplyScenarios(data_model, graph, data_model.current_dashboard);
3012
+ expect(result).toEqual([1]);
3013
+ });
3014
+
3015
+ it('returns empty array if no matching scenario is found', () => {
3016
+ const graph = { vals: [{ field: 'field3' }] };
3017
+ const result = highchartsRenderer.getDashboardApplyScenarios(data_model, graph, data_model.current_dashboard);
3018
+ expect(result).toEqual([]);
3019
+ });
3020
+ });
3021
+
3022
+ describe('function isDate', () => {
3023
+ it('returns true for valid date string', () => {
3024
+ expect(highchartsRenderer.isDate('2022-01-01')).toBe(true);
3025
+ });
3026
+
3027
+ it('returns false for invalid date string', () => {
3028
+ expect(highchartsRenderer.isDate('not a date')).toBe(false);
3029
+ });
3030
+
3031
+ it('returns false for undefined input', () => {
3032
+ expect(highchartsRenderer.isDate(undefined)).toBe(false);
3033
+ });
3034
+
3035
+ it('returns false for empty string input', () => {
3036
+ expect(highchartsRenderer.isDate('')).toBe(false);
3037
+ });
3038
+ });
3039
+
3040
+ describe('function isDateFormat', () => {
3041
+ it('returns true for valid date string and format', () => {
3042
+ expect(highchartsRenderer.isDateFormat('2022-01-01', 'YYYY-MM-DD')).toBe(true);
3043
+ });
3044
+
3045
+ it('returns false for invalid date string', () => {
3046
+ expect(highchartsRenderer.isDateFormat('not a date', 'YYYY-MM-DD')).toBe(false);
3047
+ });
3048
+
3049
+ it('returns false for null input', () => {
3050
+ expect(highchartsRenderer.isDateFormat(null, 'YYYY-MM-DD')).toBe(false);
3051
+ });
3052
+
3053
+ it('returns false for undefined input', () => {
3054
+ expect(highchartsRenderer.isDateFormat(undefined, 'YYYY-MM-DD')).toBe(false);
3055
+ });
3056
+
3057
+ it('returns false for non-string input', () => {
3058
+ expect(highchartsRenderer.isDateFormat(123, 'YYYY-MM-DD')).toBe(false);
3059
+ });
3060
+
3061
+ it('returns false for empty string input', () => {
3062
+ expect(highchartsRenderer.isDateFormat('', 'YYYY-MM-DD')).toBe(false);
3063
+ });
3064
+
3065
+ it('returns false for invalid format', () => {
3066
+ expect(highchartsRenderer.isDateFormat('2022-01-01', 'invalid format')).toBe(false);
3067
+ });
3068
+ });
3069
+
3070
+ describe('function containsIgnoreCase', () => {
3071
+ it('should return true when str contains it, ignoring case', () => {
3072
+ const str = 'The quick brown fox jumps over the lazy dog';
3073
+ const it = 'brown';
3074
+ expect(highchartsRenderer.containsIgnoreCase(str, it)).toBe(true);
3075
+ });
3076
+
3077
+ it('should return true when str contains it, with different case', () => {
3078
+ const str = 'The quick brown fox jumps over the lazy dog';
3079
+ const it = 'BROWN';
3080
+ expect(highchartsRenderer.containsIgnoreCase(str, it)).toBe(true);
3081
+ });
3082
+
3083
+ it('should return false when str does not contain it, ignoring case', () => {
3084
+ const str = 'The quick brown fox jumps over the lazy dog';
3085
+ const it = 'cat';
3086
+ expect(highchartsRenderer.containsIgnoreCase(str, it)).toBe(false);
3087
+ });
3088
+
3089
+ it('should return false when str is empty', () => {
3090
+ const str = '';
3091
+ const it = 'dog';
3092
+ expect(highchartsRenderer.containsIgnoreCase(str, it)).toBe(false);
3093
+ });
3094
+ });
3095
+
3096
+ describe('function generateTableFormula', () => {
3097
+ it('pivotUtilities.getPivotTableFormula should be called', () => {
3098
+ spyOn($.pivotUtilities, 'getPivotTableFormula').and.callFake(() => null);
3099
+ highchartsRenderer.generateTableFormula(1,2,3,4,5,6, 7);
3100
+ expect($.pivotUtilities.getPivotTableFormula).lastCalledWith(1, 2, 3, 4, 5, 6, 7);
3101
+ });
3102
+ });
3103
+
3104
+ describe('function updateSelectedOverrideValues', () => {
3105
+ const widget = {
3106
+ vals: [{ name: 'selected_name' }]
3107
+ };
3108
+
3109
+ const overrideValues = [{ name: 'override_name' }];
3110
+
3111
+ it('should update selected values in res object', () => {
3112
+ const res = [
3113
+ { override_name: 'value1', selected_name: 'valueA' },
3114
+ { override_name: 'value2', selected_name: 'valueB' }
3115
+ ];
3116
+ const expectedRes = [
3117
+ { override_name: 'value1', selected_name: 'value1' },
3118
+ { override_name: 'value2', selected_name: 'value2' }
3119
+ ];
3120
+ expect(highchartsRenderer.updateSelectedOverrideValues(widget, overrideValues, res)).toEqual(expectedRes);
3121
+ });
3122
+
3123
+ it('should not update res object if override_values array is empty', () => {
3124
+ const res = [
3125
+ { override_name: 'value1', selected_name: 'valueA' },
3126
+ { override_name: 'value2', selected_name: 'valueB' }
3127
+ ];
3128
+ expect(highchartsRenderer.updateSelectedOverrideValues(widget, [], res)).toEqual(res);
3129
+ });
3130
+
3131
+ it('should not update res object if name_to_find is no_name_for_selected', () => {
3132
+ const res = [
3133
+ { override_name: 'value1', selected_name: 'valueA' },
3134
+ { override_name: 'value2', selected_name: 'valueB' }
3135
+ ];
3136
+ const overrideValues = [{ name: 'no_name_for_selected' }];
3137
+ expect(highchartsRenderer.updateSelectedOverrideValues(widget, overrideValues, res)).toEqual(res);
3138
+ });
3139
+
3140
+ it('should not update res object if name_to_set is null', () => {
3141
+ const widget = { vals: [] };
3142
+ const res = [
3143
+ { override_name: 'value1', selected_name: 'valueA' },
3144
+ { override_name: 'value2', selected_name: 'valueB' }
3145
+ ];
3146
+ expect(highchartsRenderer.updateSelectedOverrideValues(widget, overrideValues, res)).toEqual(res);
3147
+ });
3148
+ });
3149
+
3150
+ describe('function convertUniqueDateValues', () => {
3151
+ const widget = {
3152
+ template_id: 'template1',
3153
+ vals: [
3154
+ {field: 'field1', aggregator: 'UNIQUE_VALUES'},
3155
+ {field: 'field2', aggregator: 'COUNT'}
3156
+ ]
3157
+ };
3158
+
3159
+ const templates = [
3160
+ {id: 'template1', fields: [{id: 'field1', name: 'date_field', type: 'Date'}]},
3161
+ {id: 'template2', fields: [{id: 'field3', name: 'string_field', type: 'String'}]}
3162
+ ];
3163
+
3164
+ it('should convert unique date values in res object', () => {
3165
+ const res = [
3166
+ {date_field: [1640995200, 1641081600], string_field: 'value1'},
3167
+ {date_field: [1641168000], string_field: 'value2'}
3168
+ ];
3169
+ const expectedRes = [
3170
+ {date_field: ['01/01/2022', '01/02/2022'], string_field: 'value1'},
3171
+ {date_field: ['01/03/2022'], string_field: 'value2'}
3172
+ ];
3173
+ expect(highchartsRenderer.convertUniqueDateValues(widget, templates, res)).toEqual(expectedRes);
3174
+ });
3175
+
3176
+ it('should not convert date values if fields_to_convert is empty', () => {
3177
+ const widget = {
3178
+ template_id: 'template2',
3179
+ vals: [
3180
+ {field: 'field1', aggregator: 'SUM'},
3181
+ {field: 'field2', aggregator: 'AVG'}
3182
+ ]
3183
+ };
3184
+ const res = [
3185
+ {date_field: ['2022-01-01', '2022-01-02'], string_field: 'value1'},
3186
+ {date_field: ['2022-01-03'], string_field: 'value2'}
3187
+ ];
3188
+ expect(highchartsRenderer.convertUniqueDateValues(widget, templates, res)).toEqual(res);
3189
+ });
3190
+
3191
+ it('should not convert date values if res is empty', () => {
3192
+ const res = [];
3193
+ expect(highchartsRenderer.convertUniqueDateValues(widget, templates, res)).toEqual(res);
3194
+ });
3195
+
3196
+ it('should not convert date values if widget is null', () => {
3197
+ const res = [
3198
+ {date_field: ['2022-01-01', '2022-01-02'], string_field: 'value1'},
3199
+ {date_field: ['2022-01-03'], string_field: 'value2'}
3200
+ ];
3201
+ expect(highchartsRenderer.convertUniqueDateValues(null, templates, res)).toEqual(res);
3202
+ });
3203
+
3204
+ it('should not convert date values if widget.vals is null', () => {
3205
+ const widget = {template_id: 'template1'};
3206
+ const res = [
3207
+ {date_field: ['2022-01-01', '2022-01-02'], string_field: 'value1'},
3208
+ {date_field: ['2022-01-03'], string_field: 'value2'}
3209
+ ];
3210
+ expect(highchartsRenderer.convertUniqueDateValues(widget, templates, res)).toEqual(res);
3211
+ });
3212
+ });
3213
+
3214
+ describe('function setNewFieldNames', () => {
3215
+ beforeEach(() => {
3216
+ highchartsRenderer.useTotalsCalculation = false;
3217
+ });
3218
+
3219
+ it('should return the input if useTotalsCalculation is true', () => {
3220
+ const res = [{ DR_Values: 'value1' }, { DR_Values: 'value2' }];
3221
+ highchartsRenderer.useTotalsCalculation = true;
3222
+ const result = highchartsRenderer.setNewFieldNames(res);
3223
+
3224
+ expect(result).toEqual(res);
3225
+ });
3226
+
3227
+ it('should update DR_Values field names', () => {
3228
+ const res = [{ DR_Values: 'DR_Values' }, { DR_Values: 'value2' }];
3229
+ const expected = [{ DR_Values: 'Values' }, { DR_Values: 'value2' }];
3230
+ const result = highchartsRenderer.setNewFieldNames(res);
3231
+
3232
+ expect(result).toEqual(expected);
3233
+ });
3234
+
3235
+ it('should handle empty input', () => {
3236
+ const res = null;
3237
+ const expected = null;
3238
+ const result = highchartsRenderer.setNewFieldNames(res);
3239
+
3240
+ expect(result).toEqual(expected);
3241
+ });
3242
+
3243
+ it('should handle empty DR_Values array in input', () => {
3244
+ const res = [{}];
3245
+ const expected = [{ DR_Values: undefined }];
3246
+ const result = highchartsRenderer.setNewFieldNames(res);
3247
+
3248
+ expect(result).toEqual(expected);
3249
+ });
3250
+ });
3251
+
3252
+ describe('function getOptionsForLegends', () => {
3253
+ const rowAttrsLength = 1;
3254
+ let additionOptions;
3255
+
3256
+ beforeEach(() => {
3257
+ highchartsRenderer.isMobile = false;
3258
+ additionOptions = {
3259
+ legends_position: {value: null},
3260
+ hideChartHeader: false,
3261
+ subtitle: {subtitle: null}
3262
+ };
3263
+ });
3264
+
3265
+ it('should return topPosition for mobile devices and legends_position is not set to none', () => {
3266
+ highchartsRenderer.isMobile = true;
3267
+ const result = highchartsRenderer.getOptionsForLegends(additionOptions, rowAttrsLength, false, false);
3268
+ expect(result.align).toEqual('left');
3269
+ expect(result.verticalAlign).toEqual('top');
3270
+ expect(result.layout).toEqual('horizontal');
3271
+ });
3272
+
3273
+ it('should return topPosition when legends_position is not set and not line/pie chart', () => {
3274
+ const result = highchartsRenderer.getOptionsForLegends(additionOptions, rowAttrsLength, false, false);
3275
+ expect(result.align).toEqual('left');
3276
+ expect(result.verticalAlign).toEqual('top');
3277
+ expect(result.layout).toEqual('horizontal');
3278
+ });
3279
+
3280
+ it('should return leftPosition when legends_position is not set and line chart', () => {
3281
+ const result = highchartsRenderer.getOptionsForLegends(additionOptions, rowAttrsLength, true, false);
3282
+ expect(result.align).toEqual('left');
3283
+ expect(result.verticalAlign).toEqual('top');
3284
+ expect(result.layout).toEqual('vertical');
3285
+ });
3286
+
3287
+ it('should return rightPosition when legends_position is not set and pie chart', () => {
3288
+ const result = highchartsRenderer.getOptionsForLegends(additionOptions, rowAttrsLength, false, true);
3289
+ expect(result.align).toEqual('right');
3290
+ expect(result.verticalAlign).toEqual('top');
3291
+ expect(result.layout).toEqual('vertical');
3292
+ });
3293
+
3294
+ it('should return topPosition when legends_position is set to top', () => {
3295
+ additionOptions.legends_position.value = 'top';
3296
+ const result = highchartsRenderer.getOptionsForLegends(additionOptions, rowAttrsLength, false, false);
3297
+ expect(result.align).toEqual('left');
3298
+ expect(result.verticalAlign).toEqual('top');
3299
+ expect(result.layout).toEqual('horizontal');
3300
+ });
3301
+
3302
+ it('should return bottomPosition when legends_position is set to bottom', () => {
3303
+ additionOptions.legends_position.value = 'bottom';
3304
+ const result = highchartsRenderer.getOptionsForLegends(additionOptions, rowAttrsLength, false, false);
3305
+ expect(result.maxHeight).toEqual(37);
3306
+ });
3307
+
3308
+ it('should return leftPosition when legends_position is set to left', () => {
3309
+ additionOptions.legends_position.value = 'left';
3310
+ const result = highchartsRenderer.getOptionsForLegends(additionOptions, rowAttrsLength, false, false);
3311
+ expect(result.align).toEqual('left');
3312
+ expect(result.verticalAlign).toEqual('top');
3313
+ expect(result.layout).toEqual('vertical');
3314
+ });
3315
+
3316
+ it('should return rightPosition when legends_position is set to right', () => {
3317
+ additionOptions.legends_position.value = 'right';
3318
+ const result = highchartsRenderer.getOptionsForLegends(additionOptions, rowAttrsLength, false, false);
3319
+ expect(result.align).toEqual('right');
3320
+ expect(result.verticalAlign).toEqual('top');
3321
+ expect(result.layout).toEqual('vertical');
3322
+ });
3323
+
3324
+ it('should return disabled state when legends_position is set to none', () => {
3325
+ additionOptions.legends_position.value = 'none';
3326
+ const result = highchartsRenderer.getOptionsForLegends(additionOptions, rowAttrsLength, false, false);
3327
+ expect(result.enabled).toEqual(false);
3328
+ });
3329
+ });
3330
+
3331
+ describe('function setYAxisMinMax', () => {
3332
+ let yAxis;
3333
+
3334
+ beforeEach(() => {
3335
+ yAxis = { min: null, max: null };
3336
+ });
3337
+
3338
+ it('should set the minimum and maximum values of the yAxis if the axisYOptions is defined and has valid values', () => {
3339
+ const axisYOptions = { min: '10', max: '20' };
3340
+ highchartsRenderer.setYAxisMinMax(yAxis, axisYOptions);
3341
+ expect(yAxis.min).toEqual(10);
3342
+ expect(yAxis.max).toEqual(20);
3343
+ });
3344
+
3345
+ it('should set the minimum value of the yAxis to null if the axisYOptions has an invalid minimum value', () => {
3346
+ const axisYOptions = { min: 'invalid', max: '20' };
3347
+ highchartsRenderer.setYAxisMinMax(yAxis, axisYOptions);
3348
+ expect(yAxis.min).toBeNull();
3349
+ expect(yAxis.max).toEqual(20);
3350
+ });
3351
+
3352
+ it('should set the maximum value of the yAxis to null if the axisYOptions has an invalid maximum value', () => {
3353
+ const axisYOptions = { min: '10', max: 'invalid' };
3354
+ highchartsRenderer.setYAxisMinMax(yAxis, axisYOptions);
3355
+ expect(yAxis.min).toEqual(10);
3356
+ expect(yAxis.max).toBeNull();
3357
+ });
3358
+
3359
+ it('should set the minimum and maximum values of the yAxis to null if the axisYOptions is not defined', () => {
3360
+ highchartsRenderer.setYAxisMinMax(yAxis);
3361
+ expect(yAxis.min).toBeNull();
3362
+ expect(yAxis.max).toBeNull();
3363
+ });
3364
+ });
3365
+
3366
+ describe('function getDateFieldFormat', () => {
3367
+ let widget;
3368
+ let dateField;
3369
+
3370
+ beforeEach(() => {
3371
+ widget = {
3372
+ options: {
3373
+ date_aggregation_configs: [
3374
+ {
3375
+ field_id: 1,
3376
+ aggregate_by: 'quarter',
3377
+ is_formatting_by_aggregation_method: true,
3378
+ }
3379
+ ],
3380
+ },
3381
+ };
3382
+
3383
+ dateField = {
3384
+ id: 1,
3385
+ format: '%Y-%m-%d',
3386
+ };
3387
+ });
3388
+
3389
+ it('returns format as is when there is no aggregation config', () => {
3390
+ widget.options.date_aggregation_configs = [];
3391
+ const result = highchartsRenderer.getDateFieldFormat(widget, dateField);
3392
+ expect(result).toEqual('%Y-%m-%d');
3393
+ });
3394
+
3395
+ it('returns format by time frame when there is an aggregation config', () => {
3396
+ const result = highchartsRenderer.getDateFieldFormat(widget, dateField);
3397
+ expect(result).toEqual('[Q]Q-YY');
3398
+ });
3399
+
3400
+ it('returns format as is when there is an aggregation config but no time frame specified', () => {
3401
+ widget.options.date_aggregation_configs[0].aggregate_by = null;
3402
+ const result = highchartsRenderer.getDateFieldFormat(widget, dateField);
3403
+ expect(result).toEqual('%Y-%m-%d');
3404
+ });
3405
+ });
3406
+
3407
+ describe('function getDateFormatByTimeframe', () => {
3408
+ it('should return the correct date format for "month" timeframe', () => {
3409
+ const result = highchartsRenderer.getDateFormatByTimeframe('month', 'YYYY-MM-DD');
3410
+ expect(result).toBe('MMM-YY');
3411
+ });
3412
+
3413
+ it('should return the correct date format for "year" timeframe', () => {
3414
+ const result = highchartsRenderer.getDateFormatByTimeframe('year', 'YYYY-MM-DD');
3415
+ expect(result).toBe('YYYY');
3416
+ });
3417
+
3418
+ it('should return the correct date format for "quarter" timeframe', () => {
3419
+ const result = highchartsRenderer.getDateFormatByTimeframe('quarter', 'YYYY-MM-DD');
3420
+ expect(result).toBe('[Q]Q-YY');
3421
+ });
3422
+
3423
+ it('should return the default date format for unrecognized timeframe', () => {
3424
+ expect(highchartsRenderer.getDateFormatByTimeframe('day', 'YYYY-MM-DD')).toBe('YYYY-MM-DD');
3425
+ expect(highchartsRenderer.getDateFormatByTimeframe('week', 'YYYY-MM-DD')).toBe('YYYY-MM-DD');
3426
+ });
3427
+ });
3428
+
3429
+ describe('function getOthersName', () => {
3430
+ it('returns the filtered out field name when it exists in options', () => {
3431
+ const options = {
3432
+ total_value_options: {
3433
+ filter_options: {
3434
+ filteredOutFieldName: 'Excluded'
3435
+ }
3436
+ }
3437
+ };
3438
+ const othersName = highchartsRenderer.getOthersName(options);
3439
+ expect(othersName).toBe('Excluded');
3440
+ });
3441
+
3442
+ it('returns "Others" when the filtered out field name does not exist in options', () => {
3443
+ const options = {};
3444
+ const othersName = highchartsRenderer.getOthersName(options);
3445
+ expect(othersName).toBe('Others');
3446
+ });
3447
+ });
3448
+
3449
+ describe('function transformRowsAndColsForBreakdown', () => {
3450
+ let point;
3451
+ let opts;
3452
+
3453
+ beforeEach(() => {
3454
+ point = {
3455
+ options: {},
3456
+ colKeys: ["Col1", "Col2", "Others"],
3457
+ };
3458
+
3459
+ opts = {
3460
+ total_value_options: {
3461
+ filter_options: {
3462
+ filteredOutFieldName: "Others",
3463
+ },
3464
+ },
3465
+ };
3466
+ });
3467
+
3468
+ it("should replace Others with DR_Others in cols and return rows as cols when point is not total", () => {
3469
+ const rows = ["Row1", "Row2"];
3470
+ const cols = ["Col1", "Col2", "Others"];
3471
+ const expectedResult = {
3472
+ rows: cols,
3473
+ cols: [point.colKeys[0]],
3474
+ };
3475
+
3476
+ const result = highchartsRenderer.transformRowsAndColsForBreakdown(rows, cols, point, opts);
3477
+ expect(result).toEqual(expectedResult);
3478
+ });
3479
+
3480
+ it("should set rows to empty array when point is total", () => {
3481
+ const rows = ["Row1", "Row2"];
3482
+ const cols = ["Col1", "Col2", "Not_Others"];
3483
+ point.options.isTotal = true;
3484
+ const expectedResult = {
3485
+ rows: [],
3486
+ cols: cols,
3487
+ };
3488
+
3489
+ const result = highchartsRenderer.transformRowsAndColsForBreakdown(rows, cols, point, opts);
3490
+ expect(result).toEqual(expectedResult);
3491
+ });
3492
+ });
3493
+
3494
+ describe('function getBreakdownXAxisLabelFormatter', () => {
3495
+ it('returns correct formatter function', () => {
3496
+ const chartSeries = [{
3497
+ data: [
3498
+ { name: 'Label1', isTotal: true },
3499
+ { name: 'Label2', isTotal: false }
3500
+ ]
3501
+ }];
3502
+ const formatter = highchartsRenderer.getBreakdownXAxisLabelFormatter(chartSeries);
3503
+
3504
+ const totalResult = formatter.apply({ value: 'Label1' });
3505
+ expect(totalResult).toEqual('<span style=\"\">Label1</span>');
3506
+
3507
+ const normalResult = formatter.apply({ value: 'Label2' });
3508
+ expect(normalResult).toEqual('<span style="font-weight: normal; color: #51566f;">Label2</span>');
3509
+ });
3510
+ });
3511
+
3512
+ describe('function getTrendSeriesName', () => {
3513
+ it('returns expected name when name is present in the series object', () => {
3514
+ const series = {
3515
+ name: 'Sales'
3516
+ };
3517
+ const expectedName = 'Trend Line (Sales)';
3518
+ expect(highchartsRenderer.getTrendSeriesName(series)).toBe(expectedName);
3519
+ });
3520
+
3521
+ it('returns expected name when no name is present in the series object', () => {
3522
+ const series = {};
3523
+ const expectedName = 'Trend Line';
3524
+ expect(highchartsRenderer.getTrendSeriesName(series)).toBe(expectedName);
3525
+ });
3526
+ });
397
3527
  });