chore: addition of jest test cases for dashboards panels (#5506)

* chore: added value panel wrapper jest tests

* chore: added column units and legends test for table panel wrapper
This commit is contained in:
Vikrant Gupta 2024-07-22 21:10:48 +05:30 committed by GitHub
parent 1585065fff
commit ef8b50c19e
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
7 changed files with 1091 additions and 1 deletions

View File

@ -49,7 +49,10 @@ function ValueGraph({
} }
> >
<Tooltip title={t('this_value_satisfies_multiple_thresholds')}> <Tooltip title={t('this_value_satisfies_multiple_thresholds')}>
<ExclamationCircleFilled className="value-graph-icon" /> <ExclamationCircleFilled
className="value-graph-icon"
data-testid="conflicting-thresholds"
/>
</Tooltip> </Tooltip>
</div> </div>
)} )}

View File

@ -0,0 +1,31 @@
import { render } from 'tests/test-utils';
import { Widgets } from 'types/api/dashboard/getAll';
import TablePanelWrapper from '../TablePanelWrapper';
import {
tablePanelQueryResponse,
tablePanelWidgetQuery,
} from './tablePanelWrapperHelper';
describe('Table panel wrappper tests', () => {
it('table should render fine with the query response and column units', () => {
const { container, getByText } = render(
<TablePanelWrapper
widget={(tablePanelWidgetQuery as unknown) as Widgets}
queryResponse={(tablePanelQueryResponse as unknown) as any}
onDragSelect={(): void => {}}
/>,
);
// checking the overall rendering of the table
expect(container).toMatchSnapshot();
// the first row of the table should have the latency value with units
expect(getByText('4.35 s')).toBeInTheDocument();
// the rows should have optimised value for human readability
expect(getByText('31.3 ms')).toBeInTheDocument();
// the applied legend should appear as the column header
expect(getByText('latency-per-service')).toBeInTheDocument();
});
});

View File

@ -0,0 +1,38 @@
import { render } from 'tests/test-utils';
import { Widgets } from 'types/api/dashboard/getAll';
import ValuePanelWrapper from '../ValuePanelWrapper';
import {
thresholds,
valuePanelQueryResponse,
valuePanelWidget,
} from './valuePanelWrapperHelper';
describe('Value panel wrappper tests', () => {
it('should render value panel correctly with yaxis unit', () => {
const { getByText } = render(
<ValuePanelWrapper
widget={(valuePanelWidget as unknown) as Widgets}
queryResponse={(valuePanelQueryResponse as unknown) as any}
onDragSelect={(): void => {}}
/>,
);
// selected y axis unit as miliseconds (ms)
expect(getByText('295 ms')).toBeInTheDocument();
});
it('should render tooltip when there are conflicting thresholds', () => {
const { getByTestId, container } = render(
<ValuePanelWrapper
widget={({ ...valuePanelWidget, thresholds } as unknown) as Widgets}
queryResponse={(valuePanelQueryResponse as unknown) as any}
onDragSelect={(): void => {}}
/>,
);
expect(getByTestId('conflicting-thresholds')).toBeInTheDocument();
// added snapshot test here for checking the thresholds color being applied properly
expect(container).toMatchSnapshot();
});
});

View File

@ -0,0 +1,389 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`Table panel wrappper tests table should render fine with the query response and column units 1`] = `
.c1 {
position: absolute;
right: -0.313rem;
bottom: 0;
z-index: 1;
width: 0.625rem;
height: 100%;
cursor: col-resize;
}
.c0 {
height: 95%;
overflow: hidden;
}
.c0 .ant-table-wrapper {
height: 100%;
}
.c0 .ant-spin-nested-loading {
height: 100%;
}
.c0 .ant-spin-container {
height: 100%;
display: -webkit-box;
display: -webkit-flex;
display: -ms-flexbox;
display: flex;
-webkit-flex-direction: column;
-ms-flex-direction: column;
flex-direction: column;
}
.c0 .ant-table {
-webkit-flex: 1;
-ms-flex: 1;
flex: 1;
overflow: auto;
}
.c0 .ant-table > .ant-table-container > .ant-table-content > table {
min-width: 99% !important;
}
<div>
<div
class="c0"
>
<div
class="query-table"
>
<div
class="ant-table-wrapper css-dev-only-do-not-override-2i2tap"
>
<div
class="ant-spin-nested-loading css-dev-only-do-not-override-2i2tap"
>
<div
class="ant-spin-container"
>
<div
class="ant-table ant-table-small ant-table-layout-fixed ant-table-scroll-horizontal"
>
<div
class="ant-table-container"
>
<div
class="ant-table-content"
style="overflow-x: auto; overflow-y: hidden;"
>
<table
style="width: auto; min-width: 100%; table-layout: fixed;"
>
<colgroup>
<col
style="width: 145px;"
/>
<col
style="width: 145px;"
/>
</colgroup>
<thead
class="ant-table-thead"
>
<tr>
<th
aria-label="service_name"
class="ant-table-cell ant-table-column-has-sorters react-resizable"
scope="col"
tabindex="0"
>
<div
class="ant-table-column-sorters"
>
<span
class="ant-table-column-title"
>
service_name
</span>
<span
class="ant-table-column-sorter ant-table-column-sorter-full"
>
<span
aria-hidden="true"
class="ant-table-column-sorter-inner"
>
<span
aria-label="caret-up"
class="anticon anticon-caret-up ant-table-column-sorter-up"
role="img"
>
<svg
aria-hidden="true"
data-icon="caret-up"
fill="currentColor"
focusable="false"
height="1em"
viewBox="0 0 1024 1024"
width="1em"
>
<path
d="M858.9 689L530.5 308.2c-9.4-10.9-27.5-10.9-37 0L165.1 689c-12.2 14.2-1.2 35 18.5 35h656.8c19.7 0 30.7-20.8 18.5-35z"
/>
</svg>
</span>
<span
aria-label="caret-down"
class="anticon anticon-caret-down ant-table-column-sorter-down"
role="img"
>
<svg
aria-hidden="true"
data-icon="caret-down"
fill="currentColor"
focusable="false"
height="1em"
viewBox="0 0 1024 1024"
width="1em"
>
<path
d="M840.4 300H183.6c-19.7 0-30.7 20.8-18.5 35l328.4 380.8c9.4 10.9 27.5 10.9 37 0L858.9 335c12.2-14.2 1.2-35-18.5-35z"
/>
</svg>
</span>
</span>
</span>
</div>
<span
class="c1 react-resizable-handle"
/>
</th>
<th
aria-label="latency-per-service"
class="ant-table-cell ant-table-column-has-sorters react-resizable"
scope="col"
tabindex="0"
>
<div
class="ant-table-column-sorters"
>
<span
class="ant-table-column-title"
>
latency-per-service
</span>
<span
class="ant-table-column-sorter ant-table-column-sorter-full"
>
<span
aria-hidden="true"
class="ant-table-column-sorter-inner"
>
<span
aria-label="caret-up"
class="anticon anticon-caret-up ant-table-column-sorter-up"
role="img"
>
<svg
aria-hidden="true"
data-icon="caret-up"
fill="currentColor"
focusable="false"
height="1em"
viewBox="0 0 1024 1024"
width="1em"
>
<path
d="M858.9 689L530.5 308.2c-9.4-10.9-27.5-10.9-37 0L165.1 689c-12.2 14.2-1.2 35 18.5 35h656.8c19.7 0 30.7-20.8 18.5-35z"
/>
</svg>
</span>
<span
aria-label="caret-down"
class="anticon anticon-caret-down ant-table-column-sorter-down"
role="img"
>
<svg
aria-hidden="true"
data-icon="caret-down"
fill="currentColor"
focusable="false"
height="1em"
viewBox="0 0 1024 1024"
width="1em"
>
<path
d="M840.4 300H183.6c-19.7 0-30.7 20.8-18.5 35l328.4 380.8c9.4 10.9 27.5 10.9 37 0L858.9 335c12.2-14.2 1.2-35-18.5-35z"
/>
</svg>
</span>
</span>
</span>
</div>
<span
class="c1 react-resizable-handle"
/>
</th>
</tr>
</thead>
<tbody
class="ant-table-tbody"
>
<tr
aria-hidden="true"
class="ant-table-measure-row"
style="height: 0px; font-size: 0px;"
>
<td
style="padding: 0px; border: 0px; height: 0px;"
>
<div
style="height: 0px; overflow: hidden;"
>
 
</div>
</td>
<td
style="padding: 0px; border: 0px; height: 0px;"
>
<div
style="height: 0px; overflow: hidden;"
>
 
</div>
</td>
</tr>
<tr
class="ant-table-row ant-table-row-level-0"
>
<td
class="ant-table-cell"
>
<div>
demo-app
</div>
</td>
<td
class="ant-table-cell"
>
<div>
4.35 s
</div>
</td>
</tr>
<tr
class="ant-table-row ant-table-row-level-0"
>
<td
class="ant-table-cell"
>
<div>
customer
</div>
</td>
<td
class="ant-table-cell"
>
<div>
431 ms
</div>
</td>
</tr>
<tr
class="ant-table-row ant-table-row-level-0"
>
<td
class="ant-table-cell"
>
<div>
mysql
</div>
</td>
<td
class="ant-table-cell"
>
<div>
431 ms
</div>
</td>
</tr>
<tr
class="ant-table-row ant-table-row-level-0"
>
<td
class="ant-table-cell"
>
<div>
frontend
</div>
</td>
<td
class="ant-table-cell"
>
<div>
287 ms
</div>
</td>
</tr>
<tr
class="ant-table-row ant-table-row-level-0"
>
<td
class="ant-table-cell"
>
<div>
driver
</div>
</td>
<td
class="ant-table-cell"
>
<div>
230 ms
</div>
</td>
</tr>
<tr
class="ant-table-row ant-table-row-level-0"
>
<td
class="ant-table-cell"
>
<div>
route
</div>
</td>
<td
class="ant-table-cell"
>
<div>
66.4 ms
</div>
</td>
</tr>
<tr
class="ant-table-row ant-table-row-level-0"
>
<td
class="ant-table-cell"
>
<div>
redis
</div>
</td>
<td
class="ant-table-cell"
>
<div>
31.3 ms
</div>
</td>
</tr>
</tbody>
</table>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
`;

View File

@ -0,0 +1,76 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`Value panel wrappper tests should render tooltip when there are conflicting thresholds 1`] = `
.c1 {
height: 100%;
display: -webkit-box;
display: -webkit-flex;
display: -ms-flexbox;
display: flex;
-webkit-box-pack: center;
-webkit-justify-content: center;
-ms-flex-pack: center;
justify-content: center;
-webkit-align-items: center;
-webkit-box-align: center;
-ms-flex-align: center;
align-items: center;
-webkit-flex-direction: column;
-ms-flex-direction: column;
flex-direction: column;
}
.c0 {
text-align: center;
padding-top: 1rem;
}
<div>
<div
class="c0"
>
<article
class="ant-typography css-dev-only-do-not-override-2i2tap"
/>
</div>
<div
class="c1"
>
<div
class="value-graph-container"
>
<span
class="ant-typography value-graph-text css-dev-only-do-not-override-2i2tap"
style="color: Blue;"
>
295 ms
</span>
<div
class="value-graph-textconflict"
>
<span
aria-label="exclamation-circle"
class="anticon anticon-exclamation-circle value-graph-icon"
data-testid="conflicting-thresholds"
role="img"
>
<svg
aria-hidden="true"
data-icon="exclamation-circle"
fill="currentColor"
focusable="false"
height="1em"
viewBox="64 64 896 896"
width="1em"
>
<path
d="M512 64C264.6 64 64 264.6 64 512s200.6 448 448 448 448-200.6 448-448S759.4 64 512 64zm-32 232c0-4.4 3.6-8 8-8h48c4.4 0 8 3.6 8 8v272c0 4.4-3.6 8-8 8h-48c-4.4 0-8-3.6-8-8V296zm32 440a48.01 48.01 0 010-96 48.01 48.01 0 010 96z"
/>
</svg>
</span>
</div>
</div>
</div>
</div>
`;

View File

@ -0,0 +1,286 @@
export const tablePanelWidgetQuery = {
id: '727533b0-7718-4f99-a1db-a1875649325c',
title: '',
description: '',
isStacked: false,
nullZeroValues: 'zero',
opacity: '1',
panelTypes: 'table',
query: {
clickhouse_sql: [
{
name: 'A',
legend: '',
disabled: false,
query: '',
},
],
promql: [
{
name: 'A',
query: '',
legend: '',
disabled: false,
},
],
builder: {
queryData: [
{
dataSource: 'metrics',
queryName: 'A',
aggregateOperator: 'count',
aggregateAttribute: {
key: 'signoz_latency',
dataType: 'float64',
type: 'ExponentialHistogram',
isColumn: true,
isJSON: false,
id: 'signoz_latency--float64--ExponentialHistogram--true',
},
timeAggregation: '',
spaceAggregation: 'p90',
functions: [],
filters: {
items: [],
op: 'AND',
},
expression: 'A',
disabled: false,
stepInterval: 60,
having: [],
limit: null,
orderBy: [],
groupBy: [
{
key: 'service_name',
dataType: 'string',
type: 'tag',
isColumn: false,
isJSON: false,
id: 'service_name--string--tag--false',
},
],
legend: 'latency-per-service',
reduceTo: 'avg',
},
],
queryFormulas: [],
},
id: '7feafec2-a450-4b5a-8897-260c1a9fe1e4',
queryType: 'builder',
},
timePreferance: 'GLOBAL_TIME',
softMax: null,
softMin: null,
selectedLogFields: [
{
dataType: 'string',
type: '',
name: 'body',
},
{
dataType: 'string',
type: '',
name: 'timestamp',
},
],
selectedTracesFields: [
{
key: 'serviceName',
dataType: 'string',
type: 'tag',
isColumn: true,
isJSON: false,
id: 'serviceName--string--tag--true',
},
{
key: 'name',
dataType: 'string',
type: 'tag',
isColumn: true,
isJSON: false,
id: 'name--string--tag--true',
},
{
key: 'durationNano',
dataType: 'float64',
type: 'tag',
isColumn: true,
isJSON: false,
id: 'durationNano--float64--tag--true',
},
{
key: 'httpMethod',
dataType: 'string',
type: 'tag',
isColumn: true,
isJSON: false,
id: 'httpMethod--string--tag--true',
},
{
key: 'responseStatusCode',
dataType: 'string',
type: 'tag',
isColumn: true,
isJSON: false,
id: 'responseStatusCode--string--tag--true',
},
],
yAxisUnit: 'none',
thresholds: [],
fillSpans: false,
columnUnits: {
A: 'ms',
},
bucketCount: 30,
stackedBarChart: false,
bucketWidth: 0,
mergeAllActiveQueries: false,
};
export const tablePanelQueryResponse = {
status: 'success',
isLoading: false,
isSuccess: true,
isError: false,
isIdle: false,
data: {
statusCode: 200,
error: null,
message: 'success',
payload: {
status: 'success',
data: {
resultType: '',
result: [
{
table: {
columns: [
{
name: 'service_name',
queryName: '',
isValueColumn: false,
},
{
name: 'A',
queryName: 'A',
isValueColumn: true,
},
],
rows: [
{
data: {
A: 4353.81,
service_name: 'demo-app',
},
},
{
data: {
A: 431.25,
service_name: 'customer',
},
},
{
data: {
A: 431.25,
service_name: 'mysql',
},
},
{
data: {
A: 287.11,
service_name: 'frontend',
},
},
{
data: {
A: 230.02,
service_name: 'driver',
},
},
{
data: {
A: 66.37,
service_name: 'route',
},
},
{
data: {
A: 31.3,
service_name: 'redis',
},
},
],
},
},
],
},
},
params: {
start: 1721207225000,
end: 1721207525000,
step: 60,
variables: {},
formatForWeb: true,
compositeQuery: {
queryType: 'builder',
panelType: 'table',
fillGaps: false,
builderQueries: {
A: {
dataSource: 'metrics',
queryName: 'A',
aggregateOperator: 'count',
aggregateAttribute: {
key: 'signoz_latency',
dataType: 'float64',
type: 'ExponentialHistogram',
isColumn: true,
isJSON: false,
id: 'signoz_latency--float64--ExponentialHistogram--true',
},
timeAggregation: '',
spaceAggregation: 'p90',
functions: [],
filters: {
items: [],
op: 'AND',
},
expression: 'A',
disabled: false,
stepInterval: 60,
having: [],
limit: null,
orderBy: [],
groupBy: [
{
key: 'service_name',
dataType: 'string',
type: 'tag',
isColumn: false,
isJSON: false,
id: 'service_name--string--tag--false',
},
],
legend: '',
reduceTo: 'avg',
},
},
},
},
},
dataUpdatedAt: 1721207526018,
error: null,
errorUpdatedAt: 0,
failureCount: 0,
errorUpdateCount: 0,
isFetched: true,
isFetchedAfterMount: true,
isFetching: false,
isRefetching: false,
isLoadingError: false,
isPlaceholderData: false,
isPreviousData: false,
isRefetchError: false,
isStale: true,
};

View File

@ -0,0 +1,267 @@
export const valuePanelWidget = {
id: 'b8b93086-ef01-47bf-9044-1e7abd583be4',
title: 'signoz latency in ms',
description: '',
isStacked: false,
nullZeroValues: 'zero',
opacity: '1',
panelTypes: 'value',
query: {
clickhouse_sql: [
{
name: 'A',
legend: '',
disabled: false,
query: '',
},
],
promql: [
{
name: 'A',
query: '',
legend: '',
disabled: false,
},
],
builder: {
queryData: [
{
dataSource: 'metrics',
queryName: 'A',
aggregateOperator: 'count',
aggregateAttribute: {
key: 'signoz_latency',
dataType: 'float64',
type: 'ExponentialHistogram',
isColumn: true,
isJSON: false,
id: 'signoz_latency--float64--ExponentialHistogram--true',
},
timeAggregation: '',
spaceAggregation: 'p90',
functions: [],
filters: {
items: [],
op: 'AND',
},
expression: 'A',
disabled: false,
stepInterval: 60,
having: [],
limit: null,
orderBy: [],
groupBy: [],
legend: '',
reduceTo: 'avg',
},
],
queryFormulas: [],
},
id: '3bec289c-49c3-4d7e-98bb-84d47c79909c',
queryType: 'builder',
},
timePreferance: 'GLOBAL_TIME',
softMax: null,
softMin: null,
selectedLogFields: [
{
dataType: 'string',
type: '',
name: 'body',
},
{
dataType: 'string',
type: '',
name: 'timestamp',
},
],
selectedTracesFields: [
{
key: 'serviceName',
dataType: 'string',
type: 'tag',
isColumn: true,
isJSON: false,
id: 'serviceName--string--tag--true',
},
{
key: 'name',
dataType: 'string',
type: 'tag',
isColumn: true,
isJSON: false,
id: 'name--string--tag--true',
},
{
key: 'durationNano',
dataType: 'float64',
type: 'tag',
isColumn: true,
isJSON: false,
id: 'durationNano--float64--tag--true',
},
{
key: 'httpMethod',
dataType: 'string',
type: 'tag',
isColumn: true,
isJSON: false,
id: 'httpMethod--string--tag--true',
},
{
key: 'responseStatusCode',
dataType: 'string',
type: 'tag',
isColumn: true,
isJSON: false,
id: 'responseStatusCode--string--tag--true',
},
],
yAxisUnit: 'ms',
thresholds: [],
fillSpans: false,
columnUnits: {},
bucketCount: 30,
stackedBarChart: false,
bucketWidth: 0,
mergeAllActiveQueries: false,
};
export const thresholds = [
{
index: '8eb16a3a-b4f1-47c8-943a-4b1786884583',
isEditEnabled: false,
thresholdColor: 'Blue',
thresholdFormat: 'Text',
thresholdOperator: '>',
thresholdUnit: 'none',
thresholdValue: 100,
keyIndex: 1,
selectedGraph: 'value',
thresholdTableOptions: '',
thresholdLabel: '',
},
{
index: 'eb9c1186-ad7d-42dd-8e7f-3913a321d7cf',
isEditEnabled: false,
thresholdColor: 'Red',
thresholdFormat: 'Text',
thresholdOperator: '>',
thresholdUnit: 'none',
thresholdValue: 0,
keyIndex: 0,
selectedGraph: 'value',
thresholdTableOptions: '',
thresholdLabel: '',
},
];
export const valuePanelQueryResponse = {
status: 'success',
isLoading: false,
isSuccess: true,
isError: false,
isIdle: false,
data: {
statusCode: 200,
error: null,
message: 'success',
payload: {
data: {
result: [
{
metric: {
A: 'A',
},
values: [[0, '295.4299833508185']],
queryName: 'A',
legend: 'A',
},
],
resultType: '',
newResult: {
status: 'success',
data: {
resultType: '',
result: [
{
queryName: 'A',
series: [
{
labels: {
A: 'A',
},
labelsArray: null,
values: [
{
timestamp: 0,
value: '295.4299833508185',
},
],
},
],
},
],
},
},
},
},
params: {
start: 1721203451000,
end: 1721203751000,
step: 60,
variables: {},
formatForWeb: false,
compositeQuery: {
queryType: 'builder',
panelType: 'value',
fillGaps: false,
builderQueries: {
A: {
dataSource: 'metrics',
queryName: 'A',
aggregateOperator: 'count',
aggregateAttribute: {
key: 'signoz_latency',
dataType: 'float64',
type: 'ExponentialHistogram',
isColumn: true,
isJSON: false,
id: 'signoz_latency--float64--ExponentialHistogram--true',
},
timeAggregation: '',
spaceAggregation: 'p90',
functions: [],
filters: {
items: [],
op: 'AND',
},
expression: 'A',
disabled: false,
stepInterval: 60,
having: [],
limit: null,
orderBy: [],
groupBy: [],
legend: '',
reduceTo: 'avg',
},
},
},
},
},
dataUpdatedAt: 1721203751775,
error: null,
errorUpdatedAt: 0,
failureCount: 0,
errorUpdateCount: 0,
isFetched: true,
isFetchedAfterMount: true,
isFetching: false,
isRefetching: false,
isLoadingError: false,
isPlaceholderData: false,
isPreviousData: false,
isRefetchError: false,
isStale: true,
};