import { userAtom } from '@centreon/ui-context';
import { createStore, Provider } from 'jotai';
import { useState } from 'react';
import type { LineChartData } from '../common/models';
import dataCurvesWithSameColor from '../mockedData/curvesWithSameColor.json';
import dataLastDay from '../mockedData/lastDay.json';
import dataLastDayWithIncompleteValues from '../mockedData/lastDayWithIncompleteValues.json';
import dataLastDayWithNullValues from '../mockedData/lastDayWithNullValues.json';
import dataPingServiceLines from '../mockedData/pingService.json';
import dataPingServiceLinesBars from '../mockedData/pingServiceLinesBars.json';
import dataPingServiceLinesBarsMixed from '../mockedData/pingServiceLinesBarsMixed.json';
import dataPingServiceLinesBarsStacked from '../mockedData/pingServiceLinesBarsStacked.json';
import WrapperChart from '.';
import { args as argumentsData } from './helpers/doc';
import type { LineChartProps } from './models';
import { labelAvg, labelMin } from './translatedLabels';
interface Props
extends Pick<
LineChartProps,
| 'legend'
| 'tooltip'
| 'axis'
| 'lineStyle'
| 'barStyle'
| 'additionalLines'
| 'min'
| 'max'
| 'boundariesUnit'
> {
data?: LineChartData;
}
const checkLegendInformation = (): void => {
cy.contains('hitratio').should('be.visible');
cy.contains('querytime').should('be.visible');
cy.contains('connTime').should('be.visible');
cy.contains('Min: 70.31').should('be.visible');
cy.contains('Min: 0.03').should('be.visible');
cy.contains('Max: 88.03').should('be.visible');
cy.contains('Max: 0.98').should('be.visible');
cy.contains('Max: 0.97').should('be.visible');
cy.contains('Avg: 78.07').should('be.visible');
cy.contains('Avg: 0.5').should('be.visible');
cy.contains('Avg: 0.51').should('be.visible');
};
const CustomUnitComponent = (props): JSX.Element => {
const [leftUnit, setLeftUnit] = useState('%');
const [rightUnit, setRightUnit] = useState('ms');
return (
);
};
const initialize = ({
data = dataLastDay,
tooltip,
legend,
axis,
lineStyle,
barStyle,
additionalLines,
min,
max,
boundariesUnit
}: Props): void => {
cy.adjustViewport();
const store = createStore();
store.set(userAtom, {
alias: 'admin',
locale: 'en',
name: 'admin',
timezone: 'Europe/Paris'
});
cy.mount({
Component: (
)
});
cy.viewport('macbook-13');
};
const initializeCustomUnits = ({
data = dataLastDay,
tooltip,
legend,
axis,
lineStyle
}: Props): void => {
cy.adjustViewport();
const store = createStore();
store.set(userAtom, {
alias: 'admin',
locale: 'en',
name: 'admin',
timezone: 'Europe/Paris'
});
cy.mount({
Component: (
)
});
cy.viewport('macbook-13');
};
const checkGraphWidth = (): void => {
cy.findByTestId('graph-interaction-zone')
.should('have.attr', 'height')
.and('equal', '392');
cy.findByTestId('graph-interaction-zone').then((graph) => {
expect(Number(graph[0].attributes.width.value)).to.be.greaterThan(1149);
});
};
describe('Line chart', () => {
describe('Tooltip', () => {
it('displays a tooltip when the graph is hovered', () => {
initialize({});
checkGraphWidth();
cy.contains('oracle-buffer-hit-ratio graph on srv-oracle-users').should(
'be.visible'
);
cy.contains('hitratio').should('be.visible');
cy.contains('querytime').should('be.visible');
cy.contains('connTime').should('be.visible');
cy.contains('Min: 70.31').should('be.visible');
cy.findByTestId('graph-interaction-zone').realMouseMove(240, 70);
cy.contains('06/18/2023').should('be.visible');
cy.makeSnapshot();
});
it('displays a metric highlighted when the graph is hovered and the metric is the nearest point', () => {
initialize({});
checkGraphWidth();
cy.contains('Min: 70.31').should('be.visible');
cy.findByTestId('graph-interaction-zone').realMouseMove(230, 26);
cy.get('[data-metric="querytime"]').should(
'have.attr',
'data-highlight',
'false'
);
cy.get('[data-metric="connTime"]').should(
'have.attr',
'data-highlight',
'true'
);
cy.get('[data-metric="hitratio"]').should(
'have.attr',
'data-highlight',
'false'
);
cy.makeSnapshot();
});
it('does not display the tooltip when null values are hovered', () => {
initialize({ data: dataLastDayWithNullValues });
checkGraphWidth();
cy.contains('Min: 70.31').should('be.visible');
cy.findByTestId('graph-interaction-zone').realMouseMove(1205, 100);
cy.get('[data-metric="querytime"]').should('not.exist');
cy.makeSnapshot();
});
it('displays the tooltip with defined values when the graph is hovered', () => {
initialize({ data: dataLastDayWithIncompleteValues });
checkGraphWidth();
cy.contains('Min: 70.31').should('be.visible');
cy.findByTestId('graph-interaction-zone').realMouseMove(1100, 100);
cy.get('[data-metric="querytime"]').should('be.visible');
cy.get('[data-metric="hitratio"]').should('be.visible');
cy.makeSnapshot();
});
it('does not display the tooltip when the corresponding prop is set', () => {
initialize({ tooltip: { mode: 'hidden', sortOrder: 'name' } });
checkGraphWidth();
cy.contains('Min: 70.31').should('be.visible');
cy.findByTestId('graph-interaction-zone').realMouseMove(452, 26);
cy.get('[data-metric="querytime"]').should('not.exist');
cy.get('[data-metric="connTime"]').should('not.exist');
cy.makeSnapshot();
});
it('sorts metrics by their value is ascending when the corresponding prop is set', () => {
initialize({ tooltip: { mode: 'all', sortOrder: 'ascending' } });
checkGraphWidth();
cy.contains('Min: 70.31').should('be.visible');
cy.findByTestId('graph-interaction-zone').realMouseMove(452, 26);
cy.get('[data-metric="querytime"]').should('be.visible');
cy.get('[data-metric="connTime"]').should('be.visible');
cy.makeSnapshot();
});
it('sorts metrics by their value is descending when the corresponding prop is set', () => {
initialize({ tooltip: { mode: 'all', sortOrder: 'descending' } });
checkGraphWidth();
cy.contains('Min: 70.31').should('be.visible');
cy.findByTestId('graph-interaction-zone').realMouseMove(452, 26);
cy.get('[data-metric="querytime"]').should('be.visible');
cy.get('[data-metric="connTime"]').should('be.visible');
cy.makeSnapshot();
});
});
it('displays the curves with different shades when curves have same color', () => {
initialize({ data: dataCurvesWithSameColor });
cy.findByTestId('graph-interaction-zone')
.should('have.attr', 'width')
.and('equal', '1220');
cy.get('[data-icon="true"]')
.eq(0)
.should('have.css', 'background-color', 'rgb(41, 175, 238)');
cy.get('[data-icon="true"]')
.eq(1)
.should('have.css', 'background-color', 'rgb(83, 191, 241)');
cy.get('[data-icon="true"]')
.eq(2)
.should('have.css', 'background-color', 'rgb(8, 34, 47)');
cy.get('[data-icon="true"]')
.eq(3)
.should('have.css', 'background-color', 'rgb(16, 70, 95)');
cy.get('[data-icon="true"]')
.eq(4)
.should('have.css', 'background-color', 'rgb(24, 105, 142)');
cy.get('[data-icon="true"]')
.eq(5)
.should('have.css', 'background-color', 'rgb(32, 140, 190)');
cy.get('[data-metric="1"]').should(
'have.attr',
'stroke',
'rgb(41, 175, 238)'
);
cy.get('[data-metric="21"]').should(
'have.attr',
'stroke',
'rgb(32, 140, 190)'
);
cy.get('[data-metric="17"]').should(
'have.attr',
'stroke',
'rgb(24, 105, 142)'
);
cy.get('[data-metric="13"]').should(
'have.attr',
'stroke',
'rgb(16, 70, 95)'
);
cy.get('[data-metric="9"]').should('have.attr', 'stroke', 'rgb(8, 34, 47)');
cy.get('[data-metric="5"]').should(
'have.attr',
'stroke',
'rgb(83, 191, 241)'
);
cy.makeSnapshot();
});
describe('Legend', () => {
it('displays the legend in list mode when the corresponding props is set', () => {
initialize({ legend: { mode: 'list', placement: 'bottom' } });
cy.contains('Min:').should('not.exist');
cy.contains('Max:').should('not.exist');
cy.contains('Avg:').should('not.exist');
cy.get('[data-display-side="false"]').should('exist');
cy.get('[data-as-list="true"]').should('exist');
cy.contains(':00 AM').should('be.visible');
cy.makeSnapshot();
});
it('displays the legend on the left side of the graph when the corresponding prop is set', () => {
initialize({
legend: { mode: 'grid', placement: 'left' }
});
cy.get('[data-display-side="true"]').should('exist');
cy.get('[data-as-list="true"]').should('exist');
cy.contains(':00 AM').should('be.visible');
});
it('displays the legend on the right side of the graph as list when the corresponding props are set', () => {
initialize({ legend: { mode: 'list', placement: 'right' } });
cy.get('[data-display-side="true"]').should('exist');
cy.get('[data-as-list="true"]').should('exist');
cy.contains(':00 AM').should('be.visible');
});
});
describe('Axis', () => {
it('does not display axis borders when the prop is set', () => {
initialize({ axis: { showBorder: false } });
checkGraphWidth();
cy.contains(':00 AM').should('be.visible');
cy.get('line[class*="visx-axis-line"]')
.eq(0)
.should('have.attr', 'stroke-width')
.and('equal', '0');
cy.get('line[class*="visx-axis-line"]')
.eq(1)
.should('have.attr', 'stroke-width')
.and('equal', '0');
cy.get('line[class*="visx-axis-line"]')
.eq(2)
.should('have.attr', 'stroke-width')
.and('equal', '0');
cy.makeSnapshot();
});
it('does not display grids when the prop is set', () => {
initialize({ axis: { showGridLines: false } });
checkGraphWidth();
cy.contains(':00 AM').should('be.visible');
cy.get('g[class="visx-group visx-rows"]').should('not.exist');
cy.get('g[class="visx-group visx-columns"]').should('not.exist');
cy.makeSnapshot();
});
it('displays only horizontal lines when the prop is set', () => {
initialize({ axis: { gridLinesType: 'horizontal' } });
checkGraphWidth();
cy.contains(':00 AM').should('be.visible');
cy.get('g[class="visx-group visx-rows"]').should('be.visible');
cy.get('g[class="visx-group visx-columns"]').should('not.exist');
cy.makeSnapshot();
});
it('displays only vertical lines when the prop is set', () => {
initialize({ axis: { gridLinesType: 'vertical' } });
checkGraphWidth();
cy.contains(':00 AM').should('be.visible');
cy.get('g[class="visx-group visx-rows"]').should('not.exist');
cy.get('g[class="visx-group visx-columns"]').should('be.visible');
cy.makeSnapshot();
});
it('rotates the tick label when the props is set', () => {
initialize({ axis: { yAxisTickLabelRotation: -35 } });
checkGraphWidth();
cy.contains(':00 AM').should('be.visible');
cy.get('text[transform="rotate(-35, -2, 187.52600691899028)"]').should(
'be.visible'
);
cy.makeSnapshot();
});
it('displays as centered to zero when the prop is set', () => {
initialize({ axis: { isCenteredZero: true } });
checkGraphWidth();
cy.contains(':00 AM').should('be.visible');
cy.contains('0.8').should('be.visible');
cy.contains('-0.8').should('be.visible');
cy.makeSnapshot();
});
});
describe('Line style', () => {
it('displays the curve in a natural style when the prop is set', () => {
initialize({ lineStyle: { curve: 'natural' } });
checkGraphWidth();
cy.contains(':00 AM').should('be.visible');
cy.get('[data-metric="13536"]').should('be.visible');
cy.get('[data-metric="13534"]').should('be.visible');
cy.get('[data-metric="13535"]').should('be.visible');
cy.makeSnapshot();
});
it('displays the curve in a step style when the prop is set', () => {
initialize({ data: dataPingServiceLines, lineStyle: { curve: 'step' } });
checkGraphWidth();
cy.contains(':00 AM').should('be.visible');
cy.get('[data-metric="1"]').should('be.visible');
cy.get('[data-metric="2"]').should('be.visible');
cy.get('[data-metric="3"]').should('be.visible');
cy.makeSnapshot();
});
it('shows the area when the prop is set', () => {
initialize({ lineStyle: { showArea: true } });
checkGraphWidth();
cy.contains(':00 AM').should('be.visible');
cy.get('path[fill="rgba(102, 153, 204, 0.19999999999999996)"]').should(
'be.visible'
);
cy.get('[data-metric="13536"]').should('be.visible');
cy.get('[data-metric="13534"]').should('be.visible');
cy.get('[data-metric="13535"]').should('be.visible');
checkLegendInformation();
cy.makeSnapshot();
});
it('shows the area with a custom transparency when props are set', () => {
initialize({ lineStyle: { areaTransparency: 20, showArea: true } });
checkGraphWidth();
cy.contains(':00 AM').should('be.visible');
cy.get('path[fill="rgba(102, 153, 204, 0.8)"]').should('be.visible');
});
it('shows points when the prop is set', () => {
initialize({ lineStyle: { showPoints: true } });
checkGraphWidth();
cy.contains(':00 AM').should('be.visible');
cy.get('circle').should('have.length', 864);
cy.makeSnapshot();
});
it('displays lines with a custom line width when the prop is set', () => {
initialize({ lineStyle: { lineWidth: 6 } });
checkGraphWidth();
cy.contains(':00 AM').should('be.visible');
cy.get('path[stroke-width="6"]').should('have.length', 3);
cy.makeSnapshot();
});
it('displays lines with dots width when the prop is set', () => {
initialize({ lineStyle: { dotOffset: 10, lineWidth: 4 } });
checkGraphWidth();
cy.contains(':00 AM').should('be.visible');
cy.get('path[stroke-width="4"]')
.should('have.attr', 'stroke-dasharray')
.and('equals', '4 10');
});
it('displays lines with dashes width when props are set', () => {
initialize({ lineStyle: { dashLength: 5, dashOffset: 8 } });
checkGraphWidth();
cy.contains(':00 AM').should('be.visible');
cy.get('path[stroke-width="2"]')
.should('have.attr', 'stroke-dasharray')
.and('equals', '5 8');
});
it('displays only one line with custom style when props are set', () => {
initialize({
lineStyle: [
{
dashLength: 5,
dashOffset: 4,
lineWidth: 1,
metricId: 13534,
showArea: true,
showPoints: true
}
]
});
checkGraphWidth();
cy.contains(':00 AM').should('be.visible');
cy.get('path.visx-area-closed')
.should('have.attr', 'stroke-dasharray')
.and('equals', '5 4');
cy.get('circle').should('have.length', 288);
cy.makeSnapshot();
});
});
});
describe('Lines and bars', () => {
it('displays lines and bars in the same chart', () => {
initialize({
data: dataPingServiceLinesBars
});
checkGraphWidth();
cy.get('path[data-metric="1"]').should('be.visible');
cy.get('path[data-metric="3"]').should('be.visible');
cy.get('path[data-metric="3"]').should('be.visible');
cy.findByTestId('stacked-bar-10-0-7650.368581547736').should('be.visible');
cy.makeSnapshot();
});
it('displays stacked lines and bars in the same chart', () => {
initialize({
data: dataPingServiceLinesBarsStacked
});
checkGraphWidth();
cy.get('path[data-metric="1"]').should('be.visible');
cy.get('path[data-metric="3"]').should('be.visible');
cy.get('path[data-metric="3"]').should('be.visible');
cy.findByTestId('stacked-bar-2-0-6835').should('be.visible');
cy.findByTestId('stacked-bar-10-0-14920.328518673756').should('be.visible');
cy.makeSnapshot();
});
it('displays mixed lines and bars in the same chart', () => {
initialize({
data: dataPingServiceLinesBarsMixed
});
checkGraphWidth();
cy.get('path[data-metric="1"]').should('be.visible');
cy.get('path[data-metric="3"]').should('be.visible');
cy.get('path[data-metric="3"]').should('be.visible');
cy.findByTestId('stacked-bar-10-0-7650.368581547736').should('be.visible');
cy.findByTestId('stacked-bar-2-0-10').should('be.visible');
cy.makeSnapshot();
});
it('displays lines and bars in the same chart centered in zero', () => {
initialize({
axis: {
isCenteredZero: true
},
data: dataPingServiceLinesBars
});
checkGraphWidth();
cy.get('path[data-metric="1"]').should('be.visible');
cy.get('path[data-metric="3"]').should('be.visible');
cy.get('path[data-metric="3"]').should('be.visible');
cy.findByTestId('stacked-bar-10-0-7650.368581547736').should('be.visible');
cy.makeSnapshot();
});
it('displays stacked lines and bars in the same chart centered in zero', () => {
initialize({
axis: {
isCenteredZero: true
},
data: dataPingServiceLinesBarsStacked
});
checkGraphWidth();
cy.get('path[data-metric="1"]').should('be.visible');
cy.get('path[data-metric="3"]').should('be.visible');
cy.get('path[data-metric="3"]').should('be.visible');
cy.findByTestId('stacked-bar-2-0-6835').should('be.visible');
cy.findByTestId('stacked-bar-10-0-14920.328518673756').should('be.visible');
cy.makeSnapshot();
});
it('displays mixed lines and bars in the same chart centered in zero', () => {
initialize({
axis: {
isCenteredZero: true
},
data: dataPingServiceLinesBarsMixed
});
checkGraphWidth();
cy.get('path[data-metric="1"]').should('be.visible');
cy.get('path[data-metric="3"]').should('be.visible');
cy.get('path[data-metric="3"]').should('be.visible');
cy.findByTestId('stacked-bar-10-0-7650.368581547736').should('be.visible');
cy.findByTestId('stacked-bar-2-0-10').should('be.visible');
cy.makeSnapshot();
});
it('changes the unit on the left or right scales when a new unit is selected', () => {
initializeCustomUnits({
data: dataPingServiceLinesBarsMixed
});
checkGraphWidth();
cy.findAllByTestId('unit-selector').eq(0).parent().click();
cy.findByLabelText('B').click();
cy.findAllByTestId('unit-selector').eq(0).should('have.value', 'B');
cy.contains('8.79 KiB').should('be.visible');
cy.findAllByTestId('unit-selector').eq(1).parent().click();
cy.findByLabelText('%').click();
cy.findAllByTestId('unit-selector').eq(1).should('have.value', '%');
cy.contains('20').should('be.visible');
cy.makeSnapshot();
});
it('displays stacked lines and bars when a line and a bar are customized', () => {
initialize({
barStyle: [
{
metricId: 10,
opacity: 0.5,
radius: 0.3
}
],
data: dataPingServiceLinesBarsStacked,
lineStyle: [
{
dotOffset: 4,
lineWidth: 3,
metricId: 1,
showArea: false
}
]
});
checkGraphWidth();
cy.get('[data-testid="stacked-bar-2-0-1243"]').should('be.visible');
cy.get('[data-testid="stacked-bar-10-0-8520.53622137828"]').should(
'be.visible'
);
cy.makeSnapshot();
});
it('displays additional lines when props are set', () => {
initialize({
additionalLines: [
{ color: 'pink', unit: '%', yValue: 3 },
{ color: 'red', text: 'some text', unit: 'ms', yValue: 0.15 }
],
data: dataPingServiceLines
});
checkGraphWidth();
cy.get('path[data-metric="1"]').should('be.visible');
cy.get('path[data-metric="3"]').should('be.visible');
cy.get('path[data-metric="3"]').should('be.visible');
cy.contains('some text').should('be.visible');
cy.findByTestId('pink-3').should('exist');
cy.findByTestId('red-0.15').should('exist');
cy.makeSnapshot();
});
it('displays graph according to min and max boundaries', () => {
initialize({
data: dataPingServiceLines,
max: 0.1,
min: 0.01
});
checkGraphWidth();
cy.get('path[data-metric="1"]').should('be.visible');
cy.get('path[data-metric="3"]').should('be.visible');
cy.get('path[data-metric="3"]').should('be.visible');
cy.contains('0.1 ms').should('be.visible');
cy.contains('0.1%').should('be.visible');
cy.makeSnapshot();
});
it('displays graph according to min and max boundaries for a unit', () => {
initialize({
boundariesUnit: 'ms',
data: dataPingServiceLines,
max: 0.1,
min: 0.01
});
checkGraphWidth();
cy.get('path[data-metric="1"]').should('be.visible');
cy.get('path[data-metric="3"]').should('be.visible');
cy.get('path[data-metric="3"]').should('be.visible');
cy.contains('0.1 ms').should('be.visible');
cy.contains('2%').should('be.visible');
cy.makeSnapshot();
});
it('calls the secondary function when a metric is clicked in the legend', () => {
const secondaryClick = cy.stub().as('secondaryClick');
initialize({
data: dataPingServiceLines,
legend: {
mode: 'grid',
placement: 'bottom',
secondaryClick
}
});
checkGraphWidth();
cy.contains('Packet Loss').rightclick();
cy.get('@secondaryClick').should('have.been.called');
});
it('does not displays corresponding calculations when props are set', () => {
initialize({
data: dataPingServiceLines,
legend: {
mode: 'grid',
placement: 'bottom',
showCalculations: {
avg: false,
max: false,
min: true
}
}
});
cy.contains(labelMin).should('be.visible');
cy.contains(/^Max$/).should('not.exist');
cy.contains(labelAvg).should('not.exist');
});
});