@cdc/chart 4.26.6 → 4.26.10
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.
- package/CONFIG.md +504 -368
- package/dist/cdcchart-CYc-Kayd.es.js +22488 -0
- package/dist/cdcchart-DCKn8NmI.es.js +20695 -0
- package/dist/cdcchart-Dyui9nk_.es.js +45828 -0
- package/dist/cdcchart.js +4 -96498
- package/examples/__data__/vega-remote-data.json +6 -0
- package/examples/dendrogram.json +18 -0
- package/examples/feature/bar/bar-chart-race-annual-change.json +68 -0
- package/examples/feature/heatmap/average-age-categorical.json +2 -2
- package/examples/feature/heatmap/calendar-heatmap.json +2 -2
- package/examples/feature/heatmap/cell-values-bottom-axis.json +2 -2
- package/examples/feature/heatmap/sparse-aggregation.json +2 -2
- package/examples/feature/line/line-chart-race.json +50 -0
- package/examples/feature/sankey/sankey-example-data.json +40 -1441
- package/examples/feature/sankey/sankey_chart_data.csv +9 -20
- package/examples/network.json +31 -0
- package/examples/private/box-plot.json +573 -0
- package/examples/private/custom-color-issue.json +625 -0
- package/examples/private/custom-colors.json +522 -0
- package/examples/private/cutoff.json +10750 -0
- package/examples/private/flueview.json +22051 -0
- package/examples/private/overlay-legend.json +485 -0
- package/examples/private/pie-test.json +469 -0
- package/examples/vega-remote.json +22 -0
- package/package.json +11 -13
- package/src/CdcChart.tsx +2 -2
- package/src/CdcChartComponent.tsx +444 -217
- package/src/_stories/Chart.BarRace.stories.tsx +443 -0
- package/src/_stories/Chart.BoxPlotNumericSort.stories.tsx +189 -0
- package/src/_stories/Chart.BoxPlotStatsParity.stories.tsx +207 -0
- package/src/_stories/Chart.ColorDistribution.stories.tsx +299 -0
- package/src/_stories/Chart.DataCutoff.stories.tsx +147 -0
- package/src/_stories/Chart.DataTableDownloadFilename.stories.tsx +60 -0
- package/src/_stories/Chart.Dendrogram.stories.tsx +373 -0
- package/src/_stories/Chart.Forecast.CILegend.stories.tsx +236 -0
- package/src/_stories/Chart.HeatMap.stories.tsx +170 -4
- package/src/_stories/Chart.Legend.AxisAlign.stories.tsx +119 -0
- package/src/_stories/Chart.LineRace.stories.tsx +149 -0
- package/src/_stories/Chart.Network.stories.tsx +432 -0
- package/src/_stories/Chart.PaletteConversion.Editor.stories.tsx +208 -0
- package/src/_stories/Chart.Patterns.smoke.stories.tsx +31 -0
- package/src/_stories/Chart.PercentageValue.stories.tsx +311 -0
- package/src/_stories/Chart.PieLabels.stories.tsx +49 -0
- package/src/_stories/Chart.RankByValueMutation.stories.tsx +206 -0
- package/src/_stories/Chart.RequiredFields.stories.tsx +681 -0
- package/src/_stories/Chart.Sankey.stories.tsx +417 -0
- package/src/_stories/Chart.SeriesColorAssignments.stories.tsx +47 -0
- package/src/_stories/Chart.SmallMultiplesNumericTileOrder.stories.tsx +137 -0
- package/src/_stories/Chart.TooltipSeriesLabels.stories.tsx +43 -0
- package/src/_stories/Chart.VegaRemoteData.stories.tsx +31 -0
- package/src/_stories/Chart.smoke.stories.tsx +14 -1
- package/src/_stories/ChartAnnotation.Editor.stories.tsx +78 -0
- package/src/_stories/ChartAxisTitles.smoke.stories.tsx +48 -0
- package/src/_stories/ChartBar.Editor.stories.tsx +499 -57
- package/src/_stories/ChartBrush.Editor.stories.tsx +46 -67
- package/src/_stories/ChartBrush.Regression.stories.tsx +135 -0
- package/src/_stories/ChartEditor.Editor.stories.tsx +33 -3
- package/src/_stories/ChartLine.EffectCompatibility.stories.tsx +120 -0
- package/src/_stories/ChartPrefixSuffix.smoke.stories.tsx +28 -1
- package/src/_stories/_mock/annotation_event-line_mock.json +2 -2
- package/src/_stories/_mock/editor-test-configs.json +20 -10
- package/src/_stories/_mock/editor-test-datasets.json +38 -42
- package/src/_stories/_mock/heatmap-average-age-categorical.json +2 -2
- package/src/_stories/_mock/heatmap.json +2 -2
- package/src/_stories/_mock/legend-axis-align-stacked-bar.json +125 -0
- package/src/_stories/_mock/sankey_mock.json +23 -27
- package/src/components/Annotations/components/AnnotationDraggable.styles.css +52 -0
- package/src/components/Annotations/components/AnnotationDraggable.tsx +639 -139
- package/src/components/Annotations/components/AnnotationDropdown.styles.css +44 -4
- package/src/components/Annotations/components/AnnotationDropdown.tsx +10 -32
- package/src/components/Annotations/helpers/resolveAnnotationLayout.ts +212 -0
- package/src/components/Annotations/tests/AnnotationDraggable.test.tsx +612 -19
- package/src/components/Annotations/tests/AnnotationDropdown.test.tsx +50 -0
- package/src/components/Annotations/tests/resolveAnnotationLayout.test.ts +203 -0
- package/src/components/Axis/BottomAxis.tsx +1 -1
- package/src/components/Axis/Categorical.Axis.tsx +3 -3
- package/src/components/Axis/RightAxis.tsx +21 -13
- package/src/components/BarChart/components/BarChart.Horizontal.tsx +39 -8
- package/src/components/BarChart/components/BarChart.StackedHorizontal.tsx +13 -4
- package/src/components/BarChart/components/BarChart.StackedVertical.test.ts +28 -0
- package/src/components/BarChart/components/BarChart.StackedVertical.tsx +30 -26
- package/src/components/BarChart/components/BarChart.Vertical.tsx +38 -28
- package/src/components/BarChart/components/PortionPatternOverlay.tsx +61 -0
- package/src/components/BarChart/components/context.tsx +6 -0
- package/src/components/BarChart/helpers/getBarData.ts +28 -28
- package/src/components/BarChart/helpers/getBarHeights.ts +2 -2
- package/src/components/BarChart/helpers/getPatternUrl.ts +2 -5
- package/src/components/BarChart/helpers/index.ts +8 -0
- package/src/components/BarChart/helpers/portionPattern.ts +243 -0
- package/src/components/BarChart/helpers/tests/addMinimumBarHeights.test.ts +42 -0
- package/src/components/BarChart/helpers/tests/getPatternUrl.test.ts +13 -0
- package/src/components/BarChart/helpers/tests/portionPattern.test.ts +280 -0
- package/src/components/BarChart/helpers/tests/useBarChart.test.tsx +202 -0
- package/src/components/BarChart/helpers/useBarChart.ts +60 -60
- package/src/components/BarChartRace/BarChartRace.test.tsx +199 -0
- package/src/components/BarChartRace/BarChartRace.tsx +230 -0
- package/src/components/BarChartRace/BarChartRaceFallback.test.tsx +61 -0
- package/src/components/BarChartRace/BarChartRaceFallback.tsx +48 -0
- package/src/components/BarChartRace/bar-chart-race.css +160 -0
- package/src/components/BarChartRace/helpers.test.ts +114 -0
- package/src/components/BarChartRace/helpers.ts +185 -0
- package/src/components/BarChartRace/index.ts +3 -0
- package/src/components/BoxPlot/BoxPlot.Horizontal.tsx +7 -6
- package/src/components/BoxPlot/BoxPlot.Vertical.tsx +9 -7
- package/src/components/BoxPlot/helpers/index.ts +13 -83
- package/src/components/Brush/BrushSelector.tsx +10 -24
- package/src/components/Brush/MiniChartPreview.tsx +33 -1
- package/src/components/Dendrogram/components/Dendrogram.tsx +374 -0
- package/src/components/Dendrogram/dendrogram.css +113 -0
- package/src/components/Dendrogram/helpers/layoutDendrogram.test.ts +95 -0
- package/src/components/Dendrogram/helpers/layoutDendrogram.ts +56 -0
- package/src/components/Dendrogram/helpers/prepareDendrogramData.test.ts +135 -0
- package/src/components/Dendrogram/helpers/prepareDendrogramData.ts +166 -0
- package/src/components/Dendrogram/helpers/resolveDendrogramLabels.test.ts +196 -0
- package/src/components/Dendrogram/helpers/resolveDendrogramLabels.ts +418 -0
- package/src/components/Dendrogram/index.tsx +1 -0
- package/src/components/Dendrogram/types/index.ts +66 -0
- package/src/components/EditorPanel/EditorPanel.tsx +1111 -805
- package/src/components/EditorPanel/components/Panels/Panel.Annotate.tsx +50 -5
- package/src/components/EditorPanel/components/Panels/Panel.Dendrogram.css +10 -0
- package/src/components/EditorPanel/components/Panels/Panel.Dendrogram.tsx +211 -0
- package/src/components/EditorPanel/components/Panels/Panel.ForestPlotSettings.tsx +19 -8
- package/src/components/EditorPanel/components/Panels/Panel.General.tsx +104 -61
- package/src/components/EditorPanel/components/Panels/Panel.Network.css +9 -0
- package/src/components/EditorPanel/components/Panels/Panel.Network.tsx +202 -0
- package/src/components/EditorPanel/components/Panels/Panel.PatternSettings.tsx +236 -36
- package/src/components/EditorPanel/components/Panels/Panel.Radar.tsx +6 -1
- package/src/components/EditorPanel/components/Panels/Panel.Sankey.tsx +89 -105
- package/src/components/EditorPanel/components/Panels/Panel.Series.tsx +21 -6
- package/src/components/EditorPanel/components/Panels/Panel.SmallMultiples.tsx +1 -1
- package/src/components/EditorPanel/components/Panels/Panel.Visual.tsx +8 -66
- package/src/components/EditorPanel/components/Panels/RacingControls.test.tsx +131 -0
- package/src/components/EditorPanel/components/Panels/RacingControls.tsx +185 -0
- package/src/components/EditorPanel/components/Panels/SeriesColorAssignments.tsx +2 -2
- package/src/components/EditorPanel/components/Panels/index.tsx +4 -0
- package/src/components/EditorPanel/helpers/getVisualizationTypeConfigUpdate.ts +20 -7
- package/src/components/EditorPanel/helpers/tests/getVisualizationTypeConfigUpdate.test.ts +25 -2
- package/src/components/EditorPanel/helpers/updateFieldRankByValue.ts +5 -4
- package/src/components/EditorPanel/useEditorPermissions.test.tsx +94 -0
- package/src/components/EditorPanel/useEditorPermissions.ts +75 -25
- package/src/components/Forecasting/Forecasting.tsx +16 -7
- package/src/components/HeatMap/components/HeatMap.tsx +511 -178
- package/src/components/HeatMap/heatmap.constants.ts +7 -3
- package/src/components/HeatMap/heatmap.css +101 -2
- package/src/components/HeatMap/helpers/layout.ts +80 -0
- package/src/components/HeatMap/tests/HeatMap.test.tsx +339 -16
- package/src/components/HeatMap/tests/helpers.test.ts +79 -0
- package/src/components/Legend/Legend.Component.tsx +163 -148
- package/src/components/Legend/Legend.Suppression.tsx +3 -3
- package/src/components/Legend/LegendGroup/LegendGroup.styles.css +7 -0
- package/src/components/Legend/LegendGroup/LegendGroup.tsx +47 -35
- package/src/components/Legend/helpers/createFormatLabels.test.ts +226 -0
- package/src/components/Legend/helpers/createFormatLabels.tsx +45 -51
- package/src/components/LineChart/components/LineChart.Circle.tsx +3 -3
- package/src/components/LineChart/helpers.test.ts +126 -38
- package/src/components/LineChart/helpers.ts +9 -6
- package/src/components/LineChart/index.tsx +71 -27
- package/src/components/LineChart/tests/LineChart.test.tsx +630 -0
- package/src/components/LineChartRace/LineChartRace.test.tsx +275 -0
- package/src/components/LineChartRace/LineChartRace.tsx +134 -0
- package/src/components/LineChartRace/LineChartRaceFallback.tsx +28 -0
- package/src/components/LineChartRace/helpers.test.ts +88 -0
- package/src/components/LineChartRace/helpers.ts +157 -0
- package/src/components/LineChartRace/index.ts +3 -0
- package/src/components/LineChartRace/line-chart-race.css +16 -0
- package/src/components/LinearChart/ValueAxisAnchors.tsx +58 -0
- package/src/components/LinearChart/VisualizationRenderer.tsx +18 -23
- package/src/components/LinearChart/tests/LinearChart.test.tsx +412 -13
- package/src/components/LinearChart/tests/VisualizationRenderer.test.tsx +141 -0
- package/src/components/LinearChart/tests/mockConfigContext.ts +2 -1
- package/src/components/LinearChart.tsx +85 -54
- package/src/components/Network/components/Network.tsx +372 -0
- package/src/components/Network/helpers/layoutNetwork.test.ts +68 -0
- package/src/components/Network/helpers/layoutNetwork.ts +87 -0
- package/src/components/Network/helpers/prepareNetworkData.test.ts +116 -0
- package/src/components/Network/helpers/prepareNetworkData.ts +101 -0
- package/src/components/Network/helpers/resolveNetworkLabels.test.ts +112 -0
- package/src/components/Network/helpers/resolveNetworkLabels.ts +206 -0
- package/src/components/Network/index.tsx +3 -0
- package/src/components/Network/network.css +107 -0
- package/src/components/Network/types/index.ts +56 -0
- package/src/components/PairedBarChart.jsx +5 -10
- package/src/components/PairedBarChart.test.tsx +71 -0
- package/src/components/PieChart/PieChart.tsx +121 -13
- package/src/components/PieChart/helpers/labelPlacement.test.ts +88 -0
- package/src/components/PieChart/helpers/labelPlacement.ts +95 -0
- package/src/components/RacingChartRenderer.tsx +44 -0
- package/src/components/Regions/components/Regions.test.tsx +179 -0
- package/src/components/Regions/components/Regions.tsx +104 -69
- package/src/components/Regions/index.tsx +2 -3
- package/src/components/Sankey/components/Sankey.tsx +264 -437
- package/src/components/Sankey/helpers/getSankeyTooltip.ts +12 -0
- package/src/components/Sankey/helpers/prepareSankeyData.test.ts +71 -0
- package/src/components/Sankey/helpers/prepareSankeyData.ts +90 -0
- package/src/components/Sankey/sankey.scss +57 -116
- package/src/components/Sankey/types/index.ts +41 -4
- package/src/components/ScatterPlot/ScatterPlot.jsx +28 -12
- package/src/components/ScatterPlot/ScatterPlot.test.tsx +60 -0
- package/src/components/SmallMultiples/SmallMultiples.tsx +12 -12
- package/src/components/SmallMultiples/tests/SmallMultipleTile.test.tsx +7 -5
- package/src/components/raceTiming.ts +18 -0
- package/src/data/initial-state.js +79 -31
- package/src/helpers/applyChartTypeContract.ts +71 -0
- package/src/helpers/axisLabelFontSize.ts +2 -2
- package/src/helpers/boxPlotStats.ts +60 -0
- package/src/helpers/bumpChartTooltip.ts +2 -1
- package/src/helpers/calculateHorizontalBarCategoryLabelWidth.test.ts +37 -0
- package/src/helpers/calculateHorizontalBarCategoryLabelWidth.ts +3 -2
- package/src/helpers/calculateRightYAxisWidth.ts +60 -0
- package/src/helpers/categoryOrder.ts +60 -0
- package/src/helpers/colorAssignmentHelpers.ts +2 -2
- package/src/helpers/createNewChartConfig.ts +56 -0
- package/src/helpers/dataDrivenYAxisCategories.ts +18 -0
- package/src/helpers/forecastLegend.ts +88 -0
- package/src/helpers/getBoxPlotConfig.ts +26 -38
- package/src/helpers/getChartTypeDefaultPalette.ts +29 -0
- package/src/helpers/getColorCodeCategoryColorMap.ts +26 -0
- package/src/helpers/getColorScale.ts +31 -22
- package/src/helpers/getComboChartConfig.ts +0 -1
- package/src/helpers/getDynamicYAxisCategories.ts +69 -0
- package/src/helpers/getExcludedData.ts +0 -1
- package/src/helpers/getHasBoundarySuppression.ts +4 -3
- package/src/helpers/getMinMax.ts +11 -8
- package/src/helpers/getNewRuntime.ts +4 -3
- package/src/helpers/getPiePercent.ts +3 -3
- package/src/helpers/getStackedSeriesMax.ts +51 -0
- package/src/helpers/getV21ChartDistributionColors.ts +57 -0
- package/src/helpers/handleRankByValue.ts +15 -15
- package/src/helpers/isConvertLineToBarGraph.ts +2 -2
- package/src/helpers/seriesColumnSettings.ts +31 -3
- package/src/helpers/sizeHelpers.ts +4 -5
- package/src/helpers/smallMultiplesHelpers.ts +10 -13
- package/src/helpers/tests/applyChartTypeContract.test.ts +37 -0
- package/src/helpers/tests/boxPlotStats.test.ts +31 -0
- package/src/helpers/tests/bumpChartTooltip.test.ts +29 -0
- package/src/helpers/tests/calculateRightYAxisWidth.test.ts +105 -0
- package/src/helpers/tests/categoryOrder.test.ts +57 -0
- package/src/helpers/tests/countNumOfTicks.test.ts +11 -0
- package/src/helpers/tests/createNewChartConfig.test.ts +182 -0
- package/src/helpers/tests/getBoxPlotConfig.test.ts +70 -0
- package/src/helpers/tests/getColorCodeCategoryColorMap.test.ts +113 -0
- package/src/helpers/tests/getColorScale.test.ts +226 -1
- package/src/helpers/tests/getDynamicYAxisCategories.test.ts +61 -0
- package/src/helpers/tests/getMinMax.test.ts +41 -0
- package/src/helpers/tests/getStackedSeriesMax.test.ts +26 -0
- package/src/helpers/tests/handleRankByValue.test.ts +55 -37
- package/src/helpers/tests/seriesColumnSettings.test.ts +83 -0
- package/src/helpers/tests/smallMultiplesHelpers.test.ts +37 -1
- package/src/helpers/tests/tooltipHelpers.test.ts +80 -0
- package/src/helpers/tooltipHelpers.ts +16 -0
- package/src/hooks/tests/useRightAxis.test.tsx +143 -2
- package/src/hooks/tests/useScales.test.tsx +3 -6
- package/src/hooks/tests/useTooltip.test.tsx +484 -0
- package/src/hooks/usePrefersReducedMotion.ts +22 -0
- package/src/hooks/useReduceData.ts +4 -36
- package/src/hooks/useRightAxis.ts +19 -26
- package/src/hooks/useScales.ts +15 -0
- package/src/hooks/useTooltip.tsx +106 -71
- package/src/scss/main.scss +74 -2
- package/src/store/chart.reducer.ts +4 -4
- package/src/test/CdcChart.dataTable.test.tsx +582 -14
- package/src/test/CdcChart.dendrogram.test.tsx +277 -0
- package/src/test/CdcChart.finalization.test.tsx +143 -0
- package/src/test/CdcChart.network.test.tsx +271 -0
- package/src/types/ChartConfig.ts +91 -54
- package/src/types/ChartContext.ts +5 -0
- package/src/types/Horizon.ts +1 -1
- package/LICENSE +0 -201
- package/dist/cdcchart-BWVIUcAF.es.js +0 -4802
- package/src/_stories/Chart.Sankey.smoke.stories.tsx +0 -62
- package/src/components/Sankey/components/ColumnList.tsx +0 -19
- package/src/components/Sankey/helpers/getSankeyTooltip.tsx +0 -34
- package/src/components/Sankey/useSankeyAlert.tsx +0 -60
- package/src/data/legacy-defaults.ts +0 -18
- package/src/helpers/ensureSpecialChartAxisTypes.ts +0 -11
- package/src/helpers/tests/ensureSpecialChartAxisTypes.test.ts +0 -30
|
@@ -0,0 +1,681 @@
|
|
|
1
|
+
import type { Meta, StoryObj } from '@storybook/react-vite'
|
|
2
|
+
import { expect, userEvent, within } from 'storybook/test'
|
|
3
|
+
import {
|
|
4
|
+
assertVisualizationRendered,
|
|
5
|
+
performAndAssert,
|
|
6
|
+
waitForAbsence,
|
|
7
|
+
waitForEditor,
|
|
8
|
+
waitForPresence
|
|
9
|
+
} from '@cdc/core/helpers/testing'
|
|
10
|
+
|
|
11
|
+
import Chart from '../CdcChartComponent'
|
|
12
|
+
import dendrogramConfig from '../../examples/dendrogram.json'
|
|
13
|
+
import deviationBarConfig from '../../examples/feature/deviation/planet-deviation-config.json'
|
|
14
|
+
import forestPlotConfig from '../../examples/feature/forest-plot/forest-plot.json'
|
|
15
|
+
import networkConfig from '../../examples/network.json'
|
|
16
|
+
import radarConfig from '../../examples/radar-chart-simple.json'
|
|
17
|
+
import heatMapConfig from './_mock/heatmap-average-age-categorical.json'
|
|
18
|
+
import lollipopConfig from './_mock/lollipop.json'
|
|
19
|
+
import pairedBarConfig from './_mock/paired-bar.json'
|
|
20
|
+
import pieConfig from './_mock/pie_config.json'
|
|
21
|
+
import sankeyConfig from './_mock/sankey_mock.json'
|
|
22
|
+
import scatterPlotConfig from './_mock/scatterplot_mock.json'
|
|
23
|
+
|
|
24
|
+
const meta: Meta<typeof Chart> = {
|
|
25
|
+
title: 'Components/Templates/Chart/Required Fields',
|
|
26
|
+
component: Chart
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
type Story = StoryObj<typeof Chart>
|
|
30
|
+
|
|
31
|
+
const getRequiredAlertText = (canvasElement: HTMLElement) =>
|
|
32
|
+
Array.from(canvasElement.querySelectorAll('.chart-required-fields-alerts .alert-info'))
|
|
33
|
+
.map(alert => alert.textContent?.trim() || '')
|
|
34
|
+
.join(' ')
|
|
35
|
+
|
|
36
|
+
const expectStructuredRequiredFields = (
|
|
37
|
+
canvasElement: HTMLElement,
|
|
38
|
+
expectedFields: Array<{ section: string; field: string }>
|
|
39
|
+
) => {
|
|
40
|
+
const alerts = Array.from(canvasElement.querySelectorAll('.chart-required-fields-alerts .alert-info'))
|
|
41
|
+
expect(alerts).toHaveLength(expectedFields.length)
|
|
42
|
+
expectedFields.forEach(({ section, field }, index) => {
|
|
43
|
+
expect(alerts[index]).toHaveTextContent(`Missing field: ${field}. More information`)
|
|
44
|
+
expect(
|
|
45
|
+
within(alerts[index] as HTMLElement).getByRole('button', {
|
|
46
|
+
name: `Open ${section} and focus ${field}`
|
|
47
|
+
})
|
|
48
|
+
).toBeVisible()
|
|
49
|
+
})
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
const assertAlertNavigates = async (
|
|
53
|
+
canvasElement: HTMLElement,
|
|
54
|
+
section: string,
|
|
55
|
+
field: string,
|
|
56
|
+
target: string,
|
|
57
|
+
sectionTarget = target
|
|
58
|
+
) => {
|
|
59
|
+
const canvas = within(canvasElement)
|
|
60
|
+
const link = canvas.getByRole('button', { name: `Open ${section} and focus ${field}` })
|
|
61
|
+
|
|
62
|
+
await performAndAssert(
|
|
63
|
+
`The ${field} alert opens its editor section and focuses the field`,
|
|
64
|
+
() => ({
|
|
65
|
+
expanded:
|
|
66
|
+
canvasElement
|
|
67
|
+
.querySelector(`[data-required-field-section="${sectionTarget}"]`)
|
|
68
|
+
?.getAttribute('aria-expanded') === 'true',
|
|
69
|
+
focused: document.activeElement?.getAttribute('data-required-field-control'),
|
|
70
|
+
panelVisible: !canvasElement.querySelector('.editor-panel__toggle.collapsed')
|
|
71
|
+
}),
|
|
72
|
+
async () => userEvent.click(link),
|
|
73
|
+
(_before, after) => after.expanded && after.focused === target && after.panelVisible
|
|
74
|
+
)
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
export const CompletesDataSeries: Story = {
|
|
78
|
+
args: {
|
|
79
|
+
config: {
|
|
80
|
+
...scatterPlotConfig,
|
|
81
|
+
newViz: true,
|
|
82
|
+
series: [],
|
|
83
|
+
xAxis: { ...scatterPlotConfig.xAxis, dataKey: '' }
|
|
84
|
+
},
|
|
85
|
+
isEditor: true
|
|
86
|
+
},
|
|
87
|
+
play: async ({ canvasElement }) => {
|
|
88
|
+
const canvas = within(canvasElement)
|
|
89
|
+
await waitForEditor(canvas)
|
|
90
|
+
await waitForPresence('.alert-info', canvasElement)
|
|
91
|
+
|
|
92
|
+
expectStructuredRequiredFields(canvasElement, [
|
|
93
|
+
{ section: 'Data Series', field: 'Add Data Series' },
|
|
94
|
+
{ section: 'Date/Category Axis', field: 'Data Key' }
|
|
95
|
+
])
|
|
96
|
+
expect(canvasElement.querySelector('.cove-visualization__body')).toBeNull()
|
|
97
|
+
expect(canvas.queryByText("I'm Done")).not.toBeInTheDocument()
|
|
98
|
+
expect(canvasElement.querySelector('.alert-info button[aria-label="Close"]')).toBeNull()
|
|
99
|
+
|
|
100
|
+
await assertAlertNavigates(canvasElement, 'Data Series', 'Add Data Series', 'data-series')
|
|
101
|
+
|
|
102
|
+
const seriesSelect = canvasElement.querySelector('[data-required-field-control="data-series"]') as HTMLSelectElement
|
|
103
|
+
await performAndAssert(
|
|
104
|
+
'Completing the series requirement leaves only the category-axis alert',
|
|
105
|
+
() => getRequiredAlertText(canvasElement),
|
|
106
|
+
async () => userEvent.selectOptions(seriesSelect, 'y1'),
|
|
107
|
+
(before, after) =>
|
|
108
|
+
before.includes('Add Data Series') &&
|
|
109
|
+
before.includes('Data Key') &&
|
|
110
|
+
!after.includes('Add Data Series') &&
|
|
111
|
+
after.includes('Data Key')
|
|
112
|
+
)
|
|
113
|
+
expectStructuredRequiredFields(canvasElement, [{ section: 'Date/Category Axis', field: 'Data Key' }])
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
export const CompletesCategoryAxis: Story = {
|
|
118
|
+
args: {
|
|
119
|
+
config: {
|
|
120
|
+
...scatterPlotConfig,
|
|
121
|
+
newViz: true,
|
|
122
|
+
series: scatterPlotConfig.series.map(series => ({ ...series })),
|
|
123
|
+
xAxis: { ...scatterPlotConfig.xAxis, dataKey: '' }
|
|
124
|
+
},
|
|
125
|
+
isEditor: true
|
|
126
|
+
},
|
|
127
|
+
play: async ({ canvasElement }) => {
|
|
128
|
+
const canvas = within(canvasElement)
|
|
129
|
+
await waitForEditor(canvas)
|
|
130
|
+
await waitForPresence('.alert-info', canvasElement)
|
|
131
|
+
|
|
132
|
+
expectStructuredRequiredFields(canvasElement, [{ section: 'Date/Category Axis', field: 'Data Key' }])
|
|
133
|
+
await userEvent.click(canvas.getByTitle('Collapse Editor'))
|
|
134
|
+
expect(canvas.getByTitle('Expand Editor')).toBeVisible()
|
|
135
|
+
await assertAlertNavigates(canvasElement, 'Date/Category Axis', 'Data Key', 'date-category-axis')
|
|
136
|
+
|
|
137
|
+
const dataKeySelect = canvasElement.querySelector(
|
|
138
|
+
'[data-required-field-control="date-category-axis"]'
|
|
139
|
+
) as HTMLSelectElement
|
|
140
|
+
await performAndAssert(
|
|
141
|
+
'Completing the final requirement renders the chart automatically',
|
|
142
|
+
() => ({
|
|
143
|
+
alert: getRequiredAlertText(canvasElement),
|
|
144
|
+
hasChart: Boolean(canvasElement.querySelector('.tooltip-boundary svg[role="img"], svg.linear'))
|
|
145
|
+
}),
|
|
146
|
+
async () => userEvent.selectOptions(dataKeySelect, 'x'),
|
|
147
|
+
(before, after) => Boolean(before.alert) && !after.alert && after.hasChart
|
|
148
|
+
)
|
|
149
|
+
|
|
150
|
+
await assertVisualizationRendered(canvasElement)
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
export const PieDataColumnRequired: Story = {
|
|
155
|
+
args: {
|
|
156
|
+
config: {
|
|
157
|
+
...pieConfig,
|
|
158
|
+
yAxis: { ...pieConfig.yAxis, dataKey: '' },
|
|
159
|
+
xAxis: { ...pieConfig.xAxis }
|
|
160
|
+
},
|
|
161
|
+
isEditor: true
|
|
162
|
+
},
|
|
163
|
+
play: async ({ canvasElement }) => {
|
|
164
|
+
await waitForPresence('.alert-info', canvasElement)
|
|
165
|
+
expectStructuredRequiredFields(canvasElement, [{ section: 'Data Format', field: 'Data Column' }])
|
|
166
|
+
await assertAlertNavigates(canvasElement, 'Data Format', 'Data Column', 'pie-data-column')
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
export const PieSegmentLabelsRequired: Story = {
|
|
171
|
+
args: {
|
|
172
|
+
config: {
|
|
173
|
+
...pieConfig,
|
|
174
|
+
yAxis: { ...pieConfig.yAxis },
|
|
175
|
+
xAxis: { ...pieConfig.xAxis, dataKey: '' }
|
|
176
|
+
},
|
|
177
|
+
isEditor: true
|
|
178
|
+
},
|
|
179
|
+
play: async ({ canvasElement }) => {
|
|
180
|
+
await waitForPresence('.alert-info', canvasElement)
|
|
181
|
+
expectStructuredRequiredFields(canvasElement, [{ section: 'Segments', field: 'Segment Labels' }])
|
|
182
|
+
await assertAlertNavigates(canvasElement, 'Segments', 'Segment Labels', 'pie-segments')
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
export const HeatMapRequiredFields: Story = {
|
|
187
|
+
args: {
|
|
188
|
+
config: {
|
|
189
|
+
...heatMapConfig,
|
|
190
|
+
series: [],
|
|
191
|
+
xAxis: { ...heatMapConfig.xAxis, dataKey: '' }
|
|
192
|
+
},
|
|
193
|
+
isEditor: true
|
|
194
|
+
},
|
|
195
|
+
play: async ({ canvasElement }) => {
|
|
196
|
+
await waitForPresence('.alert-info', canvasElement)
|
|
197
|
+
expectStructuredRequiredFields(canvasElement, [
|
|
198
|
+
{ section: 'Data Series', field: 'Add Data Series' },
|
|
199
|
+
{ section: 'Date/Category Axis', field: 'Data Key' }
|
|
200
|
+
])
|
|
201
|
+
expect(canvasElement.querySelector('.cove-visualization__body')).toBeNull()
|
|
202
|
+
}
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
export const HeatMapDataSeriesNavigation: Story = {
|
|
206
|
+
args: {
|
|
207
|
+
config: {
|
|
208
|
+
...heatMapConfig,
|
|
209
|
+
series: [],
|
|
210
|
+
xAxis: { ...heatMapConfig.xAxis }
|
|
211
|
+
},
|
|
212
|
+
isEditor: true
|
|
213
|
+
},
|
|
214
|
+
play: async ({ canvasElement }) => {
|
|
215
|
+
await waitForPresence('.alert-info', canvasElement)
|
|
216
|
+
expectStructuredRequiredFields(canvasElement, [{ section: 'Data Series', field: 'Add Data Series' }])
|
|
217
|
+
await assertAlertNavigates(canvasElement, 'Data Series', 'Add Data Series', 'data-series')
|
|
218
|
+
}
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
export const HeatMapCategoryAxisNavigation: Story = {
|
|
222
|
+
args: {
|
|
223
|
+
config: {
|
|
224
|
+
...heatMapConfig,
|
|
225
|
+
series: heatMapConfig.series.map(series => ({ ...series })),
|
|
226
|
+
xAxis: { ...heatMapConfig.xAxis, dataKey: '' }
|
|
227
|
+
},
|
|
228
|
+
isEditor: true
|
|
229
|
+
},
|
|
230
|
+
play: async ({ canvasElement }) => {
|
|
231
|
+
await waitForPresence('.alert-info', canvasElement)
|
|
232
|
+
expectStructuredRequiredFields(canvasElement, [{ section: 'Date/Category Axis', field: 'Data Key' }])
|
|
233
|
+
await assertAlertNavigates(canvasElement, 'Date/Category Axis', 'Data Key', 'date-category-axis')
|
|
234
|
+
}
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
export const RadarCategoryColumnRequired: Story = {
|
|
238
|
+
args: {
|
|
239
|
+
config: {
|
|
240
|
+
...radarConfig,
|
|
241
|
+
series: radarConfig.series.map(series => ({ ...series })),
|
|
242
|
+
xAxis: { ...radarConfig.xAxis, dataKey: '' }
|
|
243
|
+
},
|
|
244
|
+
isEditor: true
|
|
245
|
+
},
|
|
246
|
+
play: async ({ canvasElement }) => {
|
|
247
|
+
await waitForPresence('.alert-info', canvasElement)
|
|
248
|
+
const radarSettingsButton = canvasElement.querySelector('[data-required-field-section="radar-category"]')
|
|
249
|
+
expect(radarSettingsButton?.querySelector('.warning-icon')).toBeInTheDocument()
|
|
250
|
+
expectStructuredRequiredFields(canvasElement, [{ section: 'Radar Chart Settings', field: 'Category Column' }])
|
|
251
|
+
await assertAlertNavigates(canvasElement, 'Radar Chart Settings', 'Category Column', 'radar-category')
|
|
252
|
+
|
|
253
|
+
expect(radarConfig.series).toHaveLength(6)
|
|
254
|
+
const categorySelect = canvasElement.querySelector(
|
|
255
|
+
'[data-required-field-control="radar-category"]'
|
|
256
|
+
) as HTMLSelectElement
|
|
257
|
+
await performAndAssert(
|
|
258
|
+
'Selecting the sample category renders Radar without the existing minimum-dimensions error',
|
|
259
|
+
() => ({
|
|
260
|
+
hasRadar: Boolean(canvasElement.querySelector('svg.radar-chart')),
|
|
261
|
+
hasDimensionsError: canvasElement.textContent?.includes('Radar chart requires at least 3 dimensions'),
|
|
262
|
+
hasWarningIcon: Boolean(radarSettingsButton?.querySelector('.warning-icon'))
|
|
263
|
+
}),
|
|
264
|
+
async () => userEvent.selectOptions(categorySelect, 'Program'),
|
|
265
|
+
(_before, after) => after.hasRadar && !after.hasDimensionsError && !after.hasWarningIcon
|
|
266
|
+
)
|
|
267
|
+
}
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
export const RadarMinimumDataSeriesRequired: Story = {
|
|
271
|
+
args: {
|
|
272
|
+
config: {
|
|
273
|
+
...radarConfig,
|
|
274
|
+
series: radarConfig.series.slice(0, 2).map(series => ({ ...series })),
|
|
275
|
+
xAxis: { ...radarConfig.xAxis }
|
|
276
|
+
},
|
|
277
|
+
isEditor: true
|
|
278
|
+
},
|
|
279
|
+
play: async ({ canvasElement }) => {
|
|
280
|
+
await waitForPresence('.alert-info', canvasElement)
|
|
281
|
+
const dataSeriesButton = canvasElement.querySelector('[data-required-field-section="data-series"]')
|
|
282
|
+
expect(dataSeriesButton?.querySelector('.warning-icon')).toBeInTheDocument()
|
|
283
|
+
expectStructuredRequiredFields(canvasElement, [{ section: 'Data Series', field: 'At Least 3 Data Series' }])
|
|
284
|
+
await assertAlertNavigates(canvasElement, 'Data Series', 'At Least 3 Data Series', 'data-series')
|
|
285
|
+
expect(canvasElement.querySelector('.radar-chart-error')).toBeNull()
|
|
286
|
+
}
|
|
287
|
+
}
|
|
288
|
+
|
|
289
|
+
export const RadarRuntimeKeepsExistingMinimumDimensionsError: Story = {
|
|
290
|
+
args: {
|
|
291
|
+
config: {
|
|
292
|
+
...radarConfig,
|
|
293
|
+
series: radarConfig.series.slice(0, 2).map(series => ({ ...series })),
|
|
294
|
+
xAxis: { ...radarConfig.xAxis }
|
|
295
|
+
},
|
|
296
|
+
isEditor: false
|
|
297
|
+
},
|
|
298
|
+
play: async ({ canvasElement }) => {
|
|
299
|
+
await waitForPresence('.radar-chart-error', canvasElement)
|
|
300
|
+
expect(canvasElement).toHaveTextContent(
|
|
301
|
+
'Radar chart requires at least 3 dimensions. Please add more series in the configuration.'
|
|
302
|
+
)
|
|
303
|
+
expect(canvasElement.querySelector('.alert-info')).toBeNull()
|
|
304
|
+
}
|
|
305
|
+
}
|
|
306
|
+
|
|
307
|
+
export const LollipopExactlyOneSeriesRequired: Story = {
|
|
308
|
+
args: {
|
|
309
|
+
config: {
|
|
310
|
+
...lollipopConfig,
|
|
311
|
+
series: [
|
|
312
|
+
...lollipopConfig.series.map(series => ({ ...series })),
|
|
313
|
+
{ ...lollipopConfig.series[0], dataKey: 'Vehicle' }
|
|
314
|
+
]
|
|
315
|
+
},
|
|
316
|
+
isEditor: true
|
|
317
|
+
},
|
|
318
|
+
play: async ({ canvasElement }) => {
|
|
319
|
+
await waitForEditor(within(canvasElement))
|
|
320
|
+
await waitForPresence('.alert-info', canvasElement)
|
|
321
|
+
|
|
322
|
+
const dataSeriesButton = canvasElement.querySelector('[data-required-field-section="data-series"]')
|
|
323
|
+
expect(dataSeriesButton?.querySelector('.warning-icon')).toBeInTheDocument()
|
|
324
|
+
expectStructuredRequiredFields(canvasElement, [{ section: 'Data Series', field: 'Exactly 1 Data Series' }])
|
|
325
|
+
await assertAlertNavigates(canvasElement, 'Data Series', 'Exactly 1 Data Series', 'data-series')
|
|
326
|
+
expect(canvasElement).toHaveTextContent('Select exactly one data series for a lollipop chart.')
|
|
327
|
+
}
|
|
328
|
+
}
|
|
329
|
+
|
|
330
|
+
export const PairedBarExactlyTwoSeriesRequired: Story = {
|
|
331
|
+
args: {
|
|
332
|
+
config: {
|
|
333
|
+
...pairedBarConfig,
|
|
334
|
+
series: [
|
|
335
|
+
...pairedBarConfig.series.map(series => ({ ...series })),
|
|
336
|
+
{ ...pairedBarConfig.series[0], dataKey: 'Additional Series' }
|
|
337
|
+
]
|
|
338
|
+
},
|
|
339
|
+
isEditor: true
|
|
340
|
+
},
|
|
341
|
+
play: async ({ canvasElement }) => {
|
|
342
|
+
await waitForEditor(within(canvasElement))
|
|
343
|
+
await waitForPresence('.alert-info', canvasElement)
|
|
344
|
+
|
|
345
|
+
const dataSeriesButton = canvasElement.querySelector('[data-required-field-section="data-series"]')
|
|
346
|
+
expect(dataSeriesButton?.querySelector('.warning-icon')).toBeInTheDocument()
|
|
347
|
+
expectStructuredRequiredFields(canvasElement, [{ section: 'Data Series', field: 'Exactly 2 Data Series' }])
|
|
348
|
+
await assertAlertNavigates(canvasElement, 'Data Series', 'Exactly 2 Data Series', 'data-series')
|
|
349
|
+
expect(canvasElement).toHaveTextContent('Select two data series for paired bar chart (e.g., Male and Female).')
|
|
350
|
+
}
|
|
351
|
+
}
|
|
352
|
+
|
|
353
|
+
export const DeviationBarExactlyOneSeriesRequired: Story = {
|
|
354
|
+
args: {
|
|
355
|
+
config: {
|
|
356
|
+
...deviationBarConfig,
|
|
357
|
+
dataUrl: '',
|
|
358
|
+
data: [
|
|
359
|
+
{ name: 'Mercury', Radius: 2440, Diameter: 4880 },
|
|
360
|
+
{ name: 'Earth', Radius: 6371, Diameter: 12742 }
|
|
361
|
+
],
|
|
362
|
+
series: [
|
|
363
|
+
...deviationBarConfig.series.map(series => ({ ...series })),
|
|
364
|
+
{ ...deviationBarConfig.series[0], dataKey: 'Diameter' }
|
|
365
|
+
]
|
|
366
|
+
},
|
|
367
|
+
isEditor: true
|
|
368
|
+
},
|
|
369
|
+
play: async ({ canvasElement }) => {
|
|
370
|
+
await waitForEditor(within(canvasElement))
|
|
371
|
+
await waitForPresence('.alert-info', canvasElement)
|
|
372
|
+
|
|
373
|
+
const dataSeriesButton = canvasElement.querySelector('[data-required-field-section="data-series"]')
|
|
374
|
+
expect(dataSeriesButton?.querySelector('.warning-icon')).toBeInTheDocument()
|
|
375
|
+
expectStructuredRequiredFields(canvasElement, [{ section: 'Data Series', field: 'Exactly 1 Data Series' }])
|
|
376
|
+
await assertAlertNavigates(canvasElement, 'Data Series', 'Exactly 1 Data Series', 'data-series')
|
|
377
|
+
expect(canvasElement).toHaveTextContent('Select exactly one data series for a deviation bar chart.')
|
|
378
|
+
}
|
|
379
|
+
}
|
|
380
|
+
|
|
381
|
+
export const ForestPlotRequiredFields: Story = {
|
|
382
|
+
args: {
|
|
383
|
+
config: {
|
|
384
|
+
...forestPlotConfig,
|
|
385
|
+
xAxis: { ...forestPlotConfig.xAxis, dataKey: '' },
|
|
386
|
+
forestPlot: {
|
|
387
|
+
...forestPlotConfig.forestPlot,
|
|
388
|
+
type: '',
|
|
389
|
+
estimateField: '',
|
|
390
|
+
lower: '',
|
|
391
|
+
upper: ''
|
|
392
|
+
}
|
|
393
|
+
},
|
|
394
|
+
isEditor: true
|
|
395
|
+
},
|
|
396
|
+
play: async ({ canvasElement }) => {
|
|
397
|
+
await waitForEditor(within(canvasElement))
|
|
398
|
+
await waitForPresence('.alert-info', canvasElement)
|
|
399
|
+
|
|
400
|
+
const forestPlotButton = canvasElement.querySelector('[data-required-field-section="forest-plot-settings"]')
|
|
401
|
+
expect(forestPlotButton?.querySelector('.warning-icon')).toBeInTheDocument()
|
|
402
|
+
expectStructuredRequiredFields(canvasElement, [
|
|
403
|
+
{ section: 'Forest Plot Settings', field: 'Study Column' },
|
|
404
|
+
{ section: 'Forest Plot Settings', field: 'Forest Plot Type' },
|
|
405
|
+
{ section: 'Forest Plot Settings', field: 'Point Estimate Column' },
|
|
406
|
+
{ section: 'Forest Plot Settings', field: 'Lower CI Column' },
|
|
407
|
+
{ section: 'Forest Plot Settings', field: 'Upper CI Column' }
|
|
408
|
+
])
|
|
409
|
+
|
|
410
|
+
await assertAlertNavigates(
|
|
411
|
+
canvasElement,
|
|
412
|
+
'Forest Plot Settings',
|
|
413
|
+
'Study Column',
|
|
414
|
+
'forest-study',
|
|
415
|
+
'forest-plot-settings'
|
|
416
|
+
)
|
|
417
|
+
await assertAlertNavigates(
|
|
418
|
+
canvasElement,
|
|
419
|
+
'Forest Plot Settings',
|
|
420
|
+
'Forest Plot Type',
|
|
421
|
+
'forest-type',
|
|
422
|
+
'forest-plot-settings'
|
|
423
|
+
)
|
|
424
|
+
await assertAlertNavigates(
|
|
425
|
+
canvasElement,
|
|
426
|
+
'Forest Plot Settings',
|
|
427
|
+
'Point Estimate Column',
|
|
428
|
+
'forest-estimate',
|
|
429
|
+
'forest-plot-settings'
|
|
430
|
+
)
|
|
431
|
+
await assertAlertNavigates(
|
|
432
|
+
canvasElement,
|
|
433
|
+
'Forest Plot Settings',
|
|
434
|
+
'Lower CI Column',
|
|
435
|
+
'forest-lower',
|
|
436
|
+
'forest-plot-settings'
|
|
437
|
+
)
|
|
438
|
+
await assertAlertNavigates(
|
|
439
|
+
canvasElement,
|
|
440
|
+
'Forest Plot Settings',
|
|
441
|
+
'Upper CI Column',
|
|
442
|
+
'forest-upper',
|
|
443
|
+
'forest-plot-settings'
|
|
444
|
+
)
|
|
445
|
+
}
|
|
446
|
+
}
|
|
447
|
+
|
|
448
|
+
export const SankeyRequiredColumns: Story = {
|
|
449
|
+
args: {
|
|
450
|
+
config: {
|
|
451
|
+
...sankeyConfig,
|
|
452
|
+
sankey: { ...sankeyConfig.sankey, columns: { source: 'source', target: 'target', value: 'value' } }
|
|
453
|
+
},
|
|
454
|
+
isEditor: true
|
|
455
|
+
},
|
|
456
|
+
play: async ({ canvasElement }) => {
|
|
457
|
+
await waitForEditor(within(canvasElement))
|
|
458
|
+
await waitForPresence('.alert-info', canvasElement)
|
|
459
|
+
|
|
460
|
+
const sankeyButton = canvasElement.querySelector('[data-required-field-section="sankey-columns"]')
|
|
461
|
+
expect(sankeyButton?.querySelector('.warning-icon')).toBeInTheDocument()
|
|
462
|
+
expectStructuredRequiredFields(canvasElement, [
|
|
463
|
+
{ section: 'Sankey', field: 'Source Column' },
|
|
464
|
+
{ section: 'Sankey', field: 'Target Column' },
|
|
465
|
+
{ section: 'Sankey', field: 'Value Column' }
|
|
466
|
+
])
|
|
467
|
+
|
|
468
|
+
await assertAlertNavigates(canvasElement, 'Sankey', 'Source Column', 'sankey-source', 'sankey-columns')
|
|
469
|
+
await assertAlertNavigates(canvasElement, 'Sankey', 'Target Column', 'sankey-target', 'sankey-columns')
|
|
470
|
+
await assertAlertNavigates(canvasElement, 'Sankey', 'Value Column', 'sankey-value', 'sankey-columns')
|
|
471
|
+
}
|
|
472
|
+
}
|
|
473
|
+
|
|
474
|
+
export const SankeyCompletesRequiredColumns: Story = {
|
|
475
|
+
args: {
|
|
476
|
+
config: {
|
|
477
|
+
...sankeyConfig,
|
|
478
|
+
sankey: { ...sankeyConfig.sankey, columns: { source: 'source', target: 'target', value: 'value' } }
|
|
479
|
+
},
|
|
480
|
+
isEditor: true
|
|
481
|
+
},
|
|
482
|
+
play: async ({ canvasElement }) => {
|
|
483
|
+
await waitForEditor(within(canvasElement))
|
|
484
|
+
await waitForPresence('.alert-info', canvasElement)
|
|
485
|
+
const sankeyButton = canvasElement.querySelector('[data-required-field-section="sankey-columns"]')
|
|
486
|
+
|
|
487
|
+
await performAndAssert(
|
|
488
|
+
'Completing the Sankey mappings clears the guidance and renders the diagram',
|
|
489
|
+
() => ({
|
|
490
|
+
alertCount: canvasElement.querySelectorAll('.chart-required-fields-alerts .alert-info').length,
|
|
491
|
+
hasWarningIcon: Boolean(sankeyButton?.querySelector('.warning-icon')),
|
|
492
|
+
hasDiagram: Boolean(canvasElement.querySelector('.sankey-chart__diagram'))
|
|
493
|
+
}),
|
|
494
|
+
async () => {
|
|
495
|
+
await userEvent.selectOptions(
|
|
496
|
+
canvasElement.querySelector('[data-required-field-control="sankey-source"]') as HTMLSelectElement,
|
|
497
|
+
'example_source'
|
|
498
|
+
)
|
|
499
|
+
await userEvent.selectOptions(
|
|
500
|
+
canvasElement.querySelector('[data-required-field-control="sankey-target"]') as HTMLSelectElement,
|
|
501
|
+
'example_target'
|
|
502
|
+
)
|
|
503
|
+
await userEvent.selectOptions(
|
|
504
|
+
canvasElement.querySelector('[data-required-field-control="sankey-value"]') as HTMLSelectElement,
|
|
505
|
+
'example_value'
|
|
506
|
+
)
|
|
507
|
+
},
|
|
508
|
+
(before, after) =>
|
|
509
|
+
before.alertCount === 3 &&
|
|
510
|
+
before.hasWarningIcon &&
|
|
511
|
+
after.alertCount === 0 &&
|
|
512
|
+
!after.hasWarningIcon &&
|
|
513
|
+
after.hasDiagram
|
|
514
|
+
)
|
|
515
|
+
}
|
|
516
|
+
}
|
|
517
|
+
|
|
518
|
+
export const SankeyRuntimeKeepsExistingEmptyState: Story = {
|
|
519
|
+
args: {
|
|
520
|
+
config: {
|
|
521
|
+
...sankeyConfig,
|
|
522
|
+
sankey: { ...sankeyConfig.sankey, columns: { source: 'source', target: 'target', value: 'value' } }
|
|
523
|
+
},
|
|
524
|
+
isEditor: false
|
|
525
|
+
},
|
|
526
|
+
play: async ({ canvasElement }) => {
|
|
527
|
+
await waitForPresence('.sankey-chart--empty', canvasElement)
|
|
528
|
+
expect(canvasElement.querySelector('.alert-info')).toBeNull()
|
|
529
|
+
}
|
|
530
|
+
}
|
|
531
|
+
|
|
532
|
+
export const NetworkRequiredFields: Story = {
|
|
533
|
+
args: {
|
|
534
|
+
config: {
|
|
535
|
+
...networkConfig,
|
|
536
|
+
network: { ...networkConfig.network, columns: { ...networkConfig.network.columns, source: 'from', target: 'to' } }
|
|
537
|
+
},
|
|
538
|
+
isEditor: true
|
|
539
|
+
},
|
|
540
|
+
play: async ({ canvasElement }) => {
|
|
541
|
+
await waitForEditor(within(canvasElement))
|
|
542
|
+
await waitForPresence('.alert-info', canvasElement)
|
|
543
|
+
|
|
544
|
+
const networkButton = canvasElement.querySelector('[data-required-field-section="network-columns"]')
|
|
545
|
+
expect(networkButton?.querySelector('.warning-icon')).toBeInTheDocument()
|
|
546
|
+
expectStructuredRequiredFields(canvasElement, [
|
|
547
|
+
{ section: 'Network', field: 'Source Column' },
|
|
548
|
+
{ section: 'Network', field: 'Target Column' }
|
|
549
|
+
])
|
|
550
|
+
|
|
551
|
+
await assertAlertNavigates(canvasElement, 'Network', 'Source Column', 'network-source', 'network-columns')
|
|
552
|
+
await assertAlertNavigates(canvasElement, 'Network', 'Target Column', 'network-target', 'network-columns')
|
|
553
|
+
|
|
554
|
+
await performAndAssert(
|
|
555
|
+
'Completing the Network mappings clears the guidance and renders the graph',
|
|
556
|
+
() => ({
|
|
557
|
+
alertCount: canvasElement.querySelectorAll('.chart-required-fields-alerts .alert-info').length,
|
|
558
|
+
hasWarningIcon: Boolean(networkButton?.querySelector('.warning-icon')),
|
|
559
|
+
hasGraph: Boolean(canvasElement.querySelector('.network-chart'))
|
|
560
|
+
}),
|
|
561
|
+
async () => {
|
|
562
|
+
await userEvent.selectOptions(
|
|
563
|
+
canvasElement.querySelector('[data-required-field-control="network-source"]') as HTMLSelectElement,
|
|
564
|
+
'source'
|
|
565
|
+
)
|
|
566
|
+
await userEvent.selectOptions(
|
|
567
|
+
canvasElement.querySelector('[data-required-field-control="network-target"]') as HTMLSelectElement,
|
|
568
|
+
'target'
|
|
569
|
+
)
|
|
570
|
+
},
|
|
571
|
+
(before, after) =>
|
|
572
|
+
before.alertCount === 2 &&
|
|
573
|
+
before.hasWarningIcon &&
|
|
574
|
+
after.alertCount === 0 &&
|
|
575
|
+
!after.hasWarningIcon &&
|
|
576
|
+
after.hasGraph
|
|
577
|
+
)
|
|
578
|
+
}
|
|
579
|
+
}
|
|
580
|
+
|
|
581
|
+
export const DendrogramRequiredFields: Story = {
|
|
582
|
+
args: {
|
|
583
|
+
config: {
|
|
584
|
+
...dendrogramConfig,
|
|
585
|
+
data: [
|
|
586
|
+
{ id: 'Public Health', parentId: '' },
|
|
587
|
+
{ id: 'Programs', parentId: 'Public Health' },
|
|
588
|
+
{ id: 'Clinics', parentId: 'Programs' }
|
|
589
|
+
],
|
|
590
|
+
dendrogram: {
|
|
591
|
+
...dendrogramConfig.dendrogram,
|
|
592
|
+
columns: { node: 'node', parent: 'parent' }
|
|
593
|
+
}
|
|
594
|
+
},
|
|
595
|
+
isEditor: true
|
|
596
|
+
},
|
|
597
|
+
play: async ({ canvasElement }) => {
|
|
598
|
+
await waitForEditor(within(canvasElement))
|
|
599
|
+
await waitForPresence('.alert-info', canvasElement)
|
|
600
|
+
|
|
601
|
+
const dendrogramButton = canvasElement.querySelector('[data-required-field-section="dendrogram-columns"]')
|
|
602
|
+
expect(dendrogramButton?.querySelector('.warning-icon')).toBeInTheDocument()
|
|
603
|
+
expectStructuredRequiredFields(canvasElement, [
|
|
604
|
+
{ section: 'Dendrogram', field: 'Node ID Column' },
|
|
605
|
+
{ section: 'Dendrogram', field: 'Parent ID Column' }
|
|
606
|
+
])
|
|
607
|
+
expect(canvasElement.querySelector('.dendrogram-chart')).toBeNull()
|
|
608
|
+
|
|
609
|
+
await assertAlertNavigates(canvasElement, 'Dendrogram', 'Node ID Column', 'dendrogram-node', 'dendrogram-columns')
|
|
610
|
+
await assertAlertNavigates(
|
|
611
|
+
canvasElement,
|
|
612
|
+
'Dendrogram',
|
|
613
|
+
'Parent ID Column',
|
|
614
|
+
'dendrogram-parent',
|
|
615
|
+
'dendrogram-columns'
|
|
616
|
+
)
|
|
617
|
+
|
|
618
|
+
await performAndAssert(
|
|
619
|
+
'Completing the Node ID mapping leaves only the Parent ID requirement',
|
|
620
|
+
() => ({
|
|
621
|
+
alertText: getRequiredAlertText(canvasElement),
|
|
622
|
+
hasWarningIcon: Boolean(dendrogramButton?.querySelector('.warning-icon')),
|
|
623
|
+
hasDendrogram: Boolean(canvasElement.querySelector('.dendrogram-chart'))
|
|
624
|
+
}),
|
|
625
|
+
async () =>
|
|
626
|
+
userEvent.selectOptions(
|
|
627
|
+
canvasElement.querySelector('[data-required-field-control="dendrogram-node"]') as HTMLSelectElement,
|
|
628
|
+
'id'
|
|
629
|
+
),
|
|
630
|
+
(before, after) =>
|
|
631
|
+
before.alertText.includes('Node ID Column') &&
|
|
632
|
+
before.alertText.includes('Parent ID Column') &&
|
|
633
|
+
!after.alertText.includes('Node ID Column') &&
|
|
634
|
+
after.alertText.includes('Parent ID Column') &&
|
|
635
|
+
after.hasWarningIcon &&
|
|
636
|
+
!after.hasDendrogram
|
|
637
|
+
)
|
|
638
|
+
|
|
639
|
+
expectStructuredRequiredFields(canvasElement, [{ section: 'Dendrogram', field: 'Parent ID Column' }])
|
|
640
|
+
|
|
641
|
+
await performAndAssert(
|
|
642
|
+
'Completing both Dendrogram mappings clears the guidance and renders the diagram',
|
|
643
|
+
() => ({
|
|
644
|
+
alertCount: canvasElement.querySelectorAll('.chart-required-fields-alerts .alert-info').length,
|
|
645
|
+
hasWarningIcon: Boolean(dendrogramButton?.querySelector('.warning-icon')),
|
|
646
|
+
hasDendrogram: Boolean(canvasElement.querySelector('.dendrogram-chart'))
|
|
647
|
+
}),
|
|
648
|
+
async () =>
|
|
649
|
+
userEvent.selectOptions(
|
|
650
|
+
canvasElement.querySelector('[data-required-field-control="dendrogram-parent"]') as HTMLSelectElement,
|
|
651
|
+
'parentId'
|
|
652
|
+
),
|
|
653
|
+
(before, after) =>
|
|
654
|
+
before.alertCount === 1 &&
|
|
655
|
+
before.hasWarningIcon &&
|
|
656
|
+
after.alertCount === 0 &&
|
|
657
|
+
!after.hasWarningIcon &&
|
|
658
|
+
after.hasDendrogram
|
|
659
|
+
)
|
|
660
|
+
|
|
661
|
+
await assertVisualizationRendered(canvasElement)
|
|
662
|
+
}
|
|
663
|
+
}
|
|
664
|
+
|
|
665
|
+
export const RuntimeDoesNotExposeDirections: Story = {
|
|
666
|
+
args: {
|
|
667
|
+
config: {
|
|
668
|
+
...scatterPlotConfig,
|
|
669
|
+
series: [],
|
|
670
|
+
xAxis: { ...scatterPlotConfig.xAxis, dataKey: '' }
|
|
671
|
+
},
|
|
672
|
+
isEditor: false
|
|
673
|
+
},
|
|
674
|
+
play: async ({ canvasElement }) => {
|
|
675
|
+
await waitForAbsence('.loading', canvasElement)
|
|
676
|
+
expect(canvasElement.querySelector('.alert-info')).toBeNull()
|
|
677
|
+
expect(canvasElement.querySelector('.tooltip-boundary svg[role="img"], svg.linear')).toBeNull()
|
|
678
|
+
}
|
|
679
|
+
}
|
|
680
|
+
|
|
681
|
+
export default meta
|