mirror of
https://git.mirrors.martin98.com/https://github.com/SigNoz/signoz
synced 2025-08-15 00:26:09 +08:00
chore: added trace detail tests (#5523)
* feat: added trace filter test cases * feat: added trace filter test cases - initial render * feat: added test cases - query sync, filter section behaviour etc * feat: deleted mock-data files * feat: added test cases of undefined filters and items * feat: deleted tsconfig * feat: added clear and rest btn test cases for traces filters * feat: added collapse and uncollapse test for traces filters * chore: added trace detail tests * chore: added trace detail tests - span selection, focus and reset * chore: fixed eslint
This commit is contained in:
parent
15b0569b56
commit
fb92ddc822
@ -219,10 +219,18 @@ function TraceDetail({ response }: TraceDetailProps): JSX.Element {
|
|||||||
<Col flex={`${SPAN_DETAILS_LEFT_COL_WIDTH}px`} />
|
<Col flex={`${SPAN_DETAILS_LEFT_COL_WIDTH}px`} />
|
||||||
<Col flex="auto">
|
<Col flex="auto">
|
||||||
<StyledSpace styledclass={[styles.floatRight]}>
|
<StyledSpace styledclass={[styles.floatRight]}>
|
||||||
<Button onClick={onFocusSelectedSpanHandler} icon={<FilterOutlined />}>
|
<Button
|
||||||
|
onClick={onFocusSelectedSpanHandler}
|
||||||
|
icon={<FilterOutlined />}
|
||||||
|
data-testid="span-focus-btn"
|
||||||
|
>
|
||||||
Focus on selected span
|
Focus on selected span
|
||||||
</Button>
|
</Button>
|
||||||
<Button type="default" onClick={onResetHandler}>
|
<Button
|
||||||
|
type="default"
|
||||||
|
onClick={onResetHandler}
|
||||||
|
data-testid="reset-focus"
|
||||||
|
>
|
||||||
Reset Focus
|
Reset Focus
|
||||||
</Button>
|
</Button>
|
||||||
</StyledSpace>
|
</StyledSpace>
|
||||||
@ -262,6 +270,7 @@ function TraceDetail({ response }: TraceDetailProps): JSX.Element {
|
|||||||
collapsedWidth={40}
|
collapsedWidth={40}
|
||||||
defaultCollapsed
|
defaultCollapsed
|
||||||
onCollapse={(value): void => setCollapsed(value)}
|
onCollapse={(value): void => setCollapsed(value)}
|
||||||
|
data-testid="span-details-sider"
|
||||||
>
|
>
|
||||||
{!collapsed && (
|
{!collapsed && (
|
||||||
<StyledCol styledclass={[styles.selectedSpanDetailContainer]}>
|
<StyledCol styledclass={[styles.selectedSpanDetailContainer]}>
|
||||||
|
2089
frontend/src/mocks-server/__mockdata__/tracedetail.ts
Normal file
2089
frontend/src/mocks-server/__mockdata__/tracedetail.ts
Normal file
File diff suppressed because it is too large
Load Diff
@ -13,6 +13,7 @@ import { membersResponse } from './__mockdata__/members';
|
|||||||
import { queryRangeSuccessResponse } from './__mockdata__/query_range';
|
import { queryRangeSuccessResponse } from './__mockdata__/query_range';
|
||||||
import { serviceSuccessResponse } from './__mockdata__/services';
|
import { serviceSuccessResponse } from './__mockdata__/services';
|
||||||
import { topLevelOperationSuccessResponse } from './__mockdata__/top_level_operations';
|
import { topLevelOperationSuccessResponse } from './__mockdata__/top_level_operations';
|
||||||
|
import { traceDetailResponse } from './__mockdata__/tracedetail';
|
||||||
|
|
||||||
export const handlers = [
|
export const handlers = [
|
||||||
rest.post('http://localhost/api/v3/query_range', (req, res, ctx) =>
|
rest.post('http://localhost/api/v3/query_range', (req, res, ctx) =>
|
||||||
@ -230,6 +231,12 @@ export const handlers = [
|
|||||||
}),
|
}),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
|
||||||
|
rest.get(
|
||||||
|
'http://localhost/api/v1/traces/000000000000000071dc9b0a338729b4',
|
||||||
|
(req, res, ctx) => res(ctx.status(200), ctx.json(traceDetailResponse)),
|
||||||
|
),
|
||||||
|
|
||||||
rest.post('http://localhost/api/v1//channels', (_, res, ctx) =>
|
rest.post('http://localhost/api/v1//channels', (_, res, ctx) =>
|
||||||
res(ctx.status(200), ctx.json(allAlertChannels)),
|
res(ctx.status(200), ctx.json(allAlertChannels)),
|
||||||
),
|
),
|
||||||
|
214
frontend/src/pages/TraceDetail/__test__/TraceDetail.test.tsx
Normal file
214
frontend/src/pages/TraceDetail/__test__/TraceDetail.test.tsx
Normal file
@ -0,0 +1,214 @@
|
|||||||
|
/* eslint-disable sonarjs/no-duplicate-string */
|
||||||
|
/* eslint-disable @typescript-eslint/explicit-function-return-type */
|
||||||
|
import ROUTES from 'constants/routes';
|
||||||
|
import { MemoryRouter, Route } from 'react-router-dom';
|
||||||
|
import { fireEvent, render, screen } from 'tests/test-utils';
|
||||||
|
|
||||||
|
import TraceDetail from '..';
|
||||||
|
|
||||||
|
window.HTMLElement.prototype.scrollIntoView = jest.fn();
|
||||||
|
|
||||||
|
jest.mock('react-router-dom', () => ({
|
||||||
|
...jest.requireActual('react-router-dom'),
|
||||||
|
useLocation: (): { pathname: string; search: string } => ({
|
||||||
|
pathname: `${process.env.FRONTEND_API_ENDPOINT}${ROUTES.TRACE_DETAIL}`,
|
||||||
|
search: '?spanId=28a8a67365d0bd8b&levelUp=0&levelDown=0',
|
||||||
|
}),
|
||||||
|
|
||||||
|
useParams: jest.fn().mockReturnValue({
|
||||||
|
id: '000000000000000071dc9b0a338729b4',
|
||||||
|
}),
|
||||||
|
}));
|
||||||
|
|
||||||
|
jest.mock('container/TraceFlameGraph/index.tsx', () => ({
|
||||||
|
__esModule: true,
|
||||||
|
default: (): JSX.Element => <div>TraceFlameGraph</div>,
|
||||||
|
}));
|
||||||
|
|
||||||
|
describe('TraceDetail', () => {
|
||||||
|
it('should render tracedetail', async () => {
|
||||||
|
const { findByText, getByText, getAllByText, getByPlaceholderText } = render(
|
||||||
|
<MemoryRouter initialEntries={['/trace/000000000000000071dc9b0a338729b4']}>
|
||||||
|
<Route path={ROUTES.TRACE_DETAIL}>
|
||||||
|
<TraceDetail />
|
||||||
|
</Route>
|
||||||
|
,
|
||||||
|
</MemoryRouter>,
|
||||||
|
);
|
||||||
|
expect(await findByText('Trace Details')).toBeInTheDocument();
|
||||||
|
|
||||||
|
// as we have an active spanId, it should scroll to the selected span
|
||||||
|
expect(window.HTMLElement.prototype.scrollIntoView).toHaveBeenCalled();
|
||||||
|
|
||||||
|
// assertions
|
||||||
|
expect(getByText('TraceFlameGraph')).toBeInTheDocument();
|
||||||
|
expect(getByText('Focus on selected span')).toBeInTheDocument();
|
||||||
|
|
||||||
|
// span action buttons
|
||||||
|
expect(getByText('Reset Focus')).toBeInTheDocument();
|
||||||
|
expect(getByText('50 Spans')).toBeInTheDocument();
|
||||||
|
|
||||||
|
// trace span detail - parent -> child
|
||||||
|
expect(getAllByText('frontend')[0]).toBeInTheDocument();
|
||||||
|
expect(getByText('776.76 ms')).toBeInTheDocument();
|
||||||
|
[
|
||||||
|
{ trace: 'HTTP GET /dispatch', duration: '776.76 ms', count: '50' },
|
||||||
|
{ trace: 'HTTP GET: /customer', duration: '349.44 ms', count: '4' },
|
||||||
|
{
|
||||||
|
trace: '/driver.DriverService/FindNearest',
|
||||||
|
duration: '173.10 ms',
|
||||||
|
count: '15',
|
||||||
|
},
|
||||||
|
// and so on ...
|
||||||
|
].forEach((traceDetail) => {
|
||||||
|
expect(getByText(traceDetail.trace)).toBeInTheDocument();
|
||||||
|
expect(getByText(traceDetail.duration)).toBeInTheDocument();
|
||||||
|
expect(getByText(traceDetail.count)).toBeInTheDocument();
|
||||||
|
});
|
||||||
|
|
||||||
|
// Details for selected Span
|
||||||
|
expect(getByText('Details for selected Span')).toBeInTheDocument();
|
||||||
|
['Service', 'Operation', 'SpanKind', 'StatusCodeString'].forEach((detail) => {
|
||||||
|
expect(getByText(detail)).toBeInTheDocument();
|
||||||
|
});
|
||||||
|
|
||||||
|
// go to related logs button
|
||||||
|
const goToRelatedLogsButton = getByText('Go to Related logs');
|
||||||
|
expect(goToRelatedLogsButton).toBeInTheDocument();
|
||||||
|
|
||||||
|
// Tag and Event tabs
|
||||||
|
expect(getByText('Tags')).toBeInTheDocument();
|
||||||
|
expect(getByText('Events')).toBeInTheDocument();
|
||||||
|
expect(getByPlaceholderText('traceDetails:search_tags')).toBeInTheDocument();
|
||||||
|
|
||||||
|
// Tag details
|
||||||
|
[
|
||||||
|
{ title: 'client-uuid', value: '64a18ffd5f8adbfb' },
|
||||||
|
{ title: 'component', value: 'net/http' },
|
||||||
|
{ title: 'host.name', value: '4f6ec470feea' },
|
||||||
|
{ title: 'http.method', value: 'GET' },
|
||||||
|
{ title: 'http.url', value: '/route?dropoff=728%2C326&pickup=165%2C543' },
|
||||||
|
{ title: 'http.status_code', value: '200' },
|
||||||
|
{ title: 'ip', value: '172.25.0.2' },
|
||||||
|
{ title: 'opencensus.exporterversion', value: 'Jaeger-Go-2.30.0' },
|
||||||
|
].forEach((tag) => {
|
||||||
|
expect(getByText(tag.title)).toBeInTheDocument();
|
||||||
|
expect(getByText(tag.value)).toBeInTheDocument();
|
||||||
|
});
|
||||||
|
|
||||||
|
// see full value
|
||||||
|
expect(getAllByText('View full value')[0]).toBeInTheDocument();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should render tracedetail events tab', async () => {
|
||||||
|
const { findByText, getByText } = render(
|
||||||
|
<MemoryRouter initialEntries={['/trace/000000000000000071dc9b0a338729b4']}>
|
||||||
|
<Route path={ROUTES.TRACE_DETAIL}>
|
||||||
|
<TraceDetail />
|
||||||
|
</Route>
|
||||||
|
,
|
||||||
|
</MemoryRouter>,
|
||||||
|
);
|
||||||
|
expect(await findByText('Trace Details')).toBeInTheDocument();
|
||||||
|
|
||||||
|
fireEvent.click(getByText('Events'));
|
||||||
|
|
||||||
|
expect(await screen.findByText('HTTP request received')).toBeInTheDocument();
|
||||||
|
|
||||||
|
// event details
|
||||||
|
[
|
||||||
|
{ title: 'Event Start Time', value: '527.60 ms' },
|
||||||
|
{ title: 'level', value: 'info' },
|
||||||
|
].forEach((tag) => {
|
||||||
|
expect(getByText(tag.title)).toBeInTheDocument();
|
||||||
|
expect(getByText(tag.value)).toBeInTheDocument();
|
||||||
|
});
|
||||||
|
|
||||||
|
expect(getByText('View full log event message')).toBeInTheDocument();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should toggle slider - selected span details', async () => {
|
||||||
|
const { findByTestId, queryByText } = render(
|
||||||
|
<MemoryRouter initialEntries={['/trace/000000000000000071dc9b0a338729b4']}>
|
||||||
|
<Route path={ROUTES.TRACE_DETAIL}>
|
||||||
|
<TraceDetail />
|
||||||
|
</Route>
|
||||||
|
,
|
||||||
|
</MemoryRouter>,
|
||||||
|
);
|
||||||
|
const slider = await findByTestId('span-details-sider');
|
||||||
|
expect(slider).toBeInTheDocument();
|
||||||
|
|
||||||
|
fireEvent.click(
|
||||||
|
slider.querySelector('.ant-layout-sider-trigger') as HTMLElement,
|
||||||
|
);
|
||||||
|
|
||||||
|
expect(queryByText('Details for selected Span')).not.toBeInTheDocument();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should be able to selected another span and see its detail', async () => {
|
||||||
|
const { getByText } = render(
|
||||||
|
<MemoryRouter initialEntries={['/trace/000000000000000071dc9b0a338729b4']}>
|
||||||
|
<Route path={ROUTES.TRACE_DETAIL}>
|
||||||
|
<TraceDetail />
|
||||||
|
</Route>
|
||||||
|
,
|
||||||
|
</MemoryRouter>,
|
||||||
|
);
|
||||||
|
|
||||||
|
expect(await screen.findByText('Trace Details')).toBeInTheDocument();
|
||||||
|
|
||||||
|
const spanTitle = getByText('/driver.DriverService/FindNearest');
|
||||||
|
expect(spanTitle).toBeInTheDocument();
|
||||||
|
fireEvent.click(spanTitle);
|
||||||
|
|
||||||
|
// Tag details
|
||||||
|
[
|
||||||
|
{ title: 'client-uuid', value: '6fb81b8ca91b2b4d' },
|
||||||
|
{ title: 'component', value: 'gRPC' },
|
||||||
|
{ title: 'host.name', value: '4f6ec470feea' },
|
||||||
|
].forEach((tag) => {
|
||||||
|
expect(getByText(tag.title)).toBeInTheDocument();
|
||||||
|
expect(getByText(tag.value)).toBeInTheDocument();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('focus on selected span and reset focus action', async () => {
|
||||||
|
const { getByText, getAllByText } = render(
|
||||||
|
<MemoryRouter initialEntries={['/trace/000000000000000071dc9b0a338729b4']}>
|
||||||
|
<Route path={ROUTES.TRACE_DETAIL}>
|
||||||
|
<TraceDetail />
|
||||||
|
</Route>
|
||||||
|
,
|
||||||
|
</MemoryRouter>,
|
||||||
|
);
|
||||||
|
|
||||||
|
expect(await screen.findByText('Trace Details')).toBeInTheDocument();
|
||||||
|
|
||||||
|
const spanTitle = getByText('/driver.DriverService/FindNearest');
|
||||||
|
expect(spanTitle).toBeInTheDocument();
|
||||||
|
fireEvent.click(spanTitle);
|
||||||
|
|
||||||
|
expect(await screen.findByText('6fb81b8ca91b2b4d')).toBeInTheDocument();
|
||||||
|
|
||||||
|
// focus on selected span
|
||||||
|
const focusButton = getByText('Focus on selected span');
|
||||||
|
expect(focusButton).toBeInTheDocument();
|
||||||
|
fireEvent.click(focusButton);
|
||||||
|
|
||||||
|
// assert selected span
|
||||||
|
expect(getByText('15 Spans')).toBeInTheDocument();
|
||||||
|
expect(getAllByText('/driver.DriverService/FindNearest')).toHaveLength(3);
|
||||||
|
expect(getByText('173.10 ms')).toBeInTheDocument();
|
||||||
|
|
||||||
|
// reset focus
|
||||||
|
expect(screen.queryByText('HTTP GET /dispatch')).not.toBeInTheDocument();
|
||||||
|
|
||||||
|
const resetFocusButton = getByText('Reset Focus');
|
||||||
|
expect(resetFocusButton).toBeInTheDocument();
|
||||||
|
fireEvent.click(resetFocusButton);
|
||||||
|
|
||||||
|
expect(window.HTMLElement.prototype.scrollIntoView).toHaveBeenCalled();
|
||||||
|
expect(screen.queryByText('HTTP GET /dispatch')).toBeInTheDocument();
|
||||||
|
});
|
||||||
|
});
|
Loading…
x
Reference in New Issue
Block a user