@@ -9,6 +9,7 @@ import { indexPatternTypeConfig } from './index_pattern_type';
99import { SavedObjectsClientContract } from 'opensearch-dashboards/public' ;
1010import { DATA_STRUCTURE_META_TYPES , DataStructure , Dataset } from '../../../../../common' ;
1111import * as services from '../../../../services' ;
12+ import * as utilsModule from './utils' ;
1213
1314jest . mock ( '../../../../services' , ( ) => ( {
1415 getIndexPatterns : jest . fn ( ) ,
@@ -113,4 +114,221 @@ describe('indexPatternTypeConfig', () => {
113114 'SQL' ,
114115 ] ) ;
115116 } ) ;
117+
118+ describe ( 'fetch' , ( ) => {
119+ beforeEach ( ( ) => {
120+ ( utilsModule . injectMetaToDataStructures as jest . Mock ) . mockImplementation (
121+ ( structures : DataStructure [ ] ) => structures
122+ ) ;
123+ } ) ;
124+
125+ test ( 'should extract data source from references array (traditional method)' , async ( ) => {
126+ const client = ( {
127+ find : jest . fn ( ) . mockResolvedValue ( {
128+ savedObjects : [
129+ {
130+ id : 'pattern-123' ,
131+ type : 'index-pattern' ,
132+ attributes : {
133+ title : 'my-pattern' ,
134+ timeFieldName : '@timestamp' ,
135+ } ,
136+ references : [ { id : 'datasource-abc' , type : 'data-source' , name : 'dataSource' } ] ,
137+ } ,
138+ ] ,
139+ } ) ,
140+ bulkGet : jest . fn ( ) . mockResolvedValue ( {
141+ savedObjects : [
142+ {
143+ id : 'datasource-abc' ,
144+ type : 'data-source' ,
145+ attributes : { title : 'My Data Source' , dataSourceEngineType : 'OpenSearch' } ,
146+ } ,
147+ ] ,
148+ } ) ,
149+ } as unknown ) as SavedObjectsClientContract ;
150+
151+ // @ts -expect-error - Partial mock for testing
152+ const result = await indexPatternTypeConfig . fetch ( { savedObjects : { client } } , [ ] ) ;
153+
154+ expect ( client . find ) . toHaveBeenCalledWith ( {
155+ type : 'index-pattern' ,
156+ fields : [ 'title' , 'timeFieldName' , 'references' ] ,
157+ search : '*' ,
158+ searchFields : [ 'title' ] ,
159+ perPage : 100 ,
160+ } ) ;
161+
162+ expect ( client . bulkGet ) . toHaveBeenCalledWith ( [ { id : 'datasource-abc' , type : 'data-source' } ] ) ;
163+
164+ expect ( result . children ) . toHaveLength ( 1 ) ;
165+ expect ( result . children ! [ 0 ] ) . toEqual ( {
166+ id : 'pattern-123' ,
167+ title : 'my-pattern' ,
168+ type : 'INDEX_PATTERN' ,
169+ meta : {
170+ type : DATA_STRUCTURE_META_TYPES . CUSTOM ,
171+ timeFieldName : '@timestamp' ,
172+ } ,
173+ parent : {
174+ id : 'datasource-abc' ,
175+ title : 'My Data Source' ,
176+ type : 'OpenSearch' ,
177+ } ,
178+ } ) ;
179+ } ) ;
180+
181+ test ( 'should extract data source from namespaced ID when references are empty' , async ( ) => {
182+ const client = ( {
183+ find : jest . fn ( ) . mockResolvedValue ( {
184+ savedObjects : [
185+ {
186+ id : 'datasource-xyz::my-pattern' ,
187+ type : 'index-pattern' ,
188+ attributes : {
189+ title : 'my-pattern' ,
190+ timeFieldName : '@timestamp' ,
191+ } ,
192+ references : [ ] ,
193+ } ,
194+ ] ,
195+ } ) ,
196+ bulkGet : jest . fn ( ) . mockResolvedValue ( {
197+ savedObjects : [
198+ {
199+ id : 'datasource-xyz' ,
200+ type : 'data-source' ,
201+ attributes : { title : 'External Data Source' , dataSourceEngineType : 'OpenSearch' } ,
202+ } ,
203+ ] ,
204+ } ) ,
205+ } as unknown ) as SavedObjectsClientContract ;
206+
207+ // @ts -expect-error - Partial mock for testing
208+ const result = await indexPatternTypeConfig . fetch ( { savedObjects : { client } } , [ ] ) ;
209+
210+ expect ( client . bulkGet ) . toHaveBeenCalledWith ( [ { id : 'datasource-xyz' , type : 'data-source' } ] ) ;
211+
212+ expect ( result . children ) . toHaveLength ( 1 ) ;
213+ expect ( result . children ! [ 0 ] ) . toEqual ( {
214+ id : 'datasource-xyz::my-pattern' ,
215+ title : 'my-pattern' ,
216+ type : 'INDEX_PATTERN' ,
217+ meta : {
218+ type : DATA_STRUCTURE_META_TYPES . CUSTOM ,
219+ timeFieldName : '@timestamp' ,
220+ } ,
221+ parent : {
222+ id : 'datasource-xyz' ,
223+ title : 'External Data Source' ,
224+ type : 'OpenSearch' ,
225+ } ,
226+ } ) ;
227+ } ) ;
228+
229+ test ( 'should handle index patterns without data source' , async ( ) => {
230+ const client = ( {
231+ find : jest . fn ( ) . mockResolvedValue ( {
232+ savedObjects : [
233+ {
234+ id : 'pattern-456' ,
235+ type : 'index-pattern' ,
236+ attributes : {
237+ title : 'local-pattern' ,
238+ timeFieldName : '@timestamp' ,
239+ } ,
240+ references : [ ] ,
241+ } ,
242+ ] ,
243+ } ) ,
244+ bulkGet : jest . fn ( ) . mockResolvedValue ( { savedObjects : [ ] } ) ,
245+ } as unknown ) as SavedObjectsClientContract ;
246+
247+ // @ts -expect-error - Partial mock for testing
248+ const result = await indexPatternTypeConfig . fetch ( { savedObjects : { client } } , [ ] ) ;
249+
250+ // bulkGet should not be called when there are no data sources
251+ expect ( client . bulkGet ) . not . toHaveBeenCalled ( ) ;
252+
253+ expect ( result . children ) . toHaveLength ( 1 ) ;
254+ expect ( result . children ! [ 0 ] ) . toEqual ( {
255+ id : 'pattern-456' ,
256+ title : 'local-pattern' ,
257+ type : 'INDEX_PATTERN' ,
258+ meta : {
259+ type : DATA_STRUCTURE_META_TYPES . CUSTOM ,
260+ timeFieldName : '@timestamp' ,
261+ } ,
262+ } ) ;
263+ expect ( result . children ! [ 0 ] . parent ) . toBeUndefined ( ) ;
264+ } ) ;
265+
266+ test ( 'should handle mixed scenarios with both traditional and namespaced methods' , async ( ) => {
267+ const client = ( {
268+ find : jest . fn ( ) . mockResolvedValue ( {
269+ savedObjects : [
270+ {
271+ id : 'pattern-traditional' ,
272+ type : 'index-pattern' ,
273+ attributes : { title : 'traditional-pattern' , timeFieldName : '@timestamp' } ,
274+ references : [ { id : 'datasource-1' , type : 'data-source' , name : 'dataSource' } ] ,
275+ } ,
276+ {
277+ id : 'datasource-2::namespaced-pattern' ,
278+ type : 'index-pattern' ,
279+ attributes : { title : 'namespaced-pattern' , timeFieldName : '@timestamp' } ,
280+ references : [ ] ,
281+ } ,
282+ {
283+ id : 'local-pattern' ,
284+ type : 'index-pattern' ,
285+ attributes : { title : 'local-only' , timeFieldName : '@timestamp' } ,
286+ references : [ ] ,
287+ } ,
288+ ] ,
289+ } ) ,
290+ bulkGet : jest . fn ( ) . mockResolvedValue ( {
291+ savedObjects : [
292+ {
293+ id : 'datasource-1' ,
294+ type : 'data-source' ,
295+ attributes : { title : 'Data Source 1' , dataSourceEngineType : 'OpenSearch' } ,
296+ } ,
297+ {
298+ id : 'datasource-2' ,
299+ type : 'data-source' ,
300+ attributes : { title : 'Data Source 2' , dataSourceEngineType : 'OpenSearch' } ,
301+ } ,
302+ ] ,
303+ } ) ,
304+ } as unknown ) as SavedObjectsClientContract ;
305+
306+ // @ts -expect-error - Partial mock for testing
307+ const result = await indexPatternTypeConfig . fetch ( { savedObjects : { client } } , [ ] ) ;
308+
309+ expect ( client . bulkGet ) . toHaveBeenCalledWith ( [
310+ { id : 'datasource-1' , type : 'data-source' } ,
311+ { id : 'datasource-2' , type : 'data-source' } ,
312+ ] ) ;
313+
314+ expect ( result . children ) . toHaveLength ( 3 ) ;
315+
316+ // Traditional method
317+ expect ( result . children ! [ 0 ] . parent ) . toEqual ( {
318+ id : 'datasource-1' ,
319+ title : 'Data Source 1' ,
320+ type : 'OpenSearch' ,
321+ } ) ;
322+
323+ // Namespaced method
324+ expect ( result . children ! [ 1 ] . parent ) . toEqual ( {
325+ id : 'datasource-2' ,
326+ title : 'Data Source 2' ,
327+ type : 'OpenSearch' ,
328+ } ) ;
329+
330+ // No data source
331+ expect ( result . children ! [ 2 ] . parent ) . toBeUndefined ( ) ;
332+ } ) ;
333+ } ) ;
116334} ) ;
0 commit comments