mirror of
https://git.mirrors.martin98.com/https://github.com/SigNoz/signoz
synced 2025-08-14 21:25:53 +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="auto">
|
||||
<StyledSpace styledclass={[styles.floatRight]}>
|
||||
<Button onClick={onFocusSelectedSpanHandler} icon={<FilterOutlined />}>
|
||||
<Button
|
||||
onClick={onFocusSelectedSpanHandler}
|
||||
icon={<FilterOutlined />}
|
||||
data-testid="span-focus-btn"
|
||||
>
|
||||
Focus on selected span
|
||||
</Button>
|
||||
<Button type="default" onClick={onResetHandler}>
|
||||
<Button
|
||||
type="default"
|
||||
onClick={onResetHandler}
|
||||
data-testid="reset-focus"
|
||||
>
|
||||
Reset Focus
|
||||
</Button>
|
||||
</StyledSpace>
|
||||
@ -262,6 +270,7 @@ function TraceDetail({ response }: TraceDetailProps): JSX.Element {
|
||||
collapsedWidth={40}
|
||||
defaultCollapsed
|
||||
onCollapse={(value): void => setCollapsed(value)}
|
||||
data-testid="span-details-sider"
|
||||
>
|
||||
{!collapsed && (
|
||||
<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 { serviceSuccessResponse } from './__mockdata__/services';
|
||||
import { topLevelOperationSuccessResponse } from './__mockdata__/top_level_operations';
|
||||
import { traceDetailResponse } from './__mockdata__/tracedetail';
|
||||
|
||||
export const handlers = [
|
||||
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) =>
|
||||
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