@datarailsshared/dr_renderer 1.5.159 → 1.5.168

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (32) hide show
  1. package/.idea/jsLibraryMappings.xml +6 -0
  2. package/.idea/misc.xml +9 -0
  3. package/.nvmrc +1 -0
  4. package/jest.config.js +1 -1
  5. package/package.json +9 -11
  6. package/scripts/check-versions.js +16 -0
  7. package/src/highcharts_renderer.d.ts +2 -2
  8. package/tsconfig.json +1 -1
  9. package/.circleci/config.yml +0 -85
  10. package/.github/workflows/ai-coder-jira.yml +0 -915
  11. package/.github/workflows/ai-coder-n8n-caller.yml +0 -82
  12. package/.github/workflows/release.yml +0 -49
  13. package/tests/__snapshots__/suboptions.test.js.snap +0 -5028
  14. package/tests/dr-renderer-helpers.test.js +0 -228
  15. package/tests/dr_chart_tooltip.test.js +0 -789
  16. package/tests/dr_gauge_chart.test.js +0 -2041
  17. package/tests/errors.test.js +0 -157
  18. package/tests/highcharts_renderer.test.js +0 -9407
  19. package/tests/mock/add-in-dynamic-ranges.json +0 -127
  20. package/tests/mock/add-in-functions.json +0 -410
  21. package/tests/mock/add-in-tables.json +0 -347
  22. package/tests/mock/tables.json +0 -2258
  23. package/tests/mock/widgets.json +0 -401
  24. package/tests/options-builder.test.js +0 -1698
  25. package/tests/pivot-table/freeze-panes/constants.test.js +0 -92
  26. package/tests/pivot-table/freeze-panes/index.test.js +0 -193
  27. package/tests/pivot-table/freeze-panes/sticky-strategy.test.js +0 -542
  28. package/tests/pivot-table/freeze-panes/transform-strategy.test.js +0 -304
  29. package/tests/ptCreateDrillDownSeriesToDrilldownChart.test.js +0 -509
  30. package/tests/seriesPointStyles-helper.test.js +0 -114
  31. package/tests/suboptions.test.js +0 -322
  32. package/tests/value.formatter.test.js +0 -143
@@ -1,2041 +0,0 @@
1
- const { DrGaugeChart, GAUGE_OPTIONS_DEFAULT } = require("../src/charts/dr_gauge_chart");
2
- const helpers = require("../src/dr-renderer-helpers");
3
- const { DrChartTooltip } = require("../src/dr_chart_tooltip");
4
-
5
- jest.mock("../src/dr_chart_tooltip"); // Mock the tooltip class
6
-
7
- const mockFormattedValue = "16,549";
8
- let disableChartAnimation = false;
9
-
10
- DrGaugeChart.highchartsRenderer = {
11
- CHART_TYPES: {
12
- GAUGE_CHART_ENHANCE: "gauge-chart-enhanced",
13
- },
14
- getDefaultValueForChart: jest.fn(),
15
- ptCreateElementAndDraw: jest.fn(),
16
- ptCreateBasicLineSeries: jest.fn().mockReturnValue([{ data: [1] }, { data: [2] }]),
17
- getSingleValueAgg: jest.fn().mockReturnValue({
18
- aggfunc: (a, b) => a + b,
19
- base: 0,
20
- }),
21
- formatValue: jest.fn().mockReturnValue({
22
- value: mockFormattedValue,
23
- }),
24
- environment: {
25
- enableGaugeDynamicGoal: false,
26
- },
27
- disableChartAnimations: jest.fn((value) => disableChartAnimation = value),
28
- chartAnimationsDisabled: jest.fn(() => disableChartAnimation),
29
- };
30
-
31
- const mockAggregationValue = 1000;
32
-
33
- const mockAggregation = {
34
- widget_values_format: "###",
35
- value: jest.fn().mockReturnValue(mockAggregationValue),
36
- };
37
-
38
- const mockPivotData = {
39
- getAggregator: jest.fn().mockImplementation().mockReturnValue(mockAggregation),
40
- };
41
-
42
- const mockChartOptionsPercentage = {
43
- segments: [
44
- {
45
- from: 0,
46
- to: 60,
47
- title: "Low",
48
- color: "#BF1D30",
49
- },
50
- {
51
- from: 61,
52
- to: 80,
53
- title: "Medium",
54
- color: "#FFA310",
55
- },
56
- {
57
- from: 81,
58
- to: 100,
59
- title: "High",
60
- color: "#037C5A",
61
- },
62
- ],
63
- goal: {
64
- name: "Goal",
65
- value: 180,
66
- },
67
- isAbsoluteValue: false,
68
- label: {},
69
- gauge: {
70
- background: "white",
71
- },
72
- };
73
-
74
- const mockChartOptionsAbsolute = {
75
- segments: [
76
- {
77
- from: 0,
78
- to: 100,
79
- title: "Low",
80
- color: "#BF1D30",
81
- },
82
- {
83
- from: 101,
84
- to: 200,
85
- title: "Medium",
86
- color: "#FFA310",
87
- },
88
- {
89
- from: 201,
90
- to: 500,
91
- title: "High",
92
- color: "#037C5A",
93
- },
94
- ],
95
- goal: {
96
- name: "Goal",
97
- value: 180,
98
- },
99
- isAbsoluteValue: true,
100
- };
101
-
102
- let chart;
103
-
104
- describe("DrGaugeChart", () => {
105
- beforeEach(() => {
106
- chart = new DrGaugeChart(mockPivotData, {
107
- chartOptions: mockChartOptionsPercentage,
108
- });
109
- });
110
-
111
- describe("render", () => {
112
- it("calls configChart", () => {
113
- chart.configChart = jest.fn().mockReturnValue({
114
- options: "Option",
115
- });
116
-
117
- chart.render();
118
- expect(chart.configChart).toHaveBeenCalled();
119
- });
120
-
121
- it("disables chart animations by demand", () => {
122
- chart.render();
123
- expect(DrGaugeChart.highchartsRenderer.chartAnimationsDisabled).toHaveBeenCalledTimes(2);
124
- });
125
- });
126
-
127
- describe("isLeftQuarter", () => {
128
- it("should check in which quarter the chart value is", () => {
129
- expect(chart.isLeftQuarter(20, 100, 0)).toBe(true);
130
- expect(chart.isLeftQuarter(20, 30, 0)).toBe(false);
131
- expect(chart.isLeftQuarter(20, 20, 0)).toBe(false);
132
- expect(chart.isLeftQuarter(100, 200, 0)).toBe(false);
133
- expect(chart.isLeftQuarter(99, 200, 0)).toBe(true);
134
-
135
- expect(chart.isLeftQuarter(59, 100, 20)).toBe(true);
136
- expect(chart.isLeftQuarter(60, 100, 20)).toBe(false);
137
- });
138
-
139
- it("should use default #max and #min parameters", () => {
140
- // Max = 180
141
- // Min = 0
142
- expect(chart.isLeftQuarter(20)).toBe(true);
143
- expect(chart.isLeftQuarter(120)).toBe(false);
144
- });
145
- });
146
-
147
- describe("createPlotBands", () => {
148
- afterEach(() => {
149
- DrGaugeChart.highchartsRenderer.environment.enableGaugeDynamicGoal = false;
150
- })
151
-
152
- it("should create plots for absolute values", () => {
153
- expect(
154
- chart.createPlotBands({
155
- isAbsoluteValue: true,
156
- gauge: {
157
- thickness: 10,
158
- },
159
- goal: {
160
- value: 180,
161
- },
162
- segments: [
163
- {
164
- from: 0,
165
- to: 200,
166
- color: "red",
167
- title: "Title 1",
168
- },
169
- {
170
- from: 200,
171
- to: 400,
172
- color: "blue",
173
- title: "Title 2",
174
- },
175
- {
176
- from: 400,
177
- to: 800,
178
- color: "blue",
179
- title: "Title 3",
180
- },
181
- ],
182
- })
183
- ).toEqual([
184
- {
185
- from: 0,
186
- to: 200,
187
- color: "red",
188
- thickness: 10,
189
- title: "Title 1",
190
- },
191
- {
192
- from: 200,
193
- to: 400,
194
- color: "blue",
195
- thickness: 10,
196
- title: "Title 2",
197
- },
198
- {
199
- from: 400,
200
- to: 800,
201
- color: "blue",
202
- thickness: 10,
203
- title: "Title 3",
204
- },
205
- ]);
206
- });
207
-
208
- it("should clamp values (max of goal and last segment)", () => {
209
- expect(
210
- chart.createPlotBands({
211
- isAbsoluteValue: true,
212
- gauge: {
213
- thickness: 10,
214
- },
215
- goal: {
216
- value: 1800,
217
- },
218
- segments: [
219
- {
220
- from: 100,
221
- to: 200,
222
- color: "red",
223
- title: "Title 1",
224
- },
225
- {
226
- from: 200,
227
- to: 400,
228
- color: "blue",
229
- title: "Title 2",
230
- },
231
- {
232
- from: 400,
233
- to: 800,
234
- color: "blue",
235
- title: "Title 3",
236
- },
237
- ],
238
- })
239
- ).toEqual([
240
- {
241
- from: 100,
242
- to: 200,
243
- color: "red",
244
- thickness: 10,
245
- title: "Title 1",
246
- },
247
- {
248
- from: 200,
249
- to: 400,
250
- color: "blue",
251
- thickness: 10,
252
- title: "Title 2",
253
- },
254
- {
255
- from: 400,
256
- to: 1800,
257
- color: "blue",
258
- thickness: 10,
259
- title: "Title 3",
260
- },
261
- ]);
262
- });
263
-
264
- it("should create plots for percentage values", () => {
265
- expect(
266
- chart.createPlotBands({
267
- isAbsoluteValue: false,
268
- gauge: {
269
- thickness: 10,
270
- },
271
- goal: {
272
- value: 1000,
273
- },
274
- segments: [
275
- {
276
- from: 0,
277
- to: 50,
278
- color: "red",
279
- title: "Title 1",
280
- },
281
- {
282
- from: 50,
283
- to: 100,
284
- color: "blue",
285
- title: "Title 2",
286
- },
287
- {
288
- from: 100,
289
- to: 175,
290
- color: "blue",
291
- title: "Title 3",
292
- },
293
- ],
294
- })
295
- ).toEqual([
296
- {
297
- from: 0,
298
- to: 500,
299
- color: "red",
300
- thickness: 10,
301
- title: "Title 1",
302
- },
303
- {
304
- from: 500,
305
- to: 1000,
306
- color: "blue",
307
- thickness: 10,
308
- title: "Title 2",
309
- },
310
- {
311
- from: 1000,
312
- to: 1750,
313
- color: "blue",
314
- thickness: 10,
315
- title: "Title 3",
316
- },
317
- ]);
318
- });
319
-
320
- it("scales by needle magnitude when goal is 0 in percentage mode", () => {
321
- chart.value = 250;
322
- expect(
323
- chart.createPlotBands({
324
- isAbsoluteValue: false,
325
- gauge: { thickness: 10 },
326
- goal: { value: 0 },
327
- segments: [
328
- { from: 0, to: 50, color: "red", title: "Title 1" },
329
- { from: 50, to: 100, color: "blue", title: "Title 2" },
330
- ],
331
- })
332
- ).toEqual([
333
- { from: 0, to: 125, color: "red", thickness: 10, title: "Title 1" },
334
- { from: 125, to: 250, color: "blue", thickness: 10, title: "Title 2" },
335
- ]);
336
- });
337
-
338
- it("scales by absolute needle magnitude when goal is not a number", () => {
339
- DrGaugeChart.highchartsRenderer.environment.enableGaugeDynamicGoal = true;
340
-
341
- chart.value = -300;
342
- const res = chart.createPlotBands({
343
- isAbsoluteValue: false,
344
- gauge: { thickness: 8 },
345
- goal: { value: undefined },
346
- segments: [
347
- { from: 0, to: 50, color: "#1", title: "A" },
348
- { from: 50, to: 100, color: "#2", title: "B" },
349
- ],
350
- });
351
-
352
- expect(res).toEqual([
353
- { from: 0, to: 150, color: "#1", thickness: 8, title: "A" },
354
- { from: 150, to: 300, color: "#2", thickness: 8, title: "B" },
355
- ]);
356
- });
357
-
358
- it("normalizes bands when goal is negative in percentage mode", () => {
359
- const res = chart.createPlotBands({
360
- isAbsoluteValue: false,
361
- gauge: { thickness: 12 },
362
- goal: { value: -1000 },
363
- segments: [
364
- { from: 0, to: 50, color: "r", title: "S1" },
365
- { from: 50, to: 100, color: "b", title: "S2" },
366
- ],
367
- });
368
-
369
- expect(res[0].from).toBe(-500);
370
- expect(Math.abs(res[0].to)).toBe(0);
371
- expect(res[0].color).toBe("r");
372
- expect(res[0].thickness).toBe(12);
373
- expect(res[0].title).toBe("S1");
374
-
375
- expect(res[1]).toEqual({ from: -1000, to: -500, color: "b", thickness: 12, title: "S2" });
376
- });
377
-
378
- it("does not clamp last segment when dynamic goal feature is enabled", () => {
379
- DrGaugeChart.highchartsRenderer.environment.enableGaugeDynamicGoal = true;
380
-
381
- const res = chart.createPlotBands({
382
- isAbsoluteValue: true,
383
- gauge: { thickness: 10 },
384
- goal: { value: 1800 },
385
- segments: [
386
- { from: 100, to: 200, color: "red", title: "Title 1" },
387
- { from: 200, to: 400, color: "blue", title: "Title 2" },
388
- { from: 400, to: 800, color: "green", title: "Title 3" },
389
- ],
390
- });
391
-
392
- expect(res).toEqual([
393
- { from: 100, to: 200, color: "red", thickness: 10, title: "Title 1" },
394
- { from: 200, to: 400, color: "blue", thickness: 10, title: "Title 2" },
395
- { from: 400, to: 800, color: "green", thickness: 10, title: "Title 3" },
396
- ]);
397
- });
398
- });
399
-
400
- describe("createTicks", () => {
401
- it("should create a ticks array", () => {
402
- expect(
403
- DrGaugeChart.createTicks(
404
- [
405
- {
406
- to: 100,
407
- },
408
- {
409
- to: 150,
410
- },
411
- {
412
- to: 200,
413
- },
414
- ],
415
- {
416
- goal: {
417
- value: 180,
418
- },
419
- }
420
- )
421
- ).toEqual([0, 100, 150, 180, 200]);
422
- });
423
-
424
- it("should sort and remove duplicates", () => {
425
- expect(
426
- DrGaugeChart.createTicks(
427
- [
428
- {
429
- to: 100,
430
- },
431
- {
432
- to: 100,
433
- },
434
- {
435
- to: 50,
436
- },
437
- {
438
- to: 180,
439
- },
440
- ],
441
- {
442
- goal: {
443
- value: 180,
444
- },
445
- }
446
- )
447
- ).toEqual([0, 50, 100, 180]);
448
- });
449
- });
450
-
451
- describe("mergeOptions", () => {
452
- it("should merge provided options with default one", () => {
453
- chart.getDefaultValueForChart = jest.fn().mockReturnValue({
454
- option1: 1,
455
- option2: 2,
456
- });
457
- const mockRes = {
458
- option1: 1,
459
- option2: 2,
460
- };
461
- spyOn(helpers, "mergeDeep").and.returnValue(mockRes);
462
- expect(
463
- chart.mergeOptions({
464
- options3: 3,
465
- options4: 4,
466
- })
467
- ).toEqual(mockRes);
468
- expect(helpers.mergeDeep).toHaveBeenCalledWith(
469
- GAUGE_OPTIONS_DEFAULT,
470
- {
471
- option1: 1,
472
- option2: 2,
473
- },
474
- {
475
- options3: 3,
476
- options4: 4,
477
- }
478
- );
479
- helpers.mergeDeep.re;
480
- });
481
- });
482
-
483
- describe("getAngleForValue", () => {
484
- it("should return an angle in radians", () => {
485
- expect(chart.getAngleForValue(100, 0, 200, -90, 90)).toBe(Math.PI / 2);
486
- expect(chart.getAngleForValue(50, 0, 200, -90, 90)).toBe(Math.PI / 4);
487
- expect(chart.getAngleForValue(200, 0, 200, -90, 90)).toBe(Math.PI);
488
- });
489
-
490
- it("should use default value", () => {
491
- // min = 0;
492
- // max = 180 goal
493
- // angle -90/ 90
494
- expect(chart.getAngleForValue(90)).toBe(Math.PI / 2);
495
- });
496
- });
497
-
498
- describe("formatValue", () => {
499
- it("should format number to provided format", () => {
500
- expect(chart.formatValue(16549.1234, "#,###")).toBe(mockFormattedValue);
501
- expect(DrGaugeChart.highchartsRenderer.formatValue).toHaveBeenCalledWith("n", "#,###", 16549.1234);
502
- });
503
-
504
- it("should not format value unless it is a number", () => {
505
- expect(chart.formatValue("one", "#,###")).toBe("one");
506
- expect(DrGaugeChart.highchartsRenderer.formatValue).not.toHaveBeenCalled();
507
- });
508
-
509
- it("should use default value for format", () => {
510
- expect(chart.formatValue(16549.1234)).toBe(mockFormattedValue);
511
- expect(DrGaugeChart.highchartsRenderer.formatValue).toHaveBeenCalledWith(
512
- "n",
513
- mockAggregation.widget_values_format,
514
- 16549.1234
515
- );
516
- });
517
- });
518
-
519
- describe("toPercent", () => {
520
- it("should format absolute values", () => {
521
- chart = new DrGaugeChart(mockPivotData, {
522
- chartOptions: { ...mockChartOptionsAbsolute },
523
- });
524
- expect(chart.toPercent(100)).toBe("20%");
525
- expect(chart.toPercent(250)).toBe("50%");
526
- expect(chart.toPercent(500)).toBe("100%");
527
- // rounding
528
- expect(chart.toPercent(2)).toBe("0%");
529
- expect(chart.toPercent(3)).toBe("1%");
530
- });
531
-
532
- it("should format percentage values", () => {
533
- chart = new DrGaugeChart(mockPivotData, {
534
- chartOptions: { ...mockChartOptionsPercentage },
535
- });
536
- expect(chart.toPercent(180)).toBe("100%");
537
- expect(chart.toPercent(90)).toBe("50%");
538
- expect(chart.toPercent(18)).toBe("10%");
539
- // rounding
540
- expect(chart.toPercent(0.5)).toBe("0%");
541
- expect(chart.toPercent(2)).toBe("1%");
542
- });
543
- });
544
-
545
- describe("formatValueLabel", () => {
546
- it("should return the label html", () => {
547
- const label = chart.formatValueLabel(100, {
548
- label: {
549
- font_size: 16,
550
- font_color: "#000",
551
- show_percentage_in_value: false,
552
- },
553
- gauge: {
554
- colors: {
555
- meta: "#808080",
556
- },
557
- },
558
- });
559
- expect(simplifyString(label)).toBe(
560
- simplifyString(
561
- `<span style="display: flex; flex-direction: column; align-items: center; gap: 6px; font-size: 16px;">
562
- <span style="font-weight: 600; font-size: 1.3em; line-height: 1; color: #000">
563
- ${mockFormattedValue}
564
- </span>
565
- <span style="font-weight: 500; font-size: 0.875em; line-height: 1; color: #808080;">Current status</span>
566
- </span>`
567
- )
568
- );
569
- });
570
-
571
- it("should add percentage", () => {
572
- const label = chart.formatValueLabel(100, {
573
- label: {
574
- font_size: 24,
575
- font_color: "#000",
576
- show_percentage_in_value: true,
577
- },
578
- gauge: {
579
- colors: {
580
- meta: "#929292",
581
- },
582
- },
583
- });
584
- expect(simplifyString(label)).toBe(
585
- simplifyString(
586
- `<span style="display: flex; flex-direction: column; align-items: center; gap: 6px; font-size: 24px;">
587
- <span style="font-weight: 600; font-size: 1.3em; line-height: 1; color: #000">
588
- ${mockFormattedValue}
589
- <span style="font-size: 0.5833em; font-weight: 600; color: #929292;">(56%)</span>
590
- </span>
591
- <span style="font-weight: 500; font-size: 0.875em; line-height: 1; color: #929292;">Current status</span>
592
- </span>`
593
- )
594
- );
595
- });
596
- });
597
-
598
- describe("formatTickLabel", () => {
599
- it("should return the tick label html", () => {
600
- const label = chart.formatTickLabel(100, {
601
- label: {
602
- font_size: 16,
603
- font_color: "#000",
604
- show_percentage_in_segments: false,
605
- },
606
- goal: {
607
- value: 180,
608
- name: "Goal",
609
- },
610
- gauge: {
611
- colors: {
612
- meta: "#808080",
613
- },
614
- },
615
- });
616
-
617
- expect(simplifyString(label)).toBe(
618
- simplifyString(`<span style="
619
- display: flex;
620
- align-items: center;
621
- gap: 4px;
622
- font-weight: 600;
623
- font-size: 16px;
624
- ">
625
- <span style="color: #000;">${mockFormattedValue}</span>
626
- </span>`)
627
- );
628
- });
629
-
630
- it("should add repcentage", () => {
631
- const label = chart.formatTickLabel(100, {
632
- label: {
633
- font_size: 16,
634
- font_color: "#000",
635
- show_percentage_in_segments: true,
636
- },
637
- goal: {
638
- value: 180,
639
- name: "Goal",
640
- },
641
- gauge: {
642
- colors: {
643
- meta: "#808080",
644
- },
645
- },
646
- });
647
-
648
- expect(simplifyString(label)).toBe(
649
- simplifyString(`<span style="
650
- display: flex;
651
- align-items: center;
652
- gap: 4px;
653
- font-weight: 600;
654
- font-size: 16px;
655
- ">
656
- <span style="color: #000;">${mockFormattedValue}</span>
657
- <span style="font-size: 0.75em; color: #808080; font-weight: 400;">(56%)</span>
658
- </span>`)
659
- );
660
- });
661
-
662
- it("should apply extra styles for goal", () => {
663
- const label = chart.formatTickLabel(180, {
664
- label: {
665
- font_size: 16,
666
- font_color: "#000",
667
- show_percentage_in_segments: true,
668
- },
669
- goal: {
670
- value: 180,
671
- name: "Goal",
672
- },
673
- gauge: {
674
- colors: {
675
- meta: "#808080",
676
- goal: "#ff0",
677
- },
678
- },
679
- });
680
-
681
- expect(simplifyString(label)).toBe(
682
- simplifyString(`<span style="
683
- display: flex;
684
- align-items: center;
685
- gap: 4px;
686
- font-weight: 600;
687
- font-size: 16px;
688
- padding-left: 12px;
689
- ">
690
- <span style="font-size: 1.125em; color: #ff0;">${mockFormattedValue}</span>
691
- <span style="font-size: 0.75em; color: #808080; font-weight: 400;">(100%)</span>
692
- </span>`)
693
- );
694
- });
695
-
696
- it("should add goal title", () => {
697
- const label = chart.formatTickLabel(180, {
698
- label: {
699
- font_size: 16,
700
- font_color: "#000",
701
- show_percentage_in_segments: true,
702
- show_goal_name: true,
703
- },
704
- goal: {
705
- value: 180,
706
- title: "Goal",
707
- },
708
- gauge: {
709
- colors: {
710
- meta: "#808080",
711
- goal: "#ff0",
712
- },
713
- },
714
- });
715
-
716
- expect(simplifyString(label)).toBe(
717
- simplifyString(`<span style="
718
- display: flex;
719
- align-items: center;
720
- gap: 4px;
721
- font-weight: 600;
722
- font-size: 16px;
723
- padding-left: 12px;
724
- ">
725
- <span style="font-size: 1.125em; color: #ff0;">${mockFormattedValue}</span>
726
- <span style="font-size: 0.75em; color: #ff0;">Goal</span>
727
- <span style="font-size: 0.75em; color: #808080; font-weight: 400;">(100%)</span>
728
- </span>`)
729
- );
730
- });
731
-
732
- it("should add paddings", () => {
733
- spyOn(chart, "isLeftQuarter").and.returnValues(true, false);
734
-
735
- const labelLeft = chart.formatTickLabel(180, {
736
- label: {
737
- font_size: 16,
738
- font_color: "#000",
739
- show_percentage_in_segments: false,
740
- show_goal_name: false,
741
- },
742
- goal: {
743
- value: 180,
744
- title: "Goal",
745
- },
746
- gauge: {
747
- colors: {
748
- meta: "#808080",
749
- goal: "#ff0",
750
- },
751
- },
752
- });
753
-
754
- expect(simplifyString(labelLeft)).toBe(
755
- simplifyString(`<span style="
756
- display: flex;
757
- align-items: center;
758
- gap: 4px;
759
- font-weight: 600;
760
- font-size: 16px;
761
- padding-right: 12px;
762
- ">
763
- <span style="font-size: 1.125em; color: #ff0;">${mockFormattedValue}</span>
764
- </span>`)
765
- );
766
-
767
- const labelRight = chart.formatTickLabel(180, {
768
- label: {
769
- font_size: 16,
770
- font_color: "#000",
771
- show_percentage_in_segments: false,
772
- show_goal_name: false,
773
- },
774
- goal: {
775
- value: 180,
776
- title: "Goal",
777
- },
778
- gauge: {
779
- colors: {
780
- meta: "#808080",
781
- goal: "#ff0",
782
- },
783
- },
784
- });
785
-
786
- expect(simplifyString(labelRight)).toBe(
787
- simplifyString(`<span style="
788
- display: flex;
789
- align-items: center;
790
- gap: 4px;
791
- font-weight: 600;
792
- font-size: 16px;
793
- padding-left: 12px;
794
- ">
795
- <span style="font-size: 1.125em; color: #ff0;">${mockFormattedValue}</span>
796
- </span>`)
797
- );
798
- });
799
- });
800
-
801
- describe("getValue", () => {
802
- it("should return aggregator value unledss the total is empty", () => {
803
- DrGaugeChart.highchartsRenderer.ptCreateBasicLineSeries.mockReturnValue([]);
804
- expect(DrGaugeChart.getValue(mockPivotData, {})).toBe(mockAggregationValue);
805
- });
806
-
807
- it("should return value to display", () => {
808
- DrGaugeChart.highchartsRenderer.ptCreateBasicLineSeries.mockReturnValue([{ data: [2000] }]);
809
- expect(DrGaugeChart.getValue(mockPivotData, {})).toBe(2000);
810
- });
811
-
812
- it("should calculate total", () => {
813
- DrGaugeChart.highchartsRenderer.ptCreateBasicLineSeries.mockReturnValue([
814
- { data: [2000] },
815
- { data: [3000] },
816
- { data: [5000] },
817
- ]);
818
- expect(DrGaugeChart.getValue(mockPivotData, {})).toBe(10000);
819
- });
820
- });
821
-
822
- describe("getBorderPosition", () => {
823
- const mockChart = {
824
- pane: [
825
- {
826
- options: {
827
- center: [200, 200],
828
- size: 100,
829
- },
830
- },
831
- ],
832
- };
833
-
834
- const mockOptions = {
835
- gauge: {
836
- tickLength: 40,
837
- tickWidth: 2,
838
- },
839
- };
840
-
841
- it("return a start border position", () => {
842
- expect(DrGaugeChart.getBorderPosition(mockChart, mockOptions, "start")).toEqual({
843
- x: 170,
844
- y: 201,
845
- });
846
- });
847
-
848
- it("return an end border position", () => {
849
- expect(DrGaugeChart.getBorderPosition(mockChart, mockOptions, "end")).toEqual({
850
- x: 230,
851
- y: 201,
852
- });
853
- });
854
- });
855
-
856
- describe("createBorder", () => {
857
- beforeEach(() => {
858
- DrGaugeChart.getBorderPosition = jest.fn().mockReturnValue({
859
- x: 100,
860
- y: 200,
861
- });
862
- });
863
-
864
- const toFrontMock = jest.fn();
865
-
866
- const addMock = jest.fn().mockReturnValue({
867
- toFront: toFrontMock,
868
- });
869
-
870
- const attrMock = jest.fn().mockReturnValue({
871
- add: addMock,
872
- });
873
-
874
- const arcMock = jest.fn().mockReturnValue({
875
- attr: attrMock,
876
- });
877
-
878
- const mockChart = {
879
- renderer: {
880
- arc: arcMock,
881
- },
882
- yAxis: [
883
- {
884
- options: {
885
- plotBands: [
886
- {
887
- color: "red",
888
- },
889
- {
890
- color: "blue",
891
- },
892
- {
893
- color: "green",
894
- },
895
- ],
896
- },
897
- },
898
- ],
899
- };
900
-
901
- it("should create a start border", () => {
902
- DrGaugeChart.createBorder(
903
- mockChart,
904
- {
905
- gauge: {
906
- thickness: 10,
907
- },
908
- },
909
- "start"
910
- );
911
- // draw an arc
912
- expect(arcMock).toHaveBeenCalledWith({
913
- x: 100,
914
- y: 200,
915
- r: 5,
916
- innerR: 0,
917
- start: 0,
918
- end: Math.PI,
919
- });
920
- // set color of first segment
921
- expect(attrMock).toHaveBeenCalledWith({
922
- fill: "red",
923
- });
924
- //add to pane
925
- expect(addMock).toHaveBeenCalled();
926
- // move to front
927
- expect(toFrontMock).toHaveBeenCalled();
928
- });
929
-
930
- it("should create an end border", () => {
931
- DrGaugeChart.createBorder(
932
- mockChart,
933
- {
934
- gauge: {
935
- thickness: 20,
936
- },
937
- },
938
- "end"
939
- );
940
- // draw an arc
941
- expect(arcMock).toHaveBeenCalledWith({
942
- x: 100,
943
- y: 200,
944
- r: 10,
945
- innerR: 0,
946
- start: 0,
947
- end: Math.PI,
948
- });
949
- // set color of last segment
950
- expect(attrMock).toHaveBeenCalledWith({
951
- fill: "green",
952
- });
953
- //add to pane
954
- expect(addMock).toHaveBeenCalled();
955
- // move to front
956
- expect(toFrontMock).toHaveBeenCalled();
957
- });
958
- });
959
-
960
- describe("getGoalIconPosition", () => {
961
- it("should return an icon position", () => {
962
- chart.getAngleForValue = jest.fn().mockReturnValue(0);
963
- expect(
964
- chart.getGoalIconPosition(
965
- {
966
- pane: [
967
- {
968
- options: {
969
- center: [100, 100],
970
- size: 100,
971
- },
972
- },
973
- ],
974
- },
975
- {
976
- gauge: {
977
- goalIconSize: [16, 16],
978
- },
979
- goal: {
980
- value: 0,
981
- },
982
- }
983
- )
984
- ).toEqual({
985
- x: 42,
986
- y: 92,
987
- });
988
- expect(chart.getAngleForValue).toHaveBeenCalledWith(0);
989
- chart.getAngleForValue = jest.fn().mockReturnValue(Math.PI / 2);
990
- expect(
991
- chart.getGoalIconPosition(
992
- {
993
- pane: [
994
- {
995
- options: {
996
- center: [200, 200],
997
- size: 200,
998
- },
999
- },
1000
- ],
1001
- },
1002
- {
1003
- gauge: {
1004
- goalIconSize: [24, 24],
1005
- },
1006
- goal: {
1007
- value: 200,
1008
- },
1009
- }
1010
- )
1011
- ).toEqual({
1012
- x: 188,
1013
- y: 88,
1014
- });
1015
- expect(chart.getAngleForValue).toHaveBeenCalledWith(200);
1016
- expect(
1017
- chart.getGoalIconPosition(
1018
- {
1019
- pane: [
1020
- {
1021
- options: {
1022
- center: [500, 500],
1023
- size: 500,
1024
- },
1025
- },
1026
- ],
1027
- },
1028
- {
1029
- gauge: {
1030
- goalIconSize: [50, 50],
1031
- },
1032
- goal: {
1033
- value: 500,
1034
- },
1035
- }
1036
- )
1037
- ).toEqual({
1038
- x: 475,
1039
- y: 225,
1040
- });
1041
- expect(chart.getAngleForValue).toHaveBeenCalledWith(500);
1042
- });
1043
- });
1044
-
1045
- describe("createGoalIcon", () => {
1046
- const toFront = jest.fn();
1047
- const add = jest.fn().mockReturnValue({ toFront });
1048
- const image = jest.fn().mockReturnValue({ add });
1049
-
1050
- beforeEach(() => {
1051
- chart.getGoalIconPosition = jest.fn().mockReturnValue({
1052
- x: 100,
1053
- y: 200,
1054
- });
1055
-
1056
- chart.createGoalIcon(
1057
- {
1058
- renderer: {
1059
- image,
1060
- },
1061
- },
1062
- {
1063
- gauge: {
1064
- goalIcon: "base64hash",
1065
- goalIconSize: [16, 16],
1066
- },
1067
- }
1068
- );
1069
- });
1070
-
1071
- it("should create an goal icon", () => {
1072
- expect(image).toHaveBeenCalledWith("base64hash", 100, 200, 16, 16);
1073
- });
1074
-
1075
- it("should add icon to the plot", () => {
1076
- expect(add).toHaveBeenCalled();
1077
- });
1078
-
1079
- it("should move icon to front", () => {
1080
- expect(toFront).toHaveBeenCalled();
1081
- });
1082
- });
1083
-
1084
- describe("getValueLabelPosition", () => {
1085
- it("should return a value label position depends on the pane center and offsets", () => {
1086
- expect(
1087
- DrGaugeChart.getValueLabelPosition(
1088
- {
1089
- pane: [
1090
- {
1091
- options: {
1092
- center: [500, 300],
1093
- },
1094
- },
1095
- ],
1096
- },
1097
- {
1098
- gauge: {
1099
- valueOffset: [20, 30, 40, 30],
1100
- },
1101
- }
1102
- )
1103
- ).toEqual({
1104
- x: 500,
1105
- y: 320,
1106
- });
1107
-
1108
- expect(
1109
- DrGaugeChart.getValueLabelPosition(
1110
- {
1111
- pane: [
1112
- {
1113
- options: {
1114
- center: [200, 100],
1115
- },
1116
- },
1117
- ],
1118
- },
1119
- {
1120
- gauge: {
1121
- valueOffset: [40, 30, 40, 30],
1122
- },
1123
- }
1124
- )
1125
- ).toEqual({
1126
- x: 200,
1127
- y: 140,
1128
- });
1129
- });
1130
- });
1131
-
1132
- describe("createValueLabel", () => {
1133
- const css = jest.fn().mockReturnValue({});
1134
- const attr = jest.fn().mockReturnValue({ css });
1135
- const toFront = jest.fn().mockReturnValue({ attr });
1136
- const add = jest.fn().mockReturnValue({ toFront });
1137
- const text = jest.fn().mockReturnValue({ add });
1138
-
1139
- beforeEach(() => {
1140
- chart.formatValueLabel = jest.fn().mockReturnValue("<div>Mock label</div>");
1141
- DrGaugeChart.getValueLabelPosition = jest.fn().mockReturnValue({
1142
- x: 100,
1143
- y: 200,
1144
- });
1145
- chart.createValueLabel({
1146
- renderer: {
1147
- text,
1148
- },
1149
- });
1150
- });
1151
-
1152
- it("should create a value label", () => {
1153
- // create label
1154
- expect(text).toHaveBeenCalledWith("<div>Mock label</div>", 0, 0, true);
1155
- // set position
1156
- expect(attr).toHaveBeenCalledWith({
1157
- x: 100,
1158
- y: 200,
1159
- });
1160
- // centering
1161
- expect(css).toHaveBeenCalledWith({ transform: "translateX(-50%)" });
1162
- });
1163
- });
1164
-
1165
- describe("getPaneDimensions", () => {
1166
- const mockChart = {
1167
- chartWidth: 500,
1168
- chartHeight: 500,
1169
- renderer: {
1170
- label: jest.fn().mockReturnValue({
1171
- add: jest.fn().mockReturnValue({
1172
- destroy: jest.fn(),
1173
- bBox: {
1174
- width: 50,
1175
- height: 25,
1176
- },
1177
- }),
1178
- }),
1179
- },
1180
- };
1181
-
1182
- const mockOptions = {
1183
- gauge: {
1184
- offset: [30, 30, 30, 30],
1185
- valueOffset: [20, 20, 20, 20],
1186
- goalIconSize: [16, 16],
1187
- },
1188
- label: {
1189
- show: true,
1190
- },
1191
- goal: {
1192
- value: 100,
1193
- },
1194
- };
1195
-
1196
- beforeEach(() => {
1197
- chart.createValueLabel = jest.fn().mockReturnValue({
1198
- getBBox: jest.fn().mockReturnValue({
1199
- height: 50,
1200
- }),
1201
- destroy: jest.fn(),
1202
- });
1203
- });
1204
-
1205
- it("should calculate a pane dimensions (labels - reserve space - horizontal)", () => {
1206
- chart.getAngleForValue = jest.fn().mockReturnValue(0);
1207
- expect(chart.getPaneDimensions(mockChart, mockOptions)).toEqual({
1208
- center: [250, 380],
1209
- radius: 170,
1210
- });
1211
- });
1212
-
1213
- it("should calculate a pane dimensions (labels - reserve space - )", () => {
1214
- chart.getAngleForValue = jest.fn().mockReturnValue(Math.PI / 4);
1215
-
1216
- expect(chart.getPaneDimensions(mockChart, mockOptions)).toEqual({
1217
- center: [250, 380],
1218
- radius: 220,
1219
- });
1220
- });
1221
-
1222
- it("should calculate a pane dimensions (labels - not reserve space - vertical)", () => {
1223
- chart.getAngleForValue = jest.fn().mockReturnValue(Math.PI / 2);
1224
-
1225
- expect(chart.getPaneDimensions({ ...mockChart, ...{ chartWidth: 1000 } }, mockOptions)).toEqual({
1226
- center: [500, 380],
1227
- radius: 337.5,
1228
- });
1229
- });
1230
-
1231
- it("should calculate a pane dimensions (goal - reserve space - horizontal)", () => {
1232
- chart.getAngleForValue = jest.fn().mockReturnValue(0);
1233
- expect(
1234
- chart.getPaneDimensions(mockChart, {
1235
- ...mockOptions,
1236
- ...{
1237
- label: {
1238
- show: false,
1239
- },
1240
- },
1241
- })
1242
- ).toEqual({
1243
- center: [250, 380],
1244
- radius: 212,
1245
- });
1246
- });
1247
-
1248
- it("should calculate a pane dimensions (goal - not reserve space)", () => {
1249
- chart.getAngleForValue = jest.fn().mockReturnValue(Math.PI / 4);
1250
- expect(
1251
- chart.getPaneDimensions(mockChart, {
1252
- ...mockOptions,
1253
- ...{
1254
- label: {
1255
- show: false,
1256
- },
1257
- },
1258
- })
1259
- ).toEqual({
1260
- center: [250, 380],
1261
- radius: 220,
1262
- });
1263
- });
1264
-
1265
- it("should calculate a pane dimensions (goal - reserve space - vertical)", () => {
1266
- chart.getAngleForValue = jest.fn().mockReturnValue(Math.PI / 2);
1267
- expect(
1268
- chart.getPaneDimensions(
1269
- { ...mockChart, ...{ chartWidth: 1000 } },
1270
- {
1271
- ...mockOptions,
1272
- ...{
1273
- label: {
1274
- show: false,
1275
- },
1276
- },
1277
- }
1278
- )
1279
- ).toEqual({
1280
- center: [500, 380],
1281
- radius: 342,
1282
- });
1283
- });
1284
- });
1285
-
1286
- describe("setTicksStyles", () => {
1287
- it("should align ticks on the left", () => {
1288
- const mockChart = {
1289
- yAxis: [
1290
- {
1291
- ticks: {
1292
- 0: {
1293
- pos: 30,
1294
- css: jest.fn(),
1295
- label: {
1296
- css: jest.fn(),
1297
- },
1298
- },
1299
- 1: {
1300
- pos: 120,
1301
- label: {
1302
- css: jest.fn(),
1303
- },
1304
- },
1305
- 180: {
1306
- pos: 180,
1307
- label: {
1308
- css: jest.fn(),
1309
- },
1310
- mark: {
1311
- attr: jest.fn(),
1312
- },
1313
- },
1314
- },
1315
- },
1316
- ],
1317
- };
1318
-
1319
- chart.setTicksStyles(mockChart, {
1320
- gauge: {
1321
- colors: {
1322
- goal: "blue",
1323
- },
1324
- },
1325
- goal: {
1326
- value: 180,
1327
- },
1328
- });
1329
- // move tick on the left
1330
- expect(mockChart.yAxis[0].ticks[0].label.css).toHaveBeenCalledWith({
1331
- transform: "translate(-100%, 0)",
1332
- });
1333
- // do not move tick on the right
1334
- expect(mockChart.yAxis[0].ticks[1].label.css).toHaveBeenCalledWith({
1335
- transform: "translate(0, 0)",
1336
- });
1337
- });
1338
-
1339
- it("should align ticks on the left", () => {
1340
- const mockChart = {
1341
- yAxis: [
1342
- {
1343
- ticks: {
1344
- 180: {
1345
- pos: 180,
1346
- mark: {
1347
- attr: jest.fn(),
1348
- },
1349
- label: {
1350
- css: jest.fn(),
1351
- },
1352
- },
1353
- },
1354
- },
1355
- ],
1356
- };
1357
-
1358
- chart.setTicksStyles(mockChart, {
1359
- gauge: {
1360
- colors: {
1361
- goal: "blue",
1362
- },
1363
- },
1364
- goal: {
1365
- value: 180,
1366
- },
1367
- });
1368
- // add a goal tick styles
1369
- expect(mockChart.yAxis[0].ticks[180].mark.attr).toHaveBeenCalledWith({
1370
- "pointer-events": "none",
1371
- stroke: "blue",
1372
- "stroke-dasharray": 2,
1373
- });
1374
- });
1375
- });
1376
-
1377
- describe("addTooltips", () => {
1378
- let mockChart;
1379
- let mockOptions;
1380
- let mockInstance;
1381
-
1382
- beforeEach(() => {
1383
- mockChart = {
1384
- yAxis: [
1385
- {
1386
- ticks: {
1387
- 0: { pos: 0, label: { element: "label0" } },
1388
- 50: { pos: 50, label: { element: "label50" } },
1389
- 100: { pos: 100, label: { element: "label100" } },
1390
- },
1391
- plotLinesAndBands: [
1392
- {
1393
- options: { title: "Segment 1" },
1394
- svgElem: { element: "bandElement1" },
1395
- },
1396
- {
1397
- options: { title: "Segment 2" },
1398
- svgElem: { element: "bandElement2" },
1399
- },
1400
- ],
1401
- },
1402
- ],
1403
- label: { element: "labelElement" },
1404
- goalIcon: { element: "goalIconElement" },
1405
- };
1406
-
1407
- mockOptions = {
1408
- tooltips: {
1409
- show: true,
1410
- font_size: 16,
1411
- font_color: "black",
1412
- font_style: "Poppins",
1413
- },
1414
- label: {
1415
- show: true,
1416
- },
1417
- goal: { value: 100, title: "Goal" },
1418
- };
1419
-
1420
- // Mock DrChartTooltip instance
1421
- mockInstance = {
1422
- add: jest.fn(),
1423
- };
1424
- DrChartTooltip.mockImplementation(() => mockInstance);
1425
-
1426
- // Reset mocks
1427
- jest.clearAllMocks();
1428
- });
1429
-
1430
- afterEach(() => {
1431
- jest.restoreAllMocks();
1432
- });
1433
-
1434
- it("should return false unless tooltips is on", () => {
1435
- mockOptions.tooltips.show = false;
1436
- expect(chart.addTooltips(mockChart, mockOptions)).toBe(false);
1437
- });
1438
-
1439
- it("should initialize DrChartTooltip with correct options", () => {
1440
- chart.addTooltips(mockChart, mockOptions);
1441
-
1442
- expect(DrChartTooltip).toHaveBeenCalledWith(mockChart, {
1443
- fontSize: 16,
1444
- fontFamily: "Poppins",
1445
- color: "black",
1446
- });
1447
- });
1448
-
1449
- it("adds tooltips to plotLinesAndBands when show_segment_name is true", () => {
1450
- mockOptions.tooltips.show_segment_name = true;
1451
-
1452
- chart.addTooltips(mockChart, mockOptions);
1453
-
1454
- expect(mockInstance.add).toHaveBeenCalledWith("Segment 1", "bandElement1", { direction: "top", followPointer: true });
1455
- expect(mockInstance.add).toHaveBeenCalledWith("Segment 2", "bandElement2", { direction: "top", followPointer: true });
1456
- });
1457
-
1458
- it("adds percentage tooltip to chart label when show_percentage_in_value is true", () => {
1459
- mockOptions.tooltips.show_percentage_in_value = true;
1460
- const toPercentSpy = jest.spyOn(chart, "toPercent").mockReturnValue("50%");
1461
-
1462
- chart.addTooltips(mockChart, mockOptions);
1463
-
1464
- expect(mockInstance.add).toHaveBeenCalledWith("50%", "labelElement", { direction: "top" });
1465
-
1466
- toPercentSpy.mockRestore();
1467
- });
1468
-
1469
- it("does not add percentage tooltip to chart label when it is shown in label", () => {
1470
- mockOptions.tooltips.show_percentage_in_value = true;
1471
- mockOptions.label.show_percentage_in_value = true;
1472
-
1473
- chart.addTooltips(mockChart, mockOptions);
1474
-
1475
- expect(mockInstance.add).not.toHaveBeenCalled();
1476
- });
1477
-
1478
- it("adds goal tooltip when goal value matches tick position and labels are hidden", () => {
1479
- mockOptions.label.show_goal_name = true;
1480
- mockOptions.label.show = false;
1481
- jest.spyOn(chart, "formatValue").mockReturnValue("100%");
1482
-
1483
- chart.addTooltips(mockChart, mockOptions);
1484
-
1485
- expect(mockInstance.add).toHaveBeenCalledWith('Goal<span style="font-weight: 600">100%</span>', "goalIconElement", {
1486
- direction: "right",
1487
- });
1488
- });
1489
-
1490
- it("adds goal tooltip when goal value matches tick position and labels are hidden (without goal title)", () => {
1491
- mockOptions.label.show_goal_name = false;
1492
- mockOptions.label.show = false;
1493
- jest.spyOn(chart, "formatValue").mockReturnValue("100%");
1494
-
1495
- chart.addTooltips(mockChart, mockOptions);
1496
-
1497
- expect(mockInstance.add).toHaveBeenCalledWith('<span style="font-weight: 600">100%</span>', "goalIconElement", {
1498
- direction: "right",
1499
- });
1500
- });
1501
-
1502
- it("adds goal tooltip when goal value matches tick position and labels are hidden (undefined goal title)", () => {
1503
- mockOptions.label.show_goal_name = true;
1504
- mockOptions.goal.title = undefined;
1505
- mockOptions.label.show = false;
1506
- jest.spyOn(chart, "formatValue").mockReturnValue("100%");
1507
-
1508
- chart.addTooltips(mockChart, mockOptions);
1509
-
1510
- expect(mockInstance.add).toHaveBeenCalledWith('<span style="font-weight: 600">100%</span>', "goalIconElement", {
1511
- direction: "right",
1512
- });
1513
- });
1514
-
1515
- it("adds goal tooltip when goal value matches tick position and labels are hidden (left direction)", () => {
1516
- mockOptions.label.show_goal_name = true;
1517
- mockOptions.label.show = false;
1518
- jest.spyOn(chart, "isLeftQuarter").mockReturnValue(true);
1519
- jest.spyOn(chart, "formatValue").mockReturnValue("100%");
1520
-
1521
- chart.addTooltips(mockChart, mockOptions);
1522
-
1523
- expect(mockInstance.add).toHaveBeenCalledWith('Goal<span style="font-weight: 600">100%</span>', "goalIconElement", {
1524
- direction: "left",
1525
- });
1526
- });
1527
-
1528
- it("adds percentage tooltip to segment labels when show_percentage_in_segments is true", () => {
1529
- jest.spyOn(chart, "toPercent").mockReturnValue("100%");
1530
- mockOptions.tooltips.show_percentage_in_segments = true;
1531
- mockOptions.label.show_percentage_in_segments = false;
1532
- chart.addTooltips(mockChart, mockOptions);
1533
-
1534
- expect(mockInstance.add).toHaveBeenCalledWith("100%", "label0", { direction: "left" });
1535
- expect(mockInstance.add).toHaveBeenCalledWith("100%", "label50", { direction: "left" });
1536
- expect(mockInstance.add).toHaveBeenCalledWith("100%", "label100", { direction: "right" });
1537
- });
1538
- });
1539
-
1540
- describe("setPane", () => {
1541
- let mockChart;
1542
- let mockOptions;
1543
-
1544
- beforeEach(() => {
1545
- // Mock the chart object
1546
- mockChart = {
1547
- pane: [{ options: { size: null, center: null } }],
1548
- yAxis: [
1549
- {
1550
- options: {
1551
- plotBands: [{ outerRadius: null }, { outerRadius: null }],
1552
- },
1553
- },
1554
- ],
1555
- series: [{
1556
- options: {
1557
- dial: {
1558
- radius: '80%'
1559
- }
1560
- }
1561
- }]
1562
- };
1563
-
1564
- // Mock options
1565
- mockOptions = {
1566
- gauge: { tickLength: 20, thickness: 10 },
1567
- };
1568
-
1569
- // Mock getPaneDimensions to return specific values
1570
- jest.spyOn(chart, "getPaneDimensions").mockReturnValue({
1571
- radius: 100,
1572
- center: ["50%", "50%"],
1573
- });
1574
- });
1575
-
1576
- it("calls getPaneDimensions with correct arguments", () => {
1577
- const getPaneDimensionsSpy = jest.spyOn(chart, "getPaneDimensions");
1578
-
1579
- chart.setPane(mockChart, mockOptions);
1580
-
1581
- expect(getPaneDimensionsSpy).toHaveBeenCalledWith(mockChart, mockOptions);
1582
- });
1583
-
1584
- it("updates the pane size and center based on dimensions", () => {
1585
- chart.setPane(mockChart, mockOptions);
1586
-
1587
- expect(mockChart.pane[0].options.size).toBe(200); // 2 * radius
1588
- expect(mockChart.pane[0].options.center).toEqual(["50%", "50%"]);
1589
- });
1590
-
1591
- it("updates the outerRadius of plot bands correctly", () => {
1592
- chart.setPane(mockChart, mockOptions);
1593
-
1594
- const expectedOuterRadius = 100 - (20 - 10) / 2; // radius - (tickLength - thickness) / 2
1595
- mockChart.yAxis[0].options.plotBands.forEach((band) => {
1596
- expect(band.outerRadius).toBe(expectedOuterRadius);
1597
- });
1598
- });
1599
-
1600
- it("updates the dial radius", () => {
1601
- chart.setPane(mockChart, mockOptions);
1602
-
1603
- const expectedDialRadius = Math.round(100 * (100 - 20 - 10) / 100) + '%'; // radius - tickLength - offset) / radius
1604
- expect(mockChart.series[0].options.dial.radius).toBe(expectedDialRadius);
1605
- });
1606
-
1607
- afterEach(() => {
1608
- jest.restoreAllMocks();
1609
- });
1610
- });
1611
-
1612
- describe("setCustomElements", () => {
1613
- let mockChart;
1614
- let mockOptions;
1615
- let mockValueLabel;
1616
- let mockStartBorder;
1617
- let mockEndBorder;
1618
- let mockGoalIcon;
1619
-
1620
- beforeEach(() => {
1621
- // Mock chart object
1622
- mockChart = {};
1623
-
1624
- // Mock options
1625
- mockOptions = {
1626
- someOption: "value", // Add relevant options here
1627
- };
1628
-
1629
- // Mock custom elements
1630
- mockValueLabel = { type: "valueLabel" };
1631
- mockStartBorder = { type: "startBorder" };
1632
- mockEndBorder = { type: "endBorder" };
1633
- mockGoalIcon = { type: "goalIcon" };
1634
-
1635
- // Spy on class methods
1636
- jest.spyOn(chart, "createValueLabel").mockReturnValue(mockValueLabel);
1637
- jest.spyOn(DrGaugeChart, "createBorder").mockImplementation((chart, options, position) => {
1638
- if (position === "start") return mockStartBorder;
1639
- if (position === "end") return mockEndBorder;
1640
- });
1641
- jest.spyOn(chart, "createGoalIcon").mockReturnValue(mockGoalIcon);
1642
- });
1643
-
1644
- afterEach(() => {
1645
- jest.restoreAllMocks();
1646
- });
1647
-
1648
- it("assigns the value label to chart.label", () => {
1649
- chart.setCustomElements(mockChart, mockOptions);
1650
-
1651
- expect(chart.createValueLabel).toHaveBeenCalledWith(mockChart, mockOptions);
1652
- expect(mockChart.label).toBe(mockValueLabel);
1653
- });
1654
-
1655
- it("assigns the start border to chart.startBorder", () => {
1656
- chart.setCustomElements(mockChart, mockOptions);
1657
-
1658
- expect(DrGaugeChart.createBorder).toHaveBeenCalledWith(mockChart, mockOptions, "start");
1659
- expect(mockChart.startBorder).toBe(mockStartBorder);
1660
- });
1661
-
1662
- it("assigns the end border to chart.endBorder", () => {
1663
- chart.setCustomElements(mockChart, mockOptions);
1664
-
1665
- expect(DrGaugeChart.createBorder).toHaveBeenCalledWith(mockChart, mockOptions, "end");
1666
- expect(mockChart.endBorder).toBe(mockEndBorder);
1667
- });
1668
-
1669
- it("assigns the goal icon to chart.goalIcon", () => {
1670
- chart.setCustomElements(mockChart, mockOptions);
1671
-
1672
- expect(chart.createGoalIcon).toHaveBeenCalledWith(mockChart, mockOptions);
1673
- expect(mockChart.goalIcon).toBe(mockGoalIcon);
1674
- });
1675
- });
1676
-
1677
- describe("updateCustomElements", () => {
1678
- let mockChart;
1679
- let mockOptions;
1680
- let mockStartPosition;
1681
- let mockEndPosition;
1682
- let mockGoalIconPosition;
1683
- let mockValueLabelPosition;
1684
-
1685
- beforeEach(() => {
1686
- // Mock chart object with elements having .attr method
1687
- mockChart = {
1688
- startBorder: { attr: jest.fn() },
1689
- endBorder: { attr: jest.fn() },
1690
- goalIcon: { attr: jest.fn() },
1691
- label: { attr: jest.fn() },
1692
- };
1693
-
1694
- // Mock options
1695
- mockOptions = {
1696
- someOption: "value", // Add relevant options here
1697
- };
1698
-
1699
- // Mock positions returned by helper methods
1700
- mockStartPosition = { x: 10, y: 20 };
1701
- mockEndPosition = { x: 30, y: 40 };
1702
- mockGoalIconPosition = { x: 50, y: 60 };
1703
- mockValueLabelPosition = { x: 70, y: 80 };
1704
-
1705
- // Spy on helper methods
1706
- jest.spyOn(DrGaugeChart, "getBorderPosition").mockImplementation((chart, options, position) => {
1707
- if (position === "start") return mockStartPosition;
1708
- if (position === "end") return mockEndPosition;
1709
- });
1710
- jest.spyOn(chart, "getGoalIconPosition").mockReturnValue(mockGoalIconPosition);
1711
- jest.spyOn(DrGaugeChart, "getValueLabelPosition").mockReturnValue(mockValueLabelPosition);
1712
- });
1713
-
1714
- afterEach(() => {
1715
- jest.restoreAllMocks();
1716
- });
1717
-
1718
- it("updates startBorder attributes correctly", () => {
1719
- chart.updateCustomElements(mockChart, mockOptions);
1720
-
1721
- expect(DrGaugeChart.getBorderPosition).toHaveBeenCalledWith(mockChart, mockOptions, "start");
1722
- expect(mockChart.startBorder.attr).toHaveBeenCalledWith(mockStartPosition);
1723
- });
1724
-
1725
- it("updates endBorder attributes correctly", () => {
1726
- chart.updateCustomElements(mockChart, mockOptions);
1727
-
1728
- expect(DrGaugeChart.getBorderPosition).toHaveBeenCalledWith(mockChart, mockOptions, "end");
1729
- expect(mockChart.endBorder.attr).toHaveBeenCalledWith(mockEndPosition);
1730
- });
1731
-
1732
- it("updates goalIcon attributes correctly", () => {
1733
- chart.updateCustomElements(mockChart, mockOptions);
1734
-
1735
- expect(chart.getGoalIconPosition).toHaveBeenCalledWith(mockChart, mockOptions);
1736
- expect(mockChart.goalIcon.attr).toHaveBeenCalledWith(mockGoalIconPosition);
1737
- });
1738
-
1739
- it("updates label attributes correctly", () => {
1740
- chart.updateCustomElements(mockChart, mockOptions);
1741
-
1742
- expect(DrGaugeChart.getValueLabelPosition).toHaveBeenCalledWith(mockChart, mockOptions);
1743
- expect(mockChart.label.attr).toHaveBeenCalledWith(mockValueLabelPosition);
1744
- });
1745
- });
1746
-
1747
- describe("moveCustomElementsToFront", () => {
1748
- let mockChart;
1749
-
1750
- beforeEach(() => {
1751
- // Mock chart object with elements having .toFront method
1752
- mockChart = {
1753
- startBorder: { toFront: jest.fn() },
1754
- endBorder: { toFront: jest.fn() },
1755
- goalIcon: { toFront: jest.fn() },
1756
- };
1757
- });
1758
-
1759
- afterEach(() => {
1760
- jest.clearAllMocks();
1761
- });
1762
-
1763
- it("calls toFront on startBorder", () => {
1764
- chart.moveCustomElementsToFront(mockChart);
1765
- expect(mockChart.startBorder.toFront).toHaveBeenCalled();
1766
- });
1767
-
1768
- it("calls toFront on endBorder", () => {
1769
- chart.moveCustomElementsToFront(mockChart);
1770
- expect(mockChart.endBorder.toFront).toHaveBeenCalled();
1771
- });
1772
-
1773
- it("calls toFront on goalIcon", () => {
1774
- chart.moveCustomElementsToFront(mockChart);
1775
- expect(mockChart.goalIcon.toFront).toHaveBeenCalled();
1776
- });
1777
- });
1778
-
1779
- describe("clampValueToPane", () => {
1780
- let mockMax;
1781
-
1782
- beforeEach(() => {
1783
- // Mock max value
1784
- mockMax = 100;
1785
-
1786
- // Spy on helpers.clamp
1787
- jest.spyOn(helpers, "clamp").mockImplementation((min, value, max) => {
1788
- if (value < min) return min;
1789
- if (value > max) return max;
1790
- return value;
1791
- });
1792
- });
1793
-
1794
- afterEach(() => {
1795
- jest.restoreAllMocks();
1796
- });
1797
-
1798
- it("calls helpers.clamp with correct bounds and value", () => {
1799
- const value = 50;
1800
- const result = chart.clampValueToPane(value, 100, 0);
1801
-
1802
- expect(helpers.clamp).toHaveBeenCalledWith(-2, value, 102);
1803
- expect(result).toBe(value); // Value is within range
1804
- });
1805
-
1806
- it("returns clamped value when below range", () => {
1807
- const value = -1000;
1808
- const result = chart.clampValueToPane(value, 100, -100);
1809
-
1810
- expect(helpers.clamp).toHaveBeenCalledWith(-104, value, 104);
1811
- expect(result).toBe(-104); // Clamped to minimum
1812
- });
1813
-
1814
- it("returns clamped value when above range", () => {
1815
- const value = 200;
1816
- const result = chart.clampValueToPane(value, 100, -100);
1817
-
1818
- expect(helpers.clamp).toHaveBeenCalledWith(-104, value, 104);
1819
- expect(result).toBe(104); // Clamped to maximum
1820
- });
1821
-
1822
- it("uses the deafult max umless it is provided", () => {
1823
- const value = 50;
1824
- const result = chart.clampValueToPane(value);
1825
-
1826
- expect(helpers.clamp).toHaveBeenCalledWith(-3.6, value, 183.6);
1827
- expect(result).toBe(value); // Value is within range
1828
- });
1829
- });
1830
-
1831
- describe("configChart", () => {
1832
- const mockChart = {};
1833
- const mockOptions = {
1834
- segments: [
1835
- {
1836
- from: 0,
1837
- to: 50,
1838
- title: "Low",
1839
- color: "#BF1D30",
1840
- },
1841
- {
1842
- from: 50,
1843
- to: 160,
1844
- title: "Medium",
1845
- color: "#FFA310",
1846
- },
1847
- {
1848
- from: 160,
1849
- to: 200,
1850
- title: "High",
1851
- color: "#037C5A",
1852
- },
1853
- ],
1854
- goal: {
1855
- name: "Goal",
1856
- value: 180,
1857
- },
1858
- isAbsoluteValue: true,
1859
- label: {
1860
- show: true,
1861
- },
1862
- gauge: {
1863
- background: "white",
1864
- tickLength: 40,
1865
- tickWidth: 20,
1866
- pivot: {
1867
- color: "black",
1868
- radius: 10,
1869
- },
1870
- },
1871
- };
1872
-
1873
- beforeEach(() => {
1874
- chart = new DrGaugeChart(mockPivotData, {
1875
- chartOptions: mockOptions,
1876
- });
1877
- });
1878
-
1879
- it("returns a configuration object with the correct structure", () => {
1880
- const config = chart.configChart();
1881
-
1882
- expect(config).toBeInstanceOf(Object);
1883
- expect(config).toHaveProperty("title");
1884
- expect(config).toHaveProperty("subtitle");
1885
- expect(config).toHaveProperty("chart");
1886
- expect(config).toHaveProperty("pane");
1887
- expect(config).toHaveProperty("yAxis");
1888
- expect(config).toHaveProperty("series");
1889
- });
1890
-
1891
- it("hides title", () => {
1892
- const config = chart.configChart();
1893
- expect(config.title).toEqual({
1894
- text: null,
1895
- });
1896
- });
1897
-
1898
- it("hides subtitle", () => {
1899
- const config = chart.configChart();
1900
- expect(config.subtitle).toBe(null);
1901
- });
1902
-
1903
- it("alllows HTML on export", () => {
1904
- const config = chart.configChart();
1905
- expect(config.exporting).toEqual({
1906
- allowHTML: true,
1907
- });
1908
- });
1909
-
1910
- it("sets chart type", () => {
1911
- const config = chart.configChart();
1912
- expect(config.chart.type).toBe("gauge");
1913
- });
1914
-
1915
- it("sets default chart options", () => {
1916
- const config = chart.configChart();
1917
-
1918
- expect(config.chart.backgroundColor).toBe(mockOptions.gauge.background);
1919
- expect(config.chart.plotBackgroundColor).toBe(null);
1920
- expect(config.chart.plotBackgroundImage).toBe(null);
1921
- expect(config.chart.plotBorderWidth).toBe(0);
1922
- expect(config.chart.plotShadow).toBe(false);
1923
- });
1924
-
1925
- it("removes default offsets", () => {
1926
- const config = chart.configChart();
1927
-
1928
- expect(config.chart.margin).toEqual([0, 0, 0, 0]);
1929
- expect(config.chart.spacing).toEqual([0, 0, 0, 0]);
1930
- });
1931
-
1932
- it("sets load event handler", () => {
1933
- const config = chart.configChart();
1934
- chart.addTooltips = jest.fn();
1935
- config.chart.events.load({ target: mockChart });
1936
- expect(chart.addTooltips).toHaveBeenCalled();
1937
- });
1938
-
1939
- it("sets render event handler", () => {
1940
- const config = chart.configChart();
1941
- chart.moveCustomElementsToFront = jest.fn();
1942
- chart.setTicksStyles = jest.fn();
1943
- config.chart.events.render({ target: mockChart });
1944
- expect(chart.moveCustomElementsToFront).toHaveBeenCalled();
1945
- expect(chart.setTicksStyles).toHaveBeenCalled();
1946
- });
1947
-
1948
- it("sets beforeRedraw event handler", () => {
1949
- const config = chart.configChart();
1950
- chart.setPane = jest.fn();
1951
- chart.updateCustomElements = jest.fn();
1952
- config.chart.events.beforeRedraw({ target: mockChart });
1953
- expect(chart.setPane).toHaveBeenCalled();
1954
- expect(chart.updateCustomElements).toHaveBeenCalled();
1955
- });
1956
-
1957
- it("sets beforeRender event handler", () => {
1958
- const config = chart.configChart();
1959
- chart.setPane = jest.fn();
1960
- chart.setCustomElements = jest.fn();
1961
- config.chart.events.beforeRender({ target: mockChart });
1962
- expect(chart.setPane).toHaveBeenCalled();
1963
- expect(chart.setCustomElements).toHaveBeenCalled();
1964
- });
1965
-
1966
- it("sets pane options", () => {
1967
- const config = chart.configChart();
1968
-
1969
- expect(config.pane).toEqual({
1970
- startAngle: -90,
1971
- endAngle: 90,
1972
- background: null,
1973
- center: [0, 0],
1974
- });
1975
- });
1976
-
1977
- it("sets yAxis default options", () => {
1978
- const config = chart.configChart();
1979
-
1980
- expect(config.yAxis.min).toBe(0);
1981
- expect(config.yAxis.max).toBe(200);
1982
- expect(config.yAxis.tickPositions).toEqual([0, 50, 160, 180, 200]);
1983
- expect(config.yAxis.tickColor).toBe(mockOptions.gauge.background);
1984
- expect(config.yAxis.tickLength).toBe(40);
1985
- expect(config.yAxis.tickWidth).toBe(20);
1986
- expect(config.yAxis.minorTickInterval).toBe(null);
1987
- expect(config.yAxis.lineWidth).toBe(0);
1988
- expect(config.yAxis.plotBands).toEqual([
1989
- { color: "#BF1D30", from: 0, thickness: 16, title: "Low", to: 50 },
1990
- { color: "#FFA310", from: 50, thickness: 16, title: "Medium", to: 160 },
1991
- { color: "#037C5A", from: 160, thickness: 16, title: "High", to: 200 },
1992
- ]);
1993
- });
1994
-
1995
- it("sets yAxis labels options", () => {
1996
- const config = chart.configChart();
1997
-
1998
- expect(config.yAxis.labels.enabled).toBe(mockOptions.label.show);
1999
- expect(config.yAxis.labels.enabled).toBe(mockOptions.label.show);
2000
- expect(config.yAxis.labels.distance).toBe(0),
2001
- expect(config.yAxis.labels.verticalAlign).toBe("middle"),
2002
- expect(config.yAxis.labels.allowOverlap).toBe(false),
2003
- expect(config.yAxis.labels.align).toBe("left");
2004
- expect(config.yAxis.labels.style).toEqual({
2005
- whiteSpace: "nowrap",
2006
- width: "auto",
2007
- });
2008
- expect(config.yAxis.labels.useHTML).toBe(true);
2009
- chart.formatTickLabel = jest.fn().mockReturnValue("<span>100.00</span>");
2010
- expect(config.yAxis.labels.formatter({ value: 100 })).toBe("<span>100.00</span>");
2011
- });
2012
-
2013
- it("sets series", () => {
2014
- chart.value = 204;
2015
- const series = chart.configChart().series[0];
2016
-
2017
- expect(series.name).toBe(null);
2018
- expect(series.data).toEqual([204]);
2019
- expect(series.dataLabels).toEqual([
2020
- {
2021
- enabled: false,
2022
- },
2023
- ]);
2024
- expect(series.dial).toEqual({
2025
- radius: "70%",
2026
- backgroundColor: mockOptions.gauge.pivot.color,
2027
- baseWidth: 2 * mockOptions.gauge.pivot.radius,
2028
- baseLength: "0%",
2029
- rearLength: "0%",
2030
- });
2031
- expect(series.pivot).toEqual({
2032
- backgroundColor: mockOptions.gauge.pivot.color,
2033
- radius: mockOptions.gauge.pivot.radius,
2034
- });
2035
- });
2036
- });
2037
- });
2038
-
2039
- function simplifyString(str) {
2040
- return str.replace(/[\s\n\t]/g, "");
2041
- }