Skip to content

Commit

Permalink
Add light wrapper for Testing Library’s render function
Browse files Browse the repository at this point in the history
  • Loading branch information
tassoevan committed Aug 7, 2024
1 parent 9378d05 commit 5b96b6d
Show file tree
Hide file tree
Showing 83 changed files with 387 additions and 384 deletions.
1 change: 1 addition & 0 deletions packages/fuselage-toastbar/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,7 @@
"bump": "workspace:~",
"eslint": "~8.38.0",
"jest": "~29.7.0",
"jest-environment-jsdom": "~29.7.0",
"lint-all": "workspace:~",
"npm-run-all": "^4.1.5",
"prettier": "~2.8.7",
Expand Down
11 changes: 6 additions & 5 deletions packages/fuselage-toastbar/src/ToastBar.spec.tsx
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
import { composeStories } from '@storybook/react';
import { render, getByRole, screen } from '@testing-library/react';
import { getByRole, screen } from '@testing-library/react';
import userEvent from '@testing-library/user-event';

import * as stories from './ToastBar.stories';
import ToastBarProvider from './ToastBarProvider';
import { render } from './testing';

const { Default, TopEnd } = composeStories(stories, {
decorators: [
Expand All @@ -27,7 +28,7 @@ const topStartStyle = {

describe('[fuselage-toastbar rendering]', () => {
test('should display ToastBar on the top right of the screen by default', async () => {
render(<TopEnd />, { legacyRoot: true });
render(<TopEnd />);
const toast = screen.queryByRole('alert');
const toastContainer = toast?.parentElement?.parentElement?.parentElement;

Expand All @@ -36,7 +37,7 @@ describe('[fuselage-toastbar rendering]', () => {

test('should display ToastBar on the top right of the screen', async () => {
document.body.setAttribute('dir', 'ltr');
render(<TopEnd />, { legacyRoot: true });
render(<TopEnd />);
const toast = screen.queryByRole('alert');
const toastContainer = toast?.parentElement?.parentElement?.parentElement;

Expand All @@ -45,7 +46,7 @@ describe('[fuselage-toastbar rendering]', () => {

test('should display ToastBar on the top left of the screen', async () => {
document.body.setAttribute('dir', 'rtl');
render(<TopEnd />, { legacyRoot: true });
render(<TopEnd />);
const toast = screen.queryByRole('alert');
const toastContainer = toast?.parentElement?.parentElement?.parentElement;

Expand All @@ -55,7 +56,7 @@ describe('[fuselage-toastbar rendering]', () => {

describe('[fuselage-toastbar interacting]', () => {
test('should dispatch the ToastBar on click', async () => {
const { container } = render(<Default />, { legacyRoot: true });
const { container } = render(<Default />);
const button = getByRole(container, 'button');

userEvent.click(button);
Expand Down
34 changes: 34 additions & 0 deletions packages/fuselage-toastbar/src/testing.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
import type {
queries,
Queries,
RenderOptions,
RenderResult,
} from '@testing-library/react';
import { render as renderOriginal } from '@testing-library/react';
import type React from 'react';
import type ReactDOMClient from 'react-dom';

type RendererableContainer = ReactDOMClient.Container;
type HydrateableContainer = Parameters<(typeof ReactDOMClient)['hydrate']>[0];

/**
* Light wrapper around `react-testing-library` to provide a custom render function for transitioning to React 18
*/
export function render<
Q extends Queries = typeof queries,
Container extends RendererableContainer | HydrateableContainer = HTMLElement,
BaseElement extends RendererableContainer | HydrateableContainer = Container
>(
ui: React.ReactNode,
options: RenderOptions<Q, Container, BaseElement>
): RenderResult<Q, Container, BaseElement>;
export function render(
ui: React.ReactNode,
options?: Omit<RenderOptions, 'queries'>
): RenderResult;
export function render(ui: React.ReactNode, options?: any): any {
return renderOriginal(ui, {
legacyRoot: true,
...options,
});
}
6 changes: 3 additions & 3 deletions packages/fuselage/src/components/Accordion/Accordion.spec.tsx
Original file line number Diff line number Diff line change
@@ -1,18 +1,18 @@
import { composeStories } from '@storybook/react';
import { render } from '@testing-library/react';
import { axe } from 'jest-axe';

import { render } from '../../testing';
import * as stories from './Accordion.stories';

const { Default } = composeStories(stories);

describe('[Accordion Component]', () => {
it('renders without crashing', () => {
render(<Default />, { legacyRoot: true });
render(<Default />);
});

it('should have no a11y violations', async () => {
const { container } = render(<Default />, { legacyRoot: true });
const { container } = render(<Default />);

const results = await axe(container);
expect(results).toHaveNoViolations();
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import { composeStories } from '@storybook/react';
import { render } from '@testing-library/react';
import { axe } from 'jest-axe';
import { withResizeObserverMock } from 'testing-utils/mocks/withResizeObserverMock';

import { render } from '../../testing';
import * as stories from './AutoComplete.stories';

const testCases = Object.values(composeStories(stories)).map((Story) => [
Expand All @@ -16,15 +16,15 @@ describe('[AutoComplete Rendering]', () => {
test.each(testCases)(
`renders %s without crashing`,
async (_storyname, Story) => {
const tree = render(<Story />, { legacyRoot: true });
const tree = render(<Story />);
expect(tree.baseElement).toMatchSnapshot();
}
);

test.each(testCases)(
'%s should have no a11y violations',
async (_storyname, Story) => {
const { container } = render(<Story />, { legacyRoot: true });
const { container } = render(<Story />);

const results = await axe(container);
expect(results).toHaveNoViolations();
Expand Down
6 changes: 3 additions & 3 deletions packages/fuselage/src/components/Avatar/Avatar.spec.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { composeStories } from '@storybook/react';
import { render } from '@testing-library/react';
import { axe } from 'jest-axe';

import { render } from '../../testing';
import * as stories from './Avatar.stories';

const testCases = Object.values(composeStories(stories)).map((Story) => [
Expand All @@ -13,15 +13,15 @@ describe('[Avatar Component]', () => {
test.each(testCases)(
`renders %s without crashing`,
async (_storyname, Story) => {
const tree = render(<Story />, { legacyRoot: true });
const tree = render(<Story />);
expect(tree.baseElement).toMatchSnapshot();
}
);

test.each(testCases)(
'%s should have no a11y violations',
async (_storyname, Story) => {
const { container } = render(<Story />, { legacyRoot: true });
const { container } = render(<Story />);

const results = await axe(container);
expect(results).toHaveNoViolations();
Expand Down
31 changes: 13 additions & 18 deletions packages/fuselage/src/components/Badge/Badge.spec.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { composeStories } from '@storybook/react';
import { render, screen } from '@testing-library/react';
import { screen } from '@testing-library/react';

import { render } from '../../testing';
import { Badge } from './Badge';
import * as stories from './Badge.stories';

Expand All @@ -10,54 +11,48 @@ const { Default, Primary, Secondary, Danger, Warning, Disabled } =
describe('[Badge Component]', () => {
describe('Story renders without crashing', () => {
it('Default', () => {
render(<Default />, { legacyRoot: true });
render(<Default />);
});
it('Primary', () => {
render(<Primary />, { legacyRoot: true });
render(<Primary />);
});
it('Secondary', () => {
render(<Secondary />, { legacyRoot: true });
render(<Secondary />);
});
it('Danger', () => {
render(<Danger />, { legacyRoot: true });
render(<Danger />);
});
it('Warning', () => {
render(<Warning />, { legacyRoot: true });
render(<Warning />);
});
it('Disabled', () => {
render(<Disabled />, { legacyRoot: true });
render(<Disabled />);
});
});

it('should display children', () => {
render(<Badge>Children</Badge>, { legacyRoot: true });
render(<Badge>Children</Badge>);
screen.getByText('Children');
});

it('should have class according to variant', () => {
const { container } = render(<Badge variant='primary' />, {
legacyRoot: true,
});
const { container } = render(<Badge variant='primary' />);
expect(container.querySelector('.rcx-badge--primary')).toBeInTheDocument();
});

it('should have class passed as property', () => {
const { container } = render(<Badge className='test-class' />, {
legacyRoot: true,
});
const { container } = render(<Badge className='test-class' />);
expect(container.querySelector('.test-class')).toBeInTheDocument();
});

it('should show title when hovered', () => {
const { container } = render(<Badge title='test-title' />, {
legacyRoot: true,
});
const { container } = render(<Badge title='test-title' />);
const badgeTitle = container.querySelector('span');
expect(badgeTitle?.getAttribute('title')).toEqual('test-title');
});

it('should have disabled class if it has the disabled property', () => {
const { container } = render(<Badge disabled />, { legacyRoot: true });
const { container } = render(<Badge disabled />);
expect(container.querySelector('.rcx-badge--disabled')).toBeInTheDocument();
});
});
9 changes: 4 additions & 5 deletions packages/fuselage/src/components/Banner/Banner.spec.tsx
Original file line number Diff line number Diff line change
@@ -1,19 +1,18 @@
import { render, screen } from '@testing-library/react';
import { screen } from '@testing-library/react';
import { withResizeObserverMock } from 'testing-utils/mocks/withResizeObserverMock';

import { render } from '../../testing';
import Banner from './Banner';

withResizeObserverMock();

describe('[Banner Component]', () => {
it('renders without crashing', () => {
render(<Banner />, { legacyRoot: true });
render(<Banner />);
});

it('renders with link', () => {
render(<Banner link='https://rocket.chat' linkText='More info' />, {
legacyRoot: true,
});
render(<Banner link='https://rocket.chat' linkText='More info' />);
expect(
screen.getByRole('link', {
name: /more info/i,
Expand Down
30 changes: 10 additions & 20 deletions packages/fuselage/src/components/Box/Box.spec.tsx
Original file line number Diff line number Diff line change
@@ -1,18 +1,16 @@
import { css } from '@rocket.chat/css-in-js';
import { render } from '@testing-library/react';

import Box from '.';
import { render } from '../../testing';

describe('[Box Component]', () => {
it('renders without crashing', () => {
render(<Box />, { legacyRoot: true });
render(<Box />);
});

describe('className prop', () => {
it('accepts a string in className prop', () => {
const { container } = render(<Box className='fuselage' />, {
legacyRoot: true,
});
const { container } = render(<Box className='fuselage' />);

expect(container.firstElementChild).toHaveProperty('tagName', 'DIV');
expect(container.firstElementChild).toBeInstanceOf(HTMLDivElement);
Expand All @@ -26,8 +24,7 @@ describe('[Box Component]', () => {
className={css`
width: 10em;
`}
/>,
{ legacyRoot: true }
/>
);

expect(container.firstElementChild).toHaveProperty('tagName', 'DIV');
Expand All @@ -39,9 +36,7 @@ describe('[Box Component]', () => {
});

it('accepts an empty array in className prop', () => {
const { container } = render(<Box className={[]} />, {
legacyRoot: true,
});
const { container } = render(<Box className={[]} />);

expect(container.firstElementChild).toHaveProperty('tagName', 'DIV');
expect(container.firstElementChild).toHaveClass('rcx-box');
Expand All @@ -56,8 +51,7 @@ describe('[Box Component]', () => {
width: 10em;
`,
]}
/>,
{ legacyRoot: true }
/>
);

expect(container.firstElementChild).toHaveProperty('tagName', 'DIV');
Expand All @@ -71,8 +65,7 @@ describe('[Box Component]', () => {

it('attaches rcx-* props into className', () => {
const { container } = render(
<Box rcx-test-a rcx-test-b={false} rcx-test-c={true} rcx-test='d' />,
{ legacyRoot: true }
<Box rcx-test-a rcx-test-b={false} rcx-test-c={true} rcx-test='d' />
);

expect(container.firstElementChild).toHaveProperty('tagName', 'DIV');
Expand All @@ -91,8 +84,7 @@ describe('[Box Component]', () => {
rcx-test-b={false}
rcx-test-c={true}
rcx-test='d'
/>,
{ legacyRoot: true }
/>
);

expect(container.firstElementChild).toHaveProperty('tagName', 'DIV');
Expand All @@ -116,8 +108,7 @@ describe('[Box Component]', () => {
rcx-test-b={false}
rcx-test-c={true}
rcx-test='d'
/>,
{ legacyRoot: true }
/>
);

expect(container.firstElementChild).toHaveProperty('tagName', 'DIV');
Expand All @@ -136,14 +127,13 @@ describe('[Box Component]', () => {

describe('is props', () => {
it('accepts a instrinsic HTML element', () => {
const { container } = render(<Box is='span' />, { legacyRoot: true });
const { container } = render(<Box is='span' />);

expect(container.firstElementChild).toHaveProperty('tagName', 'SPAN');
});

it('accepts a instrinsic SVG element', () => {
const { container } = render(<Box is='path' />, {
legacyRoot: true,
wrapper: ({ children }) => <svg children={children} />,
});

Expand Down
6 changes: 3 additions & 3 deletions packages/fuselage/src/components/Bubble/Bubble.spec.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { composeStories } from '@storybook/react';
import { render } from '@testing-library/react';
import { axe } from 'jest-axe';

import { render } from '../../testing';
import * as stories from './Bubble.stories';

const testCases = Object.values(composeStories(stories)).map((Story) => [
Expand All @@ -13,15 +13,15 @@ describe('[Bubble Rendering]', () => {
test.each(testCases)(
`renders %s without crashing`,
async (_storyname, Story) => {
const tree = render(<Story />, { legacyRoot: true });
const tree = render(<Story />);
expect(tree.baseElement).toMatchSnapshot();
}
);

test.each(testCases)(
'%s should have no a11y violations',
async (_storyname, Story) => {
const { container } = render(<Story />, { legacyRoot: true });
const { container } = render(<Story />);

const results = await axe(container);
expect(results).toHaveNoViolations();
Expand Down
Loading

0 comments on commit 5b96b6d

Please sign in to comment.