Storybook: Run a11y tests against both light and dark theme (#110887)

* run storybook a11y tests in both light and dark theme

* remove unused import

* update unit tests
This commit is contained in:
Ashley Harrison
2025-09-11 13:10:41 +01:00
committed by GitHub
parent 582d1e4f0d
commit c7169b3461
9 changed files with 51 additions and 12 deletions

View File

@ -27,7 +27,7 @@ jobs:
with: with:
self: .github/workflows/storybook-a11y.yml self: .github/workflows/storybook-a11y.yml
test-storybook-a11y: test-storybook-a11y-light:
runs-on: ubuntu-latest-8-cores runs-on: ubuntu-latest-8-cores
permissions: permissions:
contents: read contents: read
@ -46,7 +46,36 @@ jobs:
- name: Install Playwright browsers - name: Install Playwright browsers
run: npx playwright install --with-deps run: npx playwright install --with-deps
- name: Start Storybook - name: Start Storybook
run: yarn storybook & run: STORYBOOK_THEME=light yarn storybook &
- name: Run tests
# the chromium browser used by Playwright sets its locale to "en_US@posix" by default
# this is not a valid language code, and causes some stories to fail to load!
# instead, we set the LANG environment variable to en_US to override this
# see https://github.com/microsoft/playwright/issues/34046
env:
LANG: en_US
run: npx wait-on --timeout 120000 http://localhost:9001 && yarn test:storybook
test-storybook-a11y-dark:
runs-on: ubuntu-latest-8-cores
permissions:
contents: read
id-token: write
needs: detect-changes
if: needs.detect-changes.outputs.changed == 'true'
name: "Run Storybook a11y tests"
steps:
- uses: actions/checkout@v5
with:
persist-credentials: false
- uses: actions/setup-node@v4
with:
node-version-file: '.nvmrc'
- run: yarn install --immutable --check-cache
- name: Install Playwright browsers
run: npx playwright install --with-deps
- name: Start Storybook
run: STORYBOOK_THEME=dark yarn storybook &
- name: Run tests - name: Run tests
# the chromium browser used by Playwright sets its locale to "en_US@posix" by default # the chromium browser used by Playwright sets its locale to "en_US@posix" by default
# this is not a valid language code, and causes some stories to fail to load! # this is not a valid language code, and causes some stories to fail to load!

View File

@ -107,7 +107,7 @@ class DarkColors implements ThemeColorsBase<Partial<ThemeRichColor>> {
text = { text = {
primary: `rgb(${this.whiteBase})`, primary: `rgb(${this.whiteBase})`,
secondary: `rgba(${this.whiteBase}, 0.65)`, secondary: `rgba(${this.whiteBase}, 0.65)`,
disabled: `rgba(${this.whiteBase}, 0.6)`, disabled: `rgba(${this.whiteBase}, 0.61)`,
link: palette.blueDarkText, link: palette.blueDarkText,
maxContrast: palette.white, maxContrast: palette.white,
}; };

View File

@ -183,6 +183,9 @@ const preview: Preview = {
}, },
tags: ['autodocs'], tags: ['autodocs'],
loaders: [mswLoader], loaders: [mswLoader],
initialGlobals: {
theme: process.env.STORYBOOK_THEME || 'system',
},
}; };
export default preview; export default preview;

View File

@ -21,7 +21,7 @@ const meta: Meta<typeof ColorPicker> = {
}, },
args: { args: {
enableNamedColors: false, enableNamedColors: false,
color: '#0000ff', color: '#ee0000',
}, },
}; };
@ -60,7 +60,7 @@ export const CustomTrigger: StoryFn<typeof ColorPicker> = ({ color, enableNamedC
ref={ref} ref={ref}
onMouseLeave={hideColorPicker} onMouseLeave={hideColorPicker}
onClick={showColorPicker} onClick={showColorPicker}
style={{ color }} style={{ color: 'white', backgroundColor: color, padding: '8px' }}
className={clearButton} className={clearButton}
> >
Open color picker Open color picker

View File

@ -21,7 +21,7 @@ const getStyles = (theme: GrafanaTheme2, variant: CounterVariant) => ({
label: 'counter', label: 'counter',
marginLeft: theme.spacing(1), marginLeft: theme.spacing(1),
borderRadius: theme.spacing(3), borderRadius: theme.spacing(3),
backgroundColor: variant === 'primary' ? theme.colors.primary.main : theme.colors.action.hover, backgroundColor: variant === 'primary' ? theme.colors.primary.main : theme.colors.secondary.main,
padding: theme.spacing(0.25, 1), padding: theme.spacing(0.25, 1),
color: theme.colors.text.secondary, color: theme.colors.text.secondary,
fontWeight: theme.typography.fontWeightMedium, fontWeight: theme.typography.fontWeightMedium,

View File

@ -316,7 +316,7 @@ export function RichColorDemo({ theme, color }: RichColorDemoProps) {
<div <div
className={css({ className={css({
background: color.shade, background: color.shade,
color: color.contrastText, color: theme.colors.getContrastText(color.shade, 4.5),
borderRadius: theme.shape.radius.default, borderRadius: theme.shape.radius.default,
padding: '8px', padding: '8px',
})} })}

View File

@ -34,7 +34,10 @@ export const BottomLegend: StoryFn = ({ height, width, legendItems }) => {
const legend = ( const legend = (
<VizLayout.Legend placement="bottom" maxHeight="30%"> <VizLayout.Legend placement="bottom" maxHeight="30%">
{items.map((_, index) => ( {items.map((_, index) => (
<div style={{ height: '30px', width: '100%', background: 'lightblue', marginBottom: '2px' }} key={index}> <div
style={{ height: '30px', width: '100%', background: 'lightblue', color: 'black', marginBottom: '2px' }}
key={index}
>
Legend item {index} Legend item {index}
</div> </div>
))} ))}
@ -65,7 +68,13 @@ export const RightLegend: StoryFn = ({ height, width, legendItems, legendWidth }
<VizLayout.Legend placement="right" maxWidth="50%"> <VizLayout.Legend placement="right" maxWidth="50%">
{items.map((_, index) => ( {items.map((_, index) => (
<div <div
style={{ height: '30px', width: `${legendWidth}px`, background: 'lightblue', marginBottom: '2px' }} style={{
height: '30px',
width: `${legendWidth}px`,
background: 'lightblue',
color: 'black',
marginBottom: '2px',
}}
key={index} key={index}
> >
Legend item {index} Legend item {index}

View File

@ -299,7 +299,6 @@ describe('TracePageHeader test', () => {
const button = screen.getByRole('button', { name: /Test Extension/i }); const button = screen.getByRole('button', { name: /Test Extension/i });
expect(button).toBeInTheDocument(); expect(button).toBeInTheDocument();
expect(button).toHaveClass('css-7byezq-button'); // Grafana button primary class
}); });
it('should render extension icons when provided', () => { it('should render extension icons when provided', () => {
@ -485,7 +484,6 @@ describe('TracePageHeader test', () => {
const buttonElement = feedbackButton.closest('a'); const buttonElement = feedbackButton.closest('a');
expect(buttonElement).toBeInTheDocument(); expect(buttonElement).toBeInTheDocument();
expect(buttonElement).toHaveClass('css-125ehy6-button'); // Secondary variant class
// Check for icon // Check for icon
const iconElement = buttonElement?.querySelector('svg'); const iconElement = buttonElement?.querySelector('svg');

View File

@ -19,7 +19,7 @@ exports[`VariableQueryEditor renders correctly 1`] = `
<div> <div>
<div> <div>
<div <div
class="css-rebjtg-input-wrapper css-smf98s" class="css-1d4urid-input-wrapper css-smf98s"
> >
<span <span
class="css-1f43avz-a11yText-A11yText" class="css-1f43avz-a11yText-A11yText"