Skip to content

Commit

Permalink
Choicegroup (v8): convert tests to use testing-library (#22208)
Browse files Browse the repository at this point in the history
  • Loading branch information
TristanWatanabe committed Mar 30, 2022
1 parent 062d979 commit 81bcf26
Show file tree
Hide file tree
Showing 2 changed files with 914 additions and 919 deletions.
167 changes: 70 additions & 97 deletions packages/react/src/components/ChoiceGroup/ChoiceGroup.test.tsx
Original file line number Diff line number Diff line change
@@ -1,48 +1,34 @@
import * as React from 'react';
import { mount, ReactWrapper } from 'enzyme';
import * as ReactTestUtils from 'react-dom/test-utils';
import * as renderer from 'react-test-renderer';
import { render } from '@testing-library/react';
import userEvent from '@testing-library/user-event';

import { ChoiceGroup } from './ChoiceGroup';
import { merge, resetIds } from '../../Utilities';
import { safeMount } from '@fluentui/test-utilities';
import { isConformant } from '../../common/isConformant';
import type { IChoiceGroupOption, IChoiceGroup, IChoiceGroupProps } from './ChoiceGroup.types';
import type { IChoiceGroupOption, IChoiceGroup } from './ChoiceGroup.types';

const TEST_OPTIONS: IChoiceGroupOption[] = [
{ key: '1', text: '1', 'data-automation-id': 'auto1', autoFocus: true } as IChoiceGroupOption,
{ key: '2', text: '2' },
{ key: '3', text: '3' },
];
const CHOICE_QUERY_SELECTOR = '.ms-ChoiceField-input';

describe('ChoiceGroup', () => {
let choiceGroup: ReactWrapper<IChoiceGroupProps> | undefined;

beforeEach(() => {
// Resetting ids to create predictability in generated ids.
resetIds();
});

afterEach(() => {
if (choiceGroup) {
choiceGroup.unmount();
choiceGroup = undefined;
}
});

it('renders ChoiceGroup correctly', () => {
const component = renderer.create(<ChoiceGroup className="testClassName" options={TEST_OPTIONS} required />);
const tree = component.toJSON();
expect(tree).toMatchSnapshot();
const { container } = render(<ChoiceGroup className="testClassName" options={TEST_OPTIONS} required />);
expect(container).toMatchSnapshot();
});

it('renders ChoiceGroup with label correctly', () => {
const component = renderer.create(
const { container } = render(
<ChoiceGroup className="testClassName" label="test label" options={TEST_OPTIONS} required />,
);
const tree = component.toJSON();
expect(tree).toMatchSnapshot();
expect(container).toMatchSnapshot();
});

isConformant({
Expand All @@ -51,39 +37,39 @@ describe('ChoiceGroup', () => {
});

it('does not use className prop from parent on label', () => {
choiceGroup = mount(<ChoiceGroup className="testClassName" label="test label" options={TEST_OPTIONS} required />);
const label = choiceGroup.getDOMNode().querySelector('label');
const { getByRole } = render(
<ChoiceGroup className="testClassName" label="test label" options={TEST_OPTIONS} required />,
);
const label = getByRole('radiogroup').firstElementChild;
expect(label).toBeTruthy();
expect(label!.textContent).toBe('test label');
expect(label!.className).not.toContain('testClassName');
});

it('can change options', () => {
choiceGroup = mount(<ChoiceGroup label="testgroup" options={TEST_OPTIONS} required={true} />);
const { getAllByRole } = render(<ChoiceGroup label="testgroup" options={TEST_OPTIONS} required={true} />);

const choiceOptions = choiceGroup
.getDOMNode()
.querySelectorAll(CHOICE_QUERY_SELECTOR) as NodeListOf<HTMLInputElement>;
const choiceOptions = getAllByRole('radio') as HTMLInputElement[];

expect(choiceOptions.length).toBe(3);

expect(choiceOptions[0].checked).toEqual(false);
expect(choiceOptions[1].checked).toEqual(false);
expect(choiceOptions[2].checked).toEqual(false);

ReactTestUtils.Simulate.change(choiceOptions[0]);
userEvent.click(choiceOptions[0]);

expect(choiceOptions[0].checked).toEqual(true);
expect(choiceOptions[1].checked).toEqual(false);
expect(choiceOptions[2].checked).toEqual(false);

ReactTestUtils.Simulate.change(choiceOptions[1]);
userEvent.click(choiceOptions[1]);

expect(choiceOptions[0].checked).toEqual(false);
expect(choiceOptions[1].checked).toEqual(true);
expect(choiceOptions[2].checked).toEqual(false);

ReactTestUtils.Simulate.change(choiceOptions[0]);
userEvent.click(choiceOptions[0]);

expect(choiceOptions[0].checked).toEqual(true);
expect(choiceOptions[1].checked).toEqual(false);
Expand All @@ -94,39 +80,36 @@ describe('ChoiceGroup', () => {
const options: IChoiceGroupOption[] = merge([], TEST_OPTIONS);
options[0].disabled = true;

choiceGroup = mount(<ChoiceGroup label="testgroup" options={options} required={true} />);
const { getAllByRole } = render(<ChoiceGroup label="testgroup" options={options} required={true} />);

const choiceOptions = choiceGroup
.getDOMNode()
.querySelectorAll(CHOICE_QUERY_SELECTOR) as NodeListOf<HTMLInputElement>;
const choiceOptions = getAllByRole('radio') as HTMLInputElement[];

expect(choiceOptions[0].disabled).toEqual(true);
expect(choiceOptions[1].disabled).toEqual(false);
expect(choiceOptions[2].disabled).toEqual(false);
});

it('renders all choice options as disabled when disabled', () => {
choiceGroup = mount(<ChoiceGroup label="testgroup" options={TEST_OPTIONS} required={true} disabled={true} />);
const { getAllByRole } = render(
<ChoiceGroup label="testgroup" options={TEST_OPTIONS} required={true} disabled={true} />,
);

const choiceOptions = choiceGroup
.getDOMNode()
.querySelectorAll(CHOICE_QUERY_SELECTOR) as NodeListOf<HTMLInputElement>;
const choiceOptions = getAllByRole('radio') as HTMLInputElement[];

expect(choiceOptions[0].disabled).toEqual(true);
expect(choiceOptions[1].disabled).toEqual(true);
expect(choiceOptions[2].disabled).toEqual(true);
});

/* Testing that the defaultSelectedKey is working correctly. */
it('can act as an uncontrolled component', () => {
choiceGroup = mount(<ChoiceGroup defaultSelectedKey="1" options={TEST_OPTIONS} />);
const { getAllByRole } = render(<ChoiceGroup defaultSelectedKey="1" options={TEST_OPTIONS} />);

const choiceOptions = choiceGroup
.getDOMNode()
.querySelectorAll(CHOICE_QUERY_SELECTOR) as NodeListOf<HTMLInputElement>;
const choiceOptions = getAllByRole('radio') as HTMLInputElement[];

expect(choiceOptions[0].checked).toEqual(true);

ReactTestUtils.Simulate.change(choiceOptions[1]);
userEvent.click(choiceOptions[1]);

expect(choiceOptions[1].checked).toEqual(true);
});
Expand All @@ -140,15 +123,13 @@ describe('ChoiceGroup', () => {
_selectedItem = item;
};

choiceGroup = mount(<ChoiceGroup selectedKey="1" options={TEST_OPTIONS} onChange={onChange} />);
const { getAllByRole } = render(<ChoiceGroup selectedKey="1" options={TEST_OPTIONS} onChange={onChange} />);

const choiceOptions = choiceGroup
.getDOMNode()
.querySelectorAll(CHOICE_QUERY_SELECTOR) as NodeListOf<HTMLInputElement>;
const choiceOptions = getAllByRole('radio') as HTMLInputElement[];

expect(choiceOptions[0].checked).toEqual(true);

ReactTestUtils.Simulate.change(choiceOptions[1]);
userEvent.click(choiceOptions[1]);

expect(choiceOptions[0].checked).toEqual(true);
expect(choiceOptions[1].checked).toEqual(false);
Expand All @@ -162,11 +143,9 @@ describe('ChoiceGroup', () => {
item: IChoiceGroupOption | undefined,
): void => undefined;

choiceGroup = mount(<ChoiceGroup options={TEST_OPTIONS} onChange={onChange} />);
const { getAllByRole } = render(<ChoiceGroup options={TEST_OPTIONS} onChange={onChange} />);

const choiceOptions = choiceGroup
.getDOMNode()
.querySelectorAll(CHOICE_QUERY_SELECTOR) as NodeListOf<HTMLInputElement>;
const choiceOptions = getAllByRole('radio') as HTMLInputElement[];

const extraAttributeGetter: (index: number) => string | null = (index: number): string | null => {
const input: HTMLInputElement = choiceOptions[index];
Expand All @@ -178,24 +157,24 @@ describe('ChoiceGroup', () => {
});

it('can set role attribute to empty string', () => {
choiceGroup = mount(<ChoiceGroup options={TEST_OPTIONS} role="" />);
const role = choiceGroup.getDOMNode().getAttribute('role');
const { container } = render(<ChoiceGroup options={TEST_OPTIONS} role="" />);
const role = container.firstElementChild!.getAttribute('role');
expect(role).toEqual('');
});

it('can set role attribute on the containing element', () => {
choiceGroup = mount(<ChoiceGroup options={TEST_OPTIONS} role="Test" />);
const role = choiceGroup.getDOMNode().getAttribute('role');
expect(role).toEqual('Test');
const { container } = render(<ChoiceGroup options={TEST_OPTIONS} role="radiogroup" />);
const role = container.firstElementChild!.getAttribute('role');
expect(role).toEqual('radiogroup');
});

it('can assign a custom aria label', () => {
const option4: IChoiceGroupOption[] = [{ key: '4', text: '4', ariaLabel: 'Custom aria label' }];
choiceGroup = mount(<ChoiceGroup label="testgroup" options={TEST_OPTIONS.concat(option4)} required={true} />);
const { getAllByRole } = render(
<ChoiceGroup label="testgroup" options={TEST_OPTIONS.concat(option4)} required={true} />,
);

const choiceOptions = choiceGroup
.getDOMNode()
.querySelectorAll(CHOICE_QUERY_SELECTOR) as NodeListOf<HTMLInputElement>;
const choiceOptions = getAllByRole('radio') as HTMLInputElement[];

expect(choiceOptions.length).toBe(4);

Expand All @@ -207,80 +186,74 @@ describe('ChoiceGroup', () => {

it('returns the current checked option with user interaction', () => {
const choiceGroupRef = React.createRef<IChoiceGroup>();
choiceGroup = mount(<ChoiceGroup options={TEST_OPTIONS} componentRef={choiceGroupRef} />);
const { getAllByRole } = render(<ChoiceGroup options={TEST_OPTIONS} componentRef={choiceGroupRef} />);

const choiceOptions = choiceGroup
.getDOMNode()
.querySelectorAll(CHOICE_QUERY_SELECTOR) as NodeListOf<HTMLInputElement>;
const choiceOptions = getAllByRole('radio') as HTMLInputElement[];

expect(choiceGroupRef.current!.checkedOption).toBeUndefined();
ReactTestUtils.Simulate.change(choiceOptions[0]);
userEvent.click(choiceOptions[0]);
expect(choiceGroupRef.current!.checkedOption).toEqual(TEST_OPTIONS[0]);
});

it('returns the current checked option with defaultSelectedKey', () => {
const choiceGroupRef = React.createRef<IChoiceGroup>();
choiceGroup = mount(<ChoiceGroup options={TEST_OPTIONS} defaultSelectedKey="1" componentRef={choiceGroupRef} />);
const { getAllByRole } = render(
<ChoiceGroup options={TEST_OPTIONS} defaultSelectedKey="1" componentRef={choiceGroupRef} />,
);

const choiceOptions = choiceGroup
.getDOMNode()
.querySelectorAll(CHOICE_QUERY_SELECTOR) as NodeListOf<HTMLInputElement>;
const choiceOptions = getAllByRole('radio') as HTMLInputElement[];

expect(choiceGroupRef.current!.checkedOption).toEqual(TEST_OPTIONS[0]);
ReactTestUtils.Simulate.change(choiceOptions[1]);
userEvent.click(choiceOptions[1]);
expect(choiceGroupRef.current!.checkedOption).toEqual(TEST_OPTIONS[1]);
});

it('returns the current checked option with selectedKey', () => {
const choiceGroupRef = React.createRef<IChoiceGroup>();
choiceGroup = mount(<ChoiceGroup options={TEST_OPTIONS} selectedKey="1" componentRef={choiceGroupRef} />);
const { getAllByRole } = render(
<ChoiceGroup options={TEST_OPTIONS} selectedKey="1" componentRef={choiceGroupRef} />,
);

const choiceOptions = choiceGroup
.getDOMNode()
.querySelectorAll(CHOICE_QUERY_SELECTOR) as NodeListOf<HTMLInputElement>;
const choiceOptions = getAllByRole('radio') as HTMLInputElement[];

expect(choiceGroupRef.current!.checkedOption).toEqual(TEST_OPTIONS[0]);
ReactTestUtils.Simulate.change(choiceOptions[1]);
userEvent.click(choiceOptions[1]);
// selectedKey is still used even though it didn't get updated for latest user click
expect(choiceGroupRef.current!.checkedOption).toEqual(TEST_OPTIONS[0]);
});

it('can render element id', () => {
choiceGroup = mount(<ChoiceGroup defaultSelectedKey="1" id="foo" options={TEST_OPTIONS} />);
expect(choiceGroup.getDOMNode().getAttribute('id')).toBe('foo');
const { container } = render(<ChoiceGroup defaultSelectedKey="1" id="foo" options={TEST_OPTIONS} />);
const root = container.firstElementChild;
expect(root!.getAttribute('id')).toBe('foo');
});

it('can focus the checked option', () => {
// This test has to mount the element to the document since ChoiceGroup.focus() uses document.getElementById()
const choiceGroupRef = React.createRef<IChoiceGroup>();
safeMount(
const { getAllByRole } = render(
<ChoiceGroup options={TEST_OPTIONS} defaultSelectedKey="1" componentRef={choiceGroupRef} />,
choiceGroup2 => {
const option = choiceGroup2.getDOMNode().querySelector(CHOICE_QUERY_SELECTOR) as HTMLInputElement;
const focusSpy = jest.spyOn(option, 'focus');

choiceGroupRef.current!.focus();
expect(focusSpy).toHaveBeenCalled();
},
true /* attach */,
);

const option = getAllByRole('radio')[0] as HTMLInputElement;
const focusSpy = jest.spyOn(option, 'focus');

choiceGroupRef.current!.focus();
expect(focusSpy).toHaveBeenCalled();
});

it('can focus the first enabled option', () => {
const choiceGroupRef = React.createRef<IChoiceGroup>();
safeMount(
const { getAllByRole } = render(
<ChoiceGroup
options={[{ key: '0', text: 'disabled', disabled: true }, ...TEST_OPTIONS]}
componentRef={choiceGroupRef}
/>,
choiceGroup2 => {
const option = choiceGroup2.getDOMNode().querySelectorAll(CHOICE_QUERY_SELECTOR)![1] as HTMLInputElement;
const focusSpy = jest.spyOn(option, 'focus');

choiceGroupRef.current!.focus();
expect(focusSpy).toHaveBeenCalled();
},
true /* attach */,
);

const option = getAllByRole('radio')[1] as HTMLInputElement;
const focusSpy = jest.spyOn(option, 'focus');

choiceGroupRef.current!.focus();
expect(focusSpy).toHaveBeenCalled();
});
});
Loading

0 comments on commit 81bcf26

Please sign in to comment.