@centreon/ui 24.5.13 → 24.6.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (28) hide show
  1. package/package.json +1 -1
  2. package/src/Graph/LineChart/BasicComponents/Axes/index.tsx +12 -3
  3. package/src/Graph/LineChart/BasicComponents/Axes/models.ts +3 -1
  4. package/src/Graph/LineChart/BasicComponents/Grids/index.tsx +28 -4
  5. package/src/Graph/LineChart/BasicComponents/Lines/Point.tsx +36 -0
  6. package/src/Graph/LineChart/BasicComponents/Lines/RegularLines/index.tsx +37 -8
  7. package/src/Graph/LineChart/BasicComponents/Lines/StackedLines/index.tsx +65 -6
  8. package/src/Graph/LineChart/BasicComponents/Lines/index.tsx +59 -6
  9. package/src/Graph/LineChart/InteractiveComponents/AnchorPoint/RegularAnchorPoint.tsx +1 -1
  10. package/src/Graph/LineChart/InteractiveComponents/AnchorPoint/StackedAnchorPoint.tsx +1 -1
  11. package/src/Graph/LineChart/InteractiveComponents/GraphValueTooltip/GraphValueTooltip.tsx +9 -3
  12. package/src/Graph/LineChart/InteractiveComponents/GraphValueTooltip/useGraphValueTooltip.ts +36 -4
  13. package/src/Graph/LineChart/InteractiveComponents/TimeShiftZones/TimeShiftZone.tsx +2 -2
  14. package/src/Graph/LineChart/InteractiveComponents/TimeShiftZones/index.tsx +10 -11
  15. package/src/Graph/LineChart/Legend/Legend.styles.ts +27 -4
  16. package/src/Graph/LineChart/Legend/LegendHeader.tsx +14 -4
  17. package/src/Graph/LineChart/Legend/index.tsx +41 -12
  18. package/src/Graph/LineChart/LineChart.cypress.spec.tsx +273 -10
  19. package/src/Graph/LineChart/LineChart.tsx +195 -98
  20. package/src/Graph/LineChart/common/index.ts +7 -4
  21. package/src/Graph/LineChart/index.stories.tsx +11 -1
  22. package/src/Graph/LineChart/index.tsx +12 -7
  23. package/src/Graph/LineChart/models.ts +27 -2
  24. package/src/Graph/common/timeSeries/index.ts +39 -6
  25. package/src/Graph/common/timeSeries/models.ts +7 -1
  26. package/src/Graph/common/utils.ts +32 -0
  27. package/src/InputField/Number/Number.tsx +4 -3
  28. package/src/InputField/Text/index.tsx +14 -0
@@ -16,9 +16,15 @@ export const useStyles = makeStyles<MakeStylesProps>()(
16
16
  color: theme.typography.body1.color
17
17
  },
18
18
  item: {
19
- minWidth: theme.spacing(legendWidth)
19
+ width: 'max-content'
20
20
  },
21
21
  items: {
22
+ '&[data-as-list="true"]': {
23
+ display: 'flex',
24
+ flexDirection: 'column',
25
+ height: '100%',
26
+ width: 'fit-content'
27
+ },
22
28
  '&[data-mode="compact"]': {
23
29
  gridAutoRows: theme.spacing(legendItemHeightCompact),
24
30
  height: limitLegendRows
@@ -38,9 +44,16 @@ export const useStyles = makeStyles<MakeStylesProps>()(
38
44
  width: '100%'
39
45
  },
40
46
  legend: {
41
- marginLeft: margin.left,
42
- marginRight: margin.right,
43
- overflow: 'hidden'
47
+ '&[data-display-side="false"]': {
48
+ marginLeft: margin.left,
49
+ marginRight: margin.right,
50
+ overflow: 'hidden'
51
+ },
52
+ '&[data-display-side="true"]': {
53
+ height: '100%',
54
+ marginTop: `${margin.top / 2}px`,
55
+ overflowY: 'auto'
56
+ }
44
57
  },
45
58
  minMaxAvgContainer: {
46
59
  columnGap: theme.spacing(0.5),
@@ -66,6 +79,9 @@ export const useLegendHeaderStyles = makeStyles<StylesProps>()(
66
79
  container: {
67
80
  width: '100%'
68
81
  },
82
+ containerList: {
83
+ width: 'fit-content'
84
+ },
69
85
  disabled: {
70
86
  color: theme.palette.text.disabled
71
87
  },
@@ -77,6 +93,9 @@ export const useLegendHeaderStyles = makeStyles<StylesProps>()(
77
93
  width: theme.spacing(1.5)
78
94
  },
79
95
  legendName: {
96
+ maxWidth: '75%'
97
+ },
98
+ legendNameSide: {
80
99
  maxWidth: '95%'
81
100
  },
82
101
  markerAndLegendName: {
@@ -95,6 +114,10 @@ export const useLegendHeaderStyles = makeStyles<StylesProps>()(
95
114
  fontSize: '0.75rem',
96
115
  fontWeight: theme.typography.fontWeightMedium,
97
116
  lineHeight: 1
117
+ },
118
+ textList: {
119
+ fontSize: '0.75rem',
120
+ fontWeight: theme.typography.fontWeightMedium
98
121
  }
99
122
  })
100
123
  );
@@ -15,6 +15,8 @@ import LegendContent from './LegendContent';
15
15
  interface Props {
16
16
  color: string;
17
17
  disabled?: boolean;
18
+ isDisplayedOnSide: boolean;
19
+ isListMode: boolean;
18
20
  line: Line;
19
21
  minMaxAvg?;
20
22
  value?: string | null;
@@ -25,7 +27,9 @@ const LegendHeader = ({
25
27
  color,
26
28
  disabled,
27
29
  value,
28
- minMaxAvg
30
+ minMaxAvg,
31
+ isListMode,
32
+ isDisplayedOnSide
29
33
  }: Props): JSX.Element => {
30
34
  const { classes, cx } = useLegendHeaderStyles({ color });
31
35
 
@@ -36,7 +40,9 @@ const LegendHeader = ({
36
40
  const legendName = legend || name;
37
41
 
38
42
  return (
39
- <div className={classes.container}>
43
+ <div
44
+ className={cx(!isListMode ? classes.container : classes.containerList)}
45
+ >
40
46
  <Tooltip
41
47
  followCursor={false}
42
48
  label={
@@ -60,7 +66,7 @@ const LegendHeader = ({
60
66
  legendName
61
67
  )
62
68
  }
63
- placement="top"
69
+ placement={isListMode ? 'right' : 'top'}
64
70
  >
65
71
  <div className={classes.markerAndLegendName}>
66
72
  <div
@@ -68,7 +74,11 @@ const LegendHeader = ({
68
74
  className={cx(classes.icon, { [classes.disabled]: disabled })}
69
75
  />
70
76
  <EllipsisTypography
71
- className={cx(classes.text, classes.legendName)}
77
+ className={cx(
78
+ classes.text,
79
+ !isListMode && classes.legendName,
80
+ !isListMode && isDisplayedOnSide && classes.legendNameSide
81
+ )}
72
82
  data-mode={
73
83
  value ? LegendDisplayMode.Compact : LegendDisplayMode.Normal
74
84
  }
@@ -1,6 +1,6 @@
1
- import { Dispatch, ReactNode, SetStateAction } from 'react';
1
+ import { Dispatch, ReactNode, SetStateAction, useMemo } from 'react';
2
2
 
3
- import { prop, slice, sortBy } from 'ramda';
3
+ import { equals, prop, slice, sortBy } from 'ramda';
4
4
 
5
5
  import { Box, alpha, useTheme } from '@mui/material';
6
6
 
@@ -9,6 +9,8 @@ import { useMemoComponent } from '@centreon/ui';
9
9
  import { formatMetricValue } from '../../common/timeSeries';
10
10
  import { Line } from '../../common/timeSeries/models';
11
11
  import { labelAvg, labelMax, labelMin } from '../translatedLabels';
12
+ import { LegendModel } from '../models';
13
+ import { margin } from '../common';
12
14
 
13
15
  import { useStyles } from './Legend.styles';
14
16
  import LegendHeader from './LegendHeader';
@@ -16,8 +18,9 @@ import { GetMetricValueProps, LegendDisplayMode } from './models';
16
18
  import useLegend from './useLegend';
17
19
  import LegendContent from './LegendContent';
18
20
 
19
- interface Props {
21
+ interface Props extends Pick<LegendModel, 'placement' | 'mode'> {
20
22
  base: number;
23
+ height: number | null;
21
24
  limitLegend?: false | number;
22
25
  lines: Array<Line>;
23
26
  renderExtraComponent?: ReactNode;
@@ -33,7 +36,10 @@ const MainLegend = ({
33
36
  limitLegend = false,
34
37
  renderExtraComponent,
35
38
  setLinesGraph,
36
- shouldDisplayLegendInCompactMode
39
+ shouldDisplayLegendInCompactMode,
40
+ placement,
41
+ height,
42
+ mode
37
43
  }: Props): JSX.Element => {
38
44
  const { classes, cx } = useStyles({ limitLegendRows: Boolean(limitLegend) });
39
45
  const theme = useTheme();
@@ -43,6 +49,8 @@ const MainLegend = ({
43
49
 
44
50
  const sortedData = sortBy(prop('metric_id'), lines);
45
51
 
52
+ const isListMode = useMemo(() => equals(mode, 'list'), [mode]);
53
+
46
54
  const displayedLines = limitLegend
47
55
  ? slice(0, limitLegend, sortedData)
48
56
  : sortedData;
@@ -68,13 +76,26 @@ const MainLegend = ({
68
76
  selectMetricLine(metric_id);
69
77
  };
70
78
 
71
- const mode = shouldDisplayLegendInCompactMode
72
- ? LegendDisplayMode.Compact
73
- : LegendDisplayMode.Normal;
79
+ const itemMode =
80
+ !isListMode && shouldDisplayLegendInCompactMode
81
+ ? LegendDisplayMode.Compact
82
+ : LegendDisplayMode.Normal;
74
83
 
75
84
  return (
76
- <div className={classes.legend}>
77
- <div className={classes.items} data-mode={mode}>
85
+ <div
86
+ className={classes.legend}
87
+ data-display-side={!equals(placement, 'bottom')}
88
+ style={{
89
+ height: !equals(placement, 'bottom')
90
+ ? height - margin.top / 2
91
+ : undefined
92
+ }}
93
+ >
94
+ <div
95
+ className={classes.items}
96
+ data-as-list={isListMode || !equals(placement, 'bottom')}
97
+ data-mode={itemMode}
98
+ >
78
99
  {displayedLines.map((line) => {
79
100
  const { color, display, highlight, metric_id } = line;
80
101
 
@@ -112,12 +133,14 @@ const MainLegend = ({
112
133
  <LegendHeader
113
134
  color={markerColor}
114
135
  disabled={!display}
136
+ isDisplayedOnSide={!equals(placement, 'bottom')}
137
+ isListMode={isListMode}
115
138
  line={line}
116
139
  minMaxAvg={
117
140
  shouldDisplayLegendInCompactMode ? minMaxAvg : undefined
118
141
  }
119
142
  />
120
- {!shouldDisplayLegendInCompactMode && (
143
+ {!shouldDisplayLegendInCompactMode && !isListMode && (
121
144
  <div>
122
145
  <div className={classes.minMaxAvgContainer}>
123
146
  {minMaxAvg.map(({ label, value }) => (
@@ -145,7 +168,10 @@ const Legend = (props: Props): JSX.Element => {
145
168
  limitLegend,
146
169
  lines,
147
170
  base,
148
- shouldDisplayLegendInCompactMode
171
+ shouldDisplayLegendInCompactMode,
172
+ placement,
173
+ height,
174
+ mode
149
175
  } = props;
150
176
 
151
177
  return useMemoComponent({
@@ -155,7 +181,10 @@ const Legend = (props: Props): JSX.Element => {
155
181
  base,
156
182
  toggable,
157
183
  limitLegend,
158
- shouldDisplayLegendInCompactMode
184
+ shouldDisplayLegendInCompactMode,
185
+ placement,
186
+ height,
187
+ mode
159
188
  ]
160
189
  });
161
190
  };
@@ -5,15 +5,31 @@ import dataLastDayWithNullValues from './mockedData/lastDayWithNullValues.json';
5
5
  import dataLastDayWithIncompleteValues from './mockedData/lastDayWithIncompleteValues.json';
6
6
  import dataCurvesWithSameColor from './mockedData/curvesWithSameColor.json';
7
7
  import { args as argumentsData } from './helpers/doc';
8
+ import { LineChartProps } from './models';
8
9
 
9
10
  import WrapperLineChart from '.';
10
11
 
11
- const initialize = (data = dataLastDay): void => {
12
+ interface Props
13
+ extends Pick<LineChartProps, 'legend' | 'tooltip' | 'axis' | 'lineStyle'> {
14
+ data?: LineChartData;
15
+ }
16
+
17
+ const initialize = ({
18
+ data = dataLastDay,
19
+ tooltip,
20
+ legend,
21
+ axis,
22
+ lineStyle
23
+ }: Props): void => {
12
24
  cy.mount({
13
25
  Component: (
14
26
  <WrapperLineChart
15
27
  {...argumentsData}
28
+ axis={axis}
16
29
  data={data as unknown as LineChartData}
30
+ legend={legend}
31
+ lineStyle={lineStyle}
32
+ tooltip={tooltip}
17
33
  />
18
34
  )
19
35
  });
@@ -22,7 +38,7 @@ const initialize = (data = dataLastDay): void => {
22
38
  describe('Line chart', () => {
23
39
  describe('Tooltip', () => {
24
40
  it('displays a tooltip when the graph is hovered', () => {
25
- initialize();
41
+ initialize({});
26
42
 
27
43
  cy.contains('oracle-buffer-hit-ratio graph on srv-oracle-users').should(
28
44
  'be.visible'
@@ -44,7 +60,7 @@ describe('Line chart', () => {
44
60
  });
45
61
 
46
62
  it('displays a metric highlighted when the graph is hovered and the metric is the nearest point', () => {
47
- initialize();
63
+ initialize({});
48
64
 
49
65
  cy.contains('Min: 70.31').should('be.visible');
50
66
 
@@ -53,23 +69,23 @@ describe('Line chart', () => {
53
69
  cy.get('[data-metric="querytime"]').should(
54
70
  'have.attr',
55
71
  'data-highlight',
56
- 'true'
72
+ 'false'
57
73
  );
58
74
  cy.get('[data-metric="connTime"]').should(
59
75
  'have.attr',
60
76
  'data-highlight',
61
- 'false'
77
+ 'true'
62
78
  );
63
79
 
64
80
  cy.makeSnapshot();
65
81
  });
66
82
 
67
83
  it('does not display the tooltip when null values are hovered', () => {
68
- initialize(dataLastDayWithNullValues);
84
+ initialize({ data: dataLastDayWithNullValues });
69
85
 
70
86
  cy.contains('Min: 70.31').should('be.visible');
71
87
 
72
- cy.findByTestId('graph-interaction-zone').realMouseMove(1160, 100);
88
+ cy.findByTestId('graph-interaction-zone').realMouseMove(1185, 100);
73
89
 
74
90
  cy.get('[data-metric="querytime"]').should('not.exist');
75
91
 
@@ -77,21 +93,77 @@ describe('Line chart', () => {
77
93
  });
78
94
 
79
95
  it('displays the tooltip with defined values whent the graph is hovered', () => {
80
- initialize(dataLastDayWithIncompleteValues);
96
+ initialize({ data: dataLastDayWithIncompleteValues });
81
97
 
82
98
  cy.contains('Min: 70.31').should('be.visible');
83
99
 
84
- cy.findByTestId('graph-interaction-zone').realMouseMove(1150, 100);
100
+ cy.findByTestId('graph-interaction-zone').realMouseMove(1162, 100);
85
101
 
86
102
  cy.get('[data-metric="querytime"]').should('be.visible');
87
103
  cy.get('[data-metric="hitratio"]').should('not.exist');
88
104
 
89
105
  cy.makeSnapshot();
90
106
  });
107
+
108
+ it('displays the tooltip a single metric when the corresponding prop is set', () => {
109
+ initialize({ tooltip: { mode: 'single', sortOrder: 'name' } });
110
+
111
+ cy.contains('Min: 70.31').should('be.visible');
112
+
113
+ cy.findByTestId('graph-interaction-zone').realMouseMove(452, 26);
114
+
115
+ cy.get('[data-metric="connTime"]').should(
116
+ 'have.attr',
117
+ 'data-highlight',
118
+ 'true'
119
+ );
120
+ cy.get('[data-metric="hitratio"]').should('not.exist');
121
+
122
+ cy.makeSnapshot();
123
+ });
124
+
125
+ it('does not display the tooltip when the corresponding prop is set', () => {
126
+ initialize({ tooltip: { mode: 'hidden', sortOrder: 'name' } });
127
+
128
+ cy.contains('Min: 70.31').should('be.visible');
129
+
130
+ cy.findByTestId('graph-interaction-zone').realMouseMove(452, 26);
131
+
132
+ cy.get('[data-metric="querytime"]').should('not.exist');
133
+ cy.get('[data-metric="connTime"]').should('not.exist');
134
+
135
+ cy.makeSnapshot();
136
+ });
137
+
138
+ it('sorts metrics by their value is ascending when the corresponding prop is set', () => {
139
+ initialize({ tooltip: { mode: 'all', sortOrder: 'ascending' } });
140
+
141
+ cy.contains('Min: 70.31').should('be.visible');
142
+
143
+ cy.findByTestId('graph-interaction-zone').realMouseMove(452, 26);
144
+
145
+ cy.get('[data-metric="querytime"]').should('be.visible');
146
+ cy.get('[data-metric="connTime"]').should('be.visible');
147
+
148
+ cy.makeSnapshot();
149
+ });
150
+
151
+ it('sorts metrics by their value is descending when the corresponding prop is set', () => {
152
+ initialize({ tooltip: { mode: 'all', sortOrder: 'descending' } });
153
+
154
+ cy.contains('Min: 70.31').should('be.visible');
155
+
156
+ cy.findByTestId('graph-interaction-zone').realMouseMove(452, 26);
157
+
158
+ cy.get('[data-metric="querytime"]').should('be.visible');
159
+ cy.get('[data-metric="connTime"]').should('be.visible');
160
+
161
+ cy.makeSnapshot();
162
+ });
91
163
  });
92
164
 
93
165
  it('displays the curves with different shades when curves have same color', () => {
94
- initialize(dataCurvesWithSameColor);
166
+ initialize({ data: dataCurvesWithSameColor });
95
167
 
96
168
  cy.findByLabelText('Centreon-Server: Round-Trip Average Time')
97
169
  .find('[data-icon="true"]')
@@ -141,4 +213,195 @@ describe('Line chart', () => {
141
213
 
142
214
  cy.makeSnapshot();
143
215
  });
216
+
217
+ describe('Legend', () => {
218
+ it('displays the legend in list mode when the corresponding props is set', () => {
219
+ initialize({ legend: { mode: 'list', placement: 'bottom' } });
220
+
221
+ cy.contains('Min:').should('not.exist');
222
+ cy.contains('Max:').should('not.exist');
223
+ cy.contains('Avg:').should('not.exist');
224
+
225
+ cy.get('[data-display-side="false"]').should('exist');
226
+ cy.get('[data-as-list="true"]').should('exist');
227
+
228
+ cy.contains('9:00 AM').should('be.visible');
229
+
230
+ cy.makeSnapshot();
231
+ });
232
+
233
+ it('displays the legend on the left side of the graph when the corresponding prop is set', () => {
234
+ initialize({ legend: { mode: 'grid', placement: 'left' } });
235
+
236
+ cy.get('[data-display-side="true"]').should('exist');
237
+ cy.get('[data-as-list="true"]').should('exist');
238
+
239
+ cy.contains('9:00 AM').should('be.visible');
240
+
241
+ cy.makeSnapshot();
242
+ });
243
+
244
+ it('displays the legend on the right side of the graph as list when the corresponding props are set', () => {
245
+ initialize({ legend: { mode: 'list', placement: 'right' } });
246
+
247
+ cy.get('[data-display-side="true"]').should('exist');
248
+ cy.get('[data-as-list="true"]').should('exist');
249
+
250
+ cy.contains('9:00 AM').should('be.visible');
251
+
252
+ cy.makeSnapshot();
253
+ });
254
+ });
255
+
256
+ describe('Axis', () => {
257
+ it('does not display axis borders when the prop is set', () => {
258
+ initialize({ axis: { showBorder: false } });
259
+
260
+ cy.contains('9:00 AM').should('be.visible');
261
+
262
+ cy.get('line[class*="visx-axis-line"]')
263
+ .eq(0)
264
+ .should('have.attr', 'stroke-width')
265
+ .and('equal', '0');
266
+ cy.get('line[class*="visx-axis-line"]')
267
+ .eq(1)
268
+ .should('have.attr', 'stroke-width')
269
+ .and('equal', '0');
270
+ cy.get('line[class*="visx-axis-line"]')
271
+ .eq(2)
272
+ .should('have.attr', 'stroke-width')
273
+ .and('equal', '0');
274
+
275
+ cy.makeSnapshot();
276
+ });
277
+
278
+ it('does not display grids when the prop is set', () => {
279
+ initialize({ axis: { showGridLines: false } });
280
+
281
+ cy.contains('9:00 AM').should('be.visible');
282
+
283
+ cy.get('g[class="visx-group visx-rows"]').should('not.exist');
284
+ cy.get('g[class="visx-group visx-columns"]').should('not.exist');
285
+
286
+ cy.makeSnapshot();
287
+ });
288
+
289
+ it('displays only horizontal lines when the prop is set', () => {
290
+ initialize({ axis: { gridLinesType: 'horizontal' } });
291
+
292
+ cy.contains('9:00 AM').should('be.visible');
293
+
294
+ cy.get('g[class="visx-group visx-rows"]').should('be.visible');
295
+ cy.get('g[class="visx-group visx-columns"]').should('not.exist');
296
+
297
+ cy.makeSnapshot();
298
+ });
299
+
300
+ it('displays only vertical lines when the prop is set', () => {
301
+ initialize({ axis: { gridLinesType: 'vertical' } });
302
+
303
+ cy.contains('9:00 AM').should('be.visible');
304
+
305
+ cy.get('g[class="visx-group visx-rows"]').should('not.exist');
306
+ cy.get('g[class="visx-group visx-columns"]').should('be.visible');
307
+
308
+ cy.makeSnapshot();
309
+ });
310
+
311
+ it('rotates the tick label when the props is set', () => {
312
+ initialize({ axis: { yAxisTickLabelRotation: -35 } });
313
+
314
+ cy.contains('9:00 AM').should('be.visible');
315
+
316
+ cy.get('text[transform="rotate(-35, -2, 388)"]').should('be.visible');
317
+
318
+ cy.makeSnapshot();
319
+ });
320
+
321
+ it('displays as centered to zero when the prop is set', () => {
322
+ initialize({ axis: { isCenteredZero: true } });
323
+
324
+ cy.contains('9:00 AM').should('be.visible');
325
+
326
+ cy.contains('0.9').should('be.visible');
327
+ cy.contains('-0.9').should('be.visible');
328
+
329
+ cy.makeSnapshot();
330
+ });
331
+ });
332
+
333
+ describe('Line style', () => {
334
+ it('displays the curve in a natural style when the prop is set', () => {
335
+ initialize({ lineStyle: { curve: 'natural' } });
336
+
337
+ cy.contains('9:00 AM').should('be.visible');
338
+
339
+ cy.makeSnapshot();
340
+ });
341
+
342
+ it('displays the curve in a step style when the prop is set', () => {
343
+ initialize({ lineStyle: { curve: 'step' } });
344
+
345
+ cy.contains('9:00 AM').should('be.visible');
346
+
347
+ cy.makeSnapshot();
348
+ });
349
+
350
+ it('shows the area when the prop is set', () => {
351
+ initialize({ lineStyle: { showArea: true } });
352
+
353
+ cy.contains('9:00 AM').should('be.visible');
354
+ cy.get('path[fill="rgba(102, 153, 204, 0.19999999999999996)"]').should(
355
+ 'be.visible'
356
+ );
357
+
358
+ cy.makeSnapshot();
359
+ });
360
+
361
+ it('shows the area with a custom transparency when props are set', () => {
362
+ initialize({ lineStyle: { areaTransparency: 20, showArea: true } });
363
+
364
+ cy.contains('9:00 AM').should('be.visible');
365
+ cy.get('path[fill="rgba(102, 153, 204, 0.8)"]').should('be.visible');
366
+
367
+ cy.makeSnapshot();
368
+ });
369
+
370
+ it('shows points when the prop is set', () => {
371
+ initialize({ lineStyle: { showPoints: true } });
372
+
373
+ cy.contains('9:00 AM').should('be.visible');
374
+ cy.get('circle[cx="4.0625"]').should('be.visible');
375
+ cy.get('circle[cy="163.69430856642046"]').should('be.visible');
376
+
377
+ cy.makeSnapshot();
378
+ });
379
+
380
+ it('displays lines with a custom line width when the prop is set', () => {
381
+ initialize({ lineStyle: { lineWidth: 6 } });
382
+
383
+ cy.contains('9:00 AM').should('be.visible');
384
+ cy.get('path[stroke-width="6"]').should('have.length', 3);
385
+
386
+ cy.makeSnapshot();
387
+ });
388
+
389
+ it('displays lines with dots width when the prop is set', () => {
390
+ initialize({ lineStyle: { dotOffset: 10, lineWidth: 4 } });
391
+
392
+ cy.contains('9:00 AM').should('be.visible');
393
+ cy.get('path[stroke-width="4"]')
394
+ .should('have.attr', 'stroke-dasharray')
395
+ .and('equals', '4 10');
396
+ });
397
+
398
+ it('displays lines with dots width when the prop is set', () => {
399
+ initialize({ lineStyle: { dashLength: 5, dashOffset: 8 } });
400
+
401
+ cy.contains('9:00 AM').should('be.visible');
402
+ cy.get('path[stroke-width="2"]')
403
+ .should('have.attr', 'stroke-dasharray')
404
+ .and('equals', '5 8');
405
+ });
406
+ });
144
407
  });