@cdc/core 4.25.11 → 4.26.2
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/.claude/agents/qa-test-developer.md +126 -0
- package/CLAUDE.local.md +67 -0
- package/_stories/Gallery.Charts.stories.tsx +300 -0
- package/_stories/Gallery.DataBite.stories.tsx +79 -0
- package/_stories/Gallery.Maps.stories.tsx +239 -0
- package/_stories/Gallery.WaffleChart.stories.tsx +187 -0
- package/_stories/PageART.stories.tsx +193 -0
- package/_stories/PageBRFSS.stories.tsx +294 -0
- package/_stories/PageCancerRegistries.stories.tsx +199 -0
- package/_stories/PageEasternEquineEncephalitis.stories.tsx +216 -0
- package/_stories/PageExcessiveAlcoholUse.stories.tsx +201 -0
- package/_stories/PageMaternalMortality.stories.tsx +193 -0
- package/_stories/PageOralHealth.stories.tsx +201 -0
- package/_stories/PageRespiratory.stories.tsx +332 -0
- package/_stories/PageSmokingTobacco.stories.tsx +200 -0
- package/_stories/PageStateDiabetesProfiles.stories.tsx +201 -0
- package/_stories/PageWastewater.stories.tsx +477 -0
- package/_stories/VegaImport.stories.tsx +401 -0
- package/_stories/vega-fixtures/bars-with-line.json +444 -0
- package/_stories/vega-fixtures/bars.json +58 -0
- package/_stories/vega-fixtures/combo-bar-rolling-mean.json +88 -0
- package/_stories/vega-fixtures/combo.json +68 -0
- package/_stories/vega-fixtures/grouped-horizontal-bars.json +83 -0
- package/_stories/vega-fixtures/grouped-horizontal-bars2.json +231 -0
- package/_stories/vega-fixtures/horizontal-bar.json +427 -0
- package/_stories/vega-fixtures/horizontal-bars-with-bad-colors.json +197 -0
- package/_stories/vega-fixtures/horizontal-bars2.json +58 -0
- package/_stories/vega-fixtures/lines.json +227 -0
- package/_stories/vega-fixtures/measles-bars.json +348 -0
- package/_stories/vega-fixtures/measles-map.json +11101 -0
- package/_stories/vega-fixtures/measles-stacked-bars.json +2147 -0
- package/_stories/vega-fixtures/multi-dataset.json +255 -0
- package/_stories/vega-fixtures/no-data.json +14 -0
- package/_stories/vega-fixtures/pie-chart.json +94 -0
- package/_stories/vega-fixtures/repeat-spec.json +47 -0
- package/_stories/vega-fixtures/stacked-area.json +222 -0
- package/_stories/vega-fixtures/stacked-bar-with-rect.json +3412 -0
- package/_stories/vega-fixtures/stacked-bars-with-line.json +364 -0
- package/_stories/vega-fixtures/stacked-bars.json +212 -0
- package/_stories/vega-fixtures/stacked-horizontal-bars.json +140 -0
- package/_stories/vega-fixtures/warning-combo.json +59 -0
- package/_stories/vega-fixtures/warning-scatter-and-line.json +1182 -0
- package/assets/icon-chart-area.svg +1 -0
- package/assets/icon-chart-radar.svg +23 -0
- package/assets/icon-magnifying-glass.svg +5 -0
- package/assets/icon-warming-stripes.svg +13 -0
- package/assets/logo2.svg +31 -0
- package/components/AdvancedEditor/AdvancedEditor.tsx +4 -0
- package/components/AdvancedEditor/EmbedEditor.tsx +513 -0
- package/components/ComboBox/ComboBox.tsx +345 -0
- package/components/ComboBox/combobox.styles.css +185 -0
- package/components/ComboBox/index.ts +1 -0
- package/components/CustomColorsEditor/CustomColorsEditor.tsx +3 -10
- package/components/DataTable/DataTable.tsx +132 -58
- package/components/DataTable/data-table.css +216 -215
- package/components/DataTable/helpers/getSeriesName.ts +6 -0
- package/components/DataTable/helpers/mapCellMatrix.tsx +14 -6
- package/components/EditorPanel/ColumnsEditor.tsx +37 -19
- package/components/EditorPanel/DataTableEditor.tsx +51 -25
- package/components/EditorPanel/EditorPanel.styles.css +16 -0
- package/components/EditorPanel/EditorPanel.tsx +144 -0
- package/components/EditorPanel/EditorPanelDispatch.tsx +75 -0
- package/components/EditorPanel/FieldSetWrapper.tsx +66 -23
- package/components/EditorPanel/Inputs.tsx +33 -7
- package/components/EditorPanel/VizFilterEditor/NestedDropdownEditor.tsx +14 -6
- package/components/EditorPanel/VizFilterEditor/VizFilterEditor.tsx +240 -175
- package/components/EditorPanel/VizFilterEditor/components/FilterOrder.tsx +33 -29
- package/components/EditorPanel/sections/VisualSection.tsx +169 -0
- package/components/Filters/Filters.tsx +31 -5
- package/components/Filters/helpers/getNestedOptions.ts +2 -1
- package/components/Filters/helpers/handleSorting.ts +1 -1
- package/components/Layout/components/Sidebar/components/sidebar.styles.scss +84 -2
- package/components/Layout/components/Visualization/index.tsx +27 -1
- package/components/Layout/components/Visualization/visualizations.scss +7 -0
- package/components/Legend/Legend.Gradient.tsx +1 -1
- package/components/MediaControls.tsx +53 -28
- package/components/_stories/CustomColorsEditor.stories.tsx +37 -0
- package/components/_stories/DataTable.stories.tsx +1 -0
- package/components/ui/Icon.tsx +3 -1
- package/components/ui/Title/index.tsx +30 -2
- package/components/ui/Title/title.styles.css +42 -0
- package/data/colorPalettes.ts +18 -5
- package/data/mapColorPalettes.ts +10 -0
- package/devTemplate/dev.js +235 -0
- package/devTemplate/index.html +30 -0
- package/devTemplate/preview.html +1503 -0
- package/devTemplate/sidebar.css +151 -0
- package/dist/cove-main.css +2803 -4448
- package/dist/cove-main.css.map +1 -1
- package/generateViteConfig.js +118 -2
- package/helpers/DataTransform.ts +1 -5
- package/helpers/addValuesToFilters.ts +6 -1
- package/helpers/cove/date.ts +33 -1
- package/helpers/cove/string.ts +29 -0
- package/helpers/coveUpdateWorker.ts +21 -12
- package/helpers/embed/embedCodeGenerator.ts +80 -0
- package/helpers/embed/embedHelper.js +158 -0
- package/helpers/embed/filterUtils.ts +121 -0
- package/helpers/embed/index.ts +21 -0
- package/helpers/embed/urlValidation.ts +119 -0
- package/helpers/filterVizData.ts +6 -1
- package/helpers/getFileExtension.ts +0 -6
- package/helpers/getUniqueValues.ts +19 -0
- package/helpers/hashObj.ts +25 -0
- package/helpers/isRightAlignedTableValue.js +5 -0
- package/helpers/metrics/helpers.ts +1 -0
- package/helpers/metrics/types.ts +3 -0
- package/helpers/palettes/colorDistributions.ts +1 -1
- package/helpers/palettes/utils.ts +12 -12
- package/helpers/parseCsvWithQuotes.ts +15 -14
- package/helpers/pivotData.ts +2 -2
- package/helpers/prepareScreenshot.ts +288 -0
- package/helpers/queryStringUtils.ts +29 -0
- package/helpers/testing.ts +44 -0
- package/helpers/tests/DataTransform.test.ts +125 -0
- package/helpers/tests/date.test.ts +64 -0
- package/helpers/tests/prepareScreenshot.test.ts +414 -0
- package/helpers/tests/queryStringUtils.test.ts +381 -0
- package/helpers/tests/testStandaloneBuild.ts +23 -5
- package/helpers/useDataVizClasses.ts +0 -1
- package/helpers/vegaConfig.ts +1 -1
- package/helpers/vegaConfigImport.ts +160 -0
- package/helpers/ver/4.26.1.ts +80 -0
- package/helpers/ver/4.26.2.ts +84 -0
- package/helpers/ver/tests/4.26.1.test.ts +105 -0
- package/helpers/ver/tests/4.26.2.test.ts +298 -0
- package/helpers/viewports.ts +2 -0
- package/hooks/useDataColumns.ts +63 -0
- package/hooks/useFilterManagement.ts +94 -0
- package/hooks/useLegendSeparators.ts +26 -0
- package/hooks/useListManagement.ts +192 -0
- package/package.json +29 -33
- package/styles/_button-section.scss +0 -3
- package/styles/v2/components/editor.scss +9 -9
- package/styles/v2/utils/_grid.scss +8 -3
- package/types/Annotation.ts +10 -11
- package/types/Axis.ts +1 -0
- package/types/ForecastingSeriesKey.ts +1 -0
- package/types/General.ts +2 -0
- package/types/MarkupInclude.ts +1 -0
- package/types/Palette.ts +21 -0
- package/types/Series.ts +3 -0
- package/types/Table.ts +1 -0
- package/types/Visualization.ts +7 -0
- package/types/VizFilter.ts +1 -0
- package/LICENSE +0 -201
- package/_stories/StoryRenderingTests.stories.tsx +0 -164
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: qa-test-developer
|
|
3
|
+
description: "Use this agent when you need to add, update, or improve test coverage for components and features. This includes writing unit tests with Vitest, creating Playwright integration tests within Storybook, and coordinating visual regression testing with Backstop. Trigger this agent after implementing new components, fixing bugs, or when test coverage needs improvement.\\n\\nExamples:\\n\\n<example>\\nContext: User has just implemented a new chart component.\\nuser: \"I just created a new PieChart component in the chart package\"\\nassistant: \"I can see the new PieChart component. Let me use the qa-test-developer agent to add comprehensive test coverage for it.\"\\n<Task tool invocation to launch qa-test-developer agent>\\n</example>\\n\\n<example>\\nContext: User wants to ensure a bug fix is properly tested.\\nuser: \"I fixed a bug in the data-table sorting logic\"\\nassistant: \"Great fix! I'll use the qa-test-developer agent to add tests that verify this bug won't regress and ensure the sorting behavior is well-covered.\"\\n<Task tool invocation to launch qa-test-developer agent>\\n</example>\\n\\n<example>\\nContext: User is asking for test coverage on existing code.\\nuser: \"Can you add tests for the Dashboard layout components?\"\\nassistant: \"I'll launch the qa-test-developer agent to analyze the Dashboard components and create comprehensive unit and integration tests.\"\\n<Task tool invocation to launch qa-test-developer agent>\\n</example>\\n\\n<example>\\nContext: Proactive usage after significant code changes detected.\\nassistant: \"I notice significant changes were made to the map visualization rendering logic. Let me use the qa-test-developer agent to ensure proper test coverage for these changes.\"\\n<Task tool invocation to launch qa-test-developer agent>\\n</example>"
|
|
4
|
+
model: sonnet
|
|
5
|
+
memory: project
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
You are an expert QA Developer specializing in React component testing within monorepo environments. You have deep expertise in Vitest for unit testing, Playwright for integration testing within Storybook, and visual regression testing with Backstop.js. Your goal is to create comprehensive, maintainable test suites that catch bugs early and document component behavior.
|
|
9
|
+
|
|
10
|
+
## Your Core Responsibilities
|
|
11
|
+
|
|
12
|
+
1. **Write Unit Tests with Vitest**
|
|
13
|
+
- Create tests in `*.test.{js,jsx,ts,tsx}` files alongside the components
|
|
14
|
+
- Use the jsdom environment configured in the project
|
|
15
|
+
- Import from `testing-setup.js` when DOM matchers are needed
|
|
16
|
+
- Test component rendering, props handling, state changes, and edge cases
|
|
17
|
+
- Mock external dependencies appropriately
|
|
18
|
+
- Follow the AAA pattern: Arrange, Act, Assert
|
|
19
|
+
- Aim for meaningful coverage, not just line coverage
|
|
20
|
+
|
|
21
|
+
2. **Create Playwright Integration Tests in Storybook**
|
|
22
|
+
- Write interaction tests using Storybook's play functions
|
|
23
|
+
- Test user workflows and component interactions
|
|
24
|
+
- Verify accessibility requirements
|
|
25
|
+
- Test responsive behavior when relevant
|
|
26
|
+
- Use `@storybook/test` utilities for assertions
|
|
27
|
+
- Structure tests to run with `yarn test-storybook`
|
|
28
|
+
|
|
29
|
+
3. **Coordinate Backstop Visual Regression Testing**
|
|
30
|
+
- **Always ask the user** if Backstop tests should be updated or created
|
|
31
|
+
- When approved, create or update Backstop scenarios
|
|
32
|
+
- Define appropriate viewports for responsive testing
|
|
33
|
+
- Set meaningful selectors and hide dynamic elements
|
|
34
|
+
- Document any visual baseline changes needed
|
|
35
|
+
|
|
36
|
+
## Testing Patterns for This Codebase
|
|
37
|
+
|
|
38
|
+
### Vitest Unit Test Structure
|
|
39
|
+
```typescript
|
|
40
|
+
import { describe, it, expect, vi } from 'vitest';
|
|
41
|
+
import { render, screen } from '@testing-library/react';
|
|
42
|
+
import userEvent from '@testing-library/user-event';
|
|
43
|
+
import { ComponentName } from './ComponentName';
|
|
44
|
+
|
|
45
|
+
describe('ComponentName', () => {
|
|
46
|
+
it('should render with default props', () => {
|
|
47
|
+
render(<ComponentName />);
|
|
48
|
+
expect(screen.getByRole('...')).toBeInTheDocument();
|
|
49
|
+
});
|
|
50
|
+
|
|
51
|
+
it('should handle user interaction', async () => {
|
|
52
|
+
const user = userEvent.setup();
|
|
53
|
+
const onAction = vi.fn();
|
|
54
|
+
render(<ComponentName onAction={onAction} />);
|
|
55
|
+
|
|
56
|
+
await user.click(screen.getByRole('button'));
|
|
57
|
+
expect(onAction).toHaveBeenCalledTimes(1);
|
|
58
|
+
});
|
|
59
|
+
});
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
### Storybook Play Function Structure
|
|
63
|
+
```typescript
|
|
64
|
+
import type { Meta, StoryObj } from '@storybook/react';
|
|
65
|
+
import { within, userEvent, expect } from '@storybook/test';
|
|
66
|
+
|
|
67
|
+
export const WithInteraction: StoryObj = {
|
|
68
|
+
play: async ({ canvasElement }) => {
|
|
69
|
+
const canvas = within(canvasElement);
|
|
70
|
+
|
|
71
|
+
await userEvent.click(canvas.getByRole('button'));
|
|
72
|
+
await expect(canvas.getByText('Expected Result')).toBeInTheDocument();
|
|
73
|
+
},
|
|
74
|
+
};
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
## Workflow
|
|
78
|
+
|
|
79
|
+
1. **Analyze the Component/Feature**: Understand what needs testing by reading the implementation
|
|
80
|
+
2. **Identify Test Scenarios**: List unit tests, integration tests, and potential visual tests
|
|
81
|
+
3. **Write Unit Tests First**: Create comprehensive Vitest tests
|
|
82
|
+
4. **Add Storybook Integration Tests**: Write play functions for user interaction flows
|
|
83
|
+
5. **Ask About Backstop**: Explicitly ask the user if visual regression tests should be added/updated
|
|
84
|
+
6. **Verify Tests Pass**: Run the tests to ensure they work correctly
|
|
85
|
+
|
|
86
|
+
## Quality Standards
|
|
87
|
+
|
|
88
|
+
- Tests should be deterministic and not flaky
|
|
89
|
+
- Use meaningful test descriptions that document behavior
|
|
90
|
+
- Avoid testing implementation details; test behavior
|
|
91
|
+
- Mock at the boundaries (API calls, external services)
|
|
92
|
+
- Keep tests focused and independent
|
|
93
|
+
- Clean up after tests (no shared state pollution)
|
|
94
|
+
|
|
95
|
+
## Before Completing
|
|
96
|
+
|
|
97
|
+
- Ensure all new tests pass: `vitest run` or `yarn test-storybook`
|
|
98
|
+
- Verify no existing tests were broken
|
|
99
|
+
- Confirm test file locations follow project conventions
|
|
100
|
+
- Ask about Backstop if visual changes are involved
|
|
101
|
+
|
|
102
|
+
**Update your agent memory** as you discover testing patterns, common test utilities used in this codebase, component testing quirks, and established testing conventions. This builds institutional knowledge for consistent test quality across the monorepo.
|
|
103
|
+
|
|
104
|
+
Examples of what to record:
|
|
105
|
+
- Common mocking patterns for specific dependencies
|
|
106
|
+
- Reusable test utilities in @cdc/core
|
|
107
|
+
- Components that require special testing setup
|
|
108
|
+
- Known flaky test patterns to avoid
|
|
109
|
+
|
|
110
|
+
# Persistent Agent Memory
|
|
111
|
+
|
|
112
|
+
You have a persistent Persistent Agent Memory directory at `/Users/adamdoe/Code/cdc-open-viz/packages/core/.claude/agent-memory/qa-test-developer/`. Its contents persist across conversations.
|
|
113
|
+
|
|
114
|
+
As you work, consult your memory files to build on previous experience. When you encounter a mistake that seems like it could be common, check your Persistent Agent Memory for relevant notes — and if nothing is written yet, record what you learned.
|
|
115
|
+
|
|
116
|
+
Guidelines:
|
|
117
|
+
- Record insights about problem constraints, strategies that worked or failed, and lessons learned
|
|
118
|
+
- Update or remove memories that turn out to be wrong or outdated
|
|
119
|
+
- Organize memory semantically by topic, not chronologically
|
|
120
|
+
- `MEMORY.md` is always loaded into your system prompt — lines after 200 will be truncated, so keep it concise and link to other files in your Persistent Agent Memory directory for details
|
|
121
|
+
- Use the Write and Edit tools to update your memory files
|
|
122
|
+
- Since this memory is project-scope and shared with your team via version control, tailor your memories to this project
|
|
123
|
+
|
|
124
|
+
## MEMORY.md
|
|
125
|
+
|
|
126
|
+
Your MEMORY.md is currently empty. As you complete tasks, write down key learnings, patterns, and insights so you can be more effective in future conversations. Anything saved in MEMORY.md will be included in your system prompt next time.
|
package/CLAUDE.local.md
ADDED
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
# @cdc/core — Package Rules
|
|
2
|
+
|
|
3
|
+
## Build
|
|
4
|
+
- Core has **no JavaScript build step**. The build script only compiles SCSS: `sass styles/cove-main.scss dist/cove-main.css`.
|
|
5
|
+
- All components, helpers, hooks, and types are imported **directly from source** by other packages. Never reference `dist/` for JS/TS imports.
|
|
6
|
+
|
|
7
|
+
## Where to Put New Code
|
|
8
|
+
|
|
9
|
+
| What you're adding | Where it goes |
|
|
10
|
+
|---|---|
|
|
11
|
+
| Shared React component | `components/<ComponentName>/` (directory with index file) |
|
|
12
|
+
| Shared helper function | `helpers/<functionName>.ts` (flat file at top level) |
|
|
13
|
+
| Shared custom hook | `hooks/use<Name>.ts` |
|
|
14
|
+
| Shared TypeScript type | `types/<TypeName>.ts` |
|
|
15
|
+
| SCSS styles | `styles/` (`base/`, `components/`, `layout/`, `themes/`, `utils/`) |
|
|
16
|
+
| Color palette data | `data/colorPalettes.ts`, `data/mapColorPalettes.ts`, or `data/sharedPalettes.ts` |
|
|
17
|
+
|
|
18
|
+
## Helpers Organization
|
|
19
|
+
- **Flat structure**: ~49 top-level files in `helpers/`.
|
|
20
|
+
- **Feature subdirectories** for complex domains:
|
|
21
|
+
- `cove/` — formatting utilities (accessibility, date, number, string)
|
|
22
|
+
- `embed/` — embed code generation, URL validation
|
|
23
|
+
- `metrics/` — analytics helpers
|
|
24
|
+
- `palettes/` — color palette migration and standardization
|
|
25
|
+
- `ver/` — version migration files (18+ migration scripts)
|
|
26
|
+
- `tests/` — shared test utilities (e.g., `testStandaloneBuild.ts`)
|
|
27
|
+
- Key constants in `helpers/constants.ts` — includes `USE_V2_MIGRATION`, `EDITOR_WIDTH`, `DATA_OPERATORS`, `DATA_FUNCTIONS`, color fallbacks.
|
|
28
|
+
|
|
29
|
+
## Commonly Imported Exports
|
|
30
|
+
Other packages depend heavily on these — be careful when modifying:
|
|
31
|
+
- **Types**: `VizFilter`, `Column`, `Table`, `General`, `Version`, `Visualization`, `FilterBehavior`, `DataSet` (imported as `Datasets`), `Action`
|
|
32
|
+
- **Helpers**: `fetchRemoteData`, `filterVizData`, `DataTransform`, `getViewport`, `updateFieldFactory`, `coveUpdateWorker`, `cloneConfig`
|
|
33
|
+
- **Components**: `Loading`, `EditorPanel`, `Filters`, `DataTable`, `Layout`, `ErrorBoundary`, ui elements (`Modal`, `Accordion`, `Tooltip`)
|
|
34
|
+
- **Contexts**: `EditorContext` (+ `EditorDispatchContext`) — shared editor state used by `@cdc/editor`
|
|
35
|
+
|
|
36
|
+
## Types Conventions
|
|
37
|
+
- 32 shared type files in `types/`.
|
|
38
|
+
- Other packages **extend** core types rather than duplicating (e.g., chart's `General` extends core's `General`).
|
|
39
|
+
- Use `import type` for type-only imports from core.
|
|
40
|
+
- Core's `Action<Type, Payload>` type is the base for all package action types.
|
|
41
|
+
|
|
42
|
+
## Components (34 directories)
|
|
43
|
+
Largest/most complex:
|
|
44
|
+
- `DataTable/` (29 files) — shared data table with sorting, pagination, search
|
|
45
|
+
- `EditorPanel/` (16 files) — shared editor panel sections
|
|
46
|
+
- `Filters/` (13 files) — shared filter UI components
|
|
47
|
+
- `ui/` (15 files) — low-level UI primitives (Modal, Accordion, Tooltip, Icon)
|
|
48
|
+
- `elements/` — Button, Card, Confirm, Error, ScreenReaderText, SkipTo
|
|
49
|
+
- `inputs/` — InputCheckbox, InputGroup, InputSelect, InputText, InputToggle
|
|
50
|
+
|
|
51
|
+
## Styles Architecture
|
|
52
|
+
- Entry point: `styles/cove-main.scss` (this is what the build compiles)
|
|
53
|
+
- Style system in `styles/` with: `base/`, `components/`, `layout/`, `themes/`, `utils/`
|
|
54
|
+
- Breakpoint mixin: `@import '@cdc/core/styles/utils/breakpoints'` — used by all packages
|
|
55
|
+
- Theme colors defined in `styles/themes/_color-definitions.scss`
|
|
56
|
+
- Use CSS custom properties (`var(--cool-gray-10)`) — never hardcode colors.
|
|
57
|
+
|
|
58
|
+
## Shared Configuration Files
|
|
59
|
+
- `generateViteConfig.js` — all packages import this for build/dev/test config. Do not modify without understanding downstream impact on every package.
|
|
60
|
+
- `testing-setup.js` — provides Testing Library matchers, matchMedia mock, URL.createObjectURL mock, auto-cleanup. All packages use this via Vitest setup.
|
|
61
|
+
- `devTemplate/` — HTML/CSS/JS for package dev servers (example-switching sidebar).
|
|
62
|
+
|
|
63
|
+
## Pitfalls
|
|
64
|
+
- Modifying any shared type (`types/*.ts`) can break multiple packages — check downstream imports first.
|
|
65
|
+
- `generateViteConfig.js` externals only include `react` and `react-dom`. If a new peer dependency is added, it must be added here too.
|
|
66
|
+
- The `data/` directory contains color palette definitions that affect every visualization — changes here are high-impact.
|
|
67
|
+
- `helpers/ver/` contains ordered version migration scripts. New migrations must maintain the correct sequence.
|
|
@@ -0,0 +1,300 @@
|
|
|
1
|
+
import type { Meta, StoryObj } from '@storybook/react-vite'
|
|
2
|
+
import { within, expect } from 'storybook/test'
|
|
3
|
+
import Chart from '@cdc/chart'
|
|
4
|
+
|
|
5
|
+
// Fallback step function for test descriptions
|
|
6
|
+
const step = async (description: string, fn: () => Promise<void> | void) => {
|
|
7
|
+
console.log(`▶ ${description}`)
|
|
8
|
+
await fn()
|
|
9
|
+
console.log(`✓ ${description}`)
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
const meta: Meta = {
|
|
13
|
+
title: 'Regression Tests/Gallery/Charts',
|
|
14
|
+
parameters: {
|
|
15
|
+
layout: 'fullscreen',
|
|
16
|
+
docs: {
|
|
17
|
+
description: {
|
|
18
|
+
component: 'Chart visualization examples from the CDC COVE Gallery'
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
},
|
|
22
|
+
tags: ['autodocs']
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
export default meta
|
|
26
|
+
|
|
27
|
+
type Story = StoryObj<typeof Chart>
|
|
28
|
+
|
|
29
|
+
// Helper function to test chart rendering
|
|
30
|
+
const testChartRendering = async (canvasElement: HTMLElement, storyName: string) => {
|
|
31
|
+
const canvas = within(canvasElement)
|
|
32
|
+
|
|
33
|
+
await step('Wait for chart to render', async () => {
|
|
34
|
+
const svgElement = await canvas.findByRole('img', { hidden: true }, { timeout: 10000 })
|
|
35
|
+
expect(svgElement).toBeInTheDocument()
|
|
36
|
+
})
|
|
37
|
+
|
|
38
|
+
await step('Verify chart SVG is present', async () => {
|
|
39
|
+
const chartSvg = canvasElement.querySelector('svg')
|
|
40
|
+
expect(chartSvg).toBeInTheDocument()
|
|
41
|
+
})
|
|
42
|
+
|
|
43
|
+
await step('Verify COVE module wrapper is present', async () => {
|
|
44
|
+
const coveModule = canvasElement.querySelector('.cdc-open-viz-module')
|
|
45
|
+
expect(coveModule).toBeInTheDocument()
|
|
46
|
+
})
|
|
47
|
+
|
|
48
|
+
console.log(` ${storyName} chart rendered successfully`)
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
// Bar Charts
|
|
52
|
+
export const Bar_Chart_Time_Based: Story = {
|
|
53
|
+
render: () => <Chart configUrl='https://www.cdc.gov/cove/examples/Example_Bar_Chart.json' />,
|
|
54
|
+
play: async ({ canvasElement }) => {
|
|
55
|
+
await testChartRendering(canvasElement, 'Bar Chart Time Based')
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
export const Bar_Chart_Categorical: Story = {
|
|
60
|
+
render: () => <Chart configUrl='https://www.cdc.gov/cove/examples/example-category-bar-char.json' />,
|
|
61
|
+
play: async ({ canvasElement }) => {
|
|
62
|
+
await testChartRendering(canvasElement, 'Bar Chart Categorical')
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
export const Bar_Chart_With_Highlighted_Value: Story = {
|
|
67
|
+
render: () => <Chart configUrl='https://www.cdc.gov/cove/examples/bar-chart-with-highlighte.json' />,
|
|
68
|
+
play: async ({ canvasElement }) => {
|
|
69
|
+
await testChartRendering(canvasElement, 'Bar Chart With Highlighted Value')
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
export const Bar_Chart_With_Confidence_Intervals: Story = {
|
|
74
|
+
render: () => <Chart configUrl='https://www.cdc.gov/cove/examples/Example_Bar_CI_1.json' />,
|
|
75
|
+
play: async ({ canvasElement }) => {
|
|
76
|
+
await testChartRendering(canvasElement, 'Bar Chart With Confidence Intervals')
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
export const Bar_Chart_With_Suppressed_Values: Story = {
|
|
81
|
+
render: () => <Chart configUrl='https://www.cdc.gov/cove/examples/bar-chart-with-suppressed-values.json' />,
|
|
82
|
+
play: async ({ canvasElement }) => {
|
|
83
|
+
await testChartRendering(canvasElement, 'Bar Chart With Suppressed Values')
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
export const Horizontal_Bar_Chart: Story = {
|
|
88
|
+
render: () => <Chart configUrl='https://www.cdc.gov/cove/examples/Horizontal_Bar_Chart_Viz.json' />,
|
|
89
|
+
play: async ({ canvasElement }) => {
|
|
90
|
+
await testChartRendering(canvasElement, 'Horizontal Bar Chart')
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
// Box and Whiskers Plots
|
|
95
|
+
export const Box_Plot_With_Outliers: Story = {
|
|
96
|
+
render: () => <Chart configUrl='https://www.cdc.gov/cove/examples/box-plot-outliers.json' />,
|
|
97
|
+
play: async ({ canvasElement }) => {
|
|
98
|
+
await testChartRendering(canvasElement, 'Box Plot With Outliers')
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
export const Horizontal_Box_Plot: Story = {
|
|
103
|
+
render: () => <Chart configUrl='https://www.cdc.gov/cove/examples/horizontal-box-plot.json' />,
|
|
104
|
+
play: async ({ canvasElement }) => {
|
|
105
|
+
await testChartRendering(canvasElement, 'Horizontal Box Plot')
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
// Bump Chart
|
|
110
|
+
export const Bump_Chart: Story = {
|
|
111
|
+
render: () => <Chart configUrl='https://www.cdc.gov/cove/examples/bump-chart.json' />,
|
|
112
|
+
play: async ({ canvasElement }) => {
|
|
113
|
+
await testChartRendering(canvasElement, 'Bump Chart')
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
// Combo Bar/Line Charts
|
|
118
|
+
export const Combo_Bar_And_Area: Story = {
|
|
119
|
+
render: () => <Chart configUrl='https://www.cdc.gov/cove/examples/Combo_Bar_Line_Viz.json' />,
|
|
120
|
+
play: async ({ canvasElement }) => {
|
|
121
|
+
await testChartRendering(canvasElement, 'Combo Bar And Area')
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
export const Epi_Style_Bar_Chart: Story = {
|
|
126
|
+
render: () => <Chart configUrl='https://www.cdc.gov/cove/examples/example-epi-style-bar-chart.json' />,
|
|
127
|
+
play: async ({ canvasElement }) => {
|
|
128
|
+
await testChartRendering(canvasElement, 'Epi Style Bar Chart')
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
// Deviation Bar Chart
|
|
133
|
+
export const Deviation_Bar_Chart: Story = {
|
|
134
|
+
render: () => <Chart configUrl='https://www.cdc.gov/cove/examples/example-deviation-bar-chart.json' />,
|
|
135
|
+
play: async ({ canvasElement }) => {
|
|
136
|
+
await testChartRendering(canvasElement, 'Deviation Bar Chart')
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
// Forecast Charts
|
|
141
|
+
export const Forecast_Chart_Single_CI: Story = {
|
|
142
|
+
render: () => <Chart configUrl='https://www.cdc.gov/cove/examples/forecast-chart-one-CI.json' />,
|
|
143
|
+
play: async ({ canvasElement }) => {
|
|
144
|
+
await testChartRendering(canvasElement, 'Forecast Chart Single CI')
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
export const Forecast_Chart_Multiple_CIs: Story = {
|
|
149
|
+
render: () => <Chart configUrl='https://www.cdc.gov/cove/examples/forecast-chart-2-CIs.json' />,
|
|
150
|
+
play: async ({ canvasElement }) => {
|
|
151
|
+
await testChartRendering(canvasElement, 'Forecast Chart Multiple CIs')
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
// Line Charts
|
|
156
|
+
export const Line_Chart_Standard: Story = {
|
|
157
|
+
render: () => <Chart configUrl='https://www.cdc.gov/cove/examples/Line_Chart_Viz.json' />,
|
|
158
|
+
play: async ({ canvasElement }) => {
|
|
159
|
+
await testChartRendering(canvasElement, 'Line Chart Standard')
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
export const Line_Chart_With_Regions: Story = {
|
|
164
|
+
render: () => <Chart configUrl='https://www.cdc.gov/cove/examples/Line_Chart_Regions_Viz.json' />,
|
|
165
|
+
play: async ({ canvasElement }) => {
|
|
166
|
+
await testChartRendering(canvasElement, 'Line Chart With Regions')
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
export const Line_Chart_Isolated: Story = {
|
|
171
|
+
render: () => <Chart configUrl='https://www.cdc.gov/cove/examples/Line_Chart_Isolated.json' />,
|
|
172
|
+
play: async ({ canvasElement }) => {
|
|
173
|
+
await testChartRendering(canvasElement, 'Line Chart Isolated')
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
export const Line_Chart_Line_Weights: Story = {
|
|
178
|
+
render: () => <Chart configUrl='https://www.cdc.gov/cove/examples/Line_Chart_Line_Weights.json' />,
|
|
179
|
+
play: async ({ canvasElement }) => {
|
|
180
|
+
await testChartRendering(canvasElement, 'Line Chart Line Weights')
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
export const Line_Chart_With_Open_Circles: Story = {
|
|
185
|
+
render: () => <Chart configUrl='https://www.cdc.gov/cove/examples/line-chart-with-open-circles.json' />,
|
|
186
|
+
play: async ({ canvasElement }) => {
|
|
187
|
+
await testChartRendering(canvasElement, 'Line Chart With Open Circles')
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
export const Line_Chart_With_Suppression: Story = {
|
|
192
|
+
render: () => <Chart configUrl='https://www.cdc.gov/cove/examples/line-chart-with-suppression.json' />,
|
|
193
|
+
play: async ({ canvasElement }) => {
|
|
194
|
+
await testChartRendering(canvasElement, 'Line Chart With Suppression')
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
// Lollipop Bar Chart
|
|
199
|
+
export const Lollipop_Horizontal_Bar_Chart: Story = {
|
|
200
|
+
render: () => <Chart configUrl='https://www.cdc.gov/cove/examples/lollipop-style-horizontal-bar-chart.json' />,
|
|
201
|
+
play: async ({ canvasElement }) => {
|
|
202
|
+
await testChartRendering(canvasElement, 'Lollipop Horizontal Bar Chart')
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
// Pie and Donut Charts
|
|
207
|
+
export const Pie_Chart: Story = {
|
|
208
|
+
render: () => <Chart configUrl='https://www.cdc.gov/cove/examples/Example_Pie_viz.json' />,
|
|
209
|
+
play: async ({ canvasElement }) => {
|
|
210
|
+
await testChartRendering(canvasElement, 'Pie Chart')
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
export const Donut_Chart: Story = {
|
|
215
|
+
render: () => <Chart configUrl='https://www.cdc.gov/cove/examples/Donut-Chart.json' />,
|
|
216
|
+
play: async ({ canvasElement }) => {
|
|
217
|
+
await testChartRendering(canvasElement, 'Donut Chart')
|
|
218
|
+
}
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
// Scatter Plots
|
|
222
|
+
export const Scatter_Plot_Negative_Trend: Story = {
|
|
223
|
+
render: () => <Chart configUrl='https://www.cdc.gov/cove/examples/scatter-plot-negative-trend.json' />,
|
|
224
|
+
play: async ({ canvasElement }) => {
|
|
225
|
+
await testChartRendering(canvasElement, 'Scatter Plot Negative Trend')
|
|
226
|
+
}
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
export const Scatter_Plot_Multi_Series: Story = {
|
|
230
|
+
render: () => <Chart configUrl='https://www.cdc.gov/cove/examples/scatter-plot-multi-series.json' />,
|
|
231
|
+
play: async ({ canvasElement }) => {
|
|
232
|
+
await testChartRendering(canvasElement, 'Scatter Plot Multi Series')
|
|
233
|
+
}
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
export const Scatter_Plot_Nonlinear_Trend: Story = {
|
|
237
|
+
render: () => <Chart configUrl='https://www.cdc.gov/cove/examples/scatter-plot-nonlinear-trend.json' />,
|
|
238
|
+
play: async ({ canvasElement }) => {
|
|
239
|
+
await testChartRendering(canvasElement, 'Scatter Plot Nonlinear Trend')
|
|
240
|
+
}
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
// Sparklines
|
|
244
|
+
export const Sparkline_2016_Outreach_Var2: Story = {
|
|
245
|
+
render: () => <Chart configUrl='https://www.cdc.gov/cove/examples/2016-outreach-2.json' />,
|
|
246
|
+
play: async ({ canvasElement }) => {
|
|
247
|
+
await testChartRendering(canvasElement, 'Sparkline 2016 Outreach Var2')
|
|
248
|
+
}
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
export const Sparkline_2016_Outreach_Var3: Story = {
|
|
252
|
+
render: () => <Chart configUrl='https://www.cdc.gov/cove/examples/2016-outreach-3.json' />,
|
|
253
|
+
play: async ({ canvasElement }) => {
|
|
254
|
+
await testChartRendering(canvasElement, 'Sparkline 2016 Outreach Var3')
|
|
255
|
+
}
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
export const Sparkline_2016_Outreach_Var4: Story = {
|
|
259
|
+
render: () => <Chart configUrl='https://www.cdc.gov/cove/examples/2016-outreach-4.json' />,
|
|
260
|
+
play: async ({ canvasElement }) => {
|
|
261
|
+
await testChartRendering(canvasElement, 'Sparkline 2016 Outreach Var4')
|
|
262
|
+
}
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
// Stacked Area Charts
|
|
266
|
+
export const Stacked_Area_Chart: Story = {
|
|
267
|
+
render: () => <Chart configUrl='https://www.cdc.gov/cove/examples/example-stacked-area-chart.json' />,
|
|
268
|
+
play: async ({ canvasElement }) => {
|
|
269
|
+
await testChartRendering(canvasElement, 'Stacked Area Chart')
|
|
270
|
+
}
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
export const Area_Chart_With_Annotations: Story = {
|
|
274
|
+
render: () => <Chart configUrl='https://www.cdc.gov/cove/examples/area-chart-with-annotations_1.json' />,
|
|
275
|
+
play: async ({ canvasElement }) => {
|
|
276
|
+
await testChartRendering(canvasElement, 'Area Chart With Annotations')
|
|
277
|
+
}
|
|
278
|
+
}
|
|
279
|
+
|
|
280
|
+
export const Area_Chart_With_Categorical_Axis: Story = {
|
|
281
|
+
render: () => <Chart configUrl='https://www.cdc.gov/cove/examples/example-area-chart-with-cat-axis.json' />,
|
|
282
|
+
play: async ({ canvasElement }) => {
|
|
283
|
+
await testChartRendering(canvasElement, 'Area Chart With Categorical Axis')
|
|
284
|
+
}
|
|
285
|
+
}
|
|
286
|
+
|
|
287
|
+
// Stacked Bar Charts
|
|
288
|
+
export const Stacked_Horizontal_Bar_Chart: Story = {
|
|
289
|
+
render: () => <Chart configUrl='https://www.cdc.gov/cove/examples/example-stacked-horizontal-chart.json' />,
|
|
290
|
+
play: async ({ canvasElement }) => {
|
|
291
|
+
await testChartRendering(canvasElement, 'Stacked Horizontal Bar Chart')
|
|
292
|
+
}
|
|
293
|
+
}
|
|
294
|
+
|
|
295
|
+
export const Stacked_Vertical_Bar_Chart: Story = {
|
|
296
|
+
render: () => <Chart configUrl='https://www.cdc.gov/cove/examples/Stacked_Bar_Viz.json' />,
|
|
297
|
+
play: async ({ canvasElement }) => {
|
|
298
|
+
await testChartRendering(canvasElement, 'Stacked Vertical Bar Chart')
|
|
299
|
+
}
|
|
300
|
+
}
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
import type { Meta, StoryObj } from '@storybook/react-vite'
|
|
2
|
+
import { within, expect, waitFor } from 'storybook/test'
|
|
3
|
+
import DataBite from '@cdc/data-bite'
|
|
4
|
+
|
|
5
|
+
// Fallback step function for test descriptions
|
|
6
|
+
const step = async (description: string, fn: () => Promise<void> | void) => {
|
|
7
|
+
console.log(`▶ ${description}`)
|
|
8
|
+
await fn()
|
|
9
|
+
console.log(`✓ ${description}`)
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
const meta: Meta = {
|
|
13
|
+
title: 'Regression Tests/Gallery/Data Bites',
|
|
14
|
+
parameters: {
|
|
15
|
+
layout: 'fullscreen',
|
|
16
|
+
docs: {
|
|
17
|
+
description: {
|
|
18
|
+
component: 'Data Bite visualization examples from the CDC COVE Gallery'
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
},
|
|
22
|
+
tags: ['autodocs']
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
export default meta
|
|
26
|
+
|
|
27
|
+
type Story = StoryObj<typeof DataBite>
|
|
28
|
+
|
|
29
|
+
// Helper function to test data bite rendering
|
|
30
|
+
const testDataBiteRendering = async (canvasElement: HTMLElement, storyName: string) => {
|
|
31
|
+
const canvas = within(canvasElement)
|
|
32
|
+
|
|
33
|
+
await step('Wait for data bite to render', async () => {
|
|
34
|
+
await waitFor(() => expect(canvasElement.querySelector('.bite-content')).toBeInTheDocument(), { timeout: 10000 })
|
|
35
|
+
})
|
|
36
|
+
|
|
37
|
+
await step('Verify COVE module wrapper is present', async () => {
|
|
38
|
+
const coveModule = canvasElement.querySelector('.cdc-open-viz-module')
|
|
39
|
+
expect(coveModule).toBeInTheDocument()
|
|
40
|
+
})
|
|
41
|
+
|
|
42
|
+
console.log(` ${storyName} data bite rendered successfully`)
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
export const Data_Bite_Circle_Average: Story = {
|
|
46
|
+
render: () => (
|
|
47
|
+
<DataBite configUrl='https://www.cdc.gov/wcms/4.0/cdc-wp/data-presentation/examples/Data_Bite_Circle_Average.json' />
|
|
48
|
+
),
|
|
49
|
+
play: async ({ canvasElement }) => {
|
|
50
|
+
await testDataBiteRendering(canvasElement, 'Data Bite Circle Average')
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
export const Data_Bite_Text_Max_Pic: Story = {
|
|
55
|
+
render: () => (
|
|
56
|
+
<DataBite configUrl='https://www.cdc.gov/wcms/4.0/cdc-wp/data-presentation/examples/Data_Bite_Text_Max_Pic.json' />
|
|
57
|
+
),
|
|
58
|
+
play: async ({ canvasElement }) => {
|
|
59
|
+
await testDataBiteRendering(canvasElement, 'Data Bite Text Max Pic')
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
export const Data_Bite_Circle_Sum: Story = {
|
|
64
|
+
render: () => (
|
|
65
|
+
<DataBite configUrl='https://www.cdc.gov/wcms/4.0/cdc-wp/data-presentation/examples/Data_Bite_Circle_Sum.json' />
|
|
66
|
+
),
|
|
67
|
+
play: async ({ canvasElement }) => {
|
|
68
|
+
await testDataBiteRendering(canvasElement, 'Data Bite Circle Sum')
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
export const Data_Bite_Text_Average_Pic: Story = {
|
|
73
|
+
render: () => (
|
|
74
|
+
<DataBite configUrl='https://www.cdc.gov/wcms/4.0/cdc-wp/data-presentation/examples/Data_Bite_Text_Average_Pic.json' />
|
|
75
|
+
),
|
|
76
|
+
play: async ({ canvasElement }) => {
|
|
77
|
+
await testDataBiteRendering(canvasElement, 'Data Bite Text Average Pic')
|
|
78
|
+
}
|
|
79
|
+
}
|