@malloydata/db-publisher 0.0.315 → 0.0.316
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/client/api.d.ts +1594 -528
- package/dist/client/api.js +1820 -553
- package/dist/client/api.js.map +1 -1
- package/dist/client/base.d.ts +1 -1
- package/dist/client/base.js +1 -1
- package/dist/client/common.d.ts +1 -1
- package/dist/client/common.js +1 -1
- package/dist/client/configuration.d.ts +1 -1
- package/dist/client/configuration.js +1 -1
- package/dist/client/index.d.ts +1 -1
- package/dist/client/index.js +1 -1
- package/dist/publisher_connection.d.ts +4 -1
- package/dist/publisher_connection.integration.spec.js +208 -0
- package/dist/publisher_connection.integration.spec.js.map +1 -0
- package/dist/publisher_connection.js +42 -11
- package/dist/publisher_connection.js.map +1 -1
- package/dist/publisher_connection.unit.spec.d.ts +1 -0
- package/dist/{publisher_connection.spec.js → publisher_connection.unit.spec.js} +214 -175
- package/dist/publisher_connection.unit.spec.js.map +1 -0
- package/package.json +2 -2
- package/publisher-api-doc.yaml +1434 -449
- package/src/client/.openapi-generator/FILES +0 -1
- package/src/client/api.ts +2513 -754
- package/src/client/base.ts +1 -1
- package/src/client/common.ts +1 -1
- package/src/client/configuration.ts +1 -1
- package/src/client/index.ts +1 -1
- package/src/publisher_connection.integration.spec.ts +200 -0
- package/src/publisher_connection.ts +67 -19
- package/src/{publisher_connection.spec.ts → publisher_connection.unit.spec.ts} +260 -175
- package/dist/publisher_connection.spec.js.map +0 -1
- /package/dist/{publisher_connection.spec.d.ts → publisher_connection.integration.spec.d.ts} +0 -0
|
@@ -5,31 +5,33 @@
|
|
|
5
5
|
* LICENSE file in the root directory of this source tree.
|
|
6
6
|
*/
|
|
7
7
|
|
|
8
|
-
import * as malloy from '@malloydata/malloy';
|
|
9
8
|
import {describeIfDatabaseAvailable} from '@malloydata/malloy/test';
|
|
10
9
|
import {PublisherConnection} from './publisher_connection';
|
|
11
|
-
import {fileURLToPath} from 'url';
|
|
12
|
-
import * as util from 'util';
|
|
13
|
-
import * as fs from 'fs';
|
|
14
10
|
import type {ConnectionAttributes} from './client';
|
|
15
|
-
import {Configuration, ConnectionsApi} from './client';
|
|
11
|
+
import {Configuration, ConnectionsApi, ConnectionsTestApi} from './client';
|
|
16
12
|
import type {AxiosResponse} from 'axios';
|
|
17
13
|
import type {
|
|
18
|
-
TableSourceDef,
|
|
19
14
|
SQLSourceDef,
|
|
20
15
|
MalloyQueryData,
|
|
21
16
|
QueryDataRow,
|
|
22
17
|
} from '@malloydata/malloy';
|
|
23
18
|
|
|
24
|
-
// mocks client code for testing
|
|
19
|
+
// mocks client code for testing - only for unit tests
|
|
25
20
|
jest.mock('./client', () => {
|
|
26
21
|
const mockConnectionsApi = {
|
|
27
22
|
getConnection: jest.fn(),
|
|
28
|
-
|
|
23
|
+
getTable: jest.fn(),
|
|
29
24
|
getTablesource: jest.fn(),
|
|
30
25
|
getSqlsource: jest.fn(),
|
|
31
26
|
getQuerydata: jest.fn(),
|
|
32
27
|
getTemporarytable: jest.fn(),
|
|
28
|
+
postSqlsource: jest.fn(),
|
|
29
|
+
postQuerydata: jest.fn(),
|
|
30
|
+
postTemporarytable: jest.fn(),
|
|
31
|
+
};
|
|
32
|
+
|
|
33
|
+
const mockConnectionsTestApi = {
|
|
34
|
+
testConnectionConfiguration: jest.fn(),
|
|
33
35
|
};
|
|
34
36
|
|
|
35
37
|
return {
|
|
@@ -37,6 +39,9 @@ jest.mock('./client', () => {
|
|
|
37
39
|
basePath: 'http://test.com/api/v0',
|
|
38
40
|
})),
|
|
39
41
|
ConnectionsApi: jest.fn().mockImplementation(() => mockConnectionsApi),
|
|
42
|
+
ConnectionsTestApi: jest
|
|
43
|
+
.fn()
|
|
44
|
+
.mockImplementation(() => mockConnectionsTestApi),
|
|
40
45
|
};
|
|
41
46
|
});
|
|
42
47
|
|
|
@@ -46,6 +51,7 @@ describe('db:Publisher', () => {
|
|
|
46
51
|
describe('unit', () => {
|
|
47
52
|
describe('create', () => {
|
|
48
53
|
let mockConnectionsApi: jest.Mocked<ConnectionsApi>;
|
|
54
|
+
let mockConnectionsTestApi: jest.Mocked<ConnectionsTestApi>;
|
|
49
55
|
let _mockConfiguration: jest.Mocked<Configuration>;
|
|
50
56
|
|
|
51
57
|
beforeEach(() => {
|
|
@@ -53,6 +59,9 @@ describe('db:Publisher', () => {
|
|
|
53
59
|
mockConnectionsApi = new ConnectionsApi(
|
|
54
60
|
new Configuration()
|
|
55
61
|
) as jest.Mocked<ConnectionsApi>;
|
|
62
|
+
mockConnectionsTestApi = new ConnectionsTestApi(
|
|
63
|
+
new Configuration()
|
|
64
|
+
) as jest.Mocked<ConnectionsTestApi>;
|
|
56
65
|
_mockConfiguration = new Configuration() as jest.Mocked<Configuration>;
|
|
57
66
|
});
|
|
58
67
|
|
|
@@ -70,7 +79,13 @@ describe('db:Publisher', () => {
|
|
|
70
79
|
|
|
71
80
|
const mockConnectionResponse: AxiosResponse = {
|
|
72
81
|
data: {
|
|
82
|
+
name: 'test-connection',
|
|
83
|
+
type: 'bigquery',
|
|
73
84
|
attributes: mockConnectionAttributes,
|
|
85
|
+
bigqueryConnection: {
|
|
86
|
+
defaultProjectId: 'test-project',
|
|
87
|
+
billingProjectId: 'test-project',
|
|
88
|
+
},
|
|
74
89
|
},
|
|
75
90
|
status: 200,
|
|
76
91
|
statusText: 'OK',
|
|
@@ -79,7 +94,10 @@ describe('db:Publisher', () => {
|
|
|
79
94
|
};
|
|
80
95
|
|
|
81
96
|
const mockTestResponse: AxiosResponse = {
|
|
82
|
-
data:
|
|
97
|
+
data: {
|
|
98
|
+
status: 'ok',
|
|
99
|
+
errorMessage: '',
|
|
100
|
+
},
|
|
83
101
|
status: 200,
|
|
84
102
|
statusText: 'OK',
|
|
85
103
|
headers: {},
|
|
@@ -89,7 +107,9 @@ describe('db:Publisher', () => {
|
|
|
89
107
|
mockConnectionsApi.getConnection.mockResolvedValueOnce(
|
|
90
108
|
mockConnectionResponse
|
|
91
109
|
);
|
|
92
|
-
|
|
110
|
+
mockConnectionsTestApi.testConnectionConfiguration.mockResolvedValueOnce(
|
|
111
|
+
mockTestResponse
|
|
112
|
+
);
|
|
93
113
|
|
|
94
114
|
const connection = await PublisherConnection.create('test-connection', {
|
|
95
115
|
connectionUri:
|
|
@@ -144,7 +164,13 @@ describe('db:Publisher', () => {
|
|
|
144
164
|
|
|
145
165
|
const mockConnectionResponse: AxiosResponse = {
|
|
146
166
|
data: {
|
|
167
|
+
name: 'test-connection',
|
|
168
|
+
type: 'bigquery',
|
|
147
169
|
attributes: mockConnectionAttributes,
|
|
170
|
+
bigqueryConnection: {
|
|
171
|
+
defaultProjectId: 'test-project',
|
|
172
|
+
billingProjectId: 'test-project',
|
|
173
|
+
},
|
|
148
174
|
},
|
|
149
175
|
status: 200,
|
|
150
176
|
statusText: 'OK',
|
|
@@ -153,7 +179,10 @@ describe('db:Publisher', () => {
|
|
|
153
179
|
};
|
|
154
180
|
|
|
155
181
|
const mockTestResponse: AxiosResponse = {
|
|
156
|
-
data:
|
|
182
|
+
data: {
|
|
183
|
+
status: 'ok',
|
|
184
|
+
errorMessage: '',
|
|
185
|
+
},
|
|
157
186
|
status: 200,
|
|
158
187
|
statusText: 'OK',
|
|
159
188
|
headers: {},
|
|
@@ -163,7 +192,9 @@ describe('db:Publisher', () => {
|
|
|
163
192
|
mockConnectionsApi.getConnection.mockResolvedValueOnce(
|
|
164
193
|
mockConnectionResponse
|
|
165
194
|
);
|
|
166
|
-
|
|
195
|
+
mockConnectionsTestApi.testConnectionConfiguration.mockResolvedValueOnce(
|
|
196
|
+
mockTestResponse
|
|
197
|
+
);
|
|
167
198
|
|
|
168
199
|
const connection = await PublisherConnection.create('test-connection', {
|
|
169
200
|
connectionUri:
|
|
@@ -198,18 +229,6 @@ describe('db:Publisher', () => {
|
|
|
198
229
|
});
|
|
199
230
|
|
|
200
231
|
it('should fetch table schema successfully', async () => {
|
|
201
|
-
const mockTableSchema: TableSourceDef = {
|
|
202
|
-
type: 'table',
|
|
203
|
-
name: 'test_table',
|
|
204
|
-
tablePath: 'test_path',
|
|
205
|
-
connection: 'test-connection',
|
|
206
|
-
dialect: 'bigquery',
|
|
207
|
-
fields: [
|
|
208
|
-
{name: 'id', type: 'number'},
|
|
209
|
-
{name: 'name', type: 'string'},
|
|
210
|
-
],
|
|
211
|
-
};
|
|
212
|
-
|
|
213
232
|
const mockConnectionResponse: AxiosResponse = {
|
|
214
233
|
data: {
|
|
215
234
|
attributes: {
|
|
@@ -227,7 +246,11 @@ describe('db:Publisher', () => {
|
|
|
227
246
|
|
|
228
247
|
const mockTableResponse: AxiosResponse = {
|
|
229
248
|
data: {
|
|
230
|
-
|
|
249
|
+
resource: 'test_path',
|
|
250
|
+
columns: [
|
|
251
|
+
{name: 'id', type: 'number'},
|
|
252
|
+
{name: 'name', type: 'string'},
|
|
253
|
+
],
|
|
231
254
|
},
|
|
232
255
|
status: 200,
|
|
233
256
|
statusText: 'OK',
|
|
@@ -238,9 +261,7 @@ describe('db:Publisher', () => {
|
|
|
238
261
|
mockConnectionsApi.getConnection.mockResolvedValueOnce(
|
|
239
262
|
mockConnectionResponse
|
|
240
263
|
);
|
|
241
|
-
mockConnectionsApi.
|
|
242
|
-
mockTableResponse
|
|
243
|
-
);
|
|
264
|
+
mockConnectionsApi.getTable.mockResolvedValueOnce(mockTableResponse);
|
|
244
265
|
|
|
245
266
|
const connection = await PublisherConnection.create('test-connection', {
|
|
246
267
|
connectionUri:
|
|
@@ -253,11 +274,21 @@ describe('db:Publisher', () => {
|
|
|
253
274
|
'test_path'
|
|
254
275
|
);
|
|
255
276
|
|
|
256
|
-
expect(schema).toEqual(
|
|
257
|
-
|
|
277
|
+
expect(schema).toEqual({
|
|
278
|
+
type: 'table',
|
|
279
|
+
name: 'test_key',
|
|
280
|
+
tablePath: 'test_path',
|
|
281
|
+
connection: 'test-connection',
|
|
282
|
+
dialect: 'bigquery',
|
|
283
|
+
fields: [
|
|
284
|
+
{name: 'id', type: 'number'},
|
|
285
|
+
{name: 'name', type: 'string'},
|
|
286
|
+
],
|
|
287
|
+
});
|
|
288
|
+
expect(mockConnectionsApi.getTable).toHaveBeenCalledWith(
|
|
258
289
|
'test-project',
|
|
259
290
|
'test-connection',
|
|
260
|
-
'
|
|
291
|
+
'test_path',
|
|
261
292
|
'test_path',
|
|
262
293
|
{
|
|
263
294
|
headers: {
|
|
@@ -268,19 +299,59 @@ describe('db:Publisher', () => {
|
|
|
268
299
|
});
|
|
269
300
|
|
|
270
301
|
it('should handle API errors', async () => {
|
|
271
|
-
await setupAndTestApiError(
|
|
272
|
-
|
|
273
|
-
'getTablesource',
|
|
274
|
-
connection => connection.fetchTableSchema('test_key', 'test_path')
|
|
302
|
+
await setupAndTestApiError(mockConnectionsApi, 'getTable', connection =>
|
|
303
|
+
connection.fetchTableSchema('test_key', 'test_path')
|
|
275
304
|
);
|
|
276
305
|
});
|
|
277
306
|
|
|
278
307
|
it('should handle invalid JSON response', async () => {
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
308
|
+
const mockConnectionResponse: AxiosResponse = {
|
|
309
|
+
data: {
|
|
310
|
+
attributes: {
|
|
311
|
+
dialectName: 'bigquery',
|
|
312
|
+
isPool: false,
|
|
313
|
+
canPersist: true,
|
|
314
|
+
canStream: true,
|
|
315
|
+
},
|
|
316
|
+
},
|
|
317
|
+
status: 200,
|
|
318
|
+
statusText: 'OK',
|
|
319
|
+
headers: {},
|
|
320
|
+
config: {} as AxiosResponse['config'],
|
|
321
|
+
};
|
|
322
|
+
|
|
323
|
+
const mockInvalidResponse: AxiosResponse = {
|
|
324
|
+
data: {resource: 'invalid json', columns: null},
|
|
325
|
+
status: 200,
|
|
326
|
+
statusText: 'OK',
|
|
327
|
+
headers: {},
|
|
328
|
+
config: {} as AxiosResponse['config'],
|
|
329
|
+
};
|
|
330
|
+
|
|
331
|
+
mockConnectionsApi.getConnection.mockResolvedValueOnce(
|
|
332
|
+
mockConnectionResponse
|
|
283
333
|
);
|
|
334
|
+
mockConnectionsApi.getTable.mockResolvedValueOnce(mockInvalidResponse);
|
|
335
|
+
|
|
336
|
+
const connection = await PublisherConnection.create('test-connection', {
|
|
337
|
+
connectionUri:
|
|
338
|
+
'http://test.com/api/v0/projects/test-project/connections/test-connection',
|
|
339
|
+
accessToken: 'test-token',
|
|
340
|
+
});
|
|
341
|
+
|
|
342
|
+
const schema = await connection.fetchTableSchema(
|
|
343
|
+
'test_key',
|
|
344
|
+
'test_path'
|
|
345
|
+
);
|
|
346
|
+
|
|
347
|
+
expect(schema).toEqual({
|
|
348
|
+
type: 'table',
|
|
349
|
+
name: 'test_key',
|
|
350
|
+
tablePath: 'test_path',
|
|
351
|
+
connection: 'test-connection',
|
|
352
|
+
dialect: 'bigquery',
|
|
353
|
+
fields: [],
|
|
354
|
+
});
|
|
284
355
|
});
|
|
285
356
|
});
|
|
286
357
|
|
|
@@ -341,7 +412,7 @@ describe('db:Publisher', () => {
|
|
|
341
412
|
mockConnectionsApi.getConnection.mockResolvedValueOnce(
|
|
342
413
|
mockConnectionResponse
|
|
343
414
|
);
|
|
344
|
-
mockConnectionsApi.
|
|
415
|
+
mockConnectionsApi.postSqlsource.mockResolvedValueOnce(mockSqlResponse);
|
|
345
416
|
|
|
346
417
|
const connection = await PublisherConnection.create('test-connection', {
|
|
347
418
|
connectionUri:
|
|
@@ -355,10 +426,12 @@ describe('db:Publisher', () => {
|
|
|
355
426
|
});
|
|
356
427
|
|
|
357
428
|
expect(schema).toEqual(mockSqlSchema);
|
|
358
|
-
expect(mockConnectionsApi.
|
|
429
|
+
expect(mockConnectionsApi.postSqlsource).toHaveBeenCalledWith(
|
|
359
430
|
'test-project',
|
|
360
431
|
'test-connection',
|
|
361
|
-
|
|
432
|
+
{
|
|
433
|
+
sqlStatement: 'SELECT * FROM test_table',
|
|
434
|
+
},
|
|
362
435
|
{
|
|
363
436
|
headers: {
|
|
364
437
|
Authorization: 'Bearer test-token',
|
|
@@ -370,7 +443,7 @@ describe('db:Publisher', () => {
|
|
|
370
443
|
it('should handle API errors', async () => {
|
|
371
444
|
await setupAndTestApiError(
|
|
372
445
|
mockConnectionsApi,
|
|
373
|
-
'
|
|
446
|
+
'postSqlsource',
|
|
374
447
|
connection =>
|
|
375
448
|
connection.fetchSelectSchema({
|
|
376
449
|
selectStr: 'SELECT * FROM test_table',
|
|
@@ -382,7 +455,7 @@ describe('db:Publisher', () => {
|
|
|
382
455
|
it('should handle invalid JSON response', async () => {
|
|
383
456
|
await setupAndTestInvalidJsonResponse(
|
|
384
457
|
mockConnectionsApi,
|
|
385
|
-
'
|
|
458
|
+
'postSqlsource',
|
|
386
459
|
connection =>
|
|
387
460
|
connection.fetchSelectSchema({
|
|
388
461
|
selectStr: 'SELECT * FROM test_table',
|
|
@@ -445,7 +518,7 @@ describe('db:Publisher', () => {
|
|
|
445
518
|
mockConnectionsApi.getConnection.mockResolvedValueOnce(
|
|
446
519
|
mockConnectionResponse
|
|
447
520
|
);
|
|
448
|
-
mockConnectionsApi.
|
|
521
|
+
mockConnectionsApi.postQuerydata.mockResolvedValueOnce(
|
|
449
522
|
mockQueryResponse
|
|
450
523
|
);
|
|
451
524
|
|
|
@@ -458,11 +531,11 @@ describe('db:Publisher', () => {
|
|
|
458
531
|
const result = await connection.runSQL('SELECT * FROM test_table');
|
|
459
532
|
|
|
460
533
|
expect(result).toEqual(mockQueryData);
|
|
461
|
-
expect(mockConnectionsApi.
|
|
534
|
+
expect(mockConnectionsApi.postQuerydata).toHaveBeenCalledWith(
|
|
462
535
|
'test-project',
|
|
463
536
|
'test-connection',
|
|
464
|
-
'SELECT * FROM test_table',
|
|
465
|
-
|
|
537
|
+
{sqlStatement: 'SELECT * FROM test_table'},
|
|
538
|
+
JSON.stringify({}),
|
|
466
539
|
{
|
|
467
540
|
headers: {
|
|
468
541
|
Authorization: 'Bearer test-token',
|
|
@@ -508,7 +581,7 @@ describe('db:Publisher', () => {
|
|
|
508
581
|
mockConnectionsApi.getConnection.mockResolvedValueOnce(
|
|
509
582
|
mockConnectionResponse
|
|
510
583
|
);
|
|
511
|
-
mockConnectionsApi.
|
|
584
|
+
mockConnectionsApi.postQuerydata.mockResolvedValueOnce(
|
|
512
585
|
mockQueryResponse
|
|
513
586
|
);
|
|
514
587
|
|
|
@@ -529,10 +602,10 @@ describe('db:Publisher', () => {
|
|
|
529
602
|
);
|
|
530
603
|
|
|
531
604
|
expect(result).toEqual(mockQueryData);
|
|
532
|
-
expect(mockConnectionsApi.
|
|
605
|
+
expect(mockConnectionsApi.postQuerydata).toHaveBeenCalledWith(
|
|
533
606
|
'test-project',
|
|
534
607
|
'test-connection',
|
|
535
|
-
'SELECT * FROM test_table',
|
|
608
|
+
{sqlStatement: 'SELECT * FROM test_table'},
|
|
536
609
|
JSON.stringify(options),
|
|
537
610
|
{
|
|
538
611
|
headers: {
|
|
@@ -545,7 +618,7 @@ describe('db:Publisher', () => {
|
|
|
545
618
|
it('should handle API errors', async () => {
|
|
546
619
|
await setupAndTestApiError(
|
|
547
620
|
mockConnectionsApi,
|
|
548
|
-
'
|
|
621
|
+
'postQuerydata',
|
|
549
622
|
connection => connection.runSQL('SELECT * FROM test_table')
|
|
550
623
|
);
|
|
551
624
|
});
|
|
@@ -553,7 +626,7 @@ describe('db:Publisher', () => {
|
|
|
553
626
|
it('should handle invalid JSON response', async () => {
|
|
554
627
|
await setupAndTestInvalidJsonResponse(
|
|
555
628
|
mockConnectionsApi,
|
|
556
|
-
'
|
|
629
|
+
'postQuerydata',
|
|
557
630
|
connection => connection.runSQL('SELECT * FROM test_table'),
|
|
558
631
|
{data: 'invalid json'}
|
|
559
632
|
);
|
|
@@ -613,7 +686,7 @@ describe('db:Publisher', () => {
|
|
|
613
686
|
mockConnectionsApi.getConnection.mockResolvedValueOnce(
|
|
614
687
|
mockConnectionResponse
|
|
615
688
|
);
|
|
616
|
-
mockConnectionsApi.
|
|
689
|
+
mockConnectionsApi.postQuerydata.mockResolvedValueOnce(
|
|
617
690
|
mockQueryResponse
|
|
618
691
|
);
|
|
619
692
|
|
|
@@ -631,10 +704,10 @@ describe('db:Publisher', () => {
|
|
|
631
704
|
}
|
|
632
705
|
|
|
633
706
|
expect(results).toEqual(mockQueryData.rows);
|
|
634
|
-
expect(mockConnectionsApi.
|
|
707
|
+
expect(mockConnectionsApi.postQuerydata).toHaveBeenCalledWith(
|
|
635
708
|
'test-project',
|
|
636
709
|
'test-connection',
|
|
637
|
-
'SELECT * FROM test_table',
|
|
710
|
+
{sqlStatement: 'SELECT * FROM test_table'},
|
|
638
711
|
'{}',
|
|
639
712
|
{
|
|
640
713
|
headers: {
|
|
@@ -681,7 +754,7 @@ describe('db:Publisher', () => {
|
|
|
681
754
|
mockConnectionsApi.getConnection.mockResolvedValueOnce(
|
|
682
755
|
mockConnectionResponse
|
|
683
756
|
);
|
|
684
|
-
mockConnectionsApi.
|
|
757
|
+
mockConnectionsApi.postQuerydata.mockResolvedValueOnce(
|
|
685
758
|
mockQueryResponse
|
|
686
759
|
);
|
|
687
760
|
|
|
@@ -707,10 +780,10 @@ describe('db:Publisher', () => {
|
|
|
707
780
|
}
|
|
708
781
|
|
|
709
782
|
expect(results).toEqual(mockQueryData.rows);
|
|
710
|
-
expect(mockConnectionsApi.
|
|
783
|
+
expect(mockConnectionsApi.postQuerydata).toHaveBeenCalledWith(
|
|
711
784
|
'test-project',
|
|
712
785
|
'test-connection',
|
|
713
|
-
'SELECT * FROM test_table',
|
|
786
|
+
{sqlStatement: 'SELECT * FROM test_table'},
|
|
714
787
|
JSON.stringify(options),
|
|
715
788
|
{
|
|
716
789
|
headers: {
|
|
@@ -723,7 +796,7 @@ describe('db:Publisher', () => {
|
|
|
723
796
|
it('should handle API errors', async () => {
|
|
724
797
|
await setupAndTestApiError(
|
|
725
798
|
mockConnectionsApi,
|
|
726
|
-
'
|
|
799
|
+
'postQuerydata',
|
|
727
800
|
async connection => {
|
|
728
801
|
const stream = connection.runSQLStream('SELECT * FROM test_table');
|
|
729
802
|
const results: QueryDataRow[] = [];
|
|
@@ -737,7 +810,7 @@ describe('db:Publisher', () => {
|
|
|
737
810
|
it('should handle invalid JSON response', async () => {
|
|
738
811
|
await setupAndTestInvalidJsonResponse(
|
|
739
812
|
mockConnectionsApi,
|
|
740
|
-
'
|
|
813
|
+
'postQuerydata',
|
|
741
814
|
async connection => {
|
|
742
815
|
const stream = connection.runSQLStream('SELECT * FROM test_table');
|
|
743
816
|
const results: QueryDataRow[] = [];
|
|
@@ -795,7 +868,7 @@ describe('db:Publisher', () => {
|
|
|
795
868
|
mockConnectionsApi.getConnection.mockResolvedValueOnce(
|
|
796
869
|
mockConnectionResponse
|
|
797
870
|
);
|
|
798
|
-
mockConnectionsApi.
|
|
871
|
+
mockConnectionsApi.postTemporarytable.mockResolvedValueOnce(
|
|
799
872
|
mockTableResponse
|
|
800
873
|
);
|
|
801
874
|
|
|
@@ -810,10 +883,10 @@ describe('db:Publisher', () => {
|
|
|
810
883
|
);
|
|
811
884
|
|
|
812
885
|
expect(tableName).toBe('temp_table_123');
|
|
813
|
-
expect(mockConnectionsApi.
|
|
886
|
+
expect(mockConnectionsApi.postTemporarytable).toHaveBeenCalledWith(
|
|
814
887
|
'test-project',
|
|
815
888
|
'test-connection',
|
|
816
|
-
'SELECT * FROM test_table',
|
|
889
|
+
{sqlStatement: 'SELECT * FROM test_table'},
|
|
817
890
|
{
|
|
818
891
|
headers: {
|
|
819
892
|
Authorization: 'Bearer test-token',
|
|
@@ -825,7 +898,7 @@ describe('db:Publisher', () => {
|
|
|
825
898
|
it('should handle API errors', async () => {
|
|
826
899
|
await setupAndTestApiError(
|
|
827
900
|
mockConnectionsApi,
|
|
828
|
-
'
|
|
901
|
+
'postTemporarytable',
|
|
829
902
|
connection =>
|
|
830
903
|
connection.manifestTemporaryTable('SELECT * FROM test_table')
|
|
831
904
|
);
|
|
@@ -834,6 +907,7 @@ describe('db:Publisher', () => {
|
|
|
834
907
|
|
|
835
908
|
describe('test', () => {
|
|
836
909
|
let mockConnectionsApi: jest.Mocked<ConnectionsApi>;
|
|
910
|
+
let mockConnectionsTestApi: jest.Mocked<ConnectionsTestApi>;
|
|
837
911
|
let _mockConfiguration: jest.Mocked<Configuration>;
|
|
838
912
|
|
|
839
913
|
beforeEach(() => {
|
|
@@ -841,6 +915,9 @@ describe('db:Publisher', () => {
|
|
|
841
915
|
mockConnectionsApi = new ConnectionsApi(
|
|
842
916
|
new Configuration()
|
|
843
917
|
) as jest.Mocked<ConnectionsApi>;
|
|
918
|
+
mockConnectionsTestApi = new ConnectionsTestApi(
|
|
919
|
+
new Configuration()
|
|
920
|
+
) as jest.Mocked<ConnectionsTestApi>;
|
|
844
921
|
_mockConfiguration = new Configuration() as jest.Mocked<Configuration>;
|
|
845
922
|
});
|
|
846
923
|
|
|
@@ -851,12 +928,18 @@ describe('db:Publisher', () => {
|
|
|
851
928
|
it('should test connection successfully', async () => {
|
|
852
929
|
const mockConnectionResponse: AxiosResponse = {
|
|
853
930
|
data: {
|
|
931
|
+
name: 'test-connection',
|
|
932
|
+
type: 'bigquery',
|
|
854
933
|
attributes: {
|
|
855
934
|
dialectName: 'bigquery',
|
|
856
935
|
isPool: false,
|
|
857
936
|
canPersist: true,
|
|
858
937
|
canStream: true,
|
|
859
938
|
},
|
|
939
|
+
bigqueryConnection: {
|
|
940
|
+
defaultProjectId: 'test-project',
|
|
941
|
+
billingProjectId: 'test-project',
|
|
942
|
+
},
|
|
860
943
|
},
|
|
861
944
|
status: 200,
|
|
862
945
|
statusText: 'OK',
|
|
@@ -865,7 +948,10 @@ describe('db:Publisher', () => {
|
|
|
865
948
|
};
|
|
866
949
|
|
|
867
950
|
const mockTestResponse: AxiosResponse = {
|
|
868
|
-
data:
|
|
951
|
+
data: {
|
|
952
|
+
status: 'ok',
|
|
953
|
+
errorMessage: '',
|
|
954
|
+
},
|
|
869
955
|
status: 200,
|
|
870
956
|
statusText: 'OK',
|
|
871
957
|
headers: {},
|
|
@@ -875,7 +961,9 @@ describe('db:Publisher', () => {
|
|
|
875
961
|
mockConnectionsApi.getConnection.mockResolvedValueOnce(
|
|
876
962
|
mockConnectionResponse
|
|
877
963
|
);
|
|
878
|
-
|
|
964
|
+
mockConnectionsTestApi.testConnectionConfiguration.mockResolvedValueOnce(
|
|
965
|
+
mockTestResponse
|
|
966
|
+
);
|
|
879
967
|
|
|
880
968
|
const connection = await PublisherConnection.create('test-connection', {
|
|
881
969
|
connectionUri:
|
|
@@ -884,9 +972,23 @@ describe('db:Publisher', () => {
|
|
|
884
972
|
});
|
|
885
973
|
|
|
886
974
|
await expect(connection.test()).resolves.not.toThrow();
|
|
887
|
-
expect(
|
|
888
|
-
|
|
889
|
-
|
|
975
|
+
expect(
|
|
976
|
+
mockConnectionsTestApi.testConnectionConfiguration
|
|
977
|
+
).toHaveBeenCalledWith(
|
|
978
|
+
{
|
|
979
|
+
name: 'test-connection',
|
|
980
|
+
type: 'bigquery',
|
|
981
|
+
attributes: {
|
|
982
|
+
dialectName: 'bigquery',
|
|
983
|
+
isPool: false,
|
|
984
|
+
canPersist: true,
|
|
985
|
+
canStream: true,
|
|
986
|
+
},
|
|
987
|
+
bigqueryConnection: {
|
|
988
|
+
defaultProjectId: 'test-project',
|
|
989
|
+
billingProjectId: 'test-project',
|
|
990
|
+
},
|
|
991
|
+
},
|
|
890
992
|
{
|
|
891
993
|
headers: {
|
|
892
994
|
Authorization: 'Bearer test-token',
|
|
@@ -895,127 +997,110 @@ describe('db:Publisher', () => {
|
|
|
895
997
|
);
|
|
896
998
|
});
|
|
897
999
|
});
|
|
898
|
-
});
|
|
899
1000
|
|
|
900
|
-
|
|
901
|
-
|
|
902
|
-
|
|
903
|
-
|
|
904
|
-
|
|
905
|
-
|
|
906
|
-
|
|
907
|
-
|
|
908
|
-
|
|
909
|
-
|
|
910
|
-
{
|
|
911
|
-
connectionUri:
|
|
912
|
-
'http://demo.data.pathways.localhost:8000/api/v0/projects/malloy-samples/connections/bigquery',
|
|
913
|
-
accessToken: 'xyz',
|
|
914
|
-
}
|
|
915
|
-
);
|
|
916
|
-
const files = {
|
|
917
|
-
readURL: async (url: URL) => {
|
|
918
|
-
const filePath = fileURLToPath(url);
|
|
919
|
-
return await util.promisify(fs.readFile)(filePath, 'utf8');
|
|
920
|
-
},
|
|
921
|
-
};
|
|
922
|
-
runtime = new malloy.Runtime({
|
|
923
|
-
urlReader: files,
|
|
924
|
-
connection: conn,
|
|
1001
|
+
describe('estimateQueryCost', () => {
|
|
1002
|
+
let mockConnectionsApi: jest.Mocked<ConnectionsApi>;
|
|
1003
|
+
let _mockConfiguration: jest.Mocked<Configuration>;
|
|
1004
|
+
|
|
1005
|
+
beforeEach(() => {
|
|
1006
|
+
// Get fresh instances of the mocks
|
|
1007
|
+
mockConnectionsApi = new ConnectionsApi(
|
|
1008
|
+
new Configuration()
|
|
1009
|
+
) as jest.Mocked<ConnectionsApi>;
|
|
1010
|
+
_mockConfiguration = new Configuration() as jest.Mocked<Configuration>;
|
|
925
1011
|
});
|
|
926
|
-
});
|
|
927
1012
|
|
|
928
|
-
|
|
929
|
-
|
|
930
|
-
|
|
1013
|
+
it('should return empty object for query cost estimation', async () => {
|
|
1014
|
+
const mockConnectionAttributes: ConnectionAttributes = {
|
|
1015
|
+
dialectName: 'bigquery',
|
|
1016
|
+
isPool: false,
|
|
1017
|
+
canPersist: true,
|
|
1018
|
+
canStream: true,
|
|
1019
|
+
};
|
|
931
1020
|
|
|
932
|
-
|
|
933
|
-
|
|
934
|
-
|
|
1021
|
+
const mockConnectionResponse: AxiosResponse = {
|
|
1022
|
+
data: {
|
|
1023
|
+
name: 'test-connection',
|
|
1024
|
+
type: 'bigquery',
|
|
1025
|
+
attributes: mockConnectionAttributes,
|
|
1026
|
+
bigqueryConnection: {
|
|
1027
|
+
defaultProjectId: 'test-project',
|
|
1028
|
+
billingProjectId: 'test-project',
|
|
1029
|
+
},
|
|
1030
|
+
},
|
|
1031
|
+
status: 200,
|
|
1032
|
+
statusText: 'OK',
|
|
1033
|
+
headers: {},
|
|
1034
|
+
config: {} as AxiosResponse['config'],
|
|
1035
|
+
};
|
|
935
1036
|
|
|
936
|
-
|
|
937
|
-
|
|
938
|
-
|
|
1037
|
+
mockConnectionsApi.getConnection.mockResolvedValueOnce(
|
|
1038
|
+
mockConnectionResponse
|
|
1039
|
+
);
|
|
939
1040
|
|
|
940
|
-
|
|
941
|
-
|
|
942
|
-
|
|
1041
|
+
const connection = await PublisherConnection.create('test-connection', {
|
|
1042
|
+
connectionUri:
|
|
1043
|
+
'http://test.com/api/v0/projects/test-project/connections/test-connection',
|
|
1044
|
+
accessToken: 'test-token',
|
|
1045
|
+
});
|
|
943
1046
|
|
|
944
|
-
|
|
945
|
-
|
|
946
|
-
|
|
1047
|
+
const cost = await connection.estimateQueryCost(
|
|
1048
|
+
'SELECT * FROM test_table'
|
|
1049
|
+
);
|
|
947
1050
|
|
|
948
|
-
|
|
949
|
-
|
|
1051
|
+
expect(cost).toEqual({});
|
|
1052
|
+
});
|
|
950
1053
|
});
|
|
951
1054
|
|
|
952
|
-
|
|
953
|
-
|
|
954
|
-
|
|
955
|
-
'bigquery-public-data.hacker_news.full'
|
|
956
|
-
);
|
|
957
|
-
expect(schema.type).toBe('table');
|
|
958
|
-
expect(schema.dialect).toBe('standardsql');
|
|
959
|
-
expect(schema.tablePath).toBe('bigquery-public-data.hacker_news.full');
|
|
960
|
-
expect(schema.fields.length).toBe(14);
|
|
961
|
-
expect(schema.fields[0].name).toBe('title');
|
|
962
|
-
expect(schema.fields[0].type).toBe('string');
|
|
963
|
-
});
|
|
1055
|
+
describe('close', () => {
|
|
1056
|
+
let mockConnectionsApi: jest.Mocked<ConnectionsApi>;
|
|
1057
|
+
let _mockConfiguration: jest.Mocked<Configuration>;
|
|
964
1058
|
|
|
965
|
-
|
|
966
|
-
|
|
967
|
-
|
|
968
|
-
|
|
1059
|
+
beforeEach(() => {
|
|
1060
|
+
// Get fresh instances of the mocks
|
|
1061
|
+
mockConnectionsApi = new ConnectionsApi(
|
|
1062
|
+
new Configuration()
|
|
1063
|
+
) as jest.Mocked<ConnectionsApi>;
|
|
1064
|
+
_mockConfiguration = new Configuration() as jest.Mocked<Configuration>;
|
|
969
1065
|
});
|
|
970
|
-
expect(schema.type).toBe('sql_select');
|
|
971
|
-
expect(schema.dialect).toBe('standardsql');
|
|
972
|
-
expect(schema.fields.length).toBe(14);
|
|
973
|
-
expect(schema.fields[0].name).toBe('title');
|
|
974
|
-
expect(schema.fields[0].type).toBe('string');
|
|
975
|
-
});
|
|
976
1066
|
|
|
977
|
-
|
|
978
|
-
|
|
979
|
-
|
|
980
|
-
|
|
1067
|
+
it('should close connection successfully', async () => {
|
|
1068
|
+
const mockConnectionAttributes: ConnectionAttributes = {
|
|
1069
|
+
dialectName: 'bigquery',
|
|
1070
|
+
isPool: false,
|
|
1071
|
+
canPersist: true,
|
|
1072
|
+
canStream: true,
|
|
1073
|
+
};
|
|
981
1074
|
|
|
982
|
-
|
|
983
|
-
|
|
984
|
-
|
|
985
|
-
|
|
986
|
-
|
|
987
|
-
|
|
988
|
-
|
|
989
|
-
|
|
990
|
-
|
|
991
|
-
|
|
992
|
-
|
|
993
|
-
|
|
994
|
-
|
|
995
|
-
|
|
996
|
-
|
|
997
|
-
expect(total).toBe(1836679);
|
|
998
|
-
});
|
|
1075
|
+
const mockConnectionResponse: AxiosResponse = {
|
|
1076
|
+
data: {
|
|
1077
|
+
name: 'test-connection',
|
|
1078
|
+
type: 'bigquery',
|
|
1079
|
+
attributes: mockConnectionAttributes,
|
|
1080
|
+
bigqueryConnection: {
|
|
1081
|
+
defaultProjectId: 'test-project',
|
|
1082
|
+
billingProjectId: 'test-project',
|
|
1083
|
+
},
|
|
1084
|
+
},
|
|
1085
|
+
status: 200,
|
|
1086
|
+
statusText: 'OK',
|
|
1087
|
+
headers: {},
|
|
1088
|
+
config: {} as AxiosResponse['config'],
|
|
1089
|
+
};
|
|
999
1090
|
|
|
1000
|
-
|
|
1001
|
-
|
|
1002
|
-
|
|
1003
|
-
"source: stories is bigquery.sql('SELECT * FROM bigquery-public-data.hacker_news.full')"
|
|
1004
|
-
)
|
|
1005
|
-
.loadQuery(
|
|
1006
|
-
'run: stories -> { aggregate: cnt is count() group_by: `by` order_by: cnt desc limit: 20 }'
|
|
1007
|
-
)
|
|
1008
|
-
.getSQL();
|
|
1009
|
-
const res = await conn.runSQL(sql);
|
|
1010
|
-
expect(res.totalRows).toBe(20);
|
|
1011
|
-
expect(res.rows[0]['cnt']).toBe(1346912);
|
|
1012
|
-
});
|
|
1091
|
+
mockConnectionsApi.getConnection.mockResolvedValueOnce(
|
|
1092
|
+
mockConnectionResponse
|
|
1093
|
+
);
|
|
1013
1094
|
|
|
1014
|
-
|
|
1015
|
-
|
|
1016
|
-
|
|
1017
|
-
|
|
1018
|
-
|
|
1095
|
+
const connection = await PublisherConnection.create('test-connection', {
|
|
1096
|
+
connectionUri:
|
|
1097
|
+
'http://test.com/api/v0/projects/test-project/connections/test-connection',
|
|
1098
|
+
accessToken: 'test-token',
|
|
1099
|
+
});
|
|
1100
|
+
|
|
1101
|
+
// close() should not throw and should return void
|
|
1102
|
+
await expect(connection.close()).resolves.toBeUndefined();
|
|
1103
|
+
});
|
|
1019
1104
|
});
|
|
1020
1105
|
});
|
|
1021
1106
|
});
|