@@ -11,6 +11,7 @@ import {
1111import { buildIndexInfoRaw } from 'src/__mocks__/redisearch' ;
1212import { DatabaseClientFactory } from 'src/modules/database/providers/database.client.factory' ;
1313import { KeyIndexesService } from 'src/modules/browser/redisearch/key-indexes.service' ;
14+ import { RedisDataType } from 'src/modules/browser/keys/dto' ;
1415
1516const mockMovieInfoRaw = buildIndexInfoRaw ( {
1617 indexName : 'idx:movie' ,
@@ -43,6 +44,15 @@ describe('KeyIndexesService', () => {
4344 const clusterClient = mockClusterRedisClient ;
4445 let service : KeyIndexesService ;
4546
47+ const mockKeyType = (
48+ key : string | Buffer ,
49+ type : string = RedisDataType . Hash ,
50+ ) => {
51+ when ( standaloneClient . sendCommand )
52+ . calledWith ( [ 'TYPE' , key ] , expect . anything ( ) )
53+ . mockResolvedValue ( type ) ;
54+ } ;
55+
4656 beforeEach ( async ( ) => {
4757 const module : TestingModule = await Test . createTestingModule ( {
4858 providers : [
@@ -66,6 +76,7 @@ describe('KeyIndexesService', () => {
6676
6777 describe ( 'getKeyIndexes' , ( ) => {
6878 it ( 'should return matching index when key matches a prefix' , async ( ) => {
79+ mockKeyType ( 'movie:1' ) ;
6980 when ( standaloneClient . sendCommand )
7081 . calledWith ( [ 'FT._LIST' ] )
7182 . mockResolvedValue ( [ Buffer . from ( 'idx:movie' ) ] ) ;
@@ -84,6 +95,7 @@ describe('KeyIndexesService', () => {
8495 } ) ;
8596
8697 it ( 'should return empty array when key matches no prefix' , async ( ) => {
98+ mockKeyType ( 'session:abc' ) ;
8799 when ( standaloneClient . sendCommand )
88100 . calledWith ( [ 'FT._LIST' ] )
89101 . mockResolvedValue ( [ Buffer . from ( 'idx:movie' ) ] ) ;
@@ -99,6 +111,7 @@ describe('KeyIndexesService', () => {
99111 } ) ;
100112
101113 it ( 'should return multiple indexes when key matches several' , async ( ) => {
114+ mockKeyType ( 'user:42' ) ;
102115 when ( standaloneClient . sendCommand )
103116 . calledWith ( [ 'FT._LIST' ] )
104117 . mockResolvedValue ( [
@@ -123,6 +136,7 @@ describe('KeyIndexesService', () => {
123136 } ) ;
124137
125138 it ( 'should match index with empty prefixes to any key' , async ( ) => {
139+ mockKeyType ( 'anything:here' ) ;
126140 when ( standaloneClient . sendCommand )
127141 . calledWith ( [ 'FT._LIST' ] )
128142 . mockResolvedValue ( [ Buffer . from ( 'idx:global' ) ] ) ;
@@ -139,6 +153,7 @@ describe('KeyIndexesService', () => {
139153 } ) ;
140154
141155 it ( 'should match key against index with multiple prefixes' , async ( ) => {
156+ mockKeyType ( 'item:99' , RedisDataType . JSON ) ;
142157 when ( standaloneClient . sendCommand )
143158 . calledWith ( [ 'FT._LIST' ] )
144159 . mockResolvedValue ( [ Buffer . from ( 'idx:multi' ) ] ) ;
@@ -156,6 +171,7 @@ describe('KeyIndexesService', () => {
156171 } ) ;
157172
158173 it ( 'should return empty when no indexes exist' , async ( ) => {
174+ mockKeyType ( 'movie:1' ) ;
159175 when ( standaloneClient . sendCommand )
160176 . calledWith ( [ 'FT._LIST' ] )
161177 . mockResolvedValue ( [ ] ) ;
@@ -168,6 +184,7 @@ describe('KeyIndexesService', () => {
168184 } ) ;
169185
170186 it ( 'should skip indexes whose FT.INFO fails' , async ( ) => {
187+ mockKeyType ( 'movie:1' ) ;
171188 when ( standaloneClient . sendCommand )
172189 . calledWith ( [ 'FT._LIST' ] )
173190 . mockResolvedValue ( [
@@ -190,13 +207,14 @@ describe('KeyIndexesService', () => {
190207 } ) ;
191208
192209 it ( 'should deduplicate index names from cluster shards' , async ( ) => {
210+ mockKeyType ( 'movie:1' ) ;
193211 when ( clusterClient . sendCommand )
194212 . calledWith ( [ 'FT._LIST' ] )
195213 . mockResolvedValue ( [ Buffer . from ( 'idx:movie' ) ] ) ;
196214 when ( standaloneClient . sendCommand )
197215 . calledWith ( [ 'FT._LIST' ] )
198216 . mockResolvedValue ( [ Buffer . from ( 'idx:movie' ) ] ) ;
199- when ( clusterClient . sendCommand )
217+ when ( standaloneClient . sendCommand )
200218 . calledWith ( [ 'FT.INFO' , 'idx:movie' ] , expect . anything ( ) )
201219 . mockResolvedValue ( mockMovieInfoRaw ) ;
202220
@@ -216,6 +234,7 @@ describe('KeyIndexesService', () => {
216234 } ) ;
217235
218236 it ( 'should handle Buffer keys' , async ( ) => {
237+ mockKeyType ( Buffer . from ( 'movie:1' ) ) ;
219238 when ( standaloneClient . sendCommand )
220239 . calledWith ( [ 'FT._LIST' ] )
221240 . mockResolvedValue ( [ Buffer . from ( 'idx:movie' ) ] ) ;
@@ -230,5 +249,50 @@ describe('KeyIndexesService', () => {
230249 expect ( result . indexes ) . toHaveLength ( 1 ) ;
231250 expect ( result . indexes [ 0 ] . name ) . toBe ( 'idx:movie' ) ;
232251 } ) ;
252+
253+ it ( 'should not match an index of a different key type' , async ( ) => {
254+ mockKeyType ( 'movie:1' , RedisDataType . JSON ) ;
255+ when ( standaloneClient . sendCommand )
256+ . calledWith ( [ 'FT._LIST' ] )
257+ . mockResolvedValue ( [ Buffer . from ( 'idx:movie' ) ] ) ;
258+ when ( standaloneClient . sendCommand )
259+ . calledWith ( [ 'FT.INFO' , 'idx:movie' ] , expect . anything ( ) )
260+ . mockResolvedValue ( mockMovieInfoRaw ) ;
261+
262+ const result = await service . getKeyIndexes ( mockBrowserClientMetadata , {
263+ key : 'movie:1' ,
264+ } ) ;
265+
266+ expect ( result . indexes ) . toHaveLength ( 0 ) ;
267+ } ) ;
268+
269+ it ( 'should respect key type for indexes with empty prefixes' , async ( ) => {
270+ mockKeyType ( 'anything:here' , RedisDataType . JSON ) ;
271+ when ( standaloneClient . sendCommand )
272+ . calledWith ( [ 'FT._LIST' ] )
273+ . mockResolvedValue ( [ Buffer . from ( 'idx:global' ) ] ) ;
274+ when ( standaloneClient . sendCommand )
275+ . calledWith ( [ 'FT.INFO' , 'idx:global' ] , expect . anything ( ) )
276+ . mockResolvedValue ( mockGlobalInfoRaw ) ;
277+
278+ const result = await service . getKeyIndexes ( mockBrowserClientMetadata , {
279+ key : 'anything:here' ,
280+ } ) ;
281+
282+ expect ( result . indexes ) . toHaveLength ( 0 ) ;
283+ } ) ;
284+
285+ it ( 'should return empty for unsupported key types without listing indexes' , async ( ) => {
286+ mockKeyType ( 'mylist' , RedisDataType . List ) ;
287+
288+ const result = await service . getKeyIndexes ( mockBrowserClientMetadata , {
289+ key : 'mylist' ,
290+ } ) ;
291+
292+ expect ( result . indexes ) . toHaveLength ( 0 ) ;
293+ expect ( standaloneClient . sendCommand ) . not . toHaveBeenCalledWith ( [
294+ 'FT._LIST' ,
295+ ] ) ;
296+ } ) ;
233297 } ) ;
234298} ) ;
0 commit comments