chore: Added jest cases for logs explorer page (#4553)

* chore: base file for logs explorer jest test cases

* chore: added base setup for logs explorer jest fixing the uplot/d3-interpolate/antd-config errors

* chore: added test for rendering of logs explorer page without API calls

* chore: added test for rendering of logs with API call

* chore: used virutoso mock to render items on the screen

* chore: used virutoso mock to render items on the screen

* chore: update dummy data
This commit is contained in:
Vikrant Gupta 2024-02-16 18:22:33 +05:30 committed by GitHub
parent bbf9787fb3
commit b10f17de78
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
7 changed files with 203 additions and 8 deletions

View File

@ -173,7 +173,9 @@ function LogsExplorerList({
{!isLoading && !isError && logs.length > 0 && (
<>
<InfinityWrapperStyled>{renderContent}</InfinityWrapperStyled>
<InfinityWrapperStyled data-testid="logs-list-virtuoso">
{renderContent}
</InfinityWrapperStyled>
<LogDetail
selectedTab={VIEW_TYPES.OVERVIEW}

View File

@ -539,6 +539,7 @@ function LogsExplorerViews({
(isMultipleQueries || isGroupByExist) && selectedView !== 'search'
}
onClick={(): void => handleModeChange(PANEL_TYPES.LIST)}
data-testid="logs-list-view"
>
List view
</Button>
@ -551,6 +552,7 @@ function LogsExplorerViews({
: 'tab'
}
onClick={(): void => handleModeChange(PANEL_TYPES.TIME_SERIES)}
data-testid="time-series-view"
>
Time series
</Button>
@ -561,6 +563,7 @@ function LogsExplorerViews({
selectedPanelType === PANEL_TYPES.TABLE ? 'selected_view tab' : 'tab'
}
onClick={(): void => handleModeChange(PANEL_TYPES.TABLE)}
data-testid="table-view"
>
Table
</Button>

View File

@ -1,6 +1,5 @@
import { SearchOutlined } from '@ant-design/icons';
import { Input, Spin } from 'antd';
import Typography from 'antd/es/typography/Typography';
import { Input, Spin, Typography } from 'antd';
import { useIsDarkMode } from 'hooks/useDarkMode';
import { useTranslation } from 'react-i18next';

View File

@ -39,7 +39,7 @@ export default function LeftToolbarActions({
)}
onClick={(): void => onChangeSelectedView(SELECTED_VIEWS.SEARCH)}
>
<MousePointerSquare size={14} />
<MousePointerSquare size={14} data-testid="search-view" />
</Button>
</Tooltip>
<Tooltip title="Query Builder">
@ -52,7 +52,7 @@ export default function LeftToolbarActions({
)}
onClick={(): void => onChangeSelectedView(SELECTED_VIEWS.QUERY_BUILDER)}
>
<Atom size={14} />
<Atom size={14} data-testid="query-builder-view" />
</Button>
</Tooltip>
@ -66,7 +66,7 @@ export default function LeftToolbarActions({
)}
onClick={(): void => onChangeSelectedView(SELECTED_VIEWS.CLICKHOUSE)}
>
<Terminal size={14} />
<Terminal size={14} data-testid="clickhouse-view" />
</Button>
)}
</div>

View File

@ -1,6 +1,5 @@
import { Tag } from 'antd';
import { Tag, Typography } from 'antd';
import { ColumnsType } from 'antd/es/table';
import Typography from 'antd/es/typography/Typography';
import ROUTES from 'constants/routes';
import { getMs } from 'container/Trace/Filters/Panel/PanelBody/Duration/util';
import { formUrlParams } from 'container/TraceDetail/utils';

View File

@ -0,0 +1,45 @@
export const logsQueryRangeSuccessResponse = {
status: 'success',
data: {
resultType: '',
result: [
{
queryName: 'A',
series: null,
list: [
{
timestamp: '2024-02-15T21:20:22Z',
data: {
attributes_bool: {},
attributes_float64: {},
attributes_int64: {},
attributes_string: {
container_id: 'container_id',
container_name: 'container_name',
driver: 'driver',
eta: '2m0s',
location: 'frontend',
log_level: 'INFO',
message: 'Dispatch successful',
service: 'frontend',
span_id: 'span_id',
trace_id: 'span_id',
},
body:
'2024-02-15T21:20:22.035Z\tINFO\tfrontend\tDispatch successful\t{"service": "frontend", "trace_id": "span_id", "span_id": "span_id", "driver": "driver", "eta": "2m0s"}',
id: 'id',
resources_string: {
'container.name': 'container_name',
},
severity_number: 0,
severity_text: '',
span_id: '',
trace_flags: 0,
trace_id: '',
},
},
],
},
],
},
};

View File

@ -0,0 +1,147 @@
import { render, waitFor } from '@testing-library/react';
import userEvent from '@testing-library/user-event';
import { logsQueryRangeSuccessResponse } from 'mocks-server/__mockdata__/logs_query_range';
import { server } from 'mocks-server/server';
import { rest } from 'msw';
import { QueryBuilderProvider } from 'providers/QueryBuilder';
import MockQueryClientProvider from 'providers/test/MockQueryClientProvider';
import { I18nextProvider } from 'react-i18next';
import { Provider } from 'react-redux';
import { MemoryRouter } from 'react-router-dom';
// https://virtuoso.dev/mocking-in-tests/
import { VirtuosoMockContext } from 'react-virtuoso';
import i18n from 'ReactI18';
import store from 'store';
import LogsExplorer from '..';
const queryRangeURL = 'http://localhost/api/v3/query_range';
// mocking the graph components in this test as this should be handled separately
jest.mock(
'container/TimeSeriesView/TimeSeriesView',
() =>
// eslint-disable-next-line func-names, @typescript-eslint/explicit-function-return-type, react/display-name
function () {
return <div>Time Series Chart</div>;
},
);
jest.mock(
'container/LogsExplorerChart',
() =>
// eslint-disable-next-line func-names, @typescript-eslint/explicit-function-return-type, react/display-name
function () {
return <div>Histogram Chart</div>;
},
);
jest.mock('constants/panelTypes', () => ({
AVAILABLE_EXPORT_PANEL_TYPES: ['graph', 'table'],
}));
jest.mock('d3-interpolate', () => ({
interpolate: jest.fn(),
}));
describe('Logs Explorer Tests', () => {
test('Logs Explorer default view test without data', async () => {
const {
getByText,
getByRole,
queryByText,
getByTestId,
queryByTestId,
} = render(
<MemoryRouter initialEntries={['/logs/logs-explorer']}>
<Provider store={store}>
<I18nextProvider i18n={i18n}>
<MockQueryClientProvider>
<QueryBuilderProvider>
<LogsExplorer />
</QueryBuilderProvider>
</MockQueryClientProvider>
</I18nextProvider>
</Provider>
</MemoryRouter>,
);
// check the presence of histogram chart
expect(getByText('Histogram Chart')).toBeInTheDocument();
// toggle the chart and check it gets removed from the DOM
const histogramToggle = getByRole('switch');
await userEvent.click(histogramToggle);
expect(queryByText('Histogram Chart')).not.toBeInTheDocument();
// check the presence of search bar and query builder and absence of clickhouse
const searchView = getByTestId('search-view');
expect(searchView).toBeInTheDocument();
const queryBuilderView = getByTestId('query-builder-view');
expect(queryBuilderView).toBeInTheDocument();
const clickhouseView = queryByTestId('clickhouse-view');
expect(clickhouseView).not.toBeInTheDocument();
// check the presence of List View / Time Series View / Table View
const listView = getByTestId('logs-list-view');
const timeSeriesView = getByTestId('time-series-view');
const tableView = getByTestId('table-view');
expect(listView).toBeInTheDocument();
expect(timeSeriesView).toBeInTheDocument();
expect(tableView).toBeInTheDocument();
// check the presence of old logs explorer CTA
const oldLogsCTA = getByText('Switch to Old Logs Explorer');
expect(oldLogsCTA).toBeInTheDocument();
});
test('Logs Explorer Page should render with data', async () => {
// mocking the query range API to return the logs
server.use(
rest.post(queryRangeURL, (req, res, ctx) =>
res(ctx.status(200), ctx.json(logsQueryRangeSuccessResponse)),
),
);
const { queryByText, queryByTestId } = render(
<MemoryRouter initialEntries={['/logs/logs-explorer']}>
<Provider store={store}>
<I18nextProvider i18n={i18n}>
<MockQueryClientProvider>
<QueryBuilderProvider>
<VirtuosoMockContext.Provider
value={{ viewportHeight: 300, itemHeight: 100 }}
>
<LogsExplorer />
</VirtuosoMockContext.Provider>
</QueryBuilderProvider>
</MockQueryClientProvider>
</I18nextProvider>
</Provider>
</MemoryRouter>,
);
// check for loading state to be not present
await waitFor(() =>
expect(
queryByText(
`Just a bit of patience, just a little bits enough ⎯ were getting your logs!`,
),
).not.toBeInTheDocument(),
);
// check for no data state to not be present
await waitFor(() =>
expect(queryByText('No logs yet.')).not.toBeInTheDocument(),
);
// check for the data container loaded
await waitFor(() =>
expect(queryByTestId('logs-list-virtuoso')).toBeInTheDocument(),
);
// check for data being present in the UI
expect(
queryByText(
'2024-02-15T21:20:22.035Z INFO frontend Dispatch successful {"service": "frontend", "trace_id": "span_id", "span_id": "span_id", "driver": "driver", "eta": "2m0s"}',
),
).toBeInTheDocument();
});
});