mirror of
https://github.com/SigNoz/signoz.git
synced 2025-12-29 16:14:42 +00:00
* feat: add drilldown options in uplot * feat: add time range to timeseries, bar charts * feat: remove unwanted code * feat: minor refactor * feat: drilldown prop drilldowned * feat: refactor code * feat: update click plugin in uplot * feat: lint fix * feat: add search to breakout and other refactor * feat: context menu - increase width and add overlay * feat: add context links * feat: context links init * feat: context links init * feat: context links init * feat: update context link modal form init * feat: add double way sync on urls and param * feat: minor refactor * feat: minor refactor * feat: change contextlinks data structure * feat: context menu changes init * feat: context menu hook refactor * feat: context links processors * feat: context variables hook added * feat: add support for field variables * feat: minor refactor * feat: minor refactor * feat: minor refactor * feat: handle on save * feat: minor refactor * feat: snapshot update * feat: revert qbv5 * feat: aggregation header val * feat: fix header color * feat: minor refactor * feat: minor refactor * feat: fix breaking changes from qb v5 * feat: change api for breakout opitons * feat: minor refactor * feat: minor refactor * fix: added fix for extractquerypararms when value is string in multivalue operator * feat: minor refactor * feat: add back in breakout * feat: minor refactor * feat: add substitute var api call to decode vars * feat: minor fix * feat: optimize query value comparison in QueryBuilderV2 * feat: minor fix * feat: minor fix * feat: test fix * feat: added dynamic variables creation flow (#7541) * feat: added dynamic variables creation flow * feat: added keys and value apis and hooks * feat: added api and select component changes * feat: added keys fetching and preview values * feat: added dynamic variable to variable items * feat: handled value persistence and tab switches * feat: added default value and formed a schema for dyn-variables * feat: added client and server side searches * feat: corrected the initial load getfieldKey api * feat: removed fetch on mount restriction * feat: added dynamic variable to the dashboard details (#7755) * feat: added dynamic variable to the dashboard details * feat: added new component to existing variables * feat: added enhancement to multiselect and select for dyn-variables * feat: added refetch method between all dynamic-variables * feat: correct error handling * feat: correct error handling * feat: enforced non-empty selectedvalues and default value * feat: added client and server side searches * feat: retry on error * feat: correct error handling * feat: handle defautl value in existing variables * feat: lowercase the source for payload * feat: fixed the incorrect assignment of active indices * feat: improved handling of all option * feat: improved the ALL option visuals * feat: handled default value enforcement in existing variables * feat: added unix time to values call * feat: added incomplete data message and info to search * feat: changed dashboard panel call handling with existing variables * feat: adjusted the response type and data with the new API schema for values * feat: code refactor * feat: made dyn-variable option as the default * feat: added test cases for dyn variable creation and completion * feat: updated test cases * feat: added variable in url and made dashboard sync around that and sharable (#7944) * feat: added dynamic variable to the dashboard details * feat: added new component to existing variables * feat: added enhancement to multiselect and select for dyn-variables * feat: added refetch method between all dynamic-variables * feat: correct error handling * feat: correct error handling * feat: enforced non-empty selectedvalues and default value * feat: added client and server side searches * feat: retry on error * feat: correct error handling * feat: handle defautl value in existing variables * feat: lowercase the source for payload * feat: fixed the incorrect assignment of active indices * feat: improved handling of all option * feat: improved the ALL option visuals * feat: handled default value enforcement in existing variables * feat: added unix time to values call * feat: added incomplete data message and info to search * feat: changed dashboard panel call handling with existing variables * feat: adjusted the response type and data with the new API schema for values * feat: code refactor * feat: made dyn-variable option as the default * feat: added test cases for dyn variable creation and completion * feat: updated test cases * feat: added variable in url and made dashboard sync around that and sharable * feat: added test cases * feat: added safety check * feat: enabled url setting on first load itself * feat: code refactor * feat: cleared options query param when on dashboard list page * feat: resolved conflicts * feat: added dynamic variable suggestion in where clause * feat: added test cases for hooks and api call functions * feat: added test case for querybuildersearchv2 suggestion changes * feat: code refactor * feat: updated test case * feat: corrected the regex matcher for resolved titles * feat: added ability to add/remove variable filter to one or more existing panels * feat: added widgetselector on variable creation * feat: show labels in widget selector * feat: added apply to all and variable removal logical * feat: refectch only related and affected panels in case of dynamic variables * feat: added button loader for apply-all * feat: light-mode styles * feat: minor refactor * feat: added test cases * feat: refactor * feat: remove consoles * feat: pass panel types to substitutevars * feat: cross filtering init * fix: added fix for query builder filters * feat: cross filtering add set/unset/create functionality * feat: test update * fix: added migration to filter expression for crud operations of variable * feat: format legend name according to existing format * feat: breakout test init * feat: breakout test match query * feat: context links tests * feat: minor refactor * feat: show edit only if user has access * feat: added dynamic variables creation flow (#7541) * feat: added dynamic variables creation flow * feat: added keys and value apis and hooks * feat: added api and select component changes * feat: added keys fetching and preview values * feat: added dynamic variable to variable items * feat: handled value persistence and tab switches * feat: added default value and formed a schema for dyn-variables * feat: added client and server side searches * feat: corrected the initial load getfieldKey api * feat: removed fetch on mount restriction * feat: added dynamic variable to the dashboard details (#7755) * feat: added dynamic variable to the dashboard details * feat: added new component to existing variables * feat: added enhancement to multiselect and select for dyn-variables * feat: added refetch method between all dynamic-variables * feat: correct error handling * feat: correct error handling * feat: enforced non-empty selectedvalues and default value * feat: added client and server side searches * feat: retry on error * feat: correct error handling * feat: handle defautl value in existing variables * feat: lowercase the source for payload * feat: fixed the incorrect assignment of active indices * feat: improved handling of all option * feat: improved the ALL option visuals * feat: handled default value enforcement in existing variables * feat: added unix time to values call * feat: added incomplete data message and info to search * feat: changed dashboard panel call handling with existing variables * feat: adjusted the response type and data with the new API schema for values * feat: code refactor * feat: made dyn-variable option as the default * feat: added test cases for dyn variable creation and completion * feat: updated test cases * feat: added dynamic variable suggestion in where clause * feat: added test cases for hooks and api call functions * feat: added test case for querybuildersearchv2 suggestion changes * feat: code refactor * feat: updated test case * feat: corrected the regex matcher for resolved titles * feat: added ability to add/remove variable filter to one or more existing panels * feat: added widgetselector on variable creation * feat: show labels in widget selector * feat: added apply to all and variable removal logical * feat: refectch only related and affected panels in case of dynamic variables * feat: added button loader for apply-all * feat: light-mode styles * fix: added migration to filter expression for crud operations of variable * feat: reverted dynamic variable url config changes (#8877) * Revert "feat: changed query param name" This reverts commit 62bee5f003bf74b0da1c5951f1b5d0f2c250905d. * Revert "feat: added user-friendly format to dashboard variable url" This reverts commit 6de8b1c2e8c6a838941014ea4929e9f5c908d975. * feat: reverted url var changes * feat: reverted url changed from usedashboardvarupdate hook * feat: send empty array for widgetId * feat: added type in the variables in query_range payload for dynamic * feat: minor fixes * fix: added fix for multivalue operator without brackets * feat: minor fix * feat: fix failing test * feat: change revert * test: added tests for querycontextUtils + querybuilderv2 utils * fix: added fix for replacing filter with the new value * fix: added fix for replacing filters + datetimepicker composite query * test: fixed querybuilderv2 utils test * feat: handle number dataType in filters * feat: correct the variable addition to panel format for new qb expression * feat: remove other queries in breakout * feat: add metric to traces mapping * feat: pass proper time range * feat: update time range logic * feat: value panel drilldown init * feat: value panel drilldown init * feat: enable context links in value panel * feat: minor fix * feat: update snapshot * feat: hide breakout in value panel * feat: add panel type to view mode * feat: add support to change panel in breakouts * feat: panel change for breakout logic added * chore: fix style * chore: show variables suggestion while creating context links * chore: add timestamp to graphs * chore: add timestamp to table panel * chore: fix failing tests * chore: fix infinite re-rendering due to queryRange * chore: send appropriate time range when signal is metrics * chore: show variables suggestion while creating context links * chore: minor refactor * chore: show trace details link if filter has trace_id * chore: fix infinite render of table component * chore: added tests for v2 * fix: context links set from dropdown * chore: minor refactor * chore: minor refactor * chore: fix test * chore: fix timerange for apm metrics * fix: get correct timestamp for clicked data * chore: comment out change to histogram on breakout by number * chore: change panel type on panel type change in url * chore: remove consoles * feat: added dynamic variables creation flow (#7541) * feat: added dynamic variables creation flow * feat: added keys and value apis and hooks * feat: added api and select component changes * feat: added keys fetching and preview values * feat: added dynamic variable to variable items * feat: handled value persistence and tab switches * feat: added default value and formed a schema for dyn-variables * feat: added client and server side searches * feat: corrected the initial load getfieldKey api * feat: removed fetch on mount restriction * feat: added dynamic variable to the dashboard details (#7755) * feat: added dynamic variable to the dashboard details * feat: added new component to existing variables * feat: added enhancement to multiselect and select for dyn-variables * feat: added refetch method between all dynamic-variables * feat: correct error handling * feat: correct error handling * feat: enforced non-empty selectedvalues and default value * feat: added client and server side searches * feat: retry on error * feat: correct error handling * feat: handle defautl value in existing variables * feat: lowercase the source for payload * feat: fixed the incorrect assignment of active indices * feat: improved handling of all option * feat: improved the ALL option visuals * feat: handled default value enforcement in existing variables * feat: added unix time to values call * feat: added incomplete data message and info to search * feat: changed dashboard panel call handling with existing variables * feat: adjusted the response type and data with the new API schema for values * feat: code refactor * feat: made dyn-variable option as the default * feat: added test cases for dyn variable creation and completion * feat: updated test cases * feat: fix lint and test cases * feat: fix typo * feat: fixed test case * feat: added dynamic variable suggestion in where clause * feat: added test cases for hooks and api call functions * feat: added test case for querybuildersearchv2 suggestion changes * feat: code refactor * feat: corrected the regex matcher for resolved titles * feat: fixed test cases * feat: added ability to add/remove variable filter to one or more existing panels * feat: added widgetselector on variable creation * feat: show labels in widget selector * feat: added apply to all and variable removal logical * feat: refectch only related and affected panels in case of dynamic variables * feat: added button loader for apply-all * feat: light-mode styles * fix: added migration to filter expression for crud operations of variable * feat: added type in the variables in query_range payload for dynamic * feat: correct the variable addition to panel format for new qb expression * feat: added test cases for dynamic variable and add/remove panel feat * feat: implemented where clause suggestion in new qb v5 * feat: added retries for dyn variable and fixed on-enter selection issue * feat: added relatedValues and existing query in param related changes * feat: sanitized data storage and removed duplicates * fix: fixed typechecks * feat: updated panel wait and refetch logic and ALL option selection * feat: fixed variable tabel reordering issue * feat: added empty name validation in variable creation * feat: change value to searchtext in values API * feat: added option for regex in the component, disabled for now * feat: added beta and not rec. tag in variable tabs * feat: added check to prevent api and updates calls with same payload * feat: optimized localstorage for all selection in dynamic variable and updated __all__ case * feat: resolved variable tables infinite loop update error * feat: aded variable name auto-update based on attribute name entered for dynamic variables * feat: modified only/all click behaviour and set all selection always true for dynamic variable * feat: fix dropdown closing doesn't reset us back to our all available values when we have a search * feat: handled all state distinction and carry forward in existing variables * feat: trucate + n more tooltip content to 10 * feat: fixed infinite loop because of dependency of frequently changing object ref in var table * feat: fixed inconsist search implementations * feat: reverted only - all updated area implementation * feat: added more space for search in multiselect component * feat: checked for variable id instead of variable key for refetch * feat: improved performance around multiselect component and added confirm modal for apply to all * feat: rewrite functionality around add and remove panels * feat: changed color for apply to all modal * feat: added changes under flag to handle variable specific removal for removeKeysFromExpression func * feat: added validation in variable edit panel * chore: fix dynamic variable update in context menu to latest logic * chore: minor fix * chore: type fix * fix: remove unwanted code * fix: remove unwanted code * fix: resolved pr comments * fix: minor fix * fix: fix tests * fix: style fix --------- Co-authored-by: Aditya Singh <adityasingh@Adityas-MacBook-Pro.local> Co-authored-by: Abhi Kumar <ahrefabhi@gmail.com> Co-authored-by: SagarRajput-7 <162284829+SagarRajput-7@users.noreply.github.com> Co-authored-by: SagarRajput-7 <sagar@signoz.io>
273 lines
8.1 KiB
TypeScript
273 lines
8.1 KiB
TypeScript
/* eslint-disable sonarjs/no-duplicate-string */
|
|
|
|
import { fireEvent, render, screen } from '@testing-library/react';
|
|
import { Button } from 'antd';
|
|
import ROUTES from 'constants/routes';
|
|
import { server } from 'mocks-server/server';
|
|
import { rest } from 'msw';
|
|
import ContextMenu, { useCoordinates } from 'periscope/components/ContextMenu';
|
|
import MockQueryClientProvider from 'providers/test/MockQueryClientProvider';
|
|
import React from 'react';
|
|
import { Provider } from 'react-redux';
|
|
import { MemoryRouter } from 'react-router-dom';
|
|
import store from 'store';
|
|
import { Query } from 'types/api/queryBuilder/queryBuilderData';
|
|
|
|
import useTableContextMenu from '../useTableContextMenu';
|
|
import {
|
|
MOCK_AGGREGATE_DATA,
|
|
MOCK_COORDINATES,
|
|
MOCK_FILTER_DATA,
|
|
MOCK_KEY_SUGGESTIONS_RESPONSE,
|
|
// MOCK_KEY_SUGGESTIONS_SEARCH_RESPONSE,
|
|
MOCK_QUERY,
|
|
} from './mockTableData';
|
|
|
|
// Mock the necessary hooks and dependencies
|
|
const mockSafeNavigate = jest.fn();
|
|
const mockRedirectWithQueryBuilderData = jest.fn();
|
|
|
|
jest.mock('hooks/useSafeNavigate', () => ({
|
|
useSafeNavigate: (): any => ({
|
|
safeNavigate: mockSafeNavigate,
|
|
}),
|
|
}));
|
|
|
|
jest.mock('hooks/queryBuilder/useQueryBuilder', () => ({
|
|
useQueryBuilder: (): any => ({
|
|
redirectWithQueryBuilderData: mockRedirectWithQueryBuilderData,
|
|
}),
|
|
}));
|
|
|
|
jest.mock('container/GridCardLayout/useResolveQuery', () => ({
|
|
__esModule: true,
|
|
default: (): any => ({
|
|
getUpdatedQuery: jest.fn().mockResolvedValue({}),
|
|
isLoading: false,
|
|
}),
|
|
}));
|
|
|
|
jest.mock('react-router-dom', () => ({
|
|
...jest.requireActual('react-router-dom'),
|
|
useLocation: (): { pathname: string } => ({
|
|
pathname: `${process.env.FRONTEND_API_ENDPOINT}/${ROUTES.DASHBOARD}/`,
|
|
}),
|
|
}));
|
|
|
|
jest.mock('react-redux', () => ({
|
|
...jest.requireActual('react-redux'),
|
|
useSelector: (): any => ({
|
|
globalTime: {
|
|
selectedTime: {
|
|
startTime: 1713734400000,
|
|
endTime: 1713738000000,
|
|
},
|
|
maxTime: 1713738000000,
|
|
minTime: 1713734400000,
|
|
},
|
|
}),
|
|
}));
|
|
|
|
jest.mock('container/QueryTable/Drilldown/useDashboardVarConfig', () => ({
|
|
__esModule: true,
|
|
default: (): any => ({
|
|
dashbaordVariablesConfig: {
|
|
items: <>items</>,
|
|
},
|
|
// contextItems: <></>,
|
|
}),
|
|
}));
|
|
|
|
function MockTableDrilldown(): JSX.Element {
|
|
const {
|
|
coordinates,
|
|
popoverPosition,
|
|
clickedData,
|
|
onClose,
|
|
onClick,
|
|
subMenu,
|
|
setSubMenu,
|
|
} = useCoordinates();
|
|
|
|
const { menuItemsConfig } = useTableContextMenu({
|
|
widgetId: 'test-widget',
|
|
query: MOCK_QUERY as Query,
|
|
clickedData,
|
|
onClose,
|
|
coordinates,
|
|
subMenu,
|
|
setSubMenu,
|
|
});
|
|
|
|
const handleClick = (type: 'aggregate' | 'filter'): void => {
|
|
// Simulate the same flow as handleColumnClick in QueryTable
|
|
onClick(
|
|
MOCK_COORDINATES,
|
|
type === 'aggregate' ? MOCK_AGGREGATE_DATA : MOCK_FILTER_DATA,
|
|
);
|
|
};
|
|
|
|
return (
|
|
<div style={{ padding: '20px' }}>
|
|
<Button type="primary" onClick={(): void => handleClick('aggregate')}>
|
|
Aggregate
|
|
</Button>
|
|
|
|
<Button type="primary" onClick={(): void => handleClick('filter')}>
|
|
Filter
|
|
</Button>
|
|
|
|
<ContextMenu
|
|
coordinates={coordinates}
|
|
popoverPosition={popoverPosition}
|
|
onClose={onClose}
|
|
items={menuItemsConfig.items}
|
|
title={
|
|
typeof menuItemsConfig.header === 'string'
|
|
? menuItemsConfig.header
|
|
: undefined
|
|
}
|
|
/>
|
|
</div>
|
|
);
|
|
}
|
|
|
|
const renderWithProviders = (
|
|
component: React.ReactElement,
|
|
): ReturnType<typeof render> =>
|
|
render(
|
|
<MockQueryClientProvider>
|
|
<MemoryRouter>
|
|
<Provider store={store}>{component}</Provider>
|
|
</MemoryRouter>
|
|
</MockQueryClientProvider>,
|
|
);
|
|
|
|
describe('TableDrilldown Breakout Functionality', () => {
|
|
beforeEach((): void => {
|
|
jest.clearAllMocks();
|
|
|
|
// Mock the substitute_vars API that's causing network errors
|
|
server.use(
|
|
rest.post('*/api/v5/substitute_vars', (req, res, ctx) =>
|
|
res(ctx.status(200), ctx.json({ status: 'success', data: {} })),
|
|
),
|
|
);
|
|
});
|
|
|
|
it('should show breakout options when "Breakout by" is clicked', async (): Promise<void> => {
|
|
// Mock the MSW server to intercept the keySuggestions API call
|
|
server.use(
|
|
rest.get('*/fields/keys', (req, res, ctx) =>
|
|
res(ctx.status(200), ctx.json(MOCK_KEY_SUGGESTIONS_RESPONSE)),
|
|
),
|
|
);
|
|
|
|
renderWithProviders(<MockTableDrilldown />);
|
|
|
|
// Find and click the aggregate button to show context menu
|
|
const aggregateButton = screen.getByRole('button', { name: /aggregate/i });
|
|
fireEvent.click(aggregateButton);
|
|
|
|
// Find and click "Breakout by" option
|
|
const breakoutOption = screen.getByText(/Breakout by/);
|
|
fireEvent.click(breakoutOption);
|
|
|
|
// Wait for the breakout options to load and verify they are displayed
|
|
await screen.findByText('Breakout by');
|
|
|
|
// Check that the search input is displayed
|
|
expect(
|
|
screen.getByPlaceholderText('Search breakout options...'),
|
|
).toBeInTheDocument();
|
|
|
|
// Wait for the API call to complete and options to load
|
|
// Check what's actually being rendered instead of waiting for specific text
|
|
await screen.findByText('deployment.environment');
|
|
|
|
// Check that the breakout options are loaded and displayed
|
|
// Based on the test output, these are the actual options being rendered
|
|
expect(screen.getByText('deployment.environment')).toBeInTheDocument();
|
|
expect(screen.getByText('http.method')).toBeInTheDocument();
|
|
expect(screen.getByText('http.status_code')).toBeInTheDocument();
|
|
|
|
// Verify that the breakout header is displayed
|
|
expect(screen.getByText('Breakout by')).toBeInTheDocument();
|
|
});
|
|
|
|
it('should add selected breakout option to groupBy and redirect with correct query', async (): Promise<void> => {
|
|
// Mock the MSW server to intercept the keySuggestions API call
|
|
server.use(
|
|
rest.get('*/fields/keys', (req, res, ctx) =>
|
|
res(ctx.status(200), ctx.json(MOCK_KEY_SUGGESTIONS_RESPONSE)),
|
|
),
|
|
);
|
|
|
|
renderWithProviders(<MockTableDrilldown />);
|
|
|
|
// Navigate to breakout options
|
|
const aggregateButton = screen.getByRole('button', { name: /aggregate/i });
|
|
fireEvent.click(aggregateButton);
|
|
|
|
const breakoutOption = screen.getByText(/Breakout by/);
|
|
fireEvent.click(breakoutOption);
|
|
|
|
// Wait for breakout options to load
|
|
await screen.findByText('deployment.environment');
|
|
|
|
// Click on a breakout option (e.g., deployment.environment)
|
|
const breakoutOptionItem = screen.getByText('deployment.environment');
|
|
fireEvent.click(breakoutOptionItem);
|
|
|
|
// Verify redirectWithQueryBuilderData was called
|
|
expect(mockRedirectWithQueryBuilderData).toHaveBeenCalledTimes(1);
|
|
|
|
const [
|
|
query,
|
|
queryParams,
|
|
,
|
|
newTab,
|
|
] = mockRedirectWithQueryBuilderData.mock.calls[0];
|
|
|
|
// Check that the query contains the correct structure
|
|
expect(query.builder).toBeDefined();
|
|
expect(query.builder.queryData).toBeDefined();
|
|
|
|
// Find the query data for the aggregate query (queryName: 'A')
|
|
const aggregateQueryData = query.builder.queryData.find(
|
|
(item: any) => item.queryName === 'A',
|
|
);
|
|
expect(aggregateQueryData).toBeDefined();
|
|
|
|
// Verify that the groupBy has been updated to only contain the selected breakout option
|
|
expect(aggregateQueryData.groupBy).toHaveLength(1);
|
|
expect(aggregateQueryData.groupBy[0].key).toEqual('deployment.environment');
|
|
|
|
// Verify that orderBy has been cleared (as per getBreakoutQuery logic)
|
|
expect(aggregateQueryData.orderBy).toEqual([]);
|
|
|
|
// Verify that the legend has been updated (check the actual value being returned)
|
|
// The legend logic in getBreakoutQuery: legend: item.legend && groupBy.key ? `{{${groupBy.key}}}` : ''
|
|
// Since the original legend might be empty, the result could be empty string
|
|
expect(aggregateQueryData.legend).toBeDefined();
|
|
|
|
// Check that the queryParams contain the expandedWidgetId
|
|
expect(queryParams).toEqual({
|
|
expandedWidgetId: 'test-widget',
|
|
graphType: 'graph',
|
|
});
|
|
|
|
// Check that newTab is true
|
|
expect(newTab).toBe(true);
|
|
|
|
// Verify that the original filters are preserved and new filters are added
|
|
expect(aggregateQueryData.filter.expression).toContain(
|
|
"service.name in $service.name AND trace_id EXISTS AND deployment.environment = '$env'",
|
|
);
|
|
// The new filter from the clicked data should also be present
|
|
expect(aggregateQueryData.filter.expression).toContain(
|
|
"service.name = 'adservice' AND trace_id = 'df2cfb0e57bb8736207689851478cd50'",
|
|
);
|
|
});
|
|
});
|