@@ -25,6 +25,22 @@ jest.mock('moment-timezone', () => {
2525 return moment ;
2626} ) ;
2727
28+ jest . mock ( './utils' , ( ) => ( {
29+ buildPPLHistogramQuery : jest . fn ( ( queryString ) => queryString ) ,
30+ processRawResultsForHistogram : jest . fn ( ( _queryString , rawResults ) => rawResults ) ,
31+ createHistogramConfigWithInterval : jest . fn ( ( ) => ( {
32+ toDsl : jest . fn ( ) . mockReturnValue ( { } ) ,
33+ aggs : [
34+ { } ,
35+ {
36+ buckets : {
37+ getInterval : jest . fn ( ( ) => ( { interval : '1h' , scale : 1 } ) ) ,
38+ } ,
39+ } ,
40+ ] ,
41+ } ) ) ,
42+ } ) ) ;
43+
2844import { configureStore } from '@reduxjs/toolkit' ;
2945import {
3046 abortAllActiveQueries ,
@@ -208,6 +224,9 @@ describe('Query Actions - Comprehensive Test Suite', () => {
208224 query : {
209225 queryString : {
210226 getQuery : jest . fn ( ) . mockReturnValue ( { query : '' , language : 'PPL' } ) ,
227+ getLanguageService : jest . fn ( ) . mockReturnValue ( {
228+ getLanguage : jest . fn ( ) . mockReturnValue ( { } ) ,
229+ } ) ,
211230 } ,
212231 filterManager : {
213232 getFilters : jest . fn ( ) . mockReturnValue ( [ ] ) ,
@@ -640,7 +659,6 @@ describe('Query Actions - Comprehensive Test Suite', () => {
640659 mockBuildPointSeriesData . mockReturnValue ( [ { x : 1609459200000 , y : 5 } ] as any ) ;
641660 mockTabifyAggResponse . mockReturnValue ( { rows : [ ] , columns : [ ] } as any ) ;
642661 } ) ;
643-
644662 it ( 'should process histogram data when timeFieldName exists' , ( ) => {
645663 const rawResults = {
646664 hits : {
@@ -1158,7 +1176,34 @@ describe('Query Actions - Comprehensive Test Suite', () => {
11581176 } ,
11591177 } ,
11601178 ] ) ,
1179+ aggs : [
1180+ { } as any ,
1181+ {
1182+ buckets : {
1183+ getInterval : jest . fn ( ( ) => ( { interval : '1h' , scale : 1 } ) ) ,
1184+ } ,
1185+ } as any ,
1186+ ] ,
11611187 } as any ) ;
1188+ mockSearchSource . fetch . mockReset ( ) ;
1189+ mockSearchSource . fetch . mockResolvedValue ( {
1190+ hits : {
1191+ hits : [
1192+ { _id : '1' , _source : { field1 : 'value1' } } ,
1193+ { _id : '2' , _source : { field2 : 'value2' } } ,
1194+ ] ,
1195+ total : 2 ,
1196+ } ,
1197+ took : 5 ,
1198+ aggregations : {
1199+ histogram : {
1200+ buckets : [
1201+ { key : 1609459200000 , doc_count : 5 } ,
1202+ { key : 1609462800000 , doc_count : 3 } ,
1203+ ] ,
1204+ } ,
1205+ } ,
1206+ } ) ;
11621207 } ) ;
11631208
11641209 it ( 'should execute histogram query with custom interval' , async ( ) => {
@@ -1174,6 +1219,92 @@ describe('Query Actions - Comprehensive Test Suite', () => {
11741219
11751220 expect ( mockServices . data . dataViews . get ) . toHaveBeenCalled ( ) ;
11761221 expect ( mockSearchSource . fetch ) . toHaveBeenCalled ( ) ;
1222+ expect ( mockDispatch ) . toHaveBeenCalledWith (
1223+ expect . objectContaining ( {
1224+ type : 'queryEditor/setIndividualQueryStatus' ,
1225+ payload : expect . objectContaining ( {
1226+ cacheKey : 'test-cache-key' ,
1227+ status : expect . objectContaining ( {
1228+ status : QueryExecutionStatus . READY ,
1229+ } ) ,
1230+ } ) ,
1231+ } )
1232+ ) ;
1233+ } ) ;
1234+
1235+ it ( 'should execute histogram query with formatter in language config' , async ( ) => {
1236+ const mockFormatter = jest . fn ( ) ;
1237+ ( mockServices . data . query . queryString . getLanguageService as jest . Mock ) . mockReturnValue ( {
1238+ getLanguage : jest . fn ( ) . mockReturnValue ( {
1239+ fields : {
1240+ formatter : mockFormatter ,
1241+ } ,
1242+ } ) ,
1243+ } ) ;
1244+
1245+ const params = {
1246+ services : mockServices ,
1247+ cacheKey : 'test-cache-key' ,
1248+ queryString : 'source=logs' ,
1249+ interval : '5m' ,
1250+ } ;
1251+
1252+ const thunk = executeHistogramQuery ( params ) ;
1253+ await thunk ( mockDispatch , mockGetState , undefined ) ;
1254+
1255+ expect ( mockServices . data . dataViews . get ) . toHaveBeenCalled ( ) ;
1256+ expect ( mockSearchSource . fetch ) . toHaveBeenCalledWith (
1257+ expect . objectContaining ( {
1258+ abortSignal : expect . any ( Object ) ,
1259+ formatter : mockFormatter ,
1260+ } )
1261+ ) ;
1262+ expect ( mockDispatch ) . toHaveBeenCalledWith (
1263+ expect . objectContaining ( {
1264+ type : 'queryEditor/setIndividualQueryStatus' ,
1265+ payload : expect . objectContaining ( {
1266+ cacheKey : 'test-cache-key' ,
1267+ status : expect . objectContaining ( {
1268+ status : QueryExecutionStatus . READY ,
1269+ } ) ,
1270+ } ) ,
1271+ } )
1272+ ) ;
1273+ } ) ;
1274+
1275+ it ( 'should execute histogram query without formatter in language config' , async ( ) => {
1276+ ( mockServices . data . query . queryString . getLanguageService as jest . Mock ) . mockReturnValue ( {
1277+ getLanguage : jest . fn ( ) . mockReturnValue ( { } ) ,
1278+ } ) ;
1279+
1280+ const params = {
1281+ services : mockServices ,
1282+ cacheKey : 'test-cache-key' ,
1283+ queryString : 'source=logs' ,
1284+ interval : '5m' ,
1285+ } ;
1286+
1287+ const thunk = executeHistogramQuery ( params ) ;
1288+ await thunk ( mockDispatch , mockGetState , undefined ) ;
1289+
1290+ expect ( mockServices . data . dataViews . get ) . toHaveBeenCalled ( ) ;
1291+ expect ( mockSearchSource . fetch ) . toHaveBeenCalledWith (
1292+ expect . objectContaining ( {
1293+ abortSignal : expect . any ( Object ) ,
1294+ withLongNumeralsSupport : false ,
1295+ } )
1296+ ) ;
1297+ expect ( mockDispatch ) . toHaveBeenCalledWith (
1298+ expect . objectContaining ( {
1299+ type : 'queryEditor/setIndividualQueryStatus' ,
1300+ payload : expect . objectContaining ( {
1301+ cacheKey : 'test-cache-key' ,
1302+ status : expect . objectContaining ( {
1303+ status : QueryExecutionStatus . READY ,
1304+ } ) ,
1305+ } ) ,
1306+ } )
1307+ ) ;
11771308 } ) ;
11781309
11791310 it ( 'should handle missing interval gracefully' , async ( ) => {
@@ -1187,6 +1318,18 @@ describe('Query Actions - Comprehensive Test Suite', () => {
11871318 await thunk ( mockDispatch , mockGetState , undefined ) ;
11881319
11891320 expect ( mockServices . data . dataViews . get ) . toHaveBeenCalled ( ) ;
1321+ expect ( mockSearchSource . fetch ) . toHaveBeenCalled ( ) ;
1322+ expect ( mockDispatch ) . toHaveBeenCalledWith (
1323+ expect . objectContaining ( {
1324+ type : 'queryEditor/setIndividualQueryStatus' ,
1325+ payload : expect . objectContaining ( {
1326+ cacheKey : 'test-cache-key' ,
1327+ status : expect . objectContaining ( {
1328+ status : QueryExecutionStatus . READY ,
1329+ } ) ,
1330+ } ) ,
1331+ } )
1332+ ) ;
11901333 } ) ;
11911334
11921335 it ( 'should handle dataView without timeFieldName' , async ( ) => {
@@ -1202,16 +1345,32 @@ describe('Query Actions - Comprehensive Test Suite', () => {
12021345
12031346 const thunk = executeHistogramQuery ( params ) ;
12041347 await thunk ( mockDispatch , mockGetState , undefined ) ;
1205-
1348+ expect ( mockServices . data . dataViews . get ) . toHaveBeenCalled ( ) ;
12061349 expect ( mockSearchSource . fetch ) . toHaveBeenCalled ( ) ;
1350+ expect ( mockDispatch ) . toHaveBeenCalledWith (
1351+ expect . objectContaining ( {
1352+ type : 'queryEditor/setIndividualQueryStatus' ,
1353+ payload : expect . objectContaining ( {
1354+ cacheKey : 'test-cache-key' ,
1355+ status : expect . objectContaining ( {
1356+ status : QueryExecutionStatus . READY ,
1357+ } ) ,
1358+ } ) ,
1359+ } )
1360+ ) ;
12071361 } ) ;
12081362
12091363 it ( 'should handle search errors gracefully' , async ( ) => {
12101364 const error = {
12111365 body : {
12121366 error : 'Search failed' ,
1213- message :
1214- '{"error":{"details":"Query syntax error","reason":"Invalid query","type":"parsing_exception"}}' ,
1367+ message : JSON . stringify ( {
1368+ error : {
1369+ details : 'Query syntax error' ,
1370+ reason : 'Invalid query' ,
1371+ type : 'parsing_exception' ,
1372+ } ,
1373+ } ) ,
12151374 statusCode : 400 ,
12161375 } ,
12171376 } ;
@@ -1235,11 +1394,20 @@ describe('Query Actions - Comprehensive Test Suite', () => {
12351394 // Verify error status is set in Redux
12361395 expect ( mockDispatch ) . toHaveBeenCalledWith (
12371396 expect . objectContaining ( {
1238- type : expect . stringContaining ( ' setIndividualQueryStatus') ,
1397+ type : 'queryEditor/ setIndividualQueryStatus',
12391398 payload : expect . objectContaining ( {
12401399 cacheKey : 'test-cache-key' ,
12411400 status : expect . objectContaining ( {
12421401 status : QueryExecutionStatus . ERROR ,
1402+ error : expect . objectContaining ( {
1403+ error : 'Search failed' ,
1404+ message : {
1405+ details : 'Query syntax error' ,
1406+ reason : 'Invalid query' ,
1407+ type : 'parsing_exception' ,
1408+ } ,
1409+ statusCode : 400 ,
1410+ } ) ,
12431411 } ) ,
12441412 } ) ,
12451413 } )
@@ -1384,6 +1552,17 @@ describe('Query Actions - Comprehensive Test Suite', () => {
13841552
13851553 const mockIndexPatterns = dataPublicModule . indexPatterns as any ;
13861554 mockIndexPatterns . isDefault . mockReturnValue ( true ) ;
1555+ mockSearchSource . fetch . mockReset ( ) ;
1556+ mockSearchSource . fetch . mockResolvedValue ( {
1557+ hits : {
1558+ hits : [
1559+ { _id : '1' , _source : { field1 : 'value1' } } ,
1560+ { _id : '2' , _source : { field2 : 'value2' } } ,
1561+ ] ,
1562+ total : 2 ,
1563+ } ,
1564+ took : 5 ,
1565+ } ) ;
13871566 } ) ;
13881567
13891568 it ( 'should execute tab query successfully' , async ( ) => {
@@ -1399,6 +1578,17 @@ describe('Query Actions - Comprehensive Test Suite', () => {
13991578 expect ( mockServices . data . dataViews . get ) . toHaveBeenCalled ( ) ;
14001579 expect ( mockSearchSource . fetch ) . toHaveBeenCalled ( ) ;
14011580 expect ( setResults ) . toHaveBeenCalled ( ) ;
1581+ expect ( mockDispatch ) . toHaveBeenCalledWith (
1582+ expect . objectContaining ( {
1583+ type : 'queryEditor/setIndividualQueryStatus' ,
1584+ payload : expect . objectContaining ( {
1585+ cacheKey : 'test-cache-key' ,
1586+ status : expect . objectContaining ( {
1587+ status : QueryExecutionStatus . READY ,
1588+ } ) ,
1589+ } ) ,
1590+ } )
1591+ ) ;
14021592 } ) ;
14031593
14041594 it ( 'should handle missing services gracefully' , async ( ) => {
0 commit comments