Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions changelogs/fragments/10574.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
feat:
- Date String Normalization ([#10574](https://github.com/opensearch-project/OpenSearch-Dashboards/pull/10574))
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@ import {
import { QueryExecutionStatus } from '../types';
import { setResults } from '../slices';
import { Query, DataView } from 'src/plugins/data/common';
import { DataPublicPluginStart } from '../../../../../../data/public';
import { ExploreServices } from '../../../../types';
import { SAMPLE_SIZE_SETTING } from '../../../../../common';

Expand Down Expand Up @@ -178,6 +177,9 @@ describe('Query Actions - Comprehensive Test Suite', () => {
query: {
queryString: {
getQuery: jest.fn().mockReturnValue({ query: '', language: 'PPL' }),
getLanguageService: jest.fn().mockReturnValue({
getLanguage: jest.fn().mockReturnValue({}),
}),
},
filterManager: {
getFilters: jest.fn().mockReturnValue([]),
Expand Down Expand Up @@ -488,7 +490,6 @@ describe('Query Actions - Comprehensive Test Suite', () => {
mockBuildPointSeriesData.mockReturnValue([{ x: 1609459200000, y: 5 }] as any);
mockTabifyAggResponse.mockReturnValue({ rows: [], columns: [] } as any);
});

it('should process histogram data when timeFieldName exists', () => {
const rawResults = {
hits: {
Expand Down Expand Up @@ -793,7 +794,34 @@ describe('Query Actions - Comprehensive Test Suite', () => {
// Using mockCreateHistogramConfigs from module scope
mockCreateHistogramConfigs.mockReturnValue({
toDsl: jest.fn().mockReturnValue({}),
aggs: [
{} as any,
{
buckets: {
getInterval: jest.fn(() => ({ interval: '1h', scale: 1 })),
},
} as any,
],
} as any);
mockSearchSource.fetch.mockReset();
mockSearchSource.fetch.mockResolvedValue({
hits: {
hits: [
{ _id: '1', _source: { field1: 'value1' } },
{ _id: '2', _source: { field2: 'value2' } },
],
total: 2,
},
took: 5,
aggregations: {
histogram: {
buckets: [
{ key: 1609459200000, doc_count: 5 },
{ key: 1609462800000, doc_count: 3 },
],
},
},
});
});

it('should execute histogram query with custom interval', async () => {
Expand All @@ -808,6 +836,17 @@ describe('Query Actions - Comprehensive Test Suite', () => {

expect(mockServices.data.dataViews.get).toHaveBeenCalled();
expect(mockSearchSource.fetch).toHaveBeenCalled();
expect(mockDispatch).toHaveBeenCalledWith(
expect.objectContaining({
type: 'queryEditor/setIndividualQueryStatus',
payload: expect.objectContaining({
cacheKey: 'test-cache-key',
status: expect.objectContaining({
status: QueryExecutionStatus.READY,
}),
}),
})
);
});

it('should handle missing interval gracefully', async () => {
Expand All @@ -820,6 +859,18 @@ describe('Query Actions - Comprehensive Test Suite', () => {
await thunk(mockDispatch, mockGetState, undefined);

expect(mockServices.data.dataViews.get).toHaveBeenCalled();
expect(mockSearchSource.fetch).toHaveBeenCalled();
expect(mockDispatch).toHaveBeenCalledWith(
expect.objectContaining({
type: 'queryEditor/setIndividualQueryStatus',
payload: expect.objectContaining({
cacheKey: 'test-cache-key',
status: expect.objectContaining({
status: QueryExecutionStatus.READY,
}),
}),
})
);
});

it('should handle dataView without timeFieldName', async () => {
Expand All @@ -834,16 +885,32 @@ describe('Query Actions - Comprehensive Test Suite', () => {

const thunk = executeHistogramQuery(params);
await thunk(mockDispatch, mockGetState, undefined);

expect(mockServices.data.dataViews.get).toHaveBeenCalled();
expect(mockSearchSource.fetch).toHaveBeenCalled();
expect(mockDispatch).toHaveBeenCalledWith(
expect.objectContaining({
type: 'queryEditor/setIndividualQueryStatus',
payload: expect.objectContaining({
cacheKey: 'test-cache-key',
status: expect.objectContaining({
status: QueryExecutionStatus.READY,
}),
}),
})
);
});

it('should handle search errors gracefully', async () => {
const error = {
body: {
error: 'Search failed',
message:
'{"error":{"details":"Query syntax error","reason":"Invalid query","type":"parsing_exception"}}',
message: JSON.stringify({
error: {
details: 'Query syntax error',
reason: 'Invalid query',
type: 'parsing_exception',
},
}),
statusCode: 400,
},
};
Expand All @@ -866,11 +933,20 @@ describe('Query Actions - Comprehensive Test Suite', () => {
// Verify error status is set in Redux
expect(mockDispatch).toHaveBeenCalledWith(
expect.objectContaining({
type: expect.stringContaining('setIndividualQueryStatus'),
type: 'queryEditor/setIndividualQueryStatus',
payload: expect.objectContaining({
cacheKey: 'test-cache-key',
status: expect.objectContaining({
status: QueryExecutionStatus.ERROR,
error: expect.objectContaining({
error: 'Search failed',
message: {
details: 'Query syntax error',
reason: 'Invalid query',
type: 'parsing_exception',
},
statusCode: 400,
}),
}),
}),
})
Expand Down Expand Up @@ -917,6 +993,17 @@ describe('Query Actions - Comprehensive Test Suite', () => {

const mockIndexPatterns = dataPublicModule.indexPatterns as any;
mockIndexPatterns.isDefault.mockReturnValue(true);
mockSearchSource.fetch.mockReset();
mockSearchSource.fetch.mockResolvedValue({
hits: {
hits: [
{ _id: '1', _source: { field1: 'value1' } },
{ _id: '2', _source: { field2: 'value2' } },
],
total: 2,
},
took: 5,
});
});

it('should execute tab query successfully', async () => {
Expand All @@ -931,6 +1018,17 @@ describe('Query Actions - Comprehensive Test Suite', () => {
expect(mockServices.data.dataViews.get).toHaveBeenCalled();
expect(mockSearchSource.fetch).toHaveBeenCalled();
expect(setResults).toHaveBeenCalled();
expect(mockDispatch).toHaveBeenCalledWith(
expect.objectContaining({
type: 'queryEditor/setIndividualQueryStatus',
payload: expect.objectContaining({
cacheKey: 'test-cache-key',
status: expect.objectContaining({
status: QueryExecutionStatus.READY,
}),
}),
})
);
});

it('should handle missing services gracefully', async () => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -385,10 +385,15 @@ const executeQueryBase = async (
});
}

const languageConfig = services.data.query.queryString
.getLanguageService()
.getLanguage(query.language);

// Execute query
const rawResults = await searchSource.fetch({
abortSignal: abortController.signal,
withLongNumeralsSupport: await services.uiSettings.get('data:withLongNumerals'),
...(languageConfig?.fields?.formatter ? { formatter: languageConfig.fields.formatter } : {}),
});

// Add response stats to inspector
Expand Down
Loading