@@ -358,3 +358,225 @@ describe('CubeApi with Abort Signal', () => {
358358 expect ( requestSpy . mock . calls [ 0 ] ?. [ 1 ] ?. signal ) . toBe ( signal ) ;
359359 } ) ;
360360} ) ;
361+
362+ describe ( 'CubeApi with baseRequestId' , ( ) => {
363+ afterEach ( ( ) => {
364+ jest . clearAllMocks ( ) ;
365+ jest . restoreAllMocks ( ) ;
366+ } ) ;
367+
368+ test ( 'should pass baseRequestId from options to request' , async ( ) => {
369+ const baseRequestId = 'custom-request-id-123' ;
370+
371+ const requestSpy = jest . spyOn ( HttpTransport . prototype , 'request' ) . mockImplementation ( ( ) => ( {
372+ subscribe : ( cb ) => Promise . resolve ( cb ( {
373+ status : 200 ,
374+ text : ( ) => Promise . resolve ( '{"results":[]}' ) ,
375+ json : ( ) => Promise . resolve ( { results : [ ] } )
376+ } as any ,
377+ async ( ) => undefined as any ) )
378+ } ) ) ;
379+
380+ const cubeApi = new CubeApi ( 'token' , {
381+ apiUrl : 'http://localhost:4000/cubejs-api/v1'
382+ } ) ;
383+
384+ await cubeApi . load (
385+ { measures : [ 'Orders.count' ] } ,
386+ { baseRequestId }
387+ ) ;
388+
389+ expect ( requestSpy ) . toHaveBeenCalled ( ) ;
390+ expect ( requestSpy . mock . calls [ 0 ] ?. [ 1 ] ?. baseRequestId ) . toBe ( baseRequestId ) ;
391+ } ) ;
392+
393+ test ( 'should generate baseRequestId if not provided' , async ( ) => {
394+ const requestSpy = jest . spyOn ( HttpTransport . prototype , 'request' ) . mockImplementation ( ( ) => ( {
395+ subscribe : ( cb ) => Promise . resolve ( cb ( {
396+ status : 200 ,
397+ text : ( ) => Promise . resolve ( '{"results":[]}' ) ,
398+ json : ( ) => Promise . resolve ( { results : [ ] } )
399+ } as any ,
400+ async ( ) => undefined as any ) )
401+ } ) ) ;
402+
403+ const cubeApi = new CubeApi ( 'token' , {
404+ apiUrl : 'http://localhost:4000/cubejs-api/v1'
405+ } ) ;
406+
407+ await cubeApi . load (
408+ { measures : [ 'Orders.count' ] }
409+ ) ;
410+
411+ expect ( requestSpy ) . toHaveBeenCalled ( ) ;
412+ // Should have a baseRequestId (generated via uuidv4)
413+ expect ( requestSpy . mock . calls [ 0 ] ?. [ 1 ] ?. baseRequestId ) . toBeDefined ( ) ;
414+ expect ( typeof requestSpy . mock . calls [ 0 ] ?. [ 1 ] ?. baseRequestId ) . toBe ( 'string' ) ;
415+ } ) ;
416+
417+ test ( 'should pass baseRequestId to sql request' , async ( ) => {
418+ const baseRequestId = 'sql-request-id-456' ;
419+
420+ const requestSpy = jest . spyOn ( HttpTransport . prototype , 'request' ) . mockImplementation ( ( ) => ( {
421+ subscribe : ( cb ) => Promise . resolve ( cb ( {
422+ status : 200 ,
423+ text : ( ) => Promise . resolve ( '{"sql":{"sql":"SELECT * FROM orders"}}' ) ,
424+ json : ( ) => Promise . resolve ( { sql : { sql : 'SELECT * FROM orders' } } )
425+ } as any ,
426+ async ( ) => undefined as any ) )
427+ } ) ) ;
428+
429+ const cubeApi = new CubeApi ( 'token' , {
430+ apiUrl : 'http://localhost:4000/cubejs-api/v1'
431+ } ) ;
432+
433+ await cubeApi . sql (
434+ { measures : [ 'Orders.count' ] } ,
435+ { baseRequestId }
436+ ) ;
437+
438+ expect ( requestSpy ) . toHaveBeenCalled ( ) ;
439+ expect ( requestSpy . mock . calls [ 0 ] ?. [ 1 ] ?. baseRequestId ) . toBe ( baseRequestId ) ;
440+ } ) ;
441+
442+ test ( 'should pass baseRequestId to dryRun request' , async ( ) => {
443+ const baseRequestId = 'dryrun-request-id-789' ;
444+
445+ const requestSpy = jest . spyOn ( HttpTransport . prototype , 'request' ) . mockImplementation ( ( ) => ( {
446+ subscribe : ( cb ) => Promise . resolve ( cb ( {
447+ status : 200 ,
448+ text : ( ) => Promise . resolve ( '{"queryType":"regular"}' ) ,
449+ json : ( ) => Promise . resolve ( { queryType : 'regular' } )
450+ } as any ,
451+ async ( ) => undefined as any ) )
452+ } ) ) ;
453+
454+ const cubeApi = new CubeApi ( 'token' , {
455+ apiUrl : 'http://localhost:4000/cubejs-api/v1'
456+ } ) ;
457+
458+ await cubeApi . dryRun (
459+ { measures : [ 'Orders.count' ] } ,
460+ { baseRequestId }
461+ ) ;
462+
463+ expect ( requestSpy ) . toHaveBeenCalled ( ) ;
464+ expect ( requestSpy . mock . calls [ 0 ] ?. [ 1 ] ?. baseRequestId ) . toBe ( baseRequestId ) ;
465+ } ) ;
466+
467+ test ( 'should pass baseRequestId to subscribe request' , async ( ) => {
468+ const baseRequestId = 'subscribe-request-id-abc' ;
469+
470+ const requestSpy = jest . spyOn ( HttpTransport . prototype , 'request' ) . mockImplementation ( ( ) => ( {
471+ subscribe : ( cb ) => Promise . resolve ( cb ( {
472+ status : 200 ,
473+ text : ( ) => Promise . resolve ( '{"results":[]}' ) ,
474+ json : ( ) => Promise . resolve ( { results : [ ] } )
475+ } as any ,
476+ async ( ) => undefined as any ) )
477+ } ) ) ;
478+
479+ const cubeApi = new CubeApi ( 'token' , {
480+ apiUrl : 'http://localhost:4000/cubejs-api/v1'
481+ } ) ;
482+
483+ const subscription = cubeApi . subscribe (
484+ { measures : [ 'Orders.count' ] } ,
485+ { baseRequestId } ,
486+ // eslint-disable-next-line @typescript-eslint/no-empty-function
487+ ( ) => { }
488+ ) ;
489+
490+ // Wait for the subscription to be initiated
491+ await new Promise ( resolve => setTimeout ( resolve , 0 ) ) ;
492+
493+ expect ( requestSpy ) . toHaveBeenCalled ( ) ;
494+ expect ( requestSpy . mock . calls [ 0 ] ?. [ 1 ] ?. baseRequestId ) . toBe ( baseRequestId ) ;
495+
496+ subscription . unsubscribe ( ) ;
497+ } ) ;
498+
499+ test ( 'should pass baseRequestId with multiple queries' , async ( ) => {
500+ const baseRequestId = 'multi-query-request-id' ;
501+
502+ const requestSpy = jest . spyOn ( HttpTransport . prototype , 'request' ) . mockImplementation ( ( ) => ( {
503+ subscribe : ( cb ) => Promise . resolve ( cb ( {
504+ status : 200 ,
505+ text : ( ) => Promise . resolve ( JSON . stringify ( DescriptiveQueryResponse ) ) ,
506+ json : ( ) => Promise . resolve ( DescriptiveQueryResponse )
507+ } as any ,
508+ async ( ) => undefined as any ) )
509+ } ) ) ;
510+
511+ const cubeApi = new CubeApi ( 'token' , {
512+ apiUrl : 'http://localhost:4000/cubejs-api/v1'
513+ } ) ;
514+
515+ await cubeApi . load (
516+ [
517+ { measures : [ 'Orders.count' ] } ,
518+ { measures : [ 'Users.count' ] }
519+ ] ,
520+ { baseRequestId }
521+ ) ;
522+
523+ expect ( requestSpy ) . toHaveBeenCalled ( ) ;
524+ expect ( requestSpy . mock . calls [ 0 ] ?. [ 1 ] ?. baseRequestId ) . toBe ( baseRequestId ) ;
525+ } ) ;
526+
527+ test ( 'should pass baseRequestId to meta request' , async ( ) => {
528+ const baseRequestId = 'meta-request-id-def' ;
529+
530+ const requestSpy = jest . spyOn ( HttpTransport . prototype , 'request' ) . mockImplementation ( ( ) => ( {
531+ subscribe : ( cb ) => Promise . resolve ( cb ( {
532+ status : 200 ,
533+ text : ( ) => Promise . resolve ( JSON . stringify ( {
534+ cubes : [ {
535+ name : 'Orders' ,
536+ title : 'Orders' ,
537+ measures : [ {
538+ name : 'count' ,
539+ title : 'Count' ,
540+ shortTitle : 'Count' ,
541+ type : 'number'
542+ } ] ,
543+ dimensions : [ {
544+ name : 'status' ,
545+ title : 'Status' ,
546+ type : 'string'
547+ } ] ,
548+ segments : [ ]
549+ } ]
550+ } ) ) ,
551+ json : ( ) => Promise . resolve ( {
552+ cubes : [ {
553+ name : 'Orders' ,
554+ title : 'Orders' ,
555+ measures : [ {
556+ name : 'count' ,
557+ title : 'Count' ,
558+ shortTitle : 'Count' ,
559+ type : 'number'
560+ } ] ,
561+ dimensions : [ {
562+ name : 'status' ,
563+ title : 'Status' ,
564+ type : 'string'
565+ } ] ,
566+ segments : [ ]
567+ } ]
568+ } )
569+ } as any ,
570+ async ( ) => undefined as any ) )
571+ } ) ) ;
572+
573+ const cubeApi = new CubeApi ( 'token' , {
574+ apiUrl : 'http://localhost:4000/cubejs-api/v1'
575+ } ) ;
576+
577+ await cubeApi . meta ( { baseRequestId } ) ;
578+
579+ expect ( requestSpy ) . toHaveBeenCalled ( ) ;
580+ expect ( requestSpy . mock . calls [ 0 ] ?. [ 1 ] ?. baseRequestId ) . toBe ( baseRequestId ) ;
581+ } ) ;
582+ } ) ;
0 commit comments