@osimatic/helpers-js 1.5.4 → 1.5.6

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,5 +1,35 @@
1
+ /**
2
+ * @jest-environment jsdom
3
+ */
1
4
  const { Chartjs } = require('../chartjs');
2
5
 
6
+ // ─── chart creation helpers ──────────────────────────────────────────────────
7
+
8
+ let mockChartInstance;
9
+
10
+ beforeEach(() => {
11
+ mockChartInstance = { data: null, config: null };
12
+ global.Chart = jest.fn((ctx, config) => {
13
+ mockChartInstance.config = config;
14
+ return mockChartInstance;
15
+ });
16
+ HTMLCanvasElement.prototype.getContext = jest.fn(() => ({}));
17
+ });
18
+
19
+ afterEach(() => {
20
+ delete global.Chart;
21
+ document.body.innerHTML = '';
22
+ jest.restoreAllMocks();
23
+ });
24
+
25
+ function makeCanvas() {
26
+ const canvas = document.createElement('canvas');
27
+ document.body.appendChild(canvas);
28
+ return canvas;
29
+ }
30
+
31
+ // ─── groupByPeriod ───────────────────────────────────────────────────────────
32
+
3
33
  describe('Chartjs', () => {
4
34
  describe('groupByPeriod', () => {
5
35
  test('should group data by day (default)', () => {
@@ -30,8 +60,8 @@ describe('Chartjs', () => {
30
60
 
31
61
  expect(result).toHaveLength(2);
32
62
  expect(result[0].label).toBe('2024-01');
33
- expect(result[0].views).toBe(15); // Average of 10 and 20
34
- expect(result[0].clicks).toBe(6.5); // Average of 5 and 8
63
+ expect(result[0].views).toBe(15);
64
+ expect(result[0].clicks).toBe(6.5);
35
65
  expect(result[1].label).toBe('2024-02');
36
66
  expect(result[1].views).toBe(15);
37
67
  expect(result[1].clicks).toBe(6);
@@ -48,9 +78,7 @@ describe('Chartjs', () => {
48
78
 
49
79
  const result = Chartjs.groupByPeriod(data, 'week', metrics);
50
80
 
51
- // Results should be grouped by weeks
52
81
  expect(result.length).toBeGreaterThan(0);
53
- // Check that labels contain week format (YYYY-SX)
54
82
  result.forEach(item => {
55
83
  expect(item.label).toMatch(/^\d{4}-S\d+$/);
56
84
  });
@@ -79,20 +107,11 @@ describe('Chartjs', () => {
79
107
  const result = Chartjs.groupByPeriod(data, 'day', metrics);
80
108
 
81
109
  expect(result).toHaveLength(1);
82
- expect(result[0]).toEqual({
83
- label: '2024-01-15',
84
- views: 10,
85
- clicks: 5,
86
- conversions: 2
87
- });
110
+ expect(result[0]).toEqual({ label: '2024-01-15', views: 10, clicks: 5, conversions: 2 });
88
111
  });
89
112
 
90
113
  test('should handle empty data', () => {
91
- const data = {};
92
- const metrics = ['views'];
93
-
94
- const result = Chartjs.groupByPeriod(data, 'day', metrics);
95
-
114
+ const result = Chartjs.groupByPeriod({}, 'day', ['views']);
96
115
  expect(result).toEqual([]);
97
116
  });
98
117
 
@@ -102,13 +121,11 @@ describe('Chartjs', () => {
102
121
  '2024-01-15': { score: 200 },
103
122
  '2024-01-20': { score: 300 }
104
123
  };
105
- const metrics = ['score'];
106
-
107
- const result = Chartjs.groupByPeriod(data, 'month', metrics);
124
+ const result = Chartjs.groupByPeriod(data, 'month', ['score']);
108
125
 
109
126
  expect(result).toHaveLength(1);
110
127
  expect(result[0].label).toBe('2024-01');
111
- expect(result[0].score).toBe(200); // Average of 100, 200, 300
128
+ expect(result[0].score).toBe(200);
112
129
  });
113
130
 
114
131
  test('should handle missing metric values', () => {
@@ -116,9 +133,7 @@ describe('Chartjs', () => {
116
133
  '2024-01-15': { views: 10 },
117
134
  '2024-01-16': { views: 20, clicks: 5 }
118
135
  };
119
- const metrics = ['views', 'clicks'];
120
-
121
- const result = Chartjs.groupByPeriod(data, 'day', metrics);
136
+ const result = Chartjs.groupByPeriod(data, 'day', ['views', 'clicks']);
122
137
 
123
138
  expect(result).toHaveLength(2);
124
139
  expect(result[0]).toEqual({ label: '2024-01-15', views: 10, clicks: NaN });
@@ -130,9 +145,7 @@ describe('Chartjs', () => {
130
145
  '2023-12-30': { count: 5 },
131
146
  '2024-01-02': { count: 10 }
132
147
  };
133
- const metrics = ['count'];
134
-
135
- const result = Chartjs.groupByPeriod(data, 'month', metrics);
148
+ const result = Chartjs.groupByPeriod(data, 'month', ['count']);
136
149
 
137
150
  expect(result).toHaveLength(2);
138
151
  expect(result[0].label).toBe('2023-12');
@@ -142,123 +155,126 @@ describe('Chartjs', () => {
142
155
 
143
156
  describe('getAutoGranularity', () => {
144
157
  test('should return day_of_month for data spanning 30 days or less', () => {
145
- const data = {
146
- '2024-01-01': {},
147
- '2024-01-15': {},
148
- '2024-01-30': {}
149
- };
158
+ expect(Chartjs.getAutoGranularity({ '2024-01-01': {}, '2024-01-15': {}, '2024-01-30': {} })).toBe('day_of_month');
159
+ });
150
160
 
151
- const result = Chartjs.getAutoGranularity(data);
161
+ test('should return week for data spanning 31-90 days', () => {
162
+ expect(Chartjs.getAutoGranularity({ '2024-01-01': {}, '2024-03-15': {} })).toBe('week');
163
+ });
152
164
 
153
- expect(result).toBe('day_of_month');
165
+ test('should return month for data spanning more than 90 days', () => {
166
+ expect(Chartjs.getAutoGranularity({ '2024-01-01': {}, '2024-05-01': {} })).toBe('month');
154
167
  });
155
168
 
156
- test('should return week for data spanning 31-90 days', () => {
157
- const data = {
158
- '2024-01-01': {},
159
- '2024-03-15': {} // 74 days
160
- };
169
+ test('should return day_of_month for single day', () => {
170
+ expect(Chartjs.getAutoGranularity({ '2024-01-01': {} })).toBe('day_of_month');
171
+ });
161
172
 
162
- const result = Chartjs.getAutoGranularity(data);
173
+ test('should return week for exactly 31 days', () => {
174
+ expect(Chartjs.getAutoGranularity({ '2024-01-01': {}, '2024-02-01': {} })).toBe('week');
175
+ });
163
176
 
164
- expect(result).toBe('week');
177
+ test('should return week for exactly 90 days', () => {
178
+ expect(Chartjs.getAutoGranularity({ '2024-01-01': {}, '2024-03-31': {} })).toBe('week');
165
179
  });
166
180
 
167
- test('should return month for data spanning more than 90 days', () => {
168
- const data = {
169
- '2024-01-01': {},
170
- '2024-05-01': {} // 121 days
171
- };
181
+ test('should return month for exactly 91 days', () => {
182
+ expect(Chartjs.getAutoGranularity({ '2024-01-01': {}, '2024-04-01': {} })).toBe('month');
183
+ });
172
184
 
173
- const result = Chartjs.getAutoGranularity(data);
185
+ test('should handle dates in random order', () => {
186
+ expect(Chartjs.getAutoGranularity({ '2024-03-01': {}, '2024-01-01': {}, '2024-02-01': {} })).toBe('week');
187
+ });
174
188
 
175
- expect(result).toBe('month');
189
+ test('should return month for data spanning a full year', () => {
190
+ expect(Chartjs.getAutoGranularity({ '2024-01-01': {}, '2024-12-31': {} })).toBe('month');
176
191
  });
192
+ });
177
193
 
178
- test('should return day_of_month for single day', () => {
179
- const data = {
180
- '2024-01-01': {}
181
- };
194
+ describe('chart creation', () => {
195
+ const chartData = { labels: ['A', 'B'], datasets: [{ label: 'X', data: [1, 2] }] };
182
196
 
183
- const result = Chartjs.getAutoGranularity(data);
197
+ test('createStackedChart clears div and calls Chart constructor', () => {
198
+ const canvas = makeCanvas();
199
+ canvas.innerHTML = '<span>old</span>';
184
200
 
185
- expect(result).toBe('day_of_month');
186
- });
201
+ Chartjs.createStackedChart(canvas, chartData);
187
202
 
188
- test('should return day_of_month for 2 days', () => {
189
- const data = {
190
- '2024-01-01': {},
191
- '2024-01-02': {}
192
- };
203
+ expect(canvas.innerHTML).toBe('');
204
+ expect(global.Chart).toHaveBeenCalledWith(expect.anything(), expect.objectContaining({ type: 'bar' }));
205
+ });
193
206
 
194
- const result = Chartjs.getAutoGranularity(data);
207
+ test('createStackedChart merges user options', () => {
208
+ Chartjs.createStackedChart(makeCanvas(), chartData, null, { options: { responsive: false } });
195
209
 
196
- expect(result).toBe('day_of_month');
210
+ expect(mockChartInstance.config.options.responsive).toBe(false);
197
211
  });
198
212
 
199
- test('should return week for exactly 31 days', () => {
200
- const data = {
201
- '2024-01-01': {},
202
- '2024-02-01': {} // 31 days
203
- };
213
+ test('createBarChart clears div and calls Chart constructor', () => {
214
+ const canvas = makeCanvas();
215
+ canvas.innerHTML = '<span>old</span>';
204
216
 
205
- const result = Chartjs.getAutoGranularity(data);
217
+ Chartjs.createBarChart(canvas, chartData);
206
218
 
207
- expect(result).toBe('week');
219
+ expect(canvas.innerHTML).toBe('');
220
+ expect(global.Chart).toHaveBeenCalledWith(expect.anything(), expect.objectContaining({ type: 'bar' }));
208
221
  });
209
222
 
210
- test('should return week for exactly 90 days', () => {
211
- const data = {
212
- '2024-01-01': {},
213
- '2024-03-31': {} // 90 days
214
- };
215
-
216
- const result = Chartjs.getAutoGranularity(data);
223
+ test('createBarChart sets title when provided', () => {
224
+ Chartjs.createBarChart(makeCanvas(), chartData, 'My Title');
217
225
 
218
- expect(result).toBe('week');
226
+ expect(mockChartInstance.config.options.plugins.title.display).toBe(true);
227
+ expect(mockChartInstance.config.options.plugins.title.text).toBe('My Title');
219
228
  });
220
229
 
221
- test('should return month for exactly 91 days', () => {
222
- const data = {
223
- '2024-01-01': {},
224
- '2024-04-01': {} // 91 days
225
- };
230
+ test('createLineChart clears div and calls Chart constructor', () => {
231
+ const canvas = makeCanvas();
232
+ Chartjs.createLineChart(canvas, chartData);
233
+
234
+ expect(canvas.innerHTML).toBe('');
235
+ expect(global.Chart).toHaveBeenCalledWith(expect.anything(), expect.objectContaining({ type: 'line' }));
236
+ });
226
237
 
227
- const result = Chartjs.getAutoGranularity(data);
238
+ test('createDoughnutChart clears div and calls Chart constructor', () => {
239
+ const canvas = makeCanvas();
240
+ Chartjs.createDoughnutChart(canvas, { labels: ['A'], values: [1], colors: ['#f00'] });
228
241
 
229
- expect(result).toBe('month');
242
+ expect(canvas.innerHTML).toBe('');
243
+ expect(global.Chart).toHaveBeenCalledWith(expect.anything(), expect.objectContaining({ type: 'doughnut' }));
230
244
  });
231
245
 
232
- test('should handle dates in random order', () => {
233
- const data = {
234
- '2024-03-01': {},
235
- '2024-01-01': {},
236
- '2024-02-01': {}
237
- };
246
+ test('createDoughnutChart uses chartData.values as dataset data', () => {
247
+ Chartjs.createDoughnutChart(makeCanvas(), { labels: ['A', 'B'], values: [30, 70], colors: ['#f00', '#00f'] });
248
+
249
+ expect(mockChartInstance.config.data.datasets[0].data).toEqual([30, 70]);
250
+ });
238
251
 
239
- const result = Chartjs.getAutoGranularity(data);
252
+ test('title not displayed when null', () => {
253
+ Chartjs.createBarChart(makeCanvas(), chartData, null);
240
254
 
241
- // Should calculate from first to last date (Jan 1 to Mar 1 = ~59 days)
242
- expect(result).toBe('week');
255
+ expect(mockChartInstance.config.options.plugins.title.display).toBe(false);
243
256
  });
244
257
 
245
- test('should return month for data spanning a full year', () => {
246
- const data = {
247
- '2024-01-01': {},
248
- '2024-12-31': {} // 365 days
249
- };
258
+ describe('jQuery compatibility (toEl)', () => {
259
+ test('createStackedChart accepts jQuery-like object', () => {
260
+ const canvas = makeCanvas();
261
+ const jq = { jquery: '3.6.0', 0: canvas, length: 1 };
250
262
 
251
- const result = Chartjs.getAutoGranularity(data);
263
+ expect(() => Chartjs.createStackedChart(jq, chartData)).not.toThrow();
264
+ expect(global.Chart).toHaveBeenCalled();
265
+ });
252
266
 
253
- expect(result).toBe('month');
254
- });
255
- });
267
+ test('createBarChart accepts jQuery-like object', () => {
268
+ const canvas = makeCanvas();
269
+ const jq = { jquery: '3.6.0', 0: canvas, length: 1 };
256
270
 
257
- describe('Chartjs class structure', () => {
258
- test('should be a class', () => {
259
- expect(typeof Chartjs).toBe('function');
271
+ expect(() => Chartjs.createBarChart(jq, chartData)).not.toThrow();
272
+ expect(global.Chart).toHaveBeenCalled();
273
+ });
260
274
  });
275
+ });
261
276
 
277
+ describe('class structure', () => {
262
278
  test('should have all expected static methods', () => {
263
279
  expect(typeof Chartjs.init).toBe('function');
264
280
  expect(typeof Chartjs.createStackedChart).toBe('function');