Skip to content

Commit

Permalink
Locust charts should change color based on theme
Browse files Browse the repository at this point in the history
  • Loading branch information
andrewbaldwin44 committed Jul 23, 2024
1 parent 49002b6 commit b82e290
Show file tree
Hide file tree
Showing 3 changed files with 64 additions and 43 deletions.
85 changes: 48 additions & 37 deletions locust/webui/src/components/LineChart/LineChart.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import { useEffect, useState, useRef } from 'react';
import {
init,
registerTheme,
dispose,
ECharts,
EChartsOption,
Expand All @@ -10,6 +9,7 @@ import {
TooltipComponentOption,
} from 'echarts';

import { useSelector } from 'redux/hooks';
import { IUiState } from 'redux/slice/ui.slice';
import { ICharts } from 'types/ui.types';
import { formatLocaleString, formatLocaleTime } from 'utils/date';
Expand Down Expand Up @@ -40,25 +40,7 @@ interface ILineChartZoomEvent {
batch?: { start: number; end: number }[];
}

const CHART_TEXT_COLOR = '#b3c3bc';
const CHART_AXIS_COLOR = '#5b6f66';

registerTheme('locust', {
backgroundColor: '#27272a',
textStyle: { color: CHART_TEXT_COLOR },
title: {
textStyle: { color: CHART_TEXT_COLOR },
},
});

const createOptions = ({ charts, title, seriesData, colors }: ICreateOptions) => ({
legend: {
icon: 'circle',
inactiveColor: CHART_TEXT_COLOR,
textStyle: {
color: CHART_TEXT_COLOR,
},
},
title: {
text: title,
x: 10,
Expand Down Expand Up @@ -98,10 +80,6 @@ const createOptions = ({ charts, title, seriesData, colors }: ICreateOptions) =>
axisPointer: {
animation: true,
},
textStyle: {
color: CHART_TEXT_COLOR,
fontSize: 13,
},
backgroundColor: 'rgba(21,35,28, 0.93)',
borderWidth: 0,
extraCssText: 'z-index:1;',
Expand All @@ -111,11 +89,6 @@ const createOptions = ({ charts, title, seriesData, colors }: ICreateOptions) =>
splitLine: {
show: false,
},
axisLine: {
lineStyle: {
color: CHART_AXIS_COLOR,
},
},
axisLabel: {
formatter: formatLocaleTime,
},
Expand All @@ -127,11 +100,6 @@ const createOptions = ({ charts, title, seriesData, colors }: ICreateOptions) =>
splitLine: {
show: false,
},
axisLine: {
lineStyle: {
color: CHART_AXIS_COLOR,
},
},
},
series: seriesData,
grid: { x: 60, y: 70, x2: 40, y2: 40 },
Expand Down Expand Up @@ -163,17 +131,18 @@ const getSeriesData = ({ charts, lines }: { charts: IUiState['charts']; lines: I
data: charts[key],
}));

const createMarkLine = (charts: ICharts) => ({
const createMarkLine = (charts: ICharts, isDarkMode: boolean) => ({
symbol: 'none',
label: {
formatter: (params: DefaultLabelFormatterCallbackParams) => `Run #${params.dataIndex + 1}`,
},
lineStyle: { color: CHART_AXIS_COLOR },
lineStyle: { color: isDarkMode ? '#5b6f66' : '#000' },
data: (charts.markers || []).map((timeMarker: string) => ({ xAxis: timeMarker })),
});

export default function LineChart({ charts, title, lines, colors }: ILineChart) {
const [chart, setChart] = useState<ECharts | null>(null);
const isDarkMode = useSelector(({ theme: { isDarkMode } }) => isDarkMode);

const chartContainer = useRef<HTMLDivElement | null>(null);

Expand Down Expand Up @@ -264,11 +233,53 @@ export default function LineChart({ charts, title, lines, colors }: ILineChart)
xAxis: { data: charts.time },
series: lines.map(({ key }, index) => ({
data: charts[key],
...(index === 0 ? { markLine: createMarkLine(charts) } : {}),
...(index === 0 ? { markLine: createMarkLine(charts, isDarkMode) } : {}),
})),
});
}
}, [charts, chart, lines]);
}, [charts, chart, lines, isDarkMode]);

useEffect(() => {
if (chart) {
const chartTextColor = isDarkMode ? '#b3c3bc' : '#000';
const chartAxisColor = isDarkMode ? '#5b6f66' : '#000';

chart.setOption({
backgroundColor: isDarkMode ? '#27272a' : '#fff',
textStyle: { color: chartTextColor },
title: {
textStyle: { color: chartTextColor },
},
legend: {
icon: 'circle',
inactiveColor: chartTextColor,
textStyle: {
color: chartTextColor,
},
},
tooltip: {
textStyle: {
color: chartTextColor,
fontSize: 13,
},
},
xAxis: {
axisLine: {
lineStyle: {
color: chartAxisColor,
},
},
},
yAxis: {
axisLine: {
lineStyle: {
color: chartAxisColor,
},
},
},
});
}
}, [chart, isDarkMode]);

return <div ref={chartContainer} style={{ width: '100%', height: '300px' }}></div>;
}
10 changes: 9 additions & 1 deletion locust/webui/src/components/SwarmCharts/SwarmCharts.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,15 @@ const percentilesToChartLines = swarmTemplateArgs.percentilesToChart
}))
: [];

const percentileColors = ['#9966CC', '#8A2BE2', '#8E4585', '#E0B0FF', '#C8A2C8', '#E6E6FA'];
const percentileColors = [
'#eeff00',
'#9966CC',
'#8A2BE2',
'#8E4585',
'#E0B0FF',
'#C8A2C8',
'#E6E6FA',
];

const availableSwarmCharts: ILineChartProps[] = [
{
Expand Down
12 changes: 7 additions & 5 deletions locust/webui/src/pages/tests/HtmlReport.test.tsx
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
import { render } from '@testing-library/react';
import { describe, expect, test } from 'vitest';

import HtmlReport from 'pages/HtmlReport';
import { swarmReportMock } from 'test/mocks/swarmState.mock';
import { renderWithProvider } from 'test/testUtils';
import { formatLocaleString } from 'utils/date';

describe('HtmlReport', () => {
test('renders a report', () => {
const { getByRole, getByText } = render(<HtmlReport {...swarmReportMock} />);
const { getByRole, getByText } = renderWithProvider(<HtmlReport {...swarmReportMock} />);

expect(getByRole('heading', { name: 'Locust Test Report' })).toBeTruthy();
expect(getByRole('heading', { name: 'Request Statistics' })).toBeTruthy();
Expand All @@ -20,7 +20,7 @@ describe('HtmlReport', () => {
});

test('formats the start and end time as expected', () => {
const { getByText } = render(<HtmlReport {...swarmReportMock} />);
const { getByText } = renderWithProvider(<HtmlReport {...swarmReportMock} />);

expect(
getByText(
Expand All @@ -32,7 +32,9 @@ describe('HtmlReport', () => {
});

test('does not render the download link when showDownloadLink is false', () => {
const { queryByRole } = render(<HtmlReport {...swarmReportMock} showDownloadLink={false} />);
const { queryByRole } = renderWithProvider(
<HtmlReport {...swarmReportMock} showDownloadLink={false} />,
);

expect(queryByRole('link', { name: 'Download the Report' })).toBeNull();
});
Expand All @@ -45,7 +47,7 @@ describe('HtmlReport', () => {
traceback: '',
};

const { getByRole, getByText } = render(
const { getByRole, getByText } = renderWithProvider(
<HtmlReport {...swarmReportMock} exceptionsStatistics={[exception]} />,
);

Expand Down

0 comments on commit b82e290

Please sign in to comment.