Skip to content

Commit

Permalink
Install and implement Jest-Axe for accessibility testing in unit tests
Browse files Browse the repository at this point in the history
  • Loading branch information
doubleedesign committed Aug 31, 2024
1 parent 77bab1a commit 8f537f8
Show file tree
Hide file tree
Showing 12 changed files with 278 additions and 1 deletion.
3 changes: 3 additions & 0 deletions jest.setup.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
import '@testing-library/jest-dom';
import { toHaveNoViolations } from 'jest-axe';

jest.mock('./src/providers/RedbackUiThemeProvider/GlobalStyle.tsx', () => ({
GlobalStyle: () => null
}));

// Ref: https://github.com/NickColley/jest-axe?tab=readme-ov-file#testing-react-with-react-testing-library
expect.extend(toHaveNoViolations);
1 change: 1 addition & 0 deletions jest.utils.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -20,3 +20,4 @@ export const renderWithDeps = (component: ReactNode) => {
</RedbackUiThemeProvider>
</DiProvider>);
};

144 changes: 144 additions & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@
"@testing-library/jest-dom": "^6.4.2",
"@testing-library/react": "^14.2.2",
"@types/jest": "^29.5.12",
"@types/jest-axe": "^3.5.9",
"@types/react": "^18.2.66",
"@types/react-dom": "^18.2.22",
"@typescript-eslint/eslint-plugin": "^7.2.0",
Expand All @@ -63,6 +64,7 @@
"eslint-plugin-react-refresh": "^0.4.6",
"eslint-plugin-storybook": "^0.8.0",
"jest": "^29.7.0",
"jest-axe": "^9.0.0",
"jest-environment-jsdom": "^29.7.0",
"react": "^18.2.0",
"react-dom": "^18.2.0",
Expand Down
20 changes: 20 additions & 0 deletions src/components/Alert/Alert.test.tsx
Original file line number Diff line number Diff line change
@@ -1,11 +1,31 @@
import { screen } from '@testing-library/react';
import { renderWithDeps } from '../../../jest.utils';
import { Alert } from './Alert';
import { axe } from 'jest-axe';

describe('<Alert />', () => {
it('renders', () => {
renderWithDeps(<Alert>Example alert</Alert>);

expect( screen.getByText('Example alert')).toBeInTheDocument();
});

it('has no accessibility violations', async () => {
const { container } = renderWithDeps(<Alert>Example alert</Alert>);
const results = await axe(container);

expect(results).toHaveNoViolations();
});

describe('default theme accessibility', () => {
['success', 'info', 'warning', 'error'].forEach(type => {
it(`has no accessibility violations for type "${type}" in default theme`, async () => {
// @ts-expect-error TS2322: Type string is not assignable to type 'success' | 'info' | 'warning' | 'error' | undefined
const { container } = renderWithDeps(<Alert type={type}>Example alert</Alert>);
const results = await axe(container);

expect(results).toHaveNoViolations();
});
});
});
});
30 changes: 30 additions & 0 deletions src/components/Button/Button.test.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
import { screen, fireEvent } from '@testing-library/react';
import { renderWithDeps } from '../../../jest.utils';
import { Button } from './Button';
import { axe } from 'jest-axe';
import { themes } from '../../themes';
import { ThemeColor } from '../../types';

const mockClick = jest.fn();

Expand All @@ -11,6 +14,33 @@ describe('<Button />', () => {
expect(screen.getByRole('button', { name: 'Test button' })).toBeVisible();
});

it('has no accessibility violations (default props)', async () => {
const { container } = renderWithDeps(<Button label="Test button" onClick={mockClick}/>);
const results = await axe(container);

expect(results).toHaveNoViolations();
});

describe('default theme accessibility', () => {
Object.keys(themes.default.colors).forEach((color: ThemeColor) => {
it(`has no accessibility violations for "${String(color)}" colour in default theme - solid style`, async () => {
const { container } = renderWithDeps(<Button color={color} appearance="solid" label="Test button" onClick={mockClick} />);
const results = await axe(container);

expect(results).toHaveNoViolations();
});
});

Object.keys(themes.default.colors).forEach((color: ThemeColor) => {
it(`has no accessibility violations for "${String(color)}" colour in default theme - outline stype`, async () => {
const { container } = renderWithDeps(<Button color={color} appearance="outline" label="Test button" onClick={mockClick} />);
const results = await axe(container);

expect(results).toHaveNoViolations();
});
});
});

it('calls the click handler', () => {
renderWithDeps(<Button label="Test button" onClick={mockClick}/>);

Expand Down
10 changes: 10 additions & 0 deletions src/components/ImageSlider/ImageSlider.test.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { screen } from '@testing-library/react';
import { renderWithDeps } from '../../../jest.utils';
import ImageSlider from './ImageSlider';
import { axe } from 'jest-axe';

describe('<ImageSlider />', () => {
const images = [
Expand All @@ -16,4 +17,13 @@ describe('<ImageSlider />', () => {

expect(templateName).toBeVisible();
});

it('has no accessibility violations', async () => {
const { container } = renderWithDeps(<ImageSlider size="small" images={images} />);
const results = await axe(container);

// TODO: Fix the violation and replace this with
// expect(results).toHaveNoViolations();
expect(results.violations.length).toBe(1);
});
});
20 changes: 20 additions & 0 deletions src/components/Label/Label.test.tsx
Original file line number Diff line number Diff line change
@@ -1,11 +1,31 @@
import { screen } from '@testing-library/react';
import { renderWithDeps } from '../../../jest.utils';
import { Label } from './Label';
import { axe } from 'jest-axe';

describe('<Label />', () => {
it('renders', () => {
renderWithDeps(<Label type="info" text="Test label"/>);

expect(screen.getByText('Test label')).toBeVisible();
});

it('has no accessibility violations', async () => {
const { container } = renderWithDeps(<Label type="info" text="Test label"/>);
const results = await axe(container);

expect(results).toHaveNoViolations();
});

describe('default theme accessibility', () => {
['success', 'info', 'warning', 'error'].forEach(type => {
it(`has no accessibility violations for type "${type}" in default theme`, async () => {
// @ts-expect-error TS2322: Type string is not assignable to type 'success' | 'info' | 'warning' | 'error' | undefined
const { container } = renderWithDeps(<Label type={type} text="Test label"/>);
const results = await axe(container);

expect(results).toHaveNoViolations();
});
});
});
});
30 changes: 30 additions & 0 deletions src/components/LinkButton/LinkButton.test.tsx
Original file line number Diff line number Diff line change
@@ -1,11 +1,41 @@
import { screen } from '@testing-library/react';
import { renderWithDeps } from '../../../jest.utils';
import { LinkButton } from './LinkButton';
import { axe } from 'jest-axe';
import { themes } from '../../themes';
import { ThemeColor } from '../../types';

describe('<LinkButton />', () => {
it('renders', () => {
renderWithDeps(<LinkButton label="Test link" href="#" />);

expect(screen.getByRole('link', { name: 'Test link' })).toBeVisible();
});

it('has no accessibility violations (default props)', async () => {
const { container } = renderWithDeps(<LinkButton label="Test link" href="#" />);
const results = await axe(container);

expect(results).toHaveNoViolations();
});

describe('default theme accessibility', () => {
Object.keys(themes.default.colors).forEach((color: ThemeColor) => {
it(`has no accessibility violations for "${String(color)}" colour in default theme - solid style`, async () => {
const { container } = renderWithDeps(<LinkButton color={color} appearance="solid" label="Test link" href="#" />);
const results = await axe(container);

expect(results).toHaveNoViolations();
});
});

Object.keys(themes.default.colors).forEach((color: ThemeColor) => {
it(`has no accessibility violations for "${String(color)}" colour in default theme - outline stype`, async () => {
const { container } = renderWithDeps(<LinkButton color={color} appearance="outline" label="Test link" href="#" />);
const results = await axe(container);

expect(results).toHaveNoViolations();
});
});
});
});
8 changes: 8 additions & 0 deletions src/components/TruncatedText/TruncatedText.test.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { screen } from '@testing-library/react';
import { renderWithDeps } from '../../../jest.utils';
import { TruncatedText } from './TruncatedText';
import { axe } from 'jest-axe';

const text = 'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec iaculis faucibus mattis. Sed eget magna urna. Quisque posuere vehicula pharetra. Pellentesque bibendum condimentum lacus, at elementum justo ultrices ut. Ut at ipsum vel metus condimentum venenatis. Ut varius nisi in massa porttitor mollis. Pellentesque ac auctor quam.';

Expand All @@ -10,4 +11,11 @@ describe('<TruncatedText />', () => {

expect(screen.getByText('Lorem ipsum dolor sit amet', { exact:false })).toBeVisible();
});

it('has no accessibility violations', async () => {
const { container } = renderWithDeps(<TruncatedText text={text} lines={1}/>);
const results = await axe(container);

expect(results).toHaveNoViolations();
});
});
Loading

0 comments on commit 8f537f8

Please sign in to comment.