@cubejs-client/core 1.6.32 → 1.6.34
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.
- package/dist/cubejs-client-core.cjs.js +20 -14
- package/dist/cubejs-client-core.cjs.js.map +1 -1
- package/dist/cubejs-client-core.umd.js +20 -14
- package/dist/cubejs-client-core.umd.js.map +1 -1
- package/dist/src/ResultSet.d.ts.map +1 -1
- package/dist/src/ResultSet.js +20 -13
- package/dist/src/format-d3-numeric-locale.d.ts +4 -0
- package/dist/src/format-d3-numeric-locale.d.ts.map +1 -0
- package/dist/src/format-d3-numeric-locale.js +103 -0
- package/dist/src/format.d.ts +17 -0
- package/dist/src/format.d.ts.map +1 -0
- package/dist/src/format.js +89 -0
- package/dist/src/index.js +2 -0
- package/dist/src/types.d.ts +13 -0
- package/dist/src/types.d.ts.map +1 -1
- package/dist/test/CubeApi.test.js +37 -37
- package/dist/test/HttpTransport.test.js +3 -3
- package/dist/test/ResultSet.bench.d.ts +2 -0
- package/dist/test/ResultSet.bench.d.ts.map +1 -0
- package/dist/test/ResultSet.bench.js +109 -0
- package/dist/test/ResultSet.test.d.ts +1 -1
- package/dist/test/ResultSet.test.d.ts.map +1 -1
- package/dist/test/ResultSet.test.js +0 -2
- package/dist/test/SqlQuery.test.js +0 -1
- package/dist/test/compare-date-range.test.d.ts +1 -1
- package/dist/test/compare-date-range.test.d.ts.map +1 -1
- package/dist/test/compare-date-range.test.js +0 -2
- package/dist/test/data-blending.test.d.ts +1 -1
- package/dist/test/data-blending.test.d.ts.map +1 -1
- package/dist/test/data-blending.test.js +0 -2
- package/dist/test/dayjs-isolation.test.d.ts +1 -1
- package/dist/test/dayjs-isolation.test.d.ts.map +1 -1
- package/dist/test/dayjs-isolation.test.js +0 -2
- package/dist/test/default-heuristics.test.d.ts +1 -1
- package/dist/test/default-heuristics.test.d.ts.map +1 -1
- package/dist/test/default-heuristics.test.js +4 -5
- package/dist/test/drill-down.test.d.ts +1 -1
- package/dist/test/drill-down.test.d.ts.map +1 -1
- package/dist/test/drill-down.test.js +4 -5
- package/dist/test/format-no-intl.test.d.ts +2 -0
- package/dist/test/format-no-intl.test.d.ts.map +1 -0
- package/dist/test/format-no-intl.test.js +49 -0
- package/dist/test/format.test.d.ts +2 -0
- package/dist/test/format.test.d.ts.map +1 -0
- package/dist/test/format.test.js +87 -0
- package/dist/test/granularity.test.d.ts +1 -1
- package/dist/test/granularity.test.d.ts.map +1 -1
- package/dist/test/granularity.test.js +0 -2
- package/dist/test/index.test.js +2 -2
- package/dist/test/table.test.d.ts +1 -1
- package/dist/test/table.test.d.ts.map +1 -1
- package/dist/test/table.test.js +0 -2
- package/dist/test/utils.test.d.ts +1 -1
- package/dist/test/utils.test.d.ts.map +1 -1
- package/dist/test/utils.test.js +0 -2
- package/package.json +12 -9
|
@@ -3,8 +3,8 @@
|
|
|
3
3
|
* @copyright Cube Dev, Inc.
|
|
4
4
|
* @fileoverview Test signal parameter in CubeApi
|
|
5
5
|
*/
|
|
6
|
-
/* globals describe,test,expect,jest,beforeEach */
|
|
7
6
|
/* eslint-disable import/first */
|
|
7
|
+
import { vi } from 'vitest';
|
|
8
8
|
import { CubeApi as CubeApiOriginal } from '../src';
|
|
9
9
|
import HttpTransport from '../src/HttpTransport';
|
|
10
10
|
import RequestError from '../src/RequestError';
|
|
@@ -31,12 +31,12 @@ describe('CubeApi Constructor', () => {
|
|
|
31
31
|
});
|
|
32
32
|
describe('CubeApi Load', () => {
|
|
33
33
|
afterEach(() => {
|
|
34
|
-
|
|
35
|
-
|
|
34
|
+
vi.clearAllMocks();
|
|
35
|
+
vi.restoreAllMocks();
|
|
36
36
|
});
|
|
37
37
|
test('simple query, no options', async () => {
|
|
38
38
|
// Create a spy on the request method
|
|
39
|
-
|
|
39
|
+
vi.spyOn(HttpTransport.prototype, 'request').mockImplementation(() => ({
|
|
40
40
|
subscribe: (cb) => Promise.resolve(cb({
|
|
41
41
|
status: 200,
|
|
42
42
|
text: () => Promise.resolve(JSON.stringify(DescriptiveQueryResponse)),
|
|
@@ -52,7 +52,7 @@ describe('CubeApi Load', () => {
|
|
|
52
52
|
});
|
|
53
53
|
test('simple query + { mutexKey, castNumerics }', async () => {
|
|
54
54
|
// Create a spy on the request method
|
|
55
|
-
|
|
55
|
+
vi.spyOn(HttpTransport.prototype, 'request').mockImplementation(() => ({
|
|
56
56
|
subscribe: (cb) => Promise.resolve(cb({
|
|
57
57
|
status: 200,
|
|
58
58
|
text: () => Promise.resolve(JSON.stringify(DescriptiveQueryResponse)),
|
|
@@ -68,7 +68,7 @@ describe('CubeApi Load', () => {
|
|
|
68
68
|
});
|
|
69
69
|
test('simple query + compact response format', async () => {
|
|
70
70
|
// Create a spy on the request method
|
|
71
|
-
|
|
71
|
+
vi.spyOn(HttpTransport.prototype, 'request').mockImplementation(() => ({
|
|
72
72
|
subscribe: (cb) => Promise.resolve(cb({
|
|
73
73
|
status: 200,
|
|
74
74
|
text: () => Promise.resolve(JSON.stringify(DescriptiveQueryResponse)),
|
|
@@ -84,7 +84,7 @@ describe('CubeApi Load', () => {
|
|
|
84
84
|
});
|
|
85
85
|
test('2 queries', async () => {
|
|
86
86
|
// Create a spy on the request method
|
|
87
|
-
|
|
87
|
+
vi.spyOn(HttpTransport.prototype, 'request').mockImplementation(() => ({
|
|
88
88
|
subscribe: (cb) => Promise.resolve(cb({
|
|
89
89
|
status: 200,
|
|
90
90
|
text: () => Promise.resolve(JSON.stringify(DescriptiveQueryResponse)),
|
|
@@ -99,7 +99,7 @@ describe('CubeApi Load', () => {
|
|
|
99
99
|
expect(res.rawData()).toEqual(DescriptiveQueryResponse.results[0].data);
|
|
100
100
|
});
|
|
101
101
|
test('simple query + { cache: "no-cache" }', async () => {
|
|
102
|
-
const requestSpy =
|
|
102
|
+
const requestSpy = vi.spyOn(HttpTransport.prototype, 'request').mockImplementation(() => ({
|
|
103
103
|
subscribe: (cb) => Promise.resolve(cb({
|
|
104
104
|
status: 200,
|
|
105
105
|
text: () => Promise.resolve(JSON.stringify(DescriptiveQueryResponse)),
|
|
@@ -115,7 +115,7 @@ describe('CubeApi Load', () => {
|
|
|
115
115
|
expect(requestSpy.mock.calls[0]?.[1]?.cache).toBe('no-cache');
|
|
116
116
|
});
|
|
117
117
|
test('simple query + { cache: "must-revalidate" }', async () => {
|
|
118
|
-
const requestSpy =
|
|
118
|
+
const requestSpy = vi.spyOn(HttpTransport.prototype, 'request').mockImplementation(() => ({
|
|
119
119
|
subscribe: (cb) => Promise.resolve(cb({
|
|
120
120
|
status: 200,
|
|
121
121
|
text: () => Promise.resolve(JSON.stringify(DescriptiveQueryResponse)),
|
|
@@ -132,7 +132,7 @@ describe('CubeApi Load', () => {
|
|
|
132
132
|
});
|
|
133
133
|
test('2 queries + compact response format', async () => {
|
|
134
134
|
// Create a spy on the request method
|
|
135
|
-
|
|
135
|
+
vi.spyOn(HttpTransport.prototype, 'request').mockImplementation(() => ({
|
|
136
136
|
subscribe: (cb) => Promise.resolve(cb({
|
|
137
137
|
status: 200,
|
|
138
138
|
text: () => Promise.resolve(JSON.stringify(DescriptiveQueryResponse)),
|
|
@@ -149,14 +149,14 @@ describe('CubeApi Load', () => {
|
|
|
149
149
|
});
|
|
150
150
|
describe('CubeApi with Abort Signal', () => {
|
|
151
151
|
afterEach(() => {
|
|
152
|
-
|
|
153
|
-
|
|
152
|
+
vi.clearAllMocks();
|
|
153
|
+
vi.restoreAllMocks();
|
|
154
154
|
});
|
|
155
155
|
test('should pass signal from constructor to request', async () => {
|
|
156
156
|
const controller = new AbortController();
|
|
157
157
|
const { signal } = controller;
|
|
158
158
|
// Create a spy on the request method
|
|
159
|
-
const requestSpy =
|
|
159
|
+
const requestSpy = vi.spyOn(HttpTransport.prototype, 'request').mockImplementation(() => ({
|
|
160
160
|
subscribe: (cb) => Promise.resolve(cb({
|
|
161
161
|
status: 200,
|
|
162
162
|
text: () => Promise.resolve('{"results":[]}'),
|
|
@@ -168,7 +168,7 @@ describe('CubeApi with Abort Signal', () => {
|
|
|
168
168
|
signal
|
|
169
169
|
});
|
|
170
170
|
// Create a second spy on the load method to verify signal is passed to HttpTransport
|
|
171
|
-
|
|
171
|
+
vi.spyOn(cubeApi, 'load');
|
|
172
172
|
await cubeApi.load({
|
|
173
173
|
measures: ['Orders.count']
|
|
174
174
|
});
|
|
@@ -187,7 +187,7 @@ describe('CubeApi with Abort Signal', () => {
|
|
|
187
187
|
const controller = new AbortController();
|
|
188
188
|
const { signal } = controller;
|
|
189
189
|
// Mock for this specific test
|
|
190
|
-
const requestSpy =
|
|
190
|
+
const requestSpy = vi.spyOn(HttpTransport.prototype, 'request').mockImplementation(() => ({
|
|
191
191
|
subscribe: (cb) => Promise.resolve(cb({
|
|
192
192
|
status: 200,
|
|
193
193
|
text: () => Promise.resolve('{"results":[]}'),
|
|
@@ -205,7 +205,7 @@ describe('CubeApi with Abort Signal', () => {
|
|
|
205
205
|
const constructorController = new AbortController();
|
|
206
206
|
const optionsController = new AbortController();
|
|
207
207
|
// Mock for this specific test
|
|
208
|
-
const requestSpy =
|
|
208
|
+
const requestSpy = vi.spyOn(HttpTransport.prototype, 'request').mockImplementation(() => ({
|
|
209
209
|
subscribe: (cb) => Promise.resolve(cb({
|
|
210
210
|
status: 200,
|
|
211
211
|
text: () => Promise.resolve('{"results":[]}'),
|
|
@@ -225,7 +225,7 @@ describe('CubeApi with Abort Signal', () => {
|
|
|
225
225
|
const controller = new AbortController();
|
|
226
226
|
const { signal } = controller;
|
|
227
227
|
// Mock for meta with proper format - include dimensions, segments, and measures with required properties
|
|
228
|
-
const requestSpy =
|
|
228
|
+
const requestSpy = vi.spyOn(HttpTransport.prototype, 'request').mockImplementation(() => ({
|
|
229
229
|
subscribe: (cb) => Promise.resolve(cb({
|
|
230
230
|
status: 200,
|
|
231
231
|
text: () => Promise.resolve(JSON.stringify({
|
|
@@ -277,7 +277,7 @@ describe('CubeApi with Abort Signal', () => {
|
|
|
277
277
|
const controller = new AbortController();
|
|
278
278
|
const { signal } = controller;
|
|
279
279
|
// Mock for SQL response
|
|
280
|
-
const requestSpy =
|
|
280
|
+
const requestSpy = vi.spyOn(HttpTransport.prototype, 'request').mockImplementation(() => ({
|
|
281
281
|
subscribe: (cb) => Promise.resolve(cb({
|
|
282
282
|
status: 200,
|
|
283
283
|
text: () => Promise.resolve('{"sql":{"sql":"SELECT * FROM orders"}}'),
|
|
@@ -295,7 +295,7 @@ describe('CubeApi with Abort Signal', () => {
|
|
|
295
295
|
const controller = new AbortController();
|
|
296
296
|
const { signal } = controller;
|
|
297
297
|
// Mock for dryRun response
|
|
298
|
-
const requestSpy =
|
|
298
|
+
const requestSpy = vi.spyOn(HttpTransport.prototype, 'request').mockImplementation(() => ({
|
|
299
299
|
subscribe: (cb) => Promise.resolve(cb({
|
|
300
300
|
status: 200,
|
|
301
301
|
text: () => Promise.resolve('{"queryType":"regular"}'),
|
|
@@ -312,8 +312,8 @@ describe('CubeApi with Abort Signal', () => {
|
|
|
312
312
|
});
|
|
313
313
|
describe('CubeApi cubeSql', () => {
|
|
314
314
|
afterEach(() => {
|
|
315
|
-
|
|
316
|
-
|
|
315
|
+
vi.clearAllMocks();
|
|
316
|
+
vi.restoreAllMocks();
|
|
317
317
|
});
|
|
318
318
|
const cubeSqlResponseBody = [
|
|
319
319
|
JSON.stringify({
|
|
@@ -335,7 +335,7 @@ describe('CubeApi cubeSql', () => {
|
|
|
335
335
|
JSON.stringify({ data: [['Active']] }),
|
|
336
336
|
].join('\n');
|
|
337
337
|
test('should parse lastRefreshTime from response', async () => {
|
|
338
|
-
|
|
338
|
+
vi.spyOn(HttpTransport.prototype, 'request').mockImplementation(() => ({
|
|
339
339
|
subscribe: (cb) => Promise.resolve(cb({
|
|
340
340
|
status: 200,
|
|
341
341
|
text: () => Promise.resolve(JSON.stringify({ error: cubeSqlResponseBody })),
|
|
@@ -357,7 +357,7 @@ describe('CubeApi cubeSql', () => {
|
|
|
357
357
|
]);
|
|
358
358
|
});
|
|
359
359
|
test('should omit lastRefreshTime when not present in response', async () => {
|
|
360
|
-
|
|
360
|
+
vi.spyOn(HttpTransport.prototype, 'request').mockImplementation(() => ({
|
|
361
361
|
subscribe: (cb) => Promise.resolve(cb({
|
|
362
362
|
status: 200,
|
|
363
363
|
text: () => Promise.resolve(JSON.stringify({ error: cubeSqlResponseBodyNoRefreshTime })),
|
|
@@ -374,12 +374,12 @@ describe('CubeApi cubeSql', () => {
|
|
|
374
374
|
});
|
|
375
375
|
describe('CubeApi with baseRequestId', () => {
|
|
376
376
|
afterEach(() => {
|
|
377
|
-
|
|
378
|
-
|
|
377
|
+
vi.clearAllMocks();
|
|
378
|
+
vi.restoreAllMocks();
|
|
379
379
|
});
|
|
380
380
|
test('should pass baseRequestId from options to request', async () => {
|
|
381
381
|
const baseRequestId = 'custom-request-id-123';
|
|
382
|
-
const requestSpy =
|
|
382
|
+
const requestSpy = vi.spyOn(HttpTransport.prototype, 'request').mockImplementation(() => ({
|
|
383
383
|
subscribe: (cb) => Promise.resolve(cb({
|
|
384
384
|
status: 200,
|
|
385
385
|
text: () => Promise.resolve('{"results":[]}'),
|
|
@@ -394,7 +394,7 @@ describe('CubeApi with baseRequestId', () => {
|
|
|
394
394
|
expect(requestSpy.mock.calls[0]?.[1]?.baseRequestId).toBe(baseRequestId);
|
|
395
395
|
});
|
|
396
396
|
test('should generate baseRequestId if not provided', async () => {
|
|
397
|
-
const requestSpy =
|
|
397
|
+
const requestSpy = vi.spyOn(HttpTransport.prototype, 'request').mockImplementation(() => ({
|
|
398
398
|
subscribe: (cb) => Promise.resolve(cb({
|
|
399
399
|
status: 200,
|
|
400
400
|
text: () => Promise.resolve('{"results":[]}'),
|
|
@@ -412,7 +412,7 @@ describe('CubeApi with baseRequestId', () => {
|
|
|
412
412
|
});
|
|
413
413
|
test('should pass baseRequestId to sql request', async () => {
|
|
414
414
|
const baseRequestId = 'sql-request-id-456';
|
|
415
|
-
const requestSpy =
|
|
415
|
+
const requestSpy = vi.spyOn(HttpTransport.prototype, 'request').mockImplementation(() => ({
|
|
416
416
|
subscribe: (cb) => Promise.resolve(cb({
|
|
417
417
|
status: 200,
|
|
418
418
|
text: () => Promise.resolve('{"sql":{"sql":"SELECT * FROM orders"}}'),
|
|
@@ -428,7 +428,7 @@ describe('CubeApi with baseRequestId', () => {
|
|
|
428
428
|
});
|
|
429
429
|
test('should pass baseRequestId to dryRun request', async () => {
|
|
430
430
|
const baseRequestId = 'dryrun-request-id-789';
|
|
431
|
-
const requestSpy =
|
|
431
|
+
const requestSpy = vi.spyOn(HttpTransport.prototype, 'request').mockImplementation(() => ({
|
|
432
432
|
subscribe: (cb) => Promise.resolve(cb({
|
|
433
433
|
status: 200,
|
|
434
434
|
text: () => Promise.resolve('{"queryType":"regular"}'),
|
|
@@ -444,7 +444,7 @@ describe('CubeApi with baseRequestId', () => {
|
|
|
444
444
|
});
|
|
445
445
|
test('should pass baseRequestId to subscribe request', async () => {
|
|
446
446
|
const baseRequestId = 'subscribe-request-id-abc';
|
|
447
|
-
const requestSpy =
|
|
447
|
+
const requestSpy = vi.spyOn(HttpTransport.prototype, 'request').mockImplementation(() => ({
|
|
448
448
|
subscribe: (cb) => Promise.resolve(cb({
|
|
449
449
|
status: 200,
|
|
450
450
|
text: () => Promise.resolve('{"results":[]}'),
|
|
@@ -465,7 +465,7 @@ describe('CubeApi with baseRequestId', () => {
|
|
|
465
465
|
});
|
|
466
466
|
test('should pass baseRequestId with multiple queries', async () => {
|
|
467
467
|
const baseRequestId = 'multi-query-request-id';
|
|
468
|
-
const requestSpy =
|
|
468
|
+
const requestSpy = vi.spyOn(HttpTransport.prototype, 'request').mockImplementation(() => ({
|
|
469
469
|
subscribe: (cb) => Promise.resolve(cb({
|
|
470
470
|
status: 200,
|
|
471
471
|
text: () => Promise.resolve(JSON.stringify(DescriptiveQueryResponse)),
|
|
@@ -484,7 +484,7 @@ describe('CubeApi with baseRequestId', () => {
|
|
|
484
484
|
});
|
|
485
485
|
test('should pass baseRequestId to meta request', async () => {
|
|
486
486
|
const baseRequestId = 'meta-request-id-def';
|
|
487
|
-
const requestSpy =
|
|
487
|
+
const requestSpy = vi.spyOn(HttpTransport.prototype, 'request').mockImplementation(() => ({
|
|
488
488
|
subscribe: (cb) => Promise.resolve(cb({
|
|
489
489
|
status: 200,
|
|
490
490
|
text: () => Promise.resolve(JSON.stringify({
|
|
@@ -535,11 +535,11 @@ describe('CubeApi with baseRequestId', () => {
|
|
|
535
535
|
});
|
|
536
536
|
describe('CubeApi Mutex Cancellation', () => {
|
|
537
537
|
afterEach(() => {
|
|
538
|
-
|
|
539
|
-
|
|
538
|
+
vi.clearAllMocks();
|
|
539
|
+
vi.restoreAllMocks();
|
|
540
540
|
});
|
|
541
541
|
test('should return null for cancelled query when a newer query invalidates it', async () => {
|
|
542
|
-
|
|
542
|
+
vi.spyOn(HttpTransport.prototype, 'request').mockImplementation(() => ({
|
|
543
543
|
subscribe: (cb) => Promise.resolve(cb({
|
|
544
544
|
status: 200,
|
|
545
545
|
text: () => Promise.resolve(JSON.stringify(DescriptiveQueryResponse)),
|
|
@@ -562,7 +562,7 @@ describe('CubeApi Mutex Cancellation', () => {
|
|
|
562
562
|
expect(second).toBeInstanceOf(ResultSet);
|
|
563
563
|
});
|
|
564
564
|
test('should return ResultSet when no mutex cancellation occurs', async () => {
|
|
565
|
-
|
|
565
|
+
vi.spyOn(HttpTransport.prototype, 'request').mockImplementation(() => ({
|
|
566
566
|
subscribe: (cb) => Promise.resolve(cb({
|
|
567
567
|
status: 200,
|
|
568
568
|
text: () => Promise.resolve(JSON.stringify(DescriptiveQueryResponse)),
|
|
@@ -579,7 +579,7 @@ describe('CubeApi Mutex Cancellation', () => {
|
|
|
579
579
|
});
|
|
580
580
|
test('should propagate non-mutex errors', async () => {
|
|
581
581
|
const errorBody = { error: 'Internal Server Error' };
|
|
582
|
-
|
|
582
|
+
vi.spyOn(HttpTransport.prototype, 'request').mockImplementation(() => ({
|
|
583
583
|
subscribe: (cb) => Promise.resolve(cb({
|
|
584
584
|
status: 500,
|
|
585
585
|
text: () => Promise.resolve(JSON.stringify(errorBody)),
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/* eslint-disable import/first */
|
|
2
|
-
|
|
2
|
+
import { vi } from 'vitest';
|
|
3
3
|
import fetch from 'cross-fetch';
|
|
4
|
-
|
|
4
|
+
vi.mock('cross-fetch');
|
|
5
5
|
import HttpTransport from '../src/HttpTransport';
|
|
6
6
|
const mockedFetch = fetch;
|
|
7
7
|
describe('HttpTransport', () => {
|
|
@@ -183,7 +183,7 @@ describe('HttpTransport', () => {
|
|
|
183
183
|
// Mock AbortSignal.timeout
|
|
184
184
|
const originalTimeout = AbortSignal.timeout;
|
|
185
185
|
const mockTimeoutSignal = {};
|
|
186
|
-
AbortSignal.timeout =
|
|
186
|
+
AbortSignal.timeout = vi.fn().mockReturnValue(mockTimeoutSignal);
|
|
187
187
|
const transport = new HttpTransport({
|
|
188
188
|
authorization: 'token',
|
|
189
189
|
apiUrl: 'http://localhost:4000/cubejs-api/v1',
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ResultSet.bench.d.ts","sourceRoot":"","sources":["../../test/ResultSet.bench.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
import { bench, describe } from 'vitest';
|
|
2
|
+
import ResultSet from '../src/ResultSet';
|
|
3
|
+
const STATUSES = ['completed', 'processing', 'shipped'];
|
|
4
|
+
function generateLoadResponse(rowCount) {
|
|
5
|
+
const data = [];
|
|
6
|
+
const startDate = new Date('2020-01-01T00:00:00.000Z');
|
|
7
|
+
for (let i = 0; i < rowCount; i++) {
|
|
8
|
+
const date = new Date(startDate.getTime() + i * 86400000);
|
|
9
|
+
const dateStr = date.toISOString().replace('Z', '');
|
|
10
|
+
data.push({
|
|
11
|
+
'Orders.createdAt.day': dateStr,
|
|
12
|
+
'Orders.createdAt': dateStr,
|
|
13
|
+
'Orders.status': STATUSES[i % 3],
|
|
14
|
+
'Orders.count': String(Math.floor(Math.random() * 1000)),
|
|
15
|
+
});
|
|
16
|
+
}
|
|
17
|
+
return {
|
|
18
|
+
query: {
|
|
19
|
+
measures: ['Orders.count'],
|
|
20
|
+
dimensions: ['Orders.status'],
|
|
21
|
+
timeDimensions: [
|
|
22
|
+
{
|
|
23
|
+
dimension: 'Orders.createdAt',
|
|
24
|
+
granularity: 'day',
|
|
25
|
+
},
|
|
26
|
+
],
|
|
27
|
+
},
|
|
28
|
+
data,
|
|
29
|
+
lastRefreshTime: '2024-01-01T00:00:00.000Z',
|
|
30
|
+
usedPreAggregations: {},
|
|
31
|
+
annotation: {
|
|
32
|
+
measures: {
|
|
33
|
+
'Orders.count': {
|
|
34
|
+
title: 'Orders Count',
|
|
35
|
+
shortTitle: 'Count',
|
|
36
|
+
type: 'number',
|
|
37
|
+
},
|
|
38
|
+
},
|
|
39
|
+
dimensions: {
|
|
40
|
+
'Orders.status': {
|
|
41
|
+
title: 'Orders Status',
|
|
42
|
+
shortTitle: 'Status',
|
|
43
|
+
type: 'string',
|
|
44
|
+
},
|
|
45
|
+
},
|
|
46
|
+
segments: {},
|
|
47
|
+
timeDimensions: {
|
|
48
|
+
'Orders.createdAt': {
|
|
49
|
+
title: 'Orders Created at',
|
|
50
|
+
shortTitle: 'Created at',
|
|
51
|
+
type: 'time',
|
|
52
|
+
},
|
|
53
|
+
'Orders.createdAt.day': {
|
|
54
|
+
title: 'Orders Created at',
|
|
55
|
+
shortTitle: 'Created at',
|
|
56
|
+
type: 'time',
|
|
57
|
+
granularity: {
|
|
58
|
+
name: 'day',
|
|
59
|
+
title: 'day',
|
|
60
|
+
interval: '1 day',
|
|
61
|
+
},
|
|
62
|
+
},
|
|
63
|
+
},
|
|
64
|
+
},
|
|
65
|
+
};
|
|
66
|
+
}
|
|
67
|
+
function computeHourRange(targetHours) {
|
|
68
|
+
const start = new Date('2020-01-01T00:00:00.000Z');
|
|
69
|
+
const end = new Date(start.getTime() + (targetHours - 1) * 3600000);
|
|
70
|
+
return [
|
|
71
|
+
start.toISOString().replace('Z', ''),
|
|
72
|
+
end.toISOString().replace('Z', ''),
|
|
73
|
+
];
|
|
74
|
+
}
|
|
75
|
+
const ROW_COUNTS = [5000, 10000, 25000, 50000, 100000];
|
|
76
|
+
// Pre-build all ResultSets outside benchmarks to avoid measuring construction time
|
|
77
|
+
const pivotResultSets = new Map();
|
|
78
|
+
for (const count of ROW_COUNTS) {
|
|
79
|
+
pivotResultSets.set(count, new ResultSet(generateLoadResponse(count)));
|
|
80
|
+
}
|
|
81
|
+
describe('pivot', () => {
|
|
82
|
+
for (const count of ROW_COUNTS) {
|
|
83
|
+
const label = `${count / 1000}k rows`;
|
|
84
|
+
const rs = pivotResultSets.get(count);
|
|
85
|
+
bench(`pivot - ${label}`, () => {
|
|
86
|
+
rs.pivot();
|
|
87
|
+
});
|
|
88
|
+
bench(`chartPivot - ${label}`, () => {
|
|
89
|
+
rs.chartPivot();
|
|
90
|
+
});
|
|
91
|
+
bench(`tablePivot - ${label}`, () => {
|
|
92
|
+
rs.tablePivot();
|
|
93
|
+
});
|
|
94
|
+
}
|
|
95
|
+
});
|
|
96
|
+
describe('timeSeries', () => {
|
|
97
|
+
const rs = new ResultSet({});
|
|
98
|
+
for (const count of ROW_COUNTS) {
|
|
99
|
+
const label = `${count / 1000}k hours`;
|
|
100
|
+
const dateRange = computeHourRange(count);
|
|
101
|
+
bench(`timeSeries - ${label}`, () => {
|
|
102
|
+
rs.timeSeries({
|
|
103
|
+
dimension: 'Orders.createdAt',
|
|
104
|
+
granularity: 'hour',
|
|
105
|
+
dateRange,
|
|
106
|
+
});
|
|
107
|
+
});
|
|
108
|
+
}
|
|
109
|
+
});
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ResultSet.test.d.ts","sourceRoot":"","sources":["../../test/ResultSet.test.ts"],"names":[],"mappings":"AAAA;;;;GAIG
|
|
1
|
+
{"version":3,"file":"ResultSet.test.d.ts","sourceRoot":"","sources":["../../test/ResultSet.test.ts"],"names":[],"mappings":"AAAA;;;;GAIG"}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
|
|
1
|
+
export {};
|
|
2
2
|
//# sourceMappingURL=compare-date-range.test.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"compare-date-range.test.d.ts","sourceRoot":"","sources":["../../test/compare-date-range.test.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"compare-date-range.test.d.ts","sourceRoot":"","sources":["../../test/compare-date-range.test.ts"],"names":[],"mappings":""}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
|
|
1
|
+
export {};
|
|
2
2
|
//# sourceMappingURL=data-blending.test.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"data-blending.test.d.ts","sourceRoot":"","sources":["../../test/data-blending.test.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"data-blending.test.d.ts","sourceRoot":"","sources":["../../test/data-blending.test.ts"],"names":[],"mappings":""}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
|
|
1
|
+
export {};
|
|
2
2
|
//# sourceMappingURL=dayjs-isolation.test.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"dayjs-isolation.test.d.ts","sourceRoot":"","sources":["../../test/dayjs-isolation.test.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"dayjs-isolation.test.d.ts","sourceRoot":"","sources":["../../test/dayjs-isolation.test.ts"],"names":[],"mappings":""}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
|
|
1
|
+
export {};
|
|
2
2
|
//# sourceMappingURL=default-heuristics.test.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"default-heuristics.test.d.ts","sourceRoot":"","sources":["../../test/default-heuristics.test.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"default-heuristics.test.d.ts","sourceRoot":"","sources":["../../test/default-heuristics.test.ts"],"names":[],"mappings":""}
|
|
@@ -1,9 +1,8 @@
|
|
|
1
|
-
|
|
2
|
-
import 'jest';
|
|
1
|
+
import { vi } from 'vitest';
|
|
3
2
|
import { defaultHeuristics } from '../src/utils';
|
|
4
|
-
|
|
5
|
-
const Moment =
|
|
6
|
-
const MomentRange =
|
|
3
|
+
vi.mock('moment-range', async () => {
|
|
4
|
+
const Moment = await vi.importActual('moment');
|
|
5
|
+
const MomentRange = await vi.importActual('moment-range');
|
|
7
6
|
const moment = MomentRange.extendMoment(Moment);
|
|
8
7
|
return {
|
|
9
8
|
extendMoment: () => moment,
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
|
|
1
|
+
export {};
|
|
2
2
|
//# sourceMappingURL=drill-down.test.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"drill-down.test.d.ts","sourceRoot":"","sources":["../../test/drill-down.test.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"drill-down.test.d.ts","sourceRoot":"","sources":["../../test/drill-down.test.ts"],"names":[],"mappings":""}
|
|
@@ -1,9 +1,8 @@
|
|
|
1
|
-
|
|
2
|
-
import 'jest';
|
|
1
|
+
import { vi } from 'vitest';
|
|
3
2
|
import ResultSet from '../src/ResultSet';
|
|
4
|
-
|
|
5
|
-
const Moment =
|
|
6
|
-
const MomentRange =
|
|
3
|
+
vi.mock('moment-range', async () => {
|
|
4
|
+
const Moment = await vi.importActual('moment');
|
|
5
|
+
const MomentRange = await vi.importActual('moment-range');
|
|
7
6
|
const moment = MomentRange.extendMoment(Moment);
|
|
8
7
|
return {
|
|
9
8
|
extendMoment: () => moment,
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"format-no-intl.test.d.ts","sourceRoot":"","sources":["../../test/format-no-intl.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import { describe, it, expect, beforeAll, afterAll, vi } from 'vitest';
|
|
2
|
+
describe('formatValue without Intl', () => {
|
|
3
|
+
const originalIntl = globalThis.Intl;
|
|
4
|
+
beforeAll(() => {
|
|
5
|
+
vi.resetModules();
|
|
6
|
+
// @ts-expect-error — intentionally removing Intl to simulate environments where it is unavailable
|
|
7
|
+
delete globalThis.Intl;
|
|
8
|
+
});
|
|
9
|
+
afterAll(() => {
|
|
10
|
+
globalThis.Intl = originalIntl;
|
|
11
|
+
});
|
|
12
|
+
it('detectLocale falls back to en-US and formatting works', async () => {
|
|
13
|
+
const { formatValue } = await import('../src/format');
|
|
14
|
+
// number type uses the detected locale (should be en-US fallback)
|
|
15
|
+
expect(formatValue(1234.56, { type: 'number' })).toBe('1,234.56');
|
|
16
|
+
});
|
|
17
|
+
it('currency formatting falls back to en-US locale definition', async () => {
|
|
18
|
+
const { formatValue } = await import('../src/format');
|
|
19
|
+
expect(formatValue(1234.56, { type: 'number', format: 'currency' })).toBe('$1,234.56');
|
|
20
|
+
});
|
|
21
|
+
it('percent formatting works without Intl', async () => {
|
|
22
|
+
const { formatValue } = await import('../src/format');
|
|
23
|
+
expect(formatValue(0.1234, { type: 'number', format: 'percent' })).toBe('12.34%');
|
|
24
|
+
});
|
|
25
|
+
it('time formatting works without Intl', async () => {
|
|
26
|
+
const { formatValue } = await import('../src/format');
|
|
27
|
+
expect(formatValue('2024-03-15T00:00:00.000', { type: 'time', granularity: 'day' })).toBe('2024-03-15');
|
|
28
|
+
});
|
|
29
|
+
it('null/undefined still return emptyPlaceholder', async () => {
|
|
30
|
+
const { formatValue } = await import('../src/format');
|
|
31
|
+
expect(formatValue(null, { type: 'number' })).toBe('∅');
|
|
32
|
+
expect(formatValue(undefined, { type: 'number' })).toBe('∅');
|
|
33
|
+
});
|
|
34
|
+
// Known locale (de-DE) — pre-built d3 definition is used,
|
|
35
|
+
// getCurrencySymbol falls back to the static currencySymbols map.
|
|
36
|
+
it('known locale (de-DE) uses pre-built locale definition', async () => {
|
|
37
|
+
const { formatValue } = await import('../src/format');
|
|
38
|
+
expect(formatValue(1234.56, { type: 'number', format: 'number', locale: 'de-DE' })).toBe('1.234,56');
|
|
39
|
+
expect(formatValue(1234.56, { type: 'number', format: 'currency', currency: 'EUR', locale: 'de-DE' })).toBe('€1.234,56');
|
|
40
|
+
expect(formatValue(0.1234, { type: 'number', format: 'percent', locale: 'de-DE' })).toBe('12,34%');
|
|
41
|
+
});
|
|
42
|
+
// Unknown locale (sv-SE) — getD3NumericLocaleFromIntl throws,
|
|
43
|
+
// falls back entirely to en-US.
|
|
44
|
+
it('unknown locale (sv-SE) falls back to en-US', async () => {
|
|
45
|
+
const { formatValue } = await import('../src/format');
|
|
46
|
+
expect(formatValue(1234.56, { type: 'number', format: 'number', locale: 'sv-SE' })).toBe('1,234.56');
|
|
47
|
+
expect(formatValue(1234.56, { type: 'number', format: 'currency', currency: 'USD', locale: 'sv-SE' })).toBe('$1,234.56');
|
|
48
|
+
});
|
|
49
|
+
});
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"format.test.d.ts","sourceRoot":"","sources":["../../test/format.test.ts"],"names":[],"mappings":""}
|