@@ -395,3 +395,96 @@ describe("EntityInstanceId.fromString", () => {
395395 expect ( ( ) => EntityInstanceId . fromString ( "@onlyname" ) ) . toThrow ( ) ;
396396 } ) ;
397397} ) ;
398+
399+ describe ( "getEntities query normalization" , ( ) => {
400+ const { TaskHubGrpcClient } = require ( "../src" ) ;
401+
402+ function getStub ( client : InstanceType < typeof TaskHubGrpcClient > ) : any {
403+ return ( client as any ) . _stub ;
404+ }
405+
406+ function mockQueryEntities (
407+ client : InstanceType < typeof TaskHubGrpcClient > ,
408+ captureRequest : ( req : pb . QueryEntitiesRequest ) => void ,
409+ ) : void {
410+ getStub ( client ) . queryEntities = ( req : pb . QueryEntitiesRequest , _metadata : any , callback : any ) => {
411+ captureRequest ( req ) ;
412+ const res = new pb . QueryEntitiesResponse ( ) ;
413+ callback ( null , res ) ;
414+ return { } ;
415+ } ;
416+ }
417+
418+ it ( "should normalize mixed-case instanceIdStartsWith prefix" , async ( ) => {
419+ const client = new TaskHubGrpcClient ( { hostAddress : "localhost:4001" } ) ;
420+ let capturedReq : pb . QueryEntitiesRequest | undefined ;
421+
422+ mockQueryEntities ( client , ( req ) => { capturedReq = req ; } ) ;
423+
424+ const query : EntityQuery = { instanceIdStartsWith : "Counter" } ;
425+ const pageable = client . getEntities ( query ) ;
426+
427+ // Consume the first page to trigger the gRPC call
428+ for await ( const _entity of pageable ) {
429+ // no-op
430+ }
431+
432+ expect ( capturedReq ) . toBeDefined ( ) ;
433+ const protoPrefix = capturedReq ! . getQuery ( ) ?. getInstanceidstartswith ( ) ?. getValue ( ) ;
434+ expect ( protoPrefix ) . toBe ( "@counter" ) ;
435+ } ) ;
436+
437+ it ( "should normalize prefix with name and key separator" , async ( ) => {
438+ const client = new TaskHubGrpcClient ( { hostAddress : "localhost:4001" } ) ;
439+ let capturedReq : pb . QueryEntitiesRequest | undefined ;
440+
441+ mockQueryEntities ( client , ( req ) => { capturedReq = req ; } ) ;
442+
443+ const query : EntityQuery = { instanceIdStartsWith : "Counter@User-123" } ;
444+ const pageable = client . getEntities ( query ) ;
445+
446+ for await ( const _entity of pageable ) {
447+ // no-op
448+ }
449+
450+ expect ( capturedReq ) . toBeDefined ( ) ;
451+ const protoPrefix = capturedReq ! . getQuery ( ) ?. getInstanceidstartswith ( ) ?. getValue ( ) ;
452+ expect ( protoPrefix ) . toBe ( "@counter@User-123" ) ;
453+ } ) ;
454+
455+ it ( "should not set prefix when instanceIdStartsWith is undefined" , async ( ) => {
456+ const client = new TaskHubGrpcClient ( { hostAddress : "localhost:4001" } ) ;
457+ let capturedReq : pb . QueryEntitiesRequest | undefined ;
458+
459+ mockQueryEntities ( client , ( req ) => { capturedReq = req ; } ) ;
460+
461+ const query : EntityQuery = { } ;
462+ const pageable = client . getEntities ( query ) ;
463+
464+ for await ( const _entity of pageable ) {
465+ // no-op
466+ }
467+
468+ expect ( capturedReq ) . toBeDefined ( ) ;
469+ const protoPrefix = capturedReq ! . getQuery ( ) ?. getInstanceidstartswith ( ) ;
470+ expect ( protoPrefix ) . toBeUndefined ( ) ;
471+ } ) ;
472+
473+ it ( "should preserve already-normalized prefix" , async ( ) => {
474+ const client = new TaskHubGrpcClient ( { hostAddress : "localhost:4001" } ) ;
475+ let capturedReq : pb . QueryEntitiesRequest | undefined ;
476+
477+ mockQueryEntities ( client , ( req ) => { capturedReq = req ; } ) ;
478+
479+ const query : EntityQuery = { instanceIdStartsWith : "@counter@" } ;
480+ const pageable = client . getEntities ( query ) ;
481+
482+ for await ( const _entity of pageable ) {
483+ // no-op
484+ }
485+
486+ expect ( capturedReq ) . toBeDefined ( ) ;
487+ const protoPrefix = capturedReq ! . getQuery ( ) ?. getInstanceidstartswith ( ) ?. getValue ( ) ;
488+ expect ( protoPrefix ) . toBe ( "@counter@" ) ;
489+ } ) ;
490+ } ) ;
0 commit comments